diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 207b5844e..499df876a 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -8,3 +8,5 @@ a3b18cfbf32a2f0e6a9c55ead043fea12a71883e 17c099c3b99172f4f623f22ddc374abcf692ee5d # Re-run black with new version 24.8.0 @johannaengland 29/08/2024 10dc8b7b612dddb042462718eea5b62f9d6455ea +# Re-format files using isort @johannaengland 30/08/2024 +975ab295654ef926379c9cfaef2017e1367e4877 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..363ea5367 --- /dev/null +++ b/.mega-linter.yml @@ -0,0 +1,18 @@ +# All available variables are described in documentation +# https://megalinter.io/configuration/ + +FILTER_REGEX_EXCLUDE: "migrations" + +LINTER_RULES_PATH: . + +ENABLE_LINTERS: + - PYTHON_BLACK + - PYTHON_ISORT + - PYTHON_RUFF + +# Make workflow fail even on non blocking errors +FORMATTERS_DISABLE_ERRORS: false + +PYTHON_BLACK_CONFIG_FILE: pyproject.toml +PYTHON_ISORT_CONFIG_FILE: pyproject.toml +PYTHON_RUFF_CONFIG_FILE: pyproject.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ed781ce56..96b834506 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,18 +7,20 @@ repos: - id: end-of-file-fixer exclude: &exclude_pattern '^changelog.d/' - id: debug-statements -- repo: https://github.com/pycqa/flake8 - rev: 7.1.1 +- repo: https://github.com/pycqa/isort + rev: 5.13.2 hooks: - - id: flake8 - name: "Flake8: critical" - args: ['--count', '--select=E9,F63,F7,F82', '--show-source', '--statistics'] - types: [file, python] + - id: isort + name: isort (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: diff --git a/pyproject.toml b/pyproject.toml index a22531b56..dba5cedfc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,10 +56,11 @@ dev = [ "black", "coverage", "django-extensions", - "flake8", "ipython", + "isort", "pre-commit", "python-dotenv", + "ruff", "towncrier", "werkzeug", "tox<4", # does not work on tox 4 for some reason @@ -89,7 +90,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 @@ -108,6 +110,24 @@ 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.isort] +profile = "black" +src_paths = ["src", "tests"] +extend_skip_glob = ["src/**/migrations"] + [tool.towncrier] directory = "changelog.d" filename = "CHANGELOG.md" diff --git a/src/argus/auth/V1/serializers.py b/src/argus/auth/V1/serializers.py index a3a2a1569..40c33a8ee 100644 --- a/src/argus/auth/V1/serializers.py +++ b/src/argus/auth/V1/serializers.py @@ -1,7 +1,9 @@ -from rest_framework import serializers from typing import List +from rest_framework import serializers + from argus.notificationprofile.models import DestinationConfig + from ..models import User diff --git a/src/argus/auth/V1/urls.py b/src/argus/auth/V1/urls.py index f10cd5649..d52bf2c31 100644 --- a/src/argus/auth/V1/urls.py +++ b/src/argus/auth/V1/urls.py @@ -1,9 +1,8 @@ from django.urls import path from rest_framework import routers -from . import views as views_V1 from .. import views - +from . import views as views_V1 router = routers.SimpleRouter() router.register(r"phone-number", views_V1.PhoneNumberViewV1, basename="phone_number") diff --git a/src/argus/auth/V1/views.py b/src/argus/auth/V1/views.py index 9ed685186..e36e6b575 100644 --- a/src/argus/auth/V1/views.py +++ b/src/argus/auth/V1/views.py @@ -8,7 +8,12 @@ from argus.drf.permissions import IsOwner from argus.notificationprofile.models import DestinationConfig from argus.notificationprofile.serializers import RequestDestinationConfigSerializer -from .serializers import RequestPhoneNumberSerializerV1, ResponsePhoneNumberSerializerV1, UserSerializerV1 + +from .serializers import ( + RequestPhoneNumberSerializerV1, + ResponsePhoneNumberSerializerV1, + UserSerializerV1, +) class CurrentUserViewV1(APIView): diff --git a/src/argus/auth/admin.py b/src/argus/auth/admin.py index 699e3f649..71182e8be 100644 --- a/src/argus/auth/admin.py +++ b/src/argus/auth/admin.py @@ -1,9 +1,10 @@ from django.contrib import admin from django.contrib.auth.admin import UserAdmin as BaseUserAdmin -from .models import User from argus.notificationprofile.models import DestinationConfig +from .models import User + class DestinationConfigInline(admin.TabularInline): model = DestinationConfig diff --git a/src/argus/auth/serializers.py b/src/argus/auth/serializers.py index f7eacc52a..f66df9148 100644 --- a/src/argus/auth/serializers.py +++ b/src/argus/auth/serializers.py @@ -3,7 +3,6 @@ from rest_framework import serializers from rest_framework.reverse import reverse - from .models import User diff --git a/src/argus/auth/urls.py b/src/argus/auth/urls.py index ab77dbfce..cb79fe4ce 100644 --- a/src/argus/auth/urls.py +++ b/src/argus/auth/urls.py @@ -3,7 +3,6 @@ from . import views - router = routers.SimpleRouter() diff --git a/src/argus/auth/utils.py b/src/argus/auth/utils.py index f38dcad6e..fa5295cc1 100644 --- a/src/argus/auth/utils.py +++ b/src/argus/auth/utils.py @@ -1,7 +1,6 @@ from django.conf import settings from django.contrib.auth.backends import ModelBackend from django.utils.module_loading import import_string - from rest_framework.reverse import reverse from social_core.backends.base import BaseAuth from social_core.backends.oauth import BaseOAuth2 diff --git a/src/argus/auth/views.py b/src/argus/auth/views.py index 899589b9d..9908f3726 100644 --- a/src/argus/auth/views.py +++ b/src/argus/auth/views.py @@ -1,18 +1,22 @@ -from django.contrib.auth import logout from django.conf import settings +from django.contrib.auth import logout from django.db import transaction - from drf_spectacular.utils import extend_schema, extend_schema_view from rest_framework import generics from rest_framework.authtoken.models import Token from rest_framework.authtoken.views import ObtainAuthToken from rest_framework.exceptions import ValidationError -from rest_framework.permissions import IsAuthenticated, AllowAny +from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView from .models import User -from .serializers import BasicUserSerializer, EmptySerializer, RefreshTokenSerializer, UserSerializer +from .serializers import ( + BasicUserSerializer, + EmptySerializer, + RefreshTokenSerializer, + UserSerializer, +) from .utils import get_authentication_backend_name_and_type diff --git a/src/argus/compat.py b/src/argus/compat.py index 70e6f0965..2795bdf2d 100644 --- a/src/argus/compat.py +++ b/src/argus/compat.py @@ -1,6 +1,5 @@ from enum import Enum - __all__ = ["StrEnum"] diff --git a/src/argus/dataporten/views.py b/src/argus/dataporten/views.py index 468652bdc..af70d6aa9 100644 --- a/src/argus/dataporten/views.py +++ b/src/argus/dataporten/views.py @@ -1,6 +1,5 @@ from django.conf import settings from django.shortcuts import redirect - from rest_framework.authtoken.models import Token from social_django import views as social_views diff --git a/src/argus/dev/management/commands/check_token_expiry.py b/src/argus/dev/management/commands/check_token_expiry.py index 4d5796738..556458dca 100644 --- a/src/argus/dev/management/commands/check_token_expiry.py +++ b/src/argus/dev/management/commands/check_token_expiry.py @@ -7,10 +7,10 @@ from rest_framework.authtoken.models import Token from argus.incident.models import ( - create_token_expiry_incident, - get_or_create_default_instances, Incident, Tag, + create_token_expiry_incident, + get_or_create_default_instances, ) diff --git a/src/argus/dev/management/commands/create_fake_incident.py b/src/argus/dev/management/commands/create_fake_incident.py index c177875e0..09a099ae8 100644 --- a/src/argus/dev/management/commands/create_fake_incident.py +++ b/src/argus/dev/management/commands/create_fake_incident.py @@ -1,11 +1,10 @@ import argparse import json from pathlib import Path -from random import randint from django.core.management.base import BaseCommand -from argus.incident.constants import MIN_INCIDENT_LEVEL, MAX_INCIDENT_LEVEL +from argus.incident.constants import MAX_INCIDENT_LEVEL, MIN_INCIDENT_LEVEL from argus.incident.models import create_fake_incident 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/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/dev/management/commands/stresstest.py b/src/argus/dev/management/commands/stresstest.py index 61bba8f8f..3d893098e 100644 --- a/src/argus/dev/management/commands/stresstest.py +++ b/src/argus/dev/management/commands/stresstest.py @@ -1,8 +1,7 @@ -from httpx import TimeoutException, HTTPStatusError, HTTPError - from django.core.management.base import BaseCommand +from httpx import HTTPError, HTTPStatusError, TimeoutException -from argus.dev.utils import StressTester, DatabaseMismatchError +from argus.dev.utils import DatabaseMismatchError, StressTester class Command(BaseCommand): diff --git a/src/argus/dev/utils.py b/src/argus/dev/utils.py index 36a89f079..e3d055c9e 100644 --- a/src/argus/dev/utils.py +++ b/src/argus/dev/utils.py @@ -1,10 +1,10 @@ -from datetime import datetime, timedelta -from urllib.parse import urljoin import asyncio import itertools -from typing import Any, Dict, AnyStr, List, Tuple +from datetime import datetime, timedelta +from typing import Any, AnyStr, Dict, List, Tuple +from urllib.parse import urljoin -from httpx import AsyncClient, TimeoutException, HTTPStatusError, post +from httpx import AsyncClient, HTTPStatusError, TimeoutException, post class DatabaseMismatchError(Exception): diff --git a/src/argus/filter/V1/serializers.py b/src/argus/filter/V1/serializers.py index 7ceae861c..47e2ae100 100644 --- a/src/argus/filter/V1/serializers.py +++ b/src/argus/filter/V1/serializers.py @@ -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 diff --git a/src/argus/filter/__init__.py b/src/argus/filter/__init__.py index de2777f40..47afee9ff 100644 --- a/src/argus/filter/__init__.py +++ b/src/argus/filter/__init__.py @@ -2,7 +2,6 @@ from django.conf import settings - DEFAULT_BACKEND = "argus.filter.default" 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/default.py b/src/argus/filter/default.py index 0ba1dc875..b1dea0430 100644 --- a/src/argus/filter/default.py +++ b/src/argus/filter/default.py @@ -1,18 +1,15 @@ -from .filterwrapper import ( # noqa: F401 - FilterWrapper, - FallbackFilterWrapper, - ComplexFilterWrapper, - ComplexFallbackFilterWrapper, -) -from .queryset_filters import QuerySetFilter # noqa: F401 from .filters import ( # noqa: F401 - IncidentFilter, - SourceLockedIncidentFilter, INCIDENT_OPENAPI_PARAMETER_DESCRIPTIONS, SOURCE_LOCKED_INCIDENT_OPENAPI_PARAMETER_DESCRIPTIONS, + IncidentFilter, + SourceLockedIncidentFilter, ) -from .serializers import ( # noqa: F401 - FilterSerializer, - FilterBlobSerializer, +from .filterwrapper import ( # noqa: F401 + ComplexFallbackFilterWrapper, + ComplexFilterWrapper, + FallbackFilterWrapper, + FilterWrapper, ) +from .queryset_filters import QuerySetFilter # noqa: F401 +from .serializers import FilterBlobSerializer, FilterSerializer # noqa: F401 from .validators import validate_jsonfilter # noqa: F401 diff --git a/src/argus/filter/factories.py b/src/argus/filter/factories.py index 5a71f94d8..fceca62c5 100644 --- a/src/argus/filter/factories.py +++ b/src/argus/filter/factories.py @@ -3,7 +3,6 @@ from argus.auth.factories import PersonUserFactory from argus.notificationprofile import models - __all__ = [ "FilterFactory", ] diff --git a/src/argus/filter/filters.py b/src/argus/filter/filters.py index ac76c1e08..0365aa7ed 100644 --- a/src/argus/filter/filters.py +++ b/src/argus/filter/filters.py @@ -6,14 +6,12 @@ from django import forms from django_filters import rest_framework as filters - from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter -from argus.notificationprofile.models import Filter, NotificationProfile from argus.incident.fields import KeyValueField from argus.incident.models import Incident - +from argus.notificationprofile.models import Filter, NotificationProfile __all__ = [ "INCIDENT_OPENAPI_PARAMETER_DESCRIPTIONS", diff --git a/src/argus/filter/filterwrapper.py b/src/argus/filter/filterwrapper.py index d014afb8c..086e1c0a0 100644 --- a/src/argus/filter/filterwrapper.py +++ b/src/argus/filter/filterwrapper.py @@ -1,14 +1,12 @@ from __future__ import annotations import logging -from operator import or_ -from typing import TYPE_CHECKING, Dict, Optional, Any, Tuple +from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple from django.conf import settings from argus.compat import StrEnum - if TYPE_CHECKING: from argus.incident.models import Event, Incident diff --git a/src/argus/filter/queryset_filters.py b/src/argus/filter/queryset_filters.py index 725d75292..d3a831416 100644 --- a/src/argus/filter/queryset_filters.py +++ b/src/argus/filter/queryset_filters.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING -from argus.filter.filterwrapper import FilterWrapper, FilterBlobType +from argus.filter.filterwrapper import FilterBlobType, FilterWrapper from argus.incident.models import Incident if TYPE_CHECKING: diff --git a/src/argus/filter/serializers.py b/src/argus/filter/serializers.py index 672e8817e..ecf106c78 100644 --- a/src/argus/filter/serializers.py +++ b/src/argus/filter/serializers.py @@ -1,10 +1,10 @@ -from rest_framework import fields, serializers +from rest_framework import serializers from argus.incident.constants import INCIDENT_LEVELS from argus.incident.models import Event from argus.notificationprofile.models import Filter -from .primitive_serializers import CustomMultipleChoiceField +from .primitive_serializers import CustomMultipleChoiceField __all__ = [ "FilterBlobSerializer", diff --git a/src/argus/filter/validators.py b/src/argus/filter/validators.py index 3cf0dd8af..1715ea674 100644 --- a/src/argus/filter/validators.py +++ b/src/argus/filter/validators.py @@ -2,7 +2,6 @@ from argus.filter.serializers import FilterBlobSerializer - __all__ = [ "validate_jsonfilter", ] diff --git a/src/argus/incident/V1/serializers.py b/src/argus/incident/V1/serializers.py index 0a37a77ec..f734e7282 100644 --- a/src/argus/incident/V1/serializers.py +++ b/src/argus/incident/V1/serializers.py @@ -1,20 +1,13 @@ from django.utils import timezone - from rest_framework import serializers from ..fields import DateTimeInfinitySerializerField -from ..models import ( - Acknowledgement, - Event, - Incident, - Tag, - IncidentTagRelation, -) +from ..models import Acknowledgement, Event, Incident, IncidentTagRelation, Tag from ..serializers import ( EventSerializer, IncidentSerializer, - SourceSystemSerializer, IncidentTagRelationSerializer, + SourceSystemSerializer, ) @@ -112,7 +105,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/V1/urls.py b/src/argus/incident/V1/urls.py index 88e07f2d5..05b84dbfc 100644 --- a/src/argus/incident/V1/urls.py +++ b/src/argus/incident/V1/urls.py @@ -1,10 +1,8 @@ from django.urls import path - from rest_framework import routers -from . import views as views_V1 from .. import views - +from . import views as views_V1 router = routers.SimpleRouter() router.register(r"sources", views.SourceSystemViewSet) diff --git a/src/argus/incident/V1/views.py b/src/argus/incident/V1/views.py index d05a34c98..0bcb54990 100644 --- a/src/argus/incident/V1/views.py +++ b/src/argus/incident/V1/views.py @@ -1,15 +1,17 @@ from django_filters import rest_framework as filters from drf_spectacular.types import OpenApiTypes -from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter +from drf_spectacular.utils import OpenApiParameter, extend_schema, extend_schema_view from rest_framework import generics, mixins, viewsets from rest_framework.decorators import action from rest_framework.generics import get_object_or_404 from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response -from argus.filter.filters import BooleanStringOAEnum -from argus.filter.filters import SourceLockedIncidentFilter -from argus.filter.filters import SOURCE_LOCKED_INCIDENT_OPENAPI_PARAMETER_DESCRIPTIONS +from argus.filter.filters import ( + SOURCE_LOCKED_INCIDENT_OPENAPI_PARAMETER_DESCRIPTIONS, + BooleanStringOAEnum, + SourceLockedIncidentFilter, +) from ..models import Incident, SourceSystem from ..serializers import IncidentPureDeserializer, SourceSystemSerializer diff --git a/src/argus/incident/admin.py b/src/argus/incident/admin.py index 3d1ee5970..fa57613b0 100644 --- a/src/argus/incident/admin.py +++ b/src/argus/incident/admin.py @@ -6,11 +6,12 @@ from django.http import HttpResponseRedirect from django.template.response import TemplateResponse from django.urls import path -from django.utils.html import format_html_join, format_html +from django.utils.html import format_html, format_html_join from django.utils.safestring import mark_safe from argus.auth.models import User from argus.util.admin_utils import add_elements_to_deleted_objects, list_filter_factory + from . import fields, widgets from .forms import AddSourceSystemForm, FakeIncidentForm from .models import ( diff --git a/src/argus/incident/apps.py b/src/argus/incident/apps.py index 88c243710..002f638f1 100644 --- a/src/argus/incident/apps.py +++ b/src/argus/incident/apps.py @@ -7,11 +7,11 @@ class IncidentConfig(AppConfig): label = "argus_incident" def ready(self): + from .signals import task_send_notification # noqa from .signals import ( close_token_incident, - delete_associated_user, delete_associated_event, - task_send_notification, # noqa + delete_associated_user, task_background_send_notification, ) diff --git a/src/argus/incident/factories.py b/src/argus/incident/factories.py index cf854663a..7f137ad12 100644 --- a/src/argus/incident/factories.py +++ b/src/argus/incident/factories.py @@ -1,10 +1,11 @@ -import factory, factory.fuzzy +import factory +import factory.fuzzy import pytz from argus.auth.factories import SourceUserFactory from argus.util.datetime_utils import INFINITY_REPR -from . import models +from . import models __all__ = [ "SourceSystemTypeFactory", diff --git a/src/argus/incident/fields.py b/src/argus/incident/fields.py index efce086a2..6f9f141b6 100644 --- a/src/argus/incident/fields.py +++ b/src/argus/incident/fields.py @@ -1,12 +1,12 @@ from datetime import datetime +import rest_framework.fields as rest_framework_fields from django import forms from django.db import models from django.forms import fields -import rest_framework.fields as rest_framework_fields - import argus.util.datetime_utils as utils + from .validators import validate_key_value diff --git a/src/argus/incident/forms.py b/src/argus/incident/forms.py index 400a93083..44ca6f0ab 100644 --- a/src/argus/incident/forms.py +++ b/src/argus/incident/forms.py @@ -3,6 +3,7 @@ from django.forms import modelform_factory from argus.auth.models import User + from .constants import INCIDENT_LEVELS from .models import Incident, SourceSystem, Tag diff --git a/src/argus/incident/models.py b/src/argus/incident/models.py index 118b8e564..86b2a98e6 100644 --- a/src/argus/incident/models.py +++ b/src/argus/incident/models.py @@ -1,7 +1,7 @@ +import logging from collections import defaultdict from datetime import datetime, timedelta from functools import reduce -import logging from operator import and_ from random import randint from urllib.parse import urljoin @@ -14,10 +14,15 @@ from argus.auth.models import User from argus.util.datetime_utils import INFINITY_REPR, get_infinity_repr -from .constants import INCIDENT_LEVELS, INCIDENT_LEVEL_CHOICES, MIN_INCIDENT_LEVEL, MAX_INCIDENT_LEVEL -from .fields import DateTimeInfinityField -from .validators import validate_lowercase, validate_key +from .constants import ( + INCIDENT_LEVEL_CHOICES, + INCIDENT_LEVELS, + MAX_INCIDENT_LEVEL, + MIN_INCIDENT_LEVEL, +) +from .fields import DateTimeInfinityField +from .validators import validate_key, validate_lowercase LOG = logging.getLogger(__name__) diff --git a/src/argus/incident/serializers.py b/src/argus/incident/serializers.py index 5ca2f901b..c75c3eb91 100644 --- a/src/argus/incident/serializers.py +++ b/src/argus/incident/serializers.py @@ -1,16 +1,15 @@ -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 from django.utils import timezone - from rest_framework import serializers from argus.auth.models import User from argus.auth.serializers import UsernameSerializer from argus.util.datetime_utils import INFINITY_REPR + from . import fields from .models import ( Acknowledgement, @@ -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")) @@ -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")) @@ -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() diff --git a/src/argus/incident/signals.py b/src/argus/incident/signals.py index 9b21127fd..0c488fdbf 100644 --- a/src/argus/incident/signals.py +++ b/src/argus/incident/signals.py @@ -1,13 +1,14 @@ 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 argus.notificationprofile.media import ( + background_send_notification, + send_notification, + send_notifications_to_users, +) + from .models import ( Acknowledgement, - ChangeEvent, Event, Incident, SourceSystem, @@ -15,7 +16,6 @@ get_or_create_default_instances, ) - __all__ = [ "delete_associated_user", "send_notification", diff --git a/src/argus/incident/ticket/dummy.py b/src/argus/incident/ticket/dummy.py index 08c93d641..48fccc3e1 100644 --- a/src/argus/incident/ticket/dummy.py +++ b/src/argus/incident/ticket/dummy.py @@ -8,14 +8,11 @@ from __future__ import annotations -from factory import Faker import logging -from typing import TYPE_CHECKING -from .base import TicketPlugin +from factory import Faker -if TYPE_CHECKING: - from argus.incident.models import Incident +from .base import TicketPlugin LOG = logging.getLogger(__name__) diff --git a/src/argus/incident/urls.py b/src/argus/incident/urls.py index a1481d043..cd9e539f1 100644 --- a/src/argus/incident/urls.py +++ b/src/argus/incident/urls.py @@ -1,10 +1,8 @@ from django.urls import path - from rest_framework import routers from . import views - router = routers.SimpleRouter() router.register(r"sources", views.SourceSystemViewSet) router.register(r"source-types", views.SourceSystemTypeViewSet) diff --git a/src/argus/incident/validators.py b/src/argus/incident/validators.py index ca59db01f..e6e1970c1 100644 --- a/src/argus/incident/validators.py +++ b/src/argus/incident/validators.py @@ -1,6 +1,5 @@ -from django.core.validators import RegexValidator, _lazy_re_compile from django.core.exceptions import ValidationError - +from django.core.validators import RegexValidator, _lazy_re_compile __all__ = [ "validate_lowercase", diff --git a/src/argus/incident/views.py b/src/argus/incident/views.py index 734eff616..33540066e 100644 --- a/src/argus/incident/views.py +++ b/src/argus/incident/views.py @@ -5,16 +5,22 @@ from django.conf import settings from django.db import IntegrityError from django.utils import timezone - 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 drf_spectacular.utils import ( + OpenApiParameter, + OpenApiResponse, + extend_schema, + extend_schema_view, +) from rest_framework import mixins, serializers, status, viewsets from rest_framework.decorators import action -from rest_framework.exceptions import ValidationError, PermissionDenied, MethodNotAllowed +from rest_framework.exceptions import ( + MethodNotAllowed, + PermissionDenied, + ValidationError, +) +from rest_framework.filters import SearchFilter from rest_framework.generics import get_object_or_404 from rest_framework.pagination import CursorPagination from rest_framework.permissions import IsAuthenticated @@ -23,24 +29,20 @@ from argus.auth.models import User from argus.drf.permissions import IsSuperuserOrReadOnly -from argus.incident.models import Acknowledgement, Event +from argus.filter import get_filter_backend 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, @@ -49,11 +51,11 @@ Tag, ) from .serializers import ( - UpdateAcknowledgementSerializer, EmptySerializer, EventSerializer, IncidentPureDeserializer, IncidentSerializer, + IncidentTagRelation, IncidentTicketUrlSerializer, RequestAcknowledgementSerializer, RequestBulkAcknowledgementSerializer, @@ -64,7 +66,7 @@ SourceSystemSerializer, SourceSystemTypeSerializer, TagSerializer, - IncidentTagRelation, + UpdateAcknowledgementSerializer, ) filter_backend = get_filter_backend() diff --git a/src/argus/incident/widgets.py b/src/argus/incident/widgets.py index b65824c07..52191858c 100644 --- a/src/argus/incident/widgets.py +++ b/src/argus/incident/widgets.py @@ -1,7 +1,7 @@ from datetime import datetime -from django.contrib.admin import widgets as admin_widgets from django import forms +from django.contrib.admin import widgets as admin_widgets from argus.util.datetime_utils import get_infinity_repr diff --git a/src/argus/notificationprofile/V1/serializers.py b/src/argus/notificationprofile/V1/serializers.py index 7eedb4721..a23892701 100644 --- a/src/argus/notificationprofile/V1/serializers.py +++ b/src/argus/notificationprofile/V1/serializers.py @@ -2,9 +2,8 @@ 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 @@ -110,11 +109,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 +121,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/notificationprofile/V1/urls.py b/src/argus/notificationprofile/V1/urls.py index 11acbd3e6..f92608959 100644 --- a/src/argus/notificationprofile/V1/urls.py +++ b/src/argus/notificationprofile/V1/urls.py @@ -1,9 +1,8 @@ from django.urls import path - from rest_framework import routers -from . import views as views_V1 from .. import views +from . import views as views_V1 router = routers.SimpleRouter() router.register(r"timeslots", views.TimeslotViewSet) diff --git a/src/argus/notificationprofile/V1/views.py b/src/argus/notificationprofile/V1/views.py index ff65f6cc3..5c794dd3e 100644 --- a/src/argus/notificationprofile/V1/views.py +++ b/src/argus/notificationprofile/V1/views.py @@ -1,23 +1,24 @@ +from drf_rw_serializers import viewsets as rw_viewsets from drf_spectacular.utils import extend_schema, extend_schema_view from rest_framework import status, viewsets from rest_framework.decorators import action from rest_framework.exceptions import ValidationError from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response -from drf_rw_serializers import viewsets as rw_viewsets from argus.drf.permissions import IsOwner from argus.filter.queryset_filters import QuerySetFilter from argus.filter.V1.serializers import ( - FilterSerializerV1, FilterBlobSerializerV1, FilterPreviewSerializer, + FilterSerializerV1, ) from argus.incident.serializers import IncidentSerializer + from ..models import Filter, NotificationProfile from .serializers import ( - ResponseNotificationProfileSerializerV1, RequestNotificationProfileSerializerV1, + ResponseNotificationProfileSerializerV1, ) diff --git a/src/argus/notificationprofile/admin.py b/src/argus/notificationprofile/admin.py index 2df8d3081..8a33b592d 100644 --- a/src/argus/notificationprofile/admin.py +++ b/src/argus/notificationprofile/admin.py @@ -2,7 +2,14 @@ from django.db.models.functions import Concat from django.utils.html import format_html_join -from .models import DestinationConfig, Filter, Media, NotificationProfile, TimeRecurrence, Timeslot +from .models import ( + DestinationConfig, + Filter, + Media, + NotificationProfile, + TimeRecurrence, + Timeslot, +) @admin.action(description="Toggle activation for selected profiles") diff --git a/src/argus/notificationprofile/apps.py b/src/argus/notificationprofile/apps.py index 3e5181a70..777757f3e 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_migrate, post_save class NotificationprofileConfig(AppConfig): @@ -9,11 +8,7 @@ class NotificationprofileConfig(AppConfig): def ready(self): # Signals - from .signals import ( - create_default_timeslot, - sync_email_destination, - sync_media, - ) + from .signals import create_default_timeslot, sync_email_destination, sync_media post_save.connect(create_default_timeslot, "argus_auth.User") post_save.connect(sync_email_destination, "argus_auth.User") diff --git a/src/argus/notificationprofile/checks.py b/src/argus/notificationprofile/checks.py index 1a418aa1c..6c6b9de73 100644 --- a/src/argus/notificationprofile/checks.py +++ b/src/argus/notificationprofile/checks.py @@ -3,7 +3,6 @@ from argus.filter import get_filter_backend - filter_backend = get_filter_backend() validate_jsonfilter = filter_backend.validate_jsonfilter diff --git a/src/argus/notificationprofile/factories.py b/src/argus/notificationprofile/factories.py index 70404446c..07fc0d96b 100644 --- a/src/argus/notificationprofile/factories.py +++ b/src/argus/notificationprofile/factories.py @@ -5,7 +5,6 @@ from argus.auth.factories import PersonUserFactory from argus.notificationprofile import models - __all__ = [ "TimeslotFactory", "TimeRecurrenceFactory", diff --git a/src/argus/notificationprofile/media/base.py b/src/argus/notificationprofile/media/base.py index d5c330e7a..9839f6fc6 100644 --- a/src/argus/notificationprofile/media/base.py +++ b/src/argus/notificationprofile/media/base.py @@ -12,10 +12,13 @@ from collections.abc import Iterable from types import NoneType - from typing import Union, Set + from typing import Set, Union + from django.db.models.query import QuerySet + from argus.auth.models import User from argus.incident.models import Event + from ..models import DestinationConfig from ..serializers import RequestDestinationConfigSerializer diff --git a/src/argus/notificationprofile/media/email.py b/src/argus/notificationprofile/media/email.py index 47772b640..ffcfd46f2 100644 --- a/src/argus/notificationprofile/media/email.py +++ b/src/argus/notificationprofile/media/email.py @@ -10,10 +10,11 @@ from rest_framework.exceptions import ValidationError from argus.incident.models import Event -from .base import NotificationMedium -from ..models import DestinationConfig from argus.util.datetime_utils import INFINITY, LOCAL_INFINITY +from ..models import DestinationConfig +from .base import NotificationMedium + if TYPE_CHECKING: import sys @@ -23,9 +24,12 @@ from collections.abc import Iterable from types import NoneType - from typing import Union, Set + from typing import Set, Union + from django.db.models.query import QuerySet + from argus.auth.models import User + from ..serializers import RequestDestinationConfigSerializer LOG = logging.getLogger(__name__) @@ -46,7 +50,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/src/argus/notificationprofile/media/sms_as_email.py b/src/argus/notificationprofile/media/sms_as_email.py index 6f945229c..06d232b38 100644 --- a/src/argus/notificationprofile/media/sms_as_email.py +++ b/src/argus/notificationprofile/media/sms_as_email.py @@ -27,10 +27,12 @@ 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 from ..serializers import RequestDestinationConfigSerializer diff --git a/src/argus/notificationprofile/models.py b/src/argus/notificationprofile/models.py index 937e992b4..5e978e47d 100644 --- a/src/argus/notificationprofile/models.py +++ b/src/argus/notificationprofile/models.py @@ -1,10 +1,9 @@ from __future__ import annotations -from datetime import datetime, time import logging -from typing import TYPE_CHECKING, Dict, Optional +from datetime import datetime, time +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 93b74fdd0..984de0aed 100644 --- a/src/argus/notificationprofile/serializers.py +++ b/src/argus/notificationprofile/serializers.py @@ -1,11 +1,15 @@ 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 +from .models import ( + DestinationConfig, + Media, + NotificationProfile, + TimeRecurrence, + Timeslot, +) filter_backend = get_filter_backend() FilterSerializer = filter_backend.FilterSerializer @@ -146,7 +150,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) diff --git a/src/argus/notificationprofile/signals.py b/src/argus/notificationprofile/signals.py index ffd41ba58..25aede7e5 100644 --- a/src/argus/notificationprofile/signals.py +++ b/src/argus/notificationprofile/signals.py @@ -2,9 +2,8 @@ from django.db.utils import ProgrammingError -from rest_framework.exceptions import APIException - from argus.auth.models import User + from .models import DestinationConfig, TimeRecurrence, Timeslot LOG = logging.getLogger(__name__) diff --git a/src/argus/notificationprofile/urls.py b/src/argus/notificationprofile/urls.py index 1f512a687..08029a567 100644 --- a/src/argus/notificationprofile/urls.py +++ b/src/argus/notificationprofile/urls.py @@ -1,5 +1,4 @@ -from django.urls import path, include - +from django.urls import path from rest_framework import routers from . import views diff --git a/src/argus/notificationprofile/views.py b/src/argus/notificationprofile/views.py index d756bfeaa..12305db9e 100644 --- a/src/argus/notificationprofile/views.py +++ b/src/argus/notificationprofile/views.py @@ -1,8 +1,7 @@ -import json - from django.db.models import Q from django.shortcuts import get_object_or_404 from django.views.generic import DetailView +from drf_rw_serializers import viewsets as rw_viewsets from drf_spectacular.utils import extend_schema, extend_schema_view from rest_framework import status, viewsets from rest_framework.decorators import action @@ -11,26 +10,25 @@ from rest_framework.response import Response from rest_framework.reverse import reverse from rest_framework.views import APIView -from drf_rw_serializers import viewsets as rw_viewsets from argus.drf.permissions import IsOwner from argus.filter import get_filter_backend from argus.incident.serializers import IncidentSerializer from argus.notificationprofile.media import api_safely_get_medium_object from argus.notificationprofile.media.base import NotificationMedium + from .models import DestinationConfig, Filter, Media, NotificationProfile, Timeslot from .serializers import ( DuplicateDestinationSerializer, JSONSchemaSerializer, MediaSerializer, - ResponseDestinationConfigSerializer, RequestDestinationConfigSerializer, - ResponseNotificationProfileSerializer, RequestNotificationProfileSerializer, + ResponseDestinationConfigSerializer, + ResponseNotificationProfileSerializer, TimeslotSerializer, ) - filter_backend = get_filter_backend() QuerySetFilter = filter_backend.QuerySetFilter FilterSerializer = filter_backend.FilterSerializer diff --git a/src/argus/site/api_v1_urls.py b/src/argus/site/api_v1_urls.py index e3fdc583e..9e31efa6e 100644 --- a/src/argus/site/api_v1_urls.py +++ b/src/argus/site/api_v1_urls.py @@ -1,5 +1,4 @@ from django.urls import include, path - from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView from argus.auth.views import ObtainNewAuthToken diff --git a/src/argus/site/api_v2_urls.py b/src/argus/site/api_v2_urls.py index 2f8fbea5e..3433acb52 100644 --- a/src/argus/site/api_v2_urls.py +++ b/src/argus/site/api_v2_urls.py @@ -1,5 +1,4 @@ from django.urls import include, path - from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView from argus.auth.views import ObtainNewAuthToken diff --git a/src/argus/site/settings/__init__.py b/src/argus/site/settings/__init__.py index 19c10bb01..b50fe389e 100644 --- a/src/argus/site/settings/__init__.py +++ b/src/argus/site/settings/__init__.py @@ -10,7 +10,6 @@ from ._serializers import ListAppSetting - __all__ = [ "SETTINGS_DIR", "SITE_DIR", @@ -122,7 +121,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]) diff --git a/src/argus/site/settings/_serializers.py b/src/argus/site/settings/_serializers.py index 978a45864..c96df93b2 100644 --- a/src/argus/site/settings/_serializers.py +++ b/src/argus/site/settings/_serializers.py @@ -1,4 +1,4 @@ -from typing import Optional, List, Dict +from typing import Dict, List, Optional from pydantic import BaseModel, Field, RootModel diff --git a/src/argus/site/settings/base.py b/src/argus/site/settings/base.py index 2747921ff..fa36ec6d6 100644 --- a/src/argus/site/settings/base.py +++ b/src/argus/site/settings/base.py @@ -14,9 +14,10 @@ import dj_database_url +from ..utils import update_context_processors_list, update_middleware_list + # Import some helpers from . import * -from ..utils import update_context_processors_list, update_middleware_list # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ diff --git a/src/argus/site/settings/dev.py b/src/argus/site/settings/dev.py index 01db00999..a389fe292 100644 --- a/src/argus/site/settings/dev.py +++ b/src/argus/site/settings/dev.py @@ -1,11 +1,8 @@ -import logging.config - from dotenv import load_dotenv load_dotenv() -from .base import * - +from .base import * # noqa DEBUG = get_bool_env("DEBUG", True) TEMPLATES[0]["OPTIONS"]["debug"] = get_bool_env("TEMPLATE_DEBUG", True) diff --git a/src/argus/site/settings/prod.py b/src/argus/site/settings/prod.py index 0c97393fe..854dde1ad 100644 --- a/src/argus/site/settings/prod.py +++ b/src/argus/site/settings/prod.py @@ -1,7 +1,7 @@ -from .base import * - from django.core.exceptions import ImproperlyConfigured +from .base import * + DEBUG = False TEMPLATES[0]["OPTIONS"]["debug"] = False diff --git a/src/argus/site/settings/test_CI.py b/src/argus/site/settings/test_CI.py index 8f8bcad4f..20812dd65 100644 --- a/src/argus/site/settings/test_CI.py +++ b/src/argus/site/settings/test_CI.py @@ -1,12 +1,9 @@ +import logging.config import os import subprocess -import logging.config - -from django.utils.log import DEFAULT_LOGGING from .base import * - DEBUG = get_bool_env("DEBUG", True) TEMPLATES[0]["OPTIONS"]["debug"] = get_bool_env("TEMPLATE_DEBUG", True) diff --git a/src/argus/site/urls.py b/src/argus/site/urls.py index 96c5f5081..40aa59adf 100644 --- a/src/argus/site/urls.py +++ b/src/argus/site/urls.py @@ -18,16 +18,14 @@ from django.contrib import admin from django.urls import include, path, re_path from django.views.generic.base import RedirectView - 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 MetadataView, index psa_urls = [ # Overrides social_django's `complete` view 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/src/argus/site/views.py b/src/argus/site/views.py index bec782251..18abf4c3d 100644 --- a/src/argus/site/views.py +++ b/src/argus/site/views.py @@ -9,11 +9,9 @@ HttpResponseServerError, ) from django.shortcuts import render, reverse - -from rest_framework.views import APIView from rest_framework import permissions from rest_framework.response import Response - +from rest_framework.views import APIView ERROR_TEMPLATE = """ {code} {reason} diff --git a/src/argus/util/datetime_utils.py b/src/argus/util/datetime_utils.py index 459441379..3bfd756e7 100644 --- a/src/argus/util/datetime_utils.py +++ b/src/argus/util/datetime_utils.py @@ -4,7 +4,6 @@ from django.utils import timezone from django.utils.dateparse import parse_datetime - INFINITY_REPR = "infinity" NEGATIVE_INFINITY_REPR = f"-{INFINITY_REPR}" diff --git a/src/argus/util/testing.py b/src/argus/util/testing.py index 12eb6488d..8a565e7e9 100644 --- a/src/argus/util/testing.py +++ b/src/argus/util/testing.py @@ -1,9 +1,7 @@ from django.db.models.signals import post_save -from argus.incident.signals import send_notification -from argus.incident.signals import background_send_notification from argus.incident.models import Event - +from argus.incident.signals import background_send_notification, send_notification __all__ = [ "disconnect_signals", diff --git a/src/argus/ws/asgi.py b/src/argus/ws/asgi.py index 29c0214b2..b59e076e1 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 @@ -15,12 +17,12 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "argus.site.settings.dev") django_http = get_asgi_application() # Sets up Django. DO NOT REORDER -from .consumers import OpenIncidentConsumer +from channels.auth import AuthMiddlewareStack # MAGIC! DO NOT MOVE THESE BEFORE ANY OTHER IMPORT from channels.routing import ProtocolTypeRouter, URLRouter -from channels.auth import AuthMiddlewareStack +from .consumers import OpenIncidentConsumer application = ProtocolTypeRouter({ "http": django_http, diff --git a/src/argus/ws/consumers.py b/src/argus/ws/consumers.py index ba260c46f..c887e12e9 100644 --- a/src/argus/ws/consumers.py +++ b/src/argus/ws/consumers.py @@ -3,6 +3,7 @@ from argus.incident.models import Incident from argus.incident.serializers import IncidentSerializer + from .models import SUBSCRIBED_OPEN_INCIDENTS diff --git a/tests/auth/V1/test_views.py b/tests/auth/V1/test_views.py index da4c63ab6..3127e1d19 100644 --- a/tests/auth/V1/test_views.py +++ b/tests/auth/V1/test_views.py @@ -1,12 +1,11 @@ from django.test import tag - from rest_framework import status from rest_framework.test import APIClient, APITestCase from argus.auth.factories import AdminUserFactory, BaseUserFactory from argus.notificationprofile.factories import DestinationConfigFactory from argus.notificationprofile.models import DestinationConfig, Media -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals @tag("API", "integration") diff --git a/tests/auth/test_utils.py b/tests/auth/test_utils.py index 71cff921d..2303baa92 100644 --- a/tests/auth/test_utils.py +++ b/tests/auth/test_utils.py @@ -3,7 +3,10 @@ from django.contrib.auth.backends import ModelBackend from django.test import TestCase -from argus.auth.utils import get_authentication_backend_name_and_type, get_psa_authentication_names +from argus.auth.utils import ( + get_authentication_backend_name_and_type, + get_psa_authentication_names, +) from argus.dataporten.social import DataportenFeideOAuth2 diff --git a/tests/auth/test_views.py b/tests/auth/test_views.py index 89a130334..30a8b2e27 100644 --- a/tests/auth/test_views.py +++ b/tests/auth/test_views.py @@ -1,10 +1,9 @@ from django.test import override_settings, tag - from rest_framework import status from rest_framework.test import APIClient, APITestCase from argus.auth.factories import AdminUserFactory, BaseUserFactory -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals @tag("API", "integration") diff --git a/tests/dev/test_check_token_expiry.py b/tests/dev/test_check_token_expiry.py index b3c67bfac..07c32fc84 100644 --- a/tests/dev/test_check_token_expiry.py +++ b/tests/dev/test_check_token_expiry.py @@ -1,20 +1,20 @@ from datetime import datetime, timedelta from io import StringIO -import pytz +import pytz from django.conf import settings from django.core.management import call_command from django.test import TestCase from rest_framework.authtoken.models import Token +from argus.auth.factories import SourceUserFactory from argus.dev.management.commands.check_token_expiry import ( close_expiry_incidents_without_expiring_tokens, find_expiring_tokens, get_tokens_without_expiry_incident, ) -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/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..f144654a8 100644 --- a/tests/dev/test_utils.py +++ b/tests/dev/test_utils.py @@ -1,7 +1,6 @@ from django.test import TestCase -from argus.dev.utils import StressTester, DatabaseMismatchError - +from argus.dev.utils import DatabaseMismatchError, StressTester from argus.util.testing import connect_signals, disconnect_signals @@ -52,7 +51,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/filter/test_filterplugin.py b/tests/filter/test_filterplugin.py index 388e4c18d..43cfc3bcc 100644 --- a/tests/filter/test_filterplugin.py +++ b/tests/filter/test_filterplugin.py @@ -1,4 +1,4 @@ -from django.test import override_settings, TestCase +from django.test import TestCase, override_settings from argus.filter import get_filter_backend diff --git a/tests/filter/test_filterwrapper.py b/tests/filter/test_filterwrapper.py index 9672f3c77..650a87b78 100644 --- a/tests/filter/test_filterwrapper.py +++ b/tests/filter/test_filterwrapper.py @@ -1,11 +1,9 @@ import unittest from unittest.mock import Mock -from django.test import override_settings -from django.test import tag +from django.test import override_settings, tag -from argus.filter.filterwrapper import FilterKey -from argus.filter.filterwrapper import FallbackFilterWrapper +from argus.filter.filterwrapper import FallbackFilterWrapper, FilterKey from argus.incident.models import Event diff --git a/tests/filter/test_queryset_filters.py b/tests/filter/test_queryset_filters.py index 886c0adab..dee320e84 100644 --- a/tests/filter/test_queryset_filters.py +++ b/tests/filter/test_queryset_filters.py @@ -1,10 +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 ( QuerySetFilter, _incidents_fitting_maxlevel, @@ -12,13 +7,9 @@ _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 argus.incident.factories import SourceSystemFactory, TagFactory +from argus.incident.models import Incident +from argus.util.testing import connect_signals, disconnect_signals from tests.notificationprofile import IncidentAPITestCaseHelper diff --git a/tests/incident/__init__.py b/tests/incident/__init__.py index 40d21cb7a..f8506e73f 100644 --- a/tests/incident/__init__.py +++ b/tests/incident/__init__.py @@ -1,6 +1,6 @@ from rest_framework.test import APIClient -from argus.auth.factories import SourceUserFactory, AdminUserFactory +from argus.auth.factories import AdminUserFactory, SourceUserFactory from argus.incident.factories import SourceSystemFactory, SourceSystemTypeFactory diff --git a/tests/incident/test_change_event.py b/tests/incident/test_change_event.py index 6f16aa6d1..ef2a9e5da 100644 --- a/tests/incident/test_change_event.py +++ b/tests/incident/test_change_event.py @@ -1,14 +1,13 @@ from django.test import override_settings, tag - from rest_framework import status from rest_framework.test import APITestCase + from argus.incident.factories import StatefulIncidentFactory -from argus.incident.models import Event, ChangeEvent -from argus.util.testing import disconnect_signals, connect_signals +from argus.incident.models import ChangeEvent, Event +from argus.util.testing import connect_signals, disconnect_signals from . import IncidentBasedAPITestCaseHelper - # format_description tests here, one for each outlier (now metadata), one for # the normal ones diff --git a/tests/incident/test_create_fake_incident.py b/tests/incident/test_create_fake_incident.py index 0e9c7843e..c0387ce44 100644 --- a/tests/incident/test_create_fake_incident.py +++ b/tests/incident/test_create_fake_incident.py @@ -1,8 +1,7 @@ from django.test import TestCase - from argus.incident.models import IncidentTagRelation, create_fake_incident -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals class EventViewSetTestCase(TestCase): diff --git a/tests/incident/test_event.py b/tests/incident/test_event.py index de8d378c0..53c7010e1 100644 --- a/tests/incident/test_event.py +++ b/tests/incident/test_event.py @@ -8,11 +8,12 @@ from rest_framework import status from rest_framework.test import APITestCase -from argus.util import datetime_utils -from argus.util.utils import duplicate -from argus.util.testing import disconnect_signals, connect_signals from argus.incident.factories import StatefulIncidentFactory from argus.incident.models import Event, Incident +from argus.util import datetime_utils +from argus.util.testing import connect_signals, disconnect_signals +from argus.util.utils import duplicate + from . import IncidentBasedAPITestCaseHelper diff --git a/tests/incident/test_filters.py b/tests/incident/test_filters.py index 909c031bb..6bc9e7e28 100644 --- a/tests/incident/test_filters.py +++ b/tests/incident/test_filters.py @@ -1,12 +1,11 @@ -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.filter.factories import FilterFactory from argus.incident.factories import ( SourceSystemFactory, SourceSystemTypeFactory, @@ -14,12 +13,16 @@ StatelessIncidentFactory, TagFactory, ) -from argus.incident.models import Incident, IncidentTagRelation, SourceSystem, get_or_create_default_instances +from argus.incident.models import ( + Incident, + IncidentTagRelation, + SourceSystem, + get_or_create_default_instances, +) from argus.incident.views import IncidentFilter -from argus.filter.factories import FilterFactory from argus.notificationprofile.factories import NotificationProfileFactory from argus.notificationprofile.models import Filter, NotificationProfile -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals class IncidentBasedAPITestCaseHelper: @@ -119,7 +122,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.py b/tests/incident/test_incident.py index 8e879bca8..f9237b656 100644 --- a/tests/incident/test_incident.py +++ b/tests/incident/test_incident.py @@ -3,11 +3,15 @@ from django.test import TestCase from django.utils import timezone -from argus.incident.factories import AcknowledgementFactory, EventFactory, StatefulIncidentFactory -from argus.incident.models import Incident, Event -from argus.incident.factories import SourceSystemFactory +from argus.incident.factories import ( + AcknowledgementFactory, + EventFactory, + SourceSystemFactory, + StatefulIncidentFactory, +) +from argus.incident.models import Event, Incident from argus.util import datetime_utils -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals class CreateIncidentTests(TestCase): diff --git a/tests/incident/test_incident_fields.py b/tests/incident/test_incident_fields.py index 4b734676a..dbdb7ace4 100644 --- a/tests/incident/test_incident_fields.py +++ b/tests/incident/test_incident_fields.py @@ -4,13 +4,12 @@ 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 argus.util.testing import connect_signals, disconnect_signals +from argus.util.utils import duplicate + from . import IncidentBasedAPITestCaseHelper @@ -119,31 +118,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_queryset.py b/tests/incident/test_queryset.py index 2c6196ef5..b67fd43b2 100644 --- a/tests/incident/test_queryset.py +++ b/tests/incident/test_queryset.py @@ -2,9 +2,13 @@ from django.utils import timezone from argus.auth.factories import PersonUserFactory -from argus.util.testing import disconnect_signals, connect_signals -from argus.incident.factories import StatefulIncidentFactory, StatelessIncidentFactory, SourceSystemFactory -from argus.incident.models import Incident, Event +from argus.incident.factories import ( + SourceSystemFactory, + StatefulIncidentFactory, + StatelessIncidentFactory, +) +from argus.incident.models import Event, Incident +from argus.util.testing import connect_signals, disconnect_signals class IncidentQuerySetTestCase(TestCase): diff --git a/tests/incident/test_serializers.py b/tests/incident/test_serializers.py index 3b3565df9..5fa30dd71 100644 --- a/tests/incident/test_serializers.py +++ b/tests/incident/test_serializers.py @@ -2,9 +2,8 @@ from django.test import TestCase from django.utils import timezone - -from rest_framework.test import APIRequestFactory from rest_framework import serializers +from rest_framework.test import APIRequestFactory from argus.auth.factories import PersonUserFactory from argus.incident.factories import IncidentTagRelationFactory, StatefulIncidentFactory @@ -17,9 +16,12 @@ TagSerializer, UpdateAcknowledgementSerializer, ) -from argus.incident.V1.serializers import AcknowledgementSerializerV1, UpdateAcknowledgementSerializerV1 +from argus.incident.V1.serializers import ( + AcknowledgementSerializerV1, + UpdateAcknowledgementSerializerV1, +) from argus.util.datetime_utils import INFINITY_REPR -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals class AcknowledgementSerializerV1Tests(TestCase): diff --git a/tests/incident/test_source_system.py b/tests/incident/test_source_system.py index 41b30aa48..d6d0e50c6 100644 --- a/tests/incident/test_source_system.py +++ b/tests/incident/test_source_system.py @@ -3,8 +3,8 @@ from rest_framework.authtoken.models import Token from rest_framework.test import APIClient, APITestCase -from argus.auth.models import User from argus.auth.factories import AdminUserFactory +from argus.auth.models import User from argus.incident.factories import SourceSystemTypeFactory from argus.incident.models import SourceSystem diff --git a/tests/incident/test_views.py b/tests/incident/test_views.py index 49f85fcd2..4b3633d4e 100644 --- a/tests/incident/test_views.py +++ b/tests/incident/test_views.py @@ -1,9 +1,8 @@ import datetime +from django.test import RequestFactory, TestCase, override_settings, tag from django.urls import reverse from django.utils.timezone import now -from django.test import TestCase, RequestFactory, override_settings, tag - from rest_framework import serializers, status, versioning from rest_framework.test import APITestCase @@ -18,8 +17,8 @@ AcknowledgementFactory, EventFactory, IncidentTagRelationFactory, - SourceSystemTypeFactory, SourceSystemFactory, + SourceSystemTypeFactory, StatefulIncidentFactory, StatelessIncidentFactory, TagFactory, @@ -35,7 +34,7 @@ ) from argus.incident.views import EventViewSet from argus.notificationprofile.models import Filter -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals def add_open_incident_with_start_event_and_tag(source, description="incident"): @@ -366,7 +365,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}/") @@ -390,7 +389,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 +404,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 +429,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 +876,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 +886,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 +901,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 +926,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 +963,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 +990,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 +1022,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 +1050,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 +1076,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 +1116,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 +1144,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 +1175,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 +1206,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 +1241,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 +1275,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 +1301,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 +1337,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 +1365,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 +1388,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/incident/ticket_plugins/test_dummy.py b/tests/incident/ticket_plugins/test_dummy.py index 5fadd1b3c..57e43e9e1 100644 --- a/tests/incident/ticket_plugins/test_dummy.py +++ b/tests/incident/ticket_plugins/test_dummy.py @@ -5,8 +5,8 @@ from argus.incident.factories import StatefulIncidentFactory from argus.incident.ticket.dummy import created_tickets from argus.incident.V1.serializers import IncidentSerializerV1 +from argus.util.testing import connect_signals, disconnect_signals from argus.util.utils import import_class_from_dotted_path -from argus.util.testing import disconnect_signals, connect_signals class DummyTicketSystemTests(TestCase): diff --git a/tests/incident/unit/test_incident_details_url.py b/tests/incident/unit/test_incident_details_url.py index bf0f44d86..1deb43fa1 100644 --- a/tests/incident/unit/test_incident_details_url.py +++ b/tests/incident/unit/test_incident_details_url.py @@ -1,8 +1,8 @@ from django.contrib.admin.sites import AdminSite from django.test import TestCase -from argus.incident.factories import StatefulIncidentFactory, SourceSystemFactory from argus.incident.admin import IncidentAdmin +from argus.incident.factories import SourceSystemFactory, StatefulIncidentFactory class IncidentDetailsUrlTestCase(TestCase): diff --git a/tests/notificationprofile/V1/test_views.py b/tests/notificationprofile/V1/test_views.py index 430530993..446b5d289 100644 --- a/tests/notificationprofile/V1/test_views.py +++ b/tests/notificationprofile/V1/test_views.py @@ -1,33 +1,31 @@ import json from django.test import tag - from rest_framework import status -from rest_framework.test import APITestCase -from rest_framework.test import APIClient +from rest_framework.test import APIClient, APITestCase +from argus.auth.factories import PersonUserFactory, SourceUserFactory from argus.filter.factories import FilterFactory from argus.filter.queryset_filters import QuerySetFilter +from argus.incident.factories import ( + IncidentTagRelationFactory, + SourceSystemFactory, + SourceSystemTypeFactory, + StatelessIncidentFactory, + TagFactory, +) from argus.notificationprofile.factories import ( DestinationConfigFactory, NotificationProfileFactory, TimeslotFactory, ) from argus.notificationprofile.models import ( + Filter, Media, NotificationProfile, - Filter, Timeslot, ) -from argus.incident.factories import ( - IncidentTagRelationFactory, - SourceSystemFactory, - SourceSystemTypeFactory, - StatelessIncidentFactory, - TagFactory, -) -from argus.auth.factories import PersonUserFactory, SourceUserFactory -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals @tag("API", "integration") diff --git a/tests/notificationprofile/__init__.py b/tests/notificationprofile/__init__.py index ed11bc80b..c8bab14e7 100644 --- a/tests/notificationprofile/__init__.py +++ b/tests/notificationprofile/__init__.py @@ -1,9 +1,9 @@ from argus.incident.factories import ( IncidentTagRelationFactory, - StatelessIncidentFactory, - SourceSystemTypeFactory, SourceSystemFactory, + SourceSystemTypeFactory, SourceUserFactory, + StatelessIncidentFactory, TagFactory, ) diff --git a/tests/notificationprofile/destinations/test_email.py b/tests/notificationprofile/destinations/test_email.py index a32c04333..1aee6cef6 100644 --- a/tests/notificationprofile/destinations/test_email.py +++ b/tests/notificationprofile/destinations/test_email.py @@ -3,7 +3,11 @@ from rest_framework.test import APIClient, APIRequestFactory, APITestCase from argus.auth.factories import PersonUserFactory -from argus.notificationprofile.factories import DestinationConfigFactory, NotificationProfileFactory, TimeslotFactory +from argus.notificationprofile.factories import ( + DestinationConfigFactory, + NotificationProfileFactory, + TimeslotFactory, +) from argus.notificationprofile.media.email import EmailNotification from argus.notificationprofile.models import DestinationConfig, Media from argus.notificationprofile.serializers import RequestDestinationConfigSerializer @@ -238,12 +242,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..baa713e85 100644 --- a/tests/notificationprofile/destinations/test_sms.py +++ b/tests/notificationprofile/destinations/test_sms.py @@ -3,7 +3,10 @@ from rest_framework.test import APIClient, APIRequestFactory, APITestCase from argus.auth.factories import PersonUserFactory -from argus.notificationprofile.factories import DestinationConfigFactory, NotificationProfileFactory +from argus.notificationprofile.factories import ( + DestinationConfigFactory, + NotificationProfileFactory, +) from argus.notificationprofile.media.sms_as_email import SMSNotification from argus.notificationprofile.models import DestinationConfig, Media from argus.notificationprofile.serializers import RequestDestinationConfigSerializer @@ -198,12 +201,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_github236.py b/tests/notificationprofile/test_github236.py index 56fb6afd4..cb317ed7a 100644 --- a/tests/notificationprofile/test_github236.py +++ b/tests/notificationprofile/test_github236.py @@ -1,14 +1,16 @@ 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 -from argus.incident.models import create_fake_incident, get_or_create_default_instances, Event +from argus.incident.models import ( + Event, + create_fake_incident, + get_or_create_default_instances, +) from argus.notificationprofile import factories from argus.notificationprofile.media import send_notifications_to_users -from argus.util.testing import disconnect_signals, connect_signals - +from argus.util.testing import connect_signals, disconnect_signals """See: @@ -52,7 +54,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_media.py b/tests/notificationprofile/test_media.py index cf93f2dd3..d3e00b83b 100644 --- a/tests/notificationprofile/test_media.py +++ b/tests/notificationprofile/test_media.py @@ -3,14 +3,20 @@ from argus.auth.factories import PersonUserFactory from argus.filter.factories import FilterFactory from argus.incident.factories import EventFactory -from argus.incident.models import create_fake_incident, get_or_create_default_instances, Event +from argus.incident.models import ( + Event, + create_fake_incident, + get_or_create_default_instances, +) from argus.notificationprofile import factories -from argus.notificationprofile.media import find_destinations_for_event -from argus.notificationprofile.media import find_destinations_for_many_events -from argus.notificationprofile.media import get_notification_media +from argus.notificationprofile.media import ( + find_destinations_for_event, + find_destinations_for_many_events, + get_notification_media, +) from argus.notificationprofile.media.email import modelinstance_to_dict from argus.notificationprofile.models import Media -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals class SerializeModelTest(TestCase): diff --git a/tests/notificationprofile/test_models.py b/tests/notificationprofile/test_models.py index 1d94cf5e2..95a53eb72 100644 --- a/tests/notificationprofile/test_models.py +++ b/tests/notificationprofile/test_models.py @@ -4,12 +4,9 @@ from django.utils.dateparse import parse_datetime, parse_time from django.utils.timezone import make_aware +from argus.notificationprofile.factories import TimeRecurrenceFactory, TimeslotFactory from argus.notificationprofile.models import TimeRecurrence -from argus.notificationprofile.factories import ( - TimeslotFactory, - TimeRecurrenceFactory, -) -from argus.util.testing import disconnect_signals, connect_signals +from argus.util.testing import connect_signals, disconnect_signals from . import IncidentAPITestCaseHelper diff --git a/tests/notificationprofile/test_serializers.py b/tests/notificationprofile/test_serializers.py index 9369988f2..42838ccc6 100644 --- a/tests/notificationprofile/test_serializers.py +++ b/tests/notificationprofile/test_serializers.py @@ -1,9 +1,8 @@ -from collections import OrderedDict import datetime +from collections import OrderedDict from django.db import IntegrityError -from django.test import tag, TestCase - +from django.test import TestCase, tag from rest_framework.test import APIRequestFactory from argus.auth.factories import PersonUserFactory @@ -91,7 +90,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 +126,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..bc05cab56 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( @@ -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") diff --git a/tests/site/test_settings_helpers.py b/tests/site/test_settings_helpers.py index 4de283a3d..b3ae10ab9 100644 --- a/tests/site/test_settings_helpers.py +++ b/tests/site/test_settings_helpers.py @@ -1,13 +1,13 @@ 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 import _add_missing_scheme_to_url, normalize_url from argus.site.settings._serializers import AppSetting -from argus.site.utils import get_urlpatterns_from_setting, update_context_processors_list +from argus.site.utils import ( + get_urlpatterns_from_setting, + update_context_processors_list, +) class NormalizeUrlTests(unittest.TestCase): @@ -110,7 +110,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):