Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace flake8 with ruff #869

45 changes: 45 additions & 0 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
# MegaLinter GitHub Action configuration file
# More info at https://megalinter.io
name: MegaLinter
on:
push:
branches: "master"
pull_request:

jobs:
megalinter:
name: MegaLinter
runs-on: ubuntu-latest
permissions:
# Give the linter write permission to comment on PRs (if PR is not from fork)
issues: write
pull-requests: write
steps:
# Git Checkout
- name: Checkout Code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
# MegaLinter
- name: MegaLinter
id: ml
# You can override MegaLinter flavor used to have faster performances
# More info at https://megalinter.io/flavors/
uses: oxsecurity/megalinter/flavors/python@v7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Validate whole codebase on pushes and only changes on pull requests
# VALIDATE_ALL_CODEBASE: ${{ github.event_name == 'push'}}
VALIDATE_ALL_CODEBASE: true

# Upload MegaLinter artifacts
- name: Archive production artifacts
if: success() || failure()
uses: actions/upload-artifact@v4
with:
name: MegaLinter reports
path: |
megalinter-reports
mega-linter.log
29 changes: 0 additions & 29 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,7 @@ on:
pull_request:

jobs:
lint:
runs-on: ubuntu-latest
name: Lint
steps:
- uses: actions/checkout@v4

- uses: actions/cache@v4
id: cache
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11

- name: Install dependencies
run: |
pip install -U pip
pip install tox flake8

- name: flake8 critical lint
run: tox -e flake8-critical

test:
needs: lint

name: "Python ${{ matrix.python-version }}"
runs-on: ubuntu-latest

Expand Down
14 changes: 14 additions & 0 deletions .mega-linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# All available variables are described in documentation
# https://megalinter.io/configuration/

LINTER_RULES_PATH: .

ENABLE_LINTERS:
- PYTHON_BLACK
- PYTHON_RUFF

# Make workflow fail even on non blocking errors
FORMATTERS_DISABLE_ERRORS: false

PYTHON_BLACK_CONFIG_FILE: pyproject.toml
PYTHON_RUFF_CONFIG_FILE: pyproject.toml
11 changes: 4 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,15 @@ repos:
- id: end-of-file-fixer
exclude: &exclude_pattern '^changelog.d/'
- id: debug-statements
- repo: https://github.com/pycqa/flake8
rev: 7.1.1
hooks:
- id: flake8
name: "Flake8: critical"
args: ['--count', '--select=E9,F63,F7,F82', '--show-source', '--statistics']
types: [file, python]
- repo: https://github.com/psf/black
rev: 24.8.0
hooks:
- id: black
exclude: migrations/
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.1
hooks:
- id: ruff
- repo: https://github.com/twisted/towncrier
rev: 24.8.0
hooks:
Expand Down
18 changes: 16 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ dev = [
"black",
"coverage",
"django-extensions",
"flake8",
"ipython",
"pre-commit",
"python-dotenv",
"ruff",
"towncrier",
"werkzeug",
"tox<4", # does not work on tox 4 for some reason
Expand Down Expand Up @@ -89,7 +89,8 @@ write_to = "src/argus/version.py"

[tool.black]
line-length = 120
exclude = '''
# Exclude files even when passed directly as argument (for MegaLinter)
force-exclude = '''
(
/(
\.eggs # exclude a few common directories in the
Expand All @@ -108,6 +109,19 @@ exclude = '''
)
'''

[tool.ruff]
line-length = 120
target-version = "py39"
exclude = [
"src/**/migrations"
]
# Exclude files even when passed directly as argument (for MegaLinter)
force-exclude = true

[tool.ruff.lint]
select = ["E4", "E7", "E9", "F"]
ignore = ["E731", "F403", "F405"]

[tool.towncrier]
directory = "changelog.d"
filename = "CHANGELOG.md"
Expand Down
1 change: 0 additions & 1 deletion src/argus/dev/management/commands/create_fake_incident.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import argparse
import json
from pathlib import Path
from random import randint

from django.core.management.base import BaseCommand

Expand Down
2 changes: 1 addition & 1 deletion src/argus/dev/management/commands/create_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ def handle(self, *args, **options):
source = options["source"]
source_type = options.get("source_type") or "argus"
sst = SourceSystemTypeFactory(name=source_type)
ss = SourceSystemFactory(name=source, type=sst)
SourceSystemFactory(name=source, type=sst)
1 change: 0 additions & 1 deletion src/argus/dev/management/commands/list_filters.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from django.contrib.auth.hashers import check_password
from django.core.management.base import BaseCommand

from argus.filter import get_filter_backend
Expand Down
3 changes: 0 additions & 3 deletions src/argus/filter/V1/serializers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import json
from typing import List

from rest_framework import fields, serializers
from rest_framework import serializers

from argus.incident.constants import INCIDENT_LEVELS
from argus.notificationprofile.models import Filter

from ..primitive_serializers import CustomMultipleChoiceField
from .validators import validate_filter_string


Expand Down
2 changes: 0 additions & 2 deletions src/argus/filter/apps.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from django.apps import AppConfig
from django.contrib.auth.signals import user_logged_in
from django.core.checks import register
from django.db.models.signals import post_save, pre_save, post_migrate


class FilterConfig(AppConfig):
Expand Down
1 change: 0 additions & 1 deletion src/argus/filter/filterwrapper.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

import logging
from operator import or_
from typing import TYPE_CHECKING, Dict, Optional, Any, Tuple

from django.conf import settings
Expand Down
2 changes: 1 addition & 1 deletion src/argus/filter/serializers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from rest_framework import fields, serializers
from rest_framework import serializers

from argus.incident.constants import INCIDENT_LEVELS
from argus.incident.models import Event
Expand Down
2 changes: 1 addition & 1 deletion src/argus/incident/V1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class Meta:
def update(self, instance, validated_data):
now = self.__class__._later_than_func()
if instance.expiration and instance.expiration < now: # expired are readonly
raise serializers.ValidationError(f"Cannot change expired Acknowledgement")
raise serializers.ValidationError("Cannot change expired Acknowledgement")
expiration = validated_data.get("expiration")
instance.expiration = expiration
instance.save()
Expand Down
3 changes: 2 additions & 1 deletion src/argus/incident/factories.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import factory, factory.fuzzy
import factory
import factory.fuzzy
import pytz

from argus.auth.factories import SourceUserFactory
Expand Down
9 changes: 4 additions & 5 deletions src/argus/incident/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from copy import deepcopy
from collections import OrderedDict
from typing import List, Tuple, Any, Dict
from typing import List, Tuple

from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
Expand Down Expand Up @@ -52,7 +51,7 @@ class TagSerializer(serializers.Serializer):
tag = serializers.CharField()

def to_internal_value(self, data: dict):
if not "tag" in data:
if "tag" not in data:
raise serializers.ValidationError('Tags need to follow the format {"tag": key=value}')

key, value = clean_tag(data.pop("tag"))
Expand Down Expand Up @@ -81,7 +80,7 @@ def create(self, validated_data: dict):
return Tag.objects.create(key=key, value=value, **validated_data)

def to_internal_value(self, data: dict):
if not "tag" in data:
if "tag" not in data:
raise serializers.ValidationError('Tags need to follow the format {"tag": key=value}')

key, value = clean_tag(data.pop("tag"))
Expand Down Expand Up @@ -341,7 +340,7 @@ class Meta:
def update(self, instance, validated_data):
now = self.__class__._later_than_func()
if instance.expiration and instance.expiration < now: # expired are readonly
raise serializers.ValidationError(f"Cannot change expired Acknowledgement")
raise serializers.ValidationError("Cannot change expired Acknowledgement")
expiration = validated_data.get("expiration")
instance.expiration = expiration
instance.save()
Expand Down
2 changes: 0 additions & 2 deletions src/argus/incident/signals.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
from django.db.models import Q
from django.utils import timezone
from rest_framework.authtoken.models import Token

from argus.notificationprofile.media import send_notifications_to_users
from argus.notificationprofile.media import background_send_notification
from argus.notificationprofile.media import send_notification
from .models import (
Acknowledgement,
ChangeEvent,
Event,
Incident,
SourceSystem,
Expand Down
4 changes: 0 additions & 4 deletions src/argus/incident/ticket/dummy.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,9 @@

from factory import Faker
import logging
from typing import TYPE_CHECKING

from .base import TicketPlugin

if TYPE_CHECKING:
from argus.incident.models import Incident

LOG = logging.getLogger(__name__)

__all__ = [
Expand Down
7 changes: 1 addition & 6 deletions src/argus/incident/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from django_filters import rest_framework as filters
from rest_framework.filters import SearchFilter
from drf_rw_serializers import viewsets as rw_viewsets
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema, extend_schema_view
from drf_spectacular.utils import OpenApiParameter, OpenApiResponse
from rest_framework import mixins, serializers, status, viewsets
Expand All @@ -23,24 +22,20 @@

from argus.auth.models import User
from argus.drf.permissions import IsSuperuserOrReadOnly
from argus.incident.models import Acknowledgement, Event
from argus.incident.ticket.base import (
TicketClientException,
TicketCreationException,
TicketPluginException,
TicketSettingsException,
)
from argus.notificationprofile.media import (
send_notifications_to_users,
background_send_notification,
)
from argus.filter import get_filter_backend
from argus.util.datetime_utils import INFINITY_REPR
from argus.util.signals import bulk_changed
from argus.util.utils import import_class_from_dotted_path

from .forms import AddSourceSystemForm
from .models import (
Acknowledgement,
ChangeEvent,
Event,
Incident,
Expand Down
8 changes: 3 additions & 5 deletions src/argus/notificationprofile/V1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

from rest_framework import fields, serializers

from argus.filter.primitive_serializers import CustomMultipleChoiceField
from argus.filter.V1.serializers import FilterSerializerV1
from argus.filter.V1.validators import validate_filter_string
from ..models import DestinationConfig, NotificationProfile
from ..serializers import TimeslotSerializer

Expand Down Expand Up @@ -110,19 +108,19 @@ def update(self, instance: NotificationProfile, validated_data: dict):
default_email_destination = instance.user.destinations.filter(media_id="email").get(
settings__email_address=instance.user.email
)
if not default_email_destination in instance.destinations.all():
if default_email_destination not in instance.destinations.all():
instance.destinations.add(default_email_destination)

first_sms_destination = instance.destinations.filter(media_id="sms").order_by("pk").first()
if (not phone_number == None) and ((not media and first_sms_destination) or "SM" in media):
if (phone_number is not None) and ((not media and first_sms_destination) or "SM" in media):
given_sms_destination = DestinationConfig.objects.filter(media_id="sms").filter(pk=phone_number).first()
if not given_sms_destination:
raise serializers.ValidationError(
{"phone_number": [f'Invalid pk "{phone_number}" - object does not exist.']}
)
if not first_sms_destination:
instance.destinations.add(given_sms_destination)
elif not first_sms_destination.pk == given_sms_destination.pk:
elif first_sms_destination.pk != given_sms_destination.pk:
instance.destinations.remove(first_sms_destination)
instance.destinations.add(given_sms_destination)

Expand Down
3 changes: 1 addition & 2 deletions src/argus/notificationprofile/apps.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from django.apps import AppConfig
from django.contrib.auth.signals import user_logged_in
from django.db.models.signals import post_save, pre_save, post_migrate
from django.db.models.signals import post_save, post_migrate


class NotificationprofileConfig(AppConfig):
Expand Down
2 changes: 1 addition & 1 deletion src/argus/notificationprofile/media/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def send_email_safely(function, additional_error=None, *args, **kwargs) -> int:
try:
result = function(*args, **kwargs)
return result
except ConnectionRefusedError as e:
except ConnectionRefusedError:
EMAIL_HOST = getattr(settings, "EMAIL_HOST", None)
if not EMAIL_HOST:
LOG.error("Notification: Email: EMAIL_HOST not set, cannot send")
Expand Down
3 changes: 1 addition & 2 deletions src/argus/notificationprofile/media/sms_as_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
else:
from collections.abc import Iterable

from typing import Union, Set
from types import NoneType
from typing import Set
from django.db.models.query import QuerySet
from argus.auth.models import User
from ..models import DestinationConfig
Expand Down
Loading
Loading