From a3fba2787b2e27a825f7b1216659347267e121af Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 11:23:43 +0200 Subject: [PATCH 01/12] Use MegaLinter for linting in workflows --- .github/workflows/linter.yml | 45 ++++++++++++++++++++++++++++++++++++ .github/workflows/python.yml | 29 ----------------------- .mega-linter.yml | 14 +++++++++++ pyproject.toml | 3 ++- 4 files changed, 61 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/linter.yml create mode 100644 .mega-linter.yml diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 000000000..aeaae1195 --- /dev/null +++ b/.github/workflows/linter.yml @@ -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 diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index c55f53af5..e43dea684 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -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 diff --git a/.mega-linter.yml b/.mega-linter.yml new file mode 100644 index 000000000..c821cc9c8 --- /dev/null +++ b/.mega-linter.yml @@ -0,0 +1,14 @@ +# All available variables are described in documentation +# https://megalinter.io/configuration/ + +LINTER_RULES_PATH: . + +ENABLE_LINTERS: + - PYTHON_BLACK + - PYTHON_FLAKE8 + +# Make workflow fail even on non blocking errors +FORMATTERS_DISABLE_ERRORS: false + +PYTHON_BLACK_CONFIG_FILE: pyproject.toml +PYTHON_FLAKE8_CONFIG_FILE: tox.ini diff --git a/pyproject.toml b/pyproject.toml index a22531b56..eb69d8bd8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 From 5b39156c947aafc48a8aeb11af274c66cdbb7762 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 11:52:59 +0200 Subject: [PATCH 02/12] Fix imports according to ruff --- src/argus/incident/factories.py | 3 ++- src/argus/site/settings/dev.py | 2 +- src/argus/ws/asgi.py | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/argus/incident/factories.py b/src/argus/incident/factories.py index cf854663a..7bb88e2d7 100644 --- a/src/argus/incident/factories.py +++ b/src/argus/incident/factories.py @@ -1,4 +1,5 @@ -import factory, factory.fuzzy +import factory +import factory.fuzzy import pytz from argus.auth.factories import SourceUserFactory diff --git a/src/argus/site/settings/dev.py b/src/argus/site/settings/dev.py index 01db00999..c4e8fbb59 100644 --- a/src/argus/site/settings/dev.py +++ b/src/argus/site/settings/dev.py @@ -4,7 +4,7 @@ load_dotenv() -from .base import * +from .base import * # noqa DEBUG = get_bool_env("DEBUG", True) diff --git a/src/argus/ws/asgi.py b/src/argus/ws/asgi.py index 29c0214b2..2a0d60e4a 100644 --- a/src/argus/ws/asgi.py +++ b/src/argus/ws/asgi.py @@ -6,6 +6,8 @@ https://channels.readthedocs.io/en/latest/deploying.html#run-protocol-servers """ +# ruff: noqa: E402 + import os from django.core.asgi import get_asgi_application From 0e9f51f0dff8e48c5a681cecc906d72ced5b5cee Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 12:02:47 +0200 Subject: [PATCH 03/12] Fix ruff complaints for not a in b instead of a not in b --- src/argus/incident/serializers.py | 4 ++-- src/argus/notificationprofile/V1/serializers.py | 6 +++--- src/argus/site/settings/__init__.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/argus/incident/serializers.py b/src/argus/incident/serializers.py index 5ca2f901b..d1f9389b7 100644 --- a/src/argus/incident/serializers.py +++ b/src/argus/incident/serializers.py @@ -52,7 +52,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")) @@ -81,7 +81,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")) diff --git a/src/argus/notificationprofile/V1/serializers.py b/src/argus/notificationprofile/V1/serializers.py index 7eedb4721..3d95583fd 100644 --- a/src/argus/notificationprofile/V1/serializers.py +++ b/src/argus/notificationprofile/V1/serializers.py @@ -110,11 +110,11 @@ 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( @@ -122,7 +122,7 @@ def update(self, instance: NotificationProfile, validated_data: dict): ) 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) diff --git a/src/argus/site/settings/__init__.py b/src/argus/site/settings/__init__.py index 19c10bb01..2dc161f6a 100644 --- a/src/argus/site/settings/__init__.py +++ b/src/argus/site/settings/__init__.py @@ -122,7 +122,7 @@ def normalize_url(url): if scheme not in ("http", "https"): # nothing to normalize return url - if port == None or port not in (80, 443): + if port is None or port not in (80, 443): # nothing to normalize return url netloc = "".join(netloc.rsplit(":", 1)[0]) From 4b6f9709e5d4eea97715eb97dd209b6174f7d1f1 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 12:03:06 +0200 Subject: [PATCH 04/12] Use isinstance to check for types --- src/argus/notificationprofile/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/argus/notificationprofile/serializers.py b/src/argus/notificationprofile/serializers.py index 93b74fdd0..1f24155b5 100644 --- a/src/argus/notificationprofile/serializers.py +++ b/src/argus/notificationprofile/serializers.py @@ -146,7 +146,7 @@ def validate(self, attrs: dict): if self.instance and "media" in attrs.keys() and not attrs["media"].slug == self.instance.media.slug: raise serializers.ValidationError("Media cannot be updated, only settings.") if "settings" in attrs.keys(): - if type(attrs["settings"]) != dict: + if not isinstance(attrs["settings"], dict): raise serializers.ValidationError("Settings has to be a dictionary.") if self.instance: medium = api_safely_get_medium_object(self.instance.media.slug) From 49580c5f5da788ade178580271d153986a449f26 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 12:27:00 +0200 Subject: [PATCH 05/12] Remove unused imports --- src/argus/dev/management/commands/create_fake_incident.py | 1 - src/argus/dev/management/commands/list_filters.py | 1 - src/argus/filter/V1/serializers.py | 4 +--- src/argus/filter/apps.py | 2 -- src/argus/filter/filterwrapper.py | 1 - src/argus/filter/serializers.py | 2 +- src/argus/incident/serializers.py | 3 +-- src/argus/incident/signals.py | 2 -- src/argus/incident/ticket/dummy.py | 4 ---- src/argus/incident/views.py | 5 ----- src/argus/notificationprofile/V1/serializers.py | 2 -- src/argus/notificationprofile/apps.py | 3 +-- src/argus/notificationprofile/media/sms_as_email.py | 3 +-- src/argus/notificationprofile/models.py | 3 +-- src/argus/notificationprofile/serializers.py | 3 --- src/argus/notificationprofile/signals.py | 1 - src/argus/notificationprofile/urls.py | 2 +- src/argus/notificationprofile/views.py | 2 -- src/argus/site/settings/dev.py | 2 -- src/argus/site/settings/test_CI.py | 1 - src/argus/site/urls.py | 4 ++-- src/argus/site/utils.py | 1 - tests/dev/test_check_token_expiry.py | 2 +- tests/filter/test_queryset_filters.py | 8 -------- tests/incident/test_filters.py | 4 +--- tests/incident/test_incident_fields.py | 4 +--- tests/notificationprofile/test_github236.py | 1 - tests/site/test_settings_helpers.py | 3 --- 28 files changed, 12 insertions(+), 62 deletions(-) diff --git a/src/argus/dev/management/commands/create_fake_incident.py b/src/argus/dev/management/commands/create_fake_incident.py index c177875e0..d846c399b 100644 --- a/src/argus/dev/management/commands/create_fake_incident.py +++ b/src/argus/dev/management/commands/create_fake_incident.py @@ -1,7 +1,6 @@ import argparse import json from pathlib import Path -from random import randint from django.core.management.base import BaseCommand diff --git a/src/argus/dev/management/commands/list_filters.py b/src/argus/dev/management/commands/list_filters.py index 6f4e3bf5b..aea6b0e21 100644 --- a/src/argus/dev/management/commands/list_filters.py +++ b/src/argus/dev/management/commands/list_filters.py @@ -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 diff --git a/src/argus/filter/V1/serializers.py b/src/argus/filter/V1/serializers.py index 7ceae861c..54bb59466 100644 --- a/src/argus/filter/V1/serializers.py +++ b/src/argus/filter/V1/serializers.py @@ -1,13 +1,11 @@ import json -from typing import List -from rest_framework import fields, serializers +from rest_framework import 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 diff --git a/src/argus/filter/apps.py b/src/argus/filter/apps.py index af6be3be1..960de33fd 100644 --- a/src/argus/filter/apps.py +++ b/src/argus/filter/apps.py @@ -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): diff --git a/src/argus/filter/filterwrapper.py b/src/argus/filter/filterwrapper.py index d014afb8c..b57472ef4 100644 --- a/src/argus/filter/filterwrapper.py +++ b/src/argus/filter/filterwrapper.py @@ -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 diff --git a/src/argus/filter/serializers.py b/src/argus/filter/serializers.py index 672e8817e..ed2599640 100644 --- a/src/argus/filter/serializers.py +++ b/src/argus/filter/serializers.py @@ -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 diff --git a/src/argus/incident/serializers.py b/src/argus/incident/serializers.py index d1f9389b7..3476bcbf9 100644 --- a/src/argus/incident/serializers.py +++ b/src/argus/incident/serializers.py @@ -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 diff --git a/src/argus/incident/signals.py b/src/argus/incident/signals.py index 9b21127fd..62f3e584b 100644 --- a/src/argus/incident/signals.py +++ b/src/argus/incident/signals.py @@ -1,5 +1,4 @@ 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 @@ -7,7 +6,6 @@ from argus.notificationprofile.media import send_notification from .models import ( Acknowledgement, - ChangeEvent, Event, Incident, SourceSystem, diff --git a/src/argus/incident/ticket/dummy.py b/src/argus/incident/ticket/dummy.py index 08c93d641..b475394e7 100644 --- a/src/argus/incident/ticket/dummy.py +++ b/src/argus/incident/ticket/dummy.py @@ -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__ = [ diff --git a/src/argus/incident/views.py b/src/argus/incident/views.py index 734eff616..487ce6c1b 100644 --- a/src/argus/incident/views.py +++ b/src/argus/incident/views.py @@ -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 @@ -30,10 +29,6 @@ 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 diff --git a/src/argus/notificationprofile/V1/serializers.py b/src/argus/notificationprofile/V1/serializers.py index 3d95583fd..fe28caeaa 100644 --- a/src/argus/notificationprofile/V1/serializers.py +++ b/src/argus/notificationprofile/V1/serializers.py @@ -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 diff --git a/src/argus/notificationprofile/apps.py b/src/argus/notificationprofile/apps.py index 3e5181a70..ff8f394fe 100644 --- a/src/argus/notificationprofile/apps.py +++ b/src/argus/notificationprofile/apps.py @@ -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): diff --git a/src/argus/notificationprofile/media/sms_as_email.py b/src/argus/notificationprofile/media/sms_as_email.py index 6f945229c..5edbdd815 100644 --- a/src/argus/notificationprofile/media/sms_as_email.py +++ b/src/argus/notificationprofile/media/sms_as_email.py @@ -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 diff --git a/src/argus/notificationprofile/models.py b/src/argus/notificationprofile/models.py index 937e992b4..065d45c67 100644 --- a/src/argus/notificationprofile/models.py +++ b/src/argus/notificationprofile/models.py @@ -2,9 +2,8 @@ from datetime import datetime, time import logging -from typing import TYPE_CHECKING, Dict, Optional +from typing import TYPE_CHECKING, Optional -from django.conf import settings from django.contrib.postgres.fields import ArrayField from django.db import models from django.utils import timezone diff --git a/src/argus/notificationprofile/serializers.py b/src/argus/notificationprofile/serializers.py index 1f24155b5..7fb24c7fd 100644 --- a/src/argus/notificationprofile/serializers.py +++ b/src/argus/notificationprofile/serializers.py @@ -1,9 +1,6 @@ from rest_framework import fields, serializers from argus.filter import get_filter_backend -from argus.filter.primitive_serializers import CustomMultipleChoiceField -from argus.incident.constants import INCIDENT_LEVELS -from argus.incident.models import Event from .media import api_safely_get_medium_object from .models import DestinationConfig, Media, NotificationProfile, TimeRecurrence, Timeslot diff --git a/src/argus/notificationprofile/signals.py b/src/argus/notificationprofile/signals.py index ffd41ba58..69872e681 100644 --- a/src/argus/notificationprofile/signals.py +++ b/src/argus/notificationprofile/signals.py @@ -2,7 +2,6 @@ from django.db.utils import ProgrammingError -from rest_framework.exceptions import APIException from argus.auth.models import User from .models import DestinationConfig, TimeRecurrence, Timeslot diff --git a/src/argus/notificationprofile/urls.py b/src/argus/notificationprofile/urls.py index 1f512a687..860dfd323 100644 --- a/src/argus/notificationprofile/urls.py +++ b/src/argus/notificationprofile/urls.py @@ -1,4 +1,4 @@ -from django.urls import path, include +from django.urls import path from rest_framework import routers diff --git a/src/argus/notificationprofile/views.py b/src/argus/notificationprofile/views.py index d756bfeaa..9c2503c3c 100644 --- a/src/argus/notificationprofile/views.py +++ b/src/argus/notificationprofile/views.py @@ -1,5 +1,3 @@ -import json - from django.db.models import Q from django.shortcuts import get_object_or_404 from django.views.generic import DetailView diff --git a/src/argus/site/settings/dev.py b/src/argus/site/settings/dev.py index c4e8fbb59..ead121553 100644 --- a/src/argus/site/settings/dev.py +++ b/src/argus/site/settings/dev.py @@ -1,5 +1,3 @@ -import logging.config - from dotenv import load_dotenv load_dotenv() diff --git a/src/argus/site/settings/test_CI.py b/src/argus/site/settings/test_CI.py index 8f8bcad4f..76f483ef8 100644 --- a/src/argus/site/settings/test_CI.py +++ b/src/argus/site/settings/test_CI.py @@ -2,7 +2,6 @@ import subprocess import logging.config -from django.utils.log import DEFAULT_LOGGING from .base import * diff --git a/src/argus/site/urls.py b/src/argus/site/urls.py index 96c5f5081..ee7dbe2db 100644 --- a/src/argus/site/urls.py +++ b/src/argus/site/urls.py @@ -22,11 +22,11 @@ from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView from social_django.urls import extra -from argus.auth.views import ObtainNewAuthToken, AuthMethodListView +from argus.auth.views import AuthMethodListView from argus.dataporten import views as dataporten_views from argus.notificationprofile.views import SchemaView from argus.site.utils import get_urlpatterns_from_setting -from argus.site.views import error, index, MetadataView +from argus.site.views import index, MetadataView psa_urls = [ diff --git a/src/argus/site/utils.py b/src/argus/site/utils.py index 27febdc95..6708fbc97 100644 --- a/src/argus/site/utils.py +++ b/src/argus/site/utils.py @@ -1,7 +1,6 @@ # nothing that imports models here! from copy import deepcopy -from django.conf import settings from django.urls import include, path diff --git a/tests/dev/test_check_token_expiry.py b/tests/dev/test_check_token_expiry.py index b3c67bfac..21369f06d 100644 --- a/tests/dev/test_check_token_expiry.py +++ b/tests/dev/test_check_token_expiry.py @@ -14,7 +14,7 @@ ) from argus.auth.factories import SourceUserFactory from argus.incident.factories import SourceSystemFactory -from argus.incident.models import Incident, IncidentTagRelation, Tag, create_token_expiry_incident +from argus.incident.models import Incident, Tag, create_token_expiry_incident from argus.util.testing import connect_signals, disconnect_signals diff --git a/tests/filter/test_queryset_filters.py b/tests/filter/test_queryset_filters.py index 886c0adab..93d13d546 100644 --- a/tests/filter/test_queryset_filters.py +++ b/tests/filter/test_queryset_filters.py @@ -1,8 +1,5 @@ from django.test import TestCase, tag -from django.utils.dateparse import parse_datetime, parse_time -from django.utils.timezone import make_aware -from argus.filter.factories import FilterFactory from argus.incident.factories import SourceSystemFactory, TagFactory from argus.incident.models import Incident from argus.filter.queryset_filters import ( @@ -12,11 +9,6 @@ _incidents_with_source_systems, _incidents_with_tags, ) -from argus.notificationprofile.models import TimeRecurrence -from argus.notificationprofile.factories import ( - TimeslotFactory, - TimeRecurrenceFactory, -) from argus.util.testing import disconnect_signals, connect_signals from tests.notificationprofile import IncidentAPITestCaseHelper diff --git a/tests/incident/test_filters.py b/tests/incident/test_filters.py index 909c031bb..10f984099 100644 --- a/tests/incident/test_filters.py +++ b/tests/incident/test_filters.py @@ -1,10 +1,8 @@ -from datetime import datetime, timedelta +from datetime import timedelta from unittest.mock import Mock -from django.core.exceptions import ValidationError from django.test import TestCase from django.utils import timezone -from django.utils.timezone import is_aware, make_aware from argus.auth.factories import PersonUserFactory, SourceUserFactory from argus.incident.factories import ( diff --git a/tests/incident/test_incident_fields.py b/tests/incident/test_incident_fields.py index 4b734676a..14277b9b6 100644 --- a/tests/incident/test_incident_fields.py +++ b/tests/incident/test_incident_fields.py @@ -4,13 +4,11 @@ from django.test import TestCase from django.utils import timezone from django.utils.timezone import is_aware, make_aware -from rest_framework.test import APIClient -from argus.auth.models import User from argus.util.utils import duplicate from argus.util.testing import disconnect_signals, connect_signals from argus.incident.fields import KeyValueField -from argus.incident.models import Incident, SourceSystem, SourceSystemType +from argus.incident.models import Incident from . import IncidentBasedAPITestCaseHelper diff --git a/tests/notificationprofile/test_github236.py b/tests/notificationprofile/test_github236.py index 56fb6afd4..5c7d768a3 100644 --- a/tests/notificationprofile/test_github236.py +++ b/tests/notificationprofile/test_github236.py @@ -1,6 +1,5 @@ from django.core import mail from django.test import TestCase, tag -import json from argus.auth.factories import PersonUserFactory from argus.filter.factories import FilterFactory diff --git a/tests/site/test_settings_helpers.py b/tests/site/test_settings_helpers.py index 4de283a3d..e13f41acc 100644 --- a/tests/site/test_settings_helpers.py +++ b/tests/site/test_settings_helpers.py @@ -1,9 +1,6 @@ import unittest -from copy import deepcopy -from django.conf import settings from django.urls.resolvers import URLResolver -from django.test import override_settings from argus.site.settings import normalize_url, _add_missing_scheme_to_url from argus.site.settings._serializers import AppSetting From 02531c61c169aa43c6af5d5d467fc889b949fe93 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 16:58:55 +0200 Subject: [PATCH 06/12] Remove or use unused variables --- .../dev/management/commands/create_source.py | 2 +- src/argus/notificationprofile/media/email.py | 2 +- tests/incident/test_filters.py | 2 +- tests/incident/test_incident_fields.py | 16 ++++++++-------- tests/incident/test_views.py | 2 +- tests/notificationprofile/test_github236.py | 1 - tests/notificationprofile/test_serializers.py | 4 ++-- tests/notificationprofile/test_views.py | 2 +- tests/site/test_settings_helpers.py | 3 ++- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/argus/dev/management/commands/create_source.py b/src/argus/dev/management/commands/create_source.py index 87b47f4be..3925fd5f3 100644 --- a/src/argus/dev/management/commands/create_source.py +++ b/src/argus/dev/management/commands/create_source.py @@ -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) diff --git a/src/argus/notificationprofile/media/email.py b/src/argus/notificationprofile/media/email.py index 47772b640..d747793e7 100644 --- a/src/argus/notificationprofile/media/email.py +++ b/src/argus/notificationprofile/media/email.py @@ -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") diff --git a/tests/incident/test_filters.py b/tests/incident/test_filters.py index 10f984099..f3b1676bf 100644 --- a/tests/incident/test_filters.py +++ b/tests/incident/test_filters.py @@ -117,7 +117,7 @@ def test_tags_single(self): for incident in (self.incident1, self.incident2, self.incident3): IncidentTagRelation.objects.get_or_create(tag=tag1, incident=incident, added_by=user) for incident in (self.incident3, self.incident4, incident5): - IncidentTagRelation.objects.get_or_create(tag=tag1, incident=incident, added_by=user) + IncidentTagRelation.objects.get_or_create(tag=tag2, incident=incident, added_by=user) qs = Incident.objects.order_by("pk") diff --git a/tests/incident/test_incident_fields.py b/tests/incident/test_incident_fields.py index 14277b9b6..179b9abb0 100644 --- a/tests/incident/test_incident_fields.py +++ b/tests/incident/test_incident_fields.py @@ -117,31 +117,31 @@ class KeyValueFieldTest(TestCase): def test_key_value_must_not_be_empty(self): f = KeyValueField() with self.assertRaises(ValidationError): - result = f.clean("") + f.clean("") def test_key_value_must_not_be_just_equals(self): f = KeyValueField() with self.assertRaises(ValidationError): - result = f.clean("=") + f.clean("=") def test_key_value_must_contain_at_least_one_equals(self): f = KeyValueField() with self.assertRaises(ValidationError): - result = f.clean("boo") + f.clean("boo") def test_value_cannot_be_empty(self): f = KeyValueField() with self.assertRaises(ValidationError): - result = f.clean("a=") + f.clean("a=") def test_key_must_fit_regex(self): # [a-z0-9_]+ f = KeyValueField() with self.assertRaises(ValidationError): - result = f.clean("=v") + f.clean("=v") with self.assertRaises(ValidationError): - result = f.clean(" =v") + f.clean(" =v") with self.assertRaises(ValidationError): - result = f.clean("A=v") + f.clean("A=v") with self.assertRaises(ValidationError): - result = f.clean("-=v") + f.clean("-=v") diff --git a/tests/incident/test_views.py b/tests/incident/test_views.py index 49f85fcd2..73c81684a 100644 --- a/tests/incident/test_views.py +++ b/tests/incident/test_views.py @@ -366,7 +366,7 @@ def test_source_cannot_delete_unowned_incident_if_indelible_is_False(self): source_type = SourceSystemTypeFactory() user = SourceUserFactory() - source = SourceSystemFactory(type=source_type, user=user) + SourceSystemFactory(type=source_type, user=user) self.client.force_authenticate(user=user) response = self.client.delete(path=f"/api/v2/incidents/{incident_pk}/") diff --git a/tests/notificationprofile/test_github236.py b/tests/notificationprofile/test_github236.py index 5c7d768a3..a234fc753 100644 --- a/tests/notificationprofile/test_github236.py +++ b/tests/notificationprofile/test_github236.py @@ -51,7 +51,6 @@ def tearDown(self): connect_signals() def test_sending_event_to_multiple_profiles_of_the_same_user_should_not_raise_exception(self): - LOG_PREFIX = "INFO:argus.notificationprofile.media:" # Send a test event self.incident = create_fake_incident() event = self.incident.events.get(type=Event.Type.INCIDENT_START) diff --git a/tests/notificationprofile/test_serializers.py b/tests/notificationprofile/test_serializers.py index 9369988f2..69767e023 100644 --- a/tests/notificationprofile/test_serializers.py +++ b/tests/notificationprofile/test_serializers.py @@ -91,7 +91,7 @@ def test_cannot_create_timeslot_with_duplicate_name(self): ) # serializer.create works on already validated data with self.assertRaises(IntegrityError): - obj = serializer.create(validated_data) + serializer.create(validated_data) def test_can_update_timeslot(self): timeslot = TimeslotFactory(name="existing name", user=self.user) @@ -127,4 +127,4 @@ def test_cannot_update_timeslot_with_duplicate_name(self): ) # serializer.create works on already validated data with self.assertRaises(IntegrityError): - obj = serializer.update(timeslot, validated_data) + serializer.update(timeslot, validated_data) diff --git a/tests/notificationprofile/test_views.py b/tests/notificationprofile/test_views.py index 86db895b8..5958bb6df 100644 --- a/tests/notificationprofile/test_views.py +++ b/tests/notificationprofile/test_views.py @@ -233,7 +233,7 @@ def setUp(self): self.source2 = SourceSystemFactory(name="System 2", type=source_type2, user=source2_user) self.incident1 = StatelessIncidentFactory(source=self.source1) - incident2 = StatelessIncidentFactory(source=self.source2) + StatelessIncidentFactory(source=self.source2) timeslot1 = TimeslotFactory(user=user1, name="Never") filter1 = FilterFactory( diff --git a/tests/site/test_settings_helpers.py b/tests/site/test_settings_helpers.py index e13f41acc..bef2c5273 100644 --- a/tests/site/test_settings_helpers.py +++ b/tests/site/test_settings_helpers.py @@ -107,7 +107,8 @@ def test_when_context_processor_setting_is_unset_it_should_do_nothing(self): # NO "context_processors"-key! } TEMPLATES = [] - result = update_context_processors_list(TEMPLATES, None) + app_setting = AppSetting(**raw_setting) + result = update_context_processors_list(TEMPLATES, [app_setting]) self.assertEqual(result, TEMPLATES) def test_when_template_setting_is_falsey_it_should_do_nothing(self): From be5245ae809485b9e2415d109513957ba7e24b4c Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 17:03:12 +0200 Subject: [PATCH 07/12] Remove `f` prefix for f-strings without placeholder --- src/argus/incident/V1/serializers.py | 2 +- src/argus/incident/serializers.py | 2 +- tests/dev/test_create_fake_incident.py | 4 +- tests/dev/test_utils.py | 2 +- tests/incident/test_views.py | 48 +++++++++---------- .../destinations/test_email.py | 4 +- .../destinations/test_sms.py | 4 +- tests/notificationprofile/test_views.py | 4 +- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/argus/incident/V1/serializers.py b/src/argus/incident/V1/serializers.py index 0a37a77ec..bb7eddcf8 100644 --- a/src/argus/incident/V1/serializers.py +++ b/src/argus/incident/V1/serializers.py @@ -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() diff --git a/src/argus/incident/serializers.py b/src/argus/incident/serializers.py index 3476bcbf9..718483d8f 100644 --- a/src/argus/incident/serializers.py +++ b/src/argus/incident/serializers.py @@ -340,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() diff --git a/tests/dev/test_create_fake_incident.py b/tests/dev/test_create_fake_incident.py index c83bfc469..f27185758 100644 --- a/tests/dev/test_create_fake_incident.py +++ b/tests/dev/test_create_fake_incident.py @@ -84,7 +84,7 @@ def test_create_fake_incident_will_create_single_fake_incident_with_set_level(se def test_create_fake_incident_will_raise_error_for_invalid_level(self): with self.assertRaises(CommandError): - self.call_command(f"--level=100") + self.call_command("--level=100") def test_create_fake_incident_will_create_single_fake_incident_with_set_tag(self): previous_incidents_pks = [incident.id for incident in Incident.objects.all()] @@ -105,7 +105,7 @@ def test_create_fake_incident_will_create_single_fake_incident_with_set_tag(self def test_create_fake_incident_will_create_single_fake_stateless_incident(self): previous_incidents_pks = [incident.id for incident in Incident.objects.all()] - out = self.call_command(f"--stateless") + out = self.call_command("--stateless") self.assertFalse(out) diff --git a/tests/dev/test_utils.py b/tests/dev/test_utils.py index c0982bd1a..ead60e929 100644 --- a/tests/dev/test_utils.py +++ b/tests/dev/test_utils.py @@ -52,7 +52,7 @@ def test_verify_description_does_not_raise_exception_for_correct_description(sel self.stresstester._verify_description(actual_data, expected_data) def test_get_auth_header_returns_correct_header_values(self): - self.assertEqual(self.stresstester._get_auth_header(), {"Authorization": f"Token token"}) + self.assertEqual(self.stresstester._get_auth_header(), {"Authorization": "Token token"}) def test_get_incidents_v1_url_returns_correct_url(self): self.assertEqual(self.stresstester._get_incidents_v1_url(), "http://localhost.com/api/v1/incidents/") diff --git a/tests/incident/test_views.py b/tests/incident/test_views.py index 73c81684a..aba70ef4a 100644 --- a/tests/incident/test_views.py +++ b/tests/incident/test_views.py @@ -390,7 +390,7 @@ class SourceSystemV1TestCase(IncidentAPITestCase): def test_can_get_all_source_types(self): source_type_names = set([type.name for type in SourceSystemType.objects.all()]) - response = self.client.get(path=f"/api/v1/incidents/source-types/") + response = self.client.get(path="/api/v1/incidents/source-types/") self.assertEqual(response.status_code, status.HTTP_200_OK) response_types = set([type["name"] for type in response.data]) @@ -405,14 +405,14 @@ def test_can_create_source_type(self): data = { "name": "test", } - response = self.client.post(path=f"/api/v1/incidents/source-types/", data=data, format="json") + response = self.client.post(path="/api/v1/incidents/source-types/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertTrue(SourceSystemType.objects.filter(name=data["name"]).exists()) def test_can_get_all_source_systems(self): source_pks = set([source.pk for source in SourceSystem.objects.all()]) - response = self.client.get(path=f"/api/v1/incidents/sources/") + response = self.client.get(path="/api/v1/incidents/sources/") self.assertEqual(response.status_code, status.HTTP_200_OK) response_source_pks = set([source["pk"] for source in response.data]) @@ -430,7 +430,7 @@ def test_can_create_source_system(self): "name": "newtest", "type": self.source.type.name, } - response = self.client.post(path=f"/api/v1/incidents/sources/", data=data, format="json") + response = self.client.post(path="/api/v1/incidents/sources/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertTrue(SourceSystem.objects.filter(name=data["name"]).exists()) @@ -877,7 +877,7 @@ def test_can_get_all_events(self): self.add_open_incident_with_start_event_and_tag() event_pks = list(Event.objects.all().values_list("pk", flat=True)) - response = self.client.get(path=f"/api/v2/incidents/events/") + response = self.client.get(path="/api/v2/incidents/events/") self.assertEqual(response.status_code, status.HTTP_200_OK) # Paging, so check "results" @@ -887,7 +887,7 @@ def test_can_get_all_events(self): def test_can_get_all_source_types(self): source_type_names = set([type.name for type in SourceSystemType.objects.all()]) - response = self.client.get(path=f"/api/v2/incidents/source-types/") + response = self.client.get(path="/api/v2/incidents/source-types/") self.assertEqual(response.status_code, status.HTTP_200_OK) response_types = set([type["name"] for type in response.data]) @@ -902,14 +902,14 @@ def test_can_create_source_type(self): data = { "name": "test", } - response = self.client.post(path=f"/api/v2/incidents/source-types/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/source-types/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertTrue(SourceSystemType.objects.filter(name=data["name"]).exists()) def test_can_get_all_source_systems(self): source_pks = set([source.pk for source in SourceSystem.objects.all()]) - response = self.client.get(path=f"/api/v2/incidents/sources/") + response = self.client.get(path="/api/v2/incidents/sources/") self.assertEqual(response.status_code, status.HTTP_200_OK) response_source_pks = set([source["pk"] for source in response.data]) @@ -927,7 +927,7 @@ def test_can_create_source_system(self): "name": "newtest", "type": self.source.type.name, } - response = self.client.post(path=f"/api/v2/incidents/sources/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/sources/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertTrue(SourceSystem.objects.filter(name=data["name"]).exists()) @@ -964,7 +964,7 @@ def test_can_bulk_create_acknowledgements_for_incidents_with_valid_ids(self): "ack": self.ack_data, } - response = self.client.post(path=f"/api/v2/incidents/acks/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/acks/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -991,7 +991,7 @@ def test_can_bulk_create_acknowledgements_without_description_and_expiration_for }, } - response = self.client.post(path=f"/api/v2/incidents/acks/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/acks/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -1023,7 +1023,7 @@ def test_can_bulk_create_acknowledgements_with_empty_description_for_incidents_w }, } - response = self.client.post(path=f"/api/v2/incidents/acks/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/acks/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -1051,7 +1051,7 @@ def test_cannot_bulk_create_acknowledgements_for_incidents_with_all_invalid_ids( "ack": self.ack_data, } - response = self.client.post(path=f"/api/v2/incidents/acks/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/acks/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -1077,7 +1077,7 @@ def test_can_partially_bulk_create_acknowledgements_for_incidents_with_some_vali "ack": self.ack_data, } - response = self.client.post(path=f"/api/v2/incidents/acks/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/acks/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -1117,7 +1117,7 @@ def test_can_bulk_create_events_for_incidents_with_valid_ids(self): "event": self.event_data, } - response = self.client.post(path=f"/api/v2/incidents/events/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/events/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -1145,7 +1145,7 @@ def test_can_bulk_create_events_without_description_for_incidents_with_valid_ids }, } - response = self.client.post(path=f"/api/v2/incidents/events/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/events/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -1176,7 +1176,7 @@ def test_can_bulk_create_events_with_description_empty_string_for_incidents_with }, } - response = self.client.post(path=f"/api/v2/incidents/events/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/events/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -1207,7 +1207,7 @@ def test_bulk_close_sets_incident_end_time(self): }, } - response = self.client.post(path=f"/api/v2/incidents/events/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/events/bulk/", data=data, format="json") incident_1.refresh_from_db() incident_2.refresh_from_db() @@ -1242,7 +1242,7 @@ def test_bulk_reopen_removes_incident_end_time(self): }, } - response = self.client.post(path=f"/api/v2/incidents/events/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/events/bulk/", data=data, format="json") incident_1.refresh_from_db() incident_2.refresh_from_db() @@ -1276,7 +1276,7 @@ def test_cannot_bulk_create_events_for_incidents_with_all_invalid_ids(self): "event": self.event_data, } - response = self.client.post(path=f"/api/v2/incidents/events/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/events/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -1302,7 +1302,7 @@ def test_can_partially_bulk_create_events_for_incidents_with_some_valid_ids(self "event": self.event_data, } - response = self.client.post(path=f"/api/v2/incidents/events/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/events/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -1338,7 +1338,7 @@ def test_can_bulk_set_ticket_url_for_incidents_with_valid_ids(self): "ticket_url": self.ticket_url, } - response = self.client.post(path=f"/api/v2/incidents/ticket_url/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/ticket_url/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -1366,7 +1366,7 @@ def test_cannot_bulk_set_ticket_url_for_incidents_with_all_invalid_ids(self): "ticket_url": self.ticket_url, } - response = self.client.post(path=f"/api/v2/incidents/ticket_url/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/ticket_url/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -1389,7 +1389,7 @@ def test_can_partially_bulk_set_ticket_url_for_incidents_with_some_valid_ids(sel "ticket_url": self.ticket_url, } - response = self.client.post(path=f"/api/v2/incidents/ticket_url/bulk/", data=data, format="json") + response = self.client.post(path="/api/v2/incidents/ticket_url/bulk/", data=data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) diff --git a/tests/notificationprofile/destinations/test_email.py b/tests/notificationprofile/destinations/test_email.py index a32c04333..5c332e20c 100644 --- a/tests/notificationprofile/destinations/test_email.py +++ b/tests/notificationprofile/destinations/test_email.py @@ -238,12 +238,12 @@ def test_should_get_json_schema_for_email(self): } } - response = self.user1_rest_client.get(path=f"/api/v2/notificationprofiles/media/email/json_schema/") + response = self.user1_rest_client.get(path="/api/v2/notificationprofiles/media/email/json_schema/") self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data, schema) def test_should_get_email_medium(self): - response = self.user1_rest_client.get(path=f"/api/v2/notificationprofiles/media/email/") + response = self.user1_rest_client.get(path="/api/v2/notificationprofiles/media/email/") self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data["name"], "Email") diff --git a/tests/notificationprofile/destinations/test_sms.py b/tests/notificationprofile/destinations/test_sms.py index 1ea34c2ad..4a16aef72 100644 --- a/tests/notificationprofile/destinations/test_sms.py +++ b/tests/notificationprofile/destinations/test_sms.py @@ -198,12 +198,12 @@ def test_should_get_json_schema_for_sms(self): } } - response = self.user1_rest_client.get(path=f"/api/v2/notificationprofiles/media/sms/json_schema/") + response = self.user1_rest_client.get(path="/api/v2/notificationprofiles/media/sms/json_schema/") self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data, schema) def test_should_get_sms_medium(self): - response = self.user1_rest_client.get(path=f"/api/v2/notificationprofiles/media/sms/") + response = self.user1_rest_client.get(path="/api/v2/notificationprofiles/media/sms/") self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data["name"], "SMS") diff --git a/tests/notificationprofile/test_views.py b/tests/notificationprofile/test_views.py index 5958bb6df..bc05cab56 100644 --- a/tests/notificationprofile/test_views.py +++ b/tests/notificationprofile/test_views.py @@ -450,13 +450,13 @@ def teardown(self): connect_signals() def test_should_get_all_media(self): - response = self.user1_rest_client.get(path=f"/api/v2/notificationprofiles/media/") + response = self.user1_rest_client.get(path="/api/v2/notificationprofiles/media/") self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(len(response.data), 2) self.assertEqual(set([medium["slug"] for medium in response.data]), set(["sms", "email"])) def test_should_get_specific_medium(self): - response = self.user1_rest_client.get(path=f"/api/v2/notificationprofiles/media/email/") + response = self.user1_rest_client.get(path="/api/v2/notificationprofiles/media/email/") self.assertEqual(response.status_code, status.HTTP_200_OK, response.data) self.assertEqual(response.data["slug"], "email") From 631ffb5a6e042576f818c61d18dedadc770d5eff Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 17:17:51 +0200 Subject: [PATCH 08/12] Remove double import --- src/argus/filter/V1/serializers.py | 1 - src/argus/incident/views.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/argus/filter/V1/serializers.py b/src/argus/filter/V1/serializers.py index 54bb59466..47e2ae100 100644 --- a/src/argus/filter/V1/serializers.py +++ b/src/argus/filter/V1/serializers.py @@ -1,6 +1,5 @@ import json -from rest_framework import serializers from rest_framework import serializers from argus.incident.constants import INCIDENT_LEVELS diff --git a/src/argus/incident/views.py b/src/argus/incident/views.py index 487ce6c1b..5ca2e7264 100644 --- a/src/argus/incident/views.py +++ b/src/argus/incident/views.py @@ -22,7 +22,6 @@ 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, @@ -36,6 +35,7 @@ from .forms import AddSourceSystemForm from .models import ( + Acknowledgement, ChangeEvent, Event, Incident, From af11b6a8dc4eb0a9ad9a0447f2777e186c34c292 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 17:23:20 +0200 Subject: [PATCH 09/12] Add ruff to MegaLinter --- .mega-linter.yml | 2 ++ pyproject.toml | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/.mega-linter.yml b/.mega-linter.yml index c821cc9c8..2990e61d1 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -6,9 +6,11 @@ LINTER_RULES_PATH: . ENABLE_LINTERS: - PYTHON_BLACK - PYTHON_FLAKE8 + - 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 PYTHON_FLAKE8_CONFIG_FILE: tox.ini diff --git a/pyproject.toml b/pyproject.toml index eb69d8bd8..ff7b859bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -109,6 +109,19 @@ force-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" From 25241c4b48340b9d3925f6d01df21d4c79023556 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 17:24:03 +0200 Subject: [PATCH 10/12] Add ruff to pre-commit --- .pre-commit-config.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ed781ce56..b67f375c9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,6 +19,10 @@ repos: 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: From 19eeaa6cc176b2f1b704618a93059893298b2a85 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Thu, 29 Aug 2024 17:25:48 +0200 Subject: [PATCH 11/12] Add ruff to dev dependencies --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index ff7b859bb..70f775141 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,6 +60,7 @@ dev = [ "ipython", "pre-commit", "python-dotenv", + "ruff", "towncrier", "werkzeug", "tox<4", # does not work on tox 4 for some reason From 115d6410472430a01e631ef6f355afb0f7b2e8a7 Mon Sep 17 00:00:00 2001 From: Johanna England Date: Fri, 30 Aug 2024 12:24:40 +0200 Subject: [PATCH 12/12] Remove flake8 from workflow and pre-commit --- .mega-linter.yml | 2 -- .pre-commit-config.yaml | 7 ------- pyproject.toml | 1 - 3 files changed, 10 deletions(-) diff --git a/.mega-linter.yml b/.mega-linter.yml index 2990e61d1..0d76ca74b 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -5,7 +5,6 @@ LINTER_RULES_PATH: . ENABLE_LINTERS: - PYTHON_BLACK - - PYTHON_FLAKE8 - PYTHON_RUFF # Make workflow fail even on non blocking errors @@ -13,4 +12,3 @@ FORMATTERS_DISABLE_ERRORS: false PYTHON_BLACK_CONFIG_FILE: pyproject.toml PYTHON_RUFF_CONFIG_FILE: pyproject.toml -PYTHON_FLAKE8_CONFIG_FILE: tox.ini diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b67f375c9..58f65b528 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,13 +7,6 @@ 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: diff --git a/pyproject.toml b/pyproject.toml index 70f775141..0002c1543 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,6 @@ dev = [ "black", "coverage", "django-extensions", - "flake8", "ipython", "pre-commit", "python-dotenv",