diff --git a/src/backend/core/admin.py b/src/backend/core/admin.py index f9a50422..ea9a749c 100644 --- a/src/backend/core/admin.py +++ b/src/backend/core/admin.py @@ -1,4 +1,5 @@ """Admin classes and registrations for core app.""" + from django.contrib import admin from django.contrib.auth import admin as auth_admin from django.utils.translation import gettext_lazy as _ diff --git a/src/backend/core/api/__init__.py b/src/backend/core/api/__init__.py index c8152ab5..bc8d1329 100644 --- a/src/backend/core/api/__init__.py +++ b/src/backend/core/api/__init__.py @@ -1,4 +1,5 @@ """Impress core API endpoints""" + from django.conf import settings from django.core.exceptions import ValidationError @@ -16,9 +17,9 @@ def exception_handler(exc, context): https://gist.github.com/twidi/9d55486c36b6a51bdcb05ce3a763e79f """ if isinstance(exc, ValidationError): - if hasattr(exc, "message_dict"): - detail = exc.message_dict - elif hasattr(exc, "message"): + detail = exc.message_dict + + if hasattr(exc, "message"): detail = exc.message elif hasattr(exc, "messages"): detail = exc.messages diff --git a/src/backend/core/api/fields.py b/src/backend/core/api/fields.py index 9c2424b7..11256224 100644 --- a/src/backend/core/api/fields.py +++ b/src/backend/core/api/fields.py @@ -1,4 +1,5 @@ """A JSONField for DRF to handle serialization/deserialization.""" + import json from rest_framework import serializers diff --git a/src/backend/core/api/permissions.py b/src/backend/core/api/permissions.py index 4b3f418a..5166a6de 100644 --- a/src/backend/core/api/permissions.py +++ b/src/backend/core/api/permissions.py @@ -1,4 +1,5 @@ """Permission handlers for the impress core app.""" + from django.core import exceptions from rest_framework import permissions diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index e43f7e76..63a9f44b 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -1,4 +1,5 @@ """Client serializers for the impress core app.""" + from django.db.models import Q from django.utils.translation import gettext_lazy as _ diff --git a/src/backend/core/api/viewsets.py b/src/backend/core/api/viewsets.py index c6550aaa..31ccf823 100644 --- a/src/backend/core/api/viewsets.py +++ b/src/backend/core/api/viewsets.py @@ -1,4 +1,5 @@ """API endpoints""" + from django.contrib.postgres.aggregates import ArrayAgg from django.db.models import ( OuterRef, diff --git a/src/backend/core/enums.py b/src/backend/core/enums.py index f4e0e11a..e67d7b5b 100644 --- a/src/backend/core/enums.py +++ b/src/backend/core/enums.py @@ -1,6 +1,7 @@ """ Core application enums declaration """ + from django.conf import global_settings, settings from django.utils.translation import gettext_lazy as _ diff --git a/src/backend/core/factories.py b/src/backend/core/factories.py index f17b61b2..1350b999 100644 --- a/src/backend/core/factories.py +++ b/src/backend/core/factories.py @@ -2,6 +2,7 @@ """ Core application factories """ + from django.conf import settings from django.contrib.auth.hashers import make_password diff --git a/src/backend/core/models.py b/src/backend/core/models.py index 59818582..e0030d52 100644 --- a/src/backend/core/models.py +++ b/src/backend/core/models.py @@ -1,6 +1,7 @@ """ Declare and configure the models for the impress core application """ + import hashlib import os import tempfile @@ -316,6 +317,29 @@ class Document(BaseModel): def __str__(self): return self.title + def save(self, *args, **kwargs): + """Write content to object storage only if _content has changed.""" + super().save(*args, **kwargs) + + if self._content: + file_key = self.file_key + bytes_content = self._content.encode("utf-8") + + if default_storage.exists(file_key): + response = default_storage.connection.meta.client.head_object( + Bucket=default_storage.bucket_name, Key=file_key + ) + has_changed = ( + response["ETag"].strip('"') + != hashlib.md5(bytes_content).hexdigest() # noqa + ) + else: + has_changed = True + + if has_changed: + content_file = ContentFile(bytes_content) + default_storage.save(file_key, content_file) + @property def key_base(self): """Key base of the location where the document is stored in object storage.""" @@ -356,28 +380,6 @@ class Document(BaseModel): Bucket=default_storage.bucket_name, Key=self.file_key, VersionId=version_id ) - def save(self, *args, **kwargs): - """Write content to object storage only if _content has changed.""" - super().save(*args, **kwargs) - - if self._content: - file_key = self.file_key - bytes_content = self._content.encode("utf-8") - - if default_storage.exists(file_key): - response = default_storage.connection.meta.client.head_object( - Bucket=default_storage.bucket_name, Key=file_key - ) - has_changed = ( - response["ETag"].strip('"') - != hashlib.md5(bytes_content).hexdigest() # noqa - ) - else: - has_changed = True - if has_changed: - content_file = ContentFile(bytes_content) - default_storage.save(file_key, content_file) - def get_versions_slice( self, from_version_id="", from_datetime=None, page_size=None ): diff --git a/src/backend/core/tests/authentication/test_backends.py b/src/backend/core/tests/authentication/test_backends.py index c18635f2..6e216c2d 100644 --- a/src/backend/core/tests/authentication/test_backends.py +++ b/src/backend/core/tests/authentication/test_backends.py @@ -92,9 +92,12 @@ def test_models_oidc_user_getter_invalid_token(django_assert_num_queries, monkey monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked) - with django_assert_num_queries(0), pytest.raises( - SuspiciousOperation, - match="User info contained no recognizable user identification", + with ( + django_assert_num_queries(0), + pytest.raises( + SuspiciousOperation, + match="User info contained no recognizable user identification", + ), ): klass.get_or_create_user(access_token="test-token", id_token=None, payload=None) diff --git a/src/backend/core/tests/conftest.py b/src/backend/core/tests/conftest.py index 5a6a3e4a..113245c4 100644 --- a/src/backend/core/tests/conftest.py +++ b/src/backend/core/tests/conftest.py @@ -1,4 +1,5 @@ """Fixtures for tests in the impress core application""" + from unittest import mock import pytest diff --git a/src/backend/core/tests/documents/test_api_document_accesses.py b/src/backend/core/tests/documents/test_api_document_accesses.py index bb57f8cc..69f0cd0b 100644 --- a/src/backend/core/tests/documents/test_api_document_accesses.py +++ b/src/backend/core/tests/documents/test_api_document_accesses.py @@ -1,6 +1,7 @@ """ Test document accesses API endpoints for users in impress's core app. """ + import random from uuid import uuid4 @@ -67,6 +68,7 @@ def test_api_document_accesses_list_authenticated_related(via, mock_user_get_tea client.force_login(user) document = factories.DocumentFactory() + user_access = None if via == USER: user_access = models.DocumentAccess.objects.create( document=document, @@ -543,6 +545,7 @@ def test_api_document_accesses_update_owner_self(via, mock_user_get_teams): client.force_login(user) document = factories.DocumentFactory() + access = None if via == USER: access = factories.UserDocumentAccessFactory( document=document, user=user, role="owner" @@ -773,6 +776,7 @@ def test_api_document_accesses_delete_owners_last_owner(via, mock_user_get_teams client.force_login(user) document = factories.DocumentFactory() + access = None if via == USER: access = factories.UserDocumentAccessFactory( document=document, user=user, role="owner" diff --git a/src/backend/core/tests/documents/test_api_document_accesses_create.py b/src/backend/core/tests/documents/test_api_document_accesses_create.py index 2d8d03dc..92e1afec 100644 --- a/src/backend/core/tests/documents/test_api_document_accesses_create.py +++ b/src/backend/core/tests/documents/test_api_document_accesses_create.py @@ -1,6 +1,7 @@ """ Test document accesses API endpoints for users in impress's core app. """ + import random from django.core import mail diff --git a/src/backend/core/tests/documents/test_api_document_invitations.py b/src/backend/core/tests/documents/test_api_document_invitations.py index d6d46bc8..8e36dc8b 100644 --- a/src/backend/core/tests/documents/test_api_document_invitations.py +++ b/src/backend/core/tests/documents/test_api_document_invitations.py @@ -1,6 +1,7 @@ """ Unit tests for the Invitation model """ + import random import time @@ -250,7 +251,7 @@ def test_api_document_invitations__create__cannot_duplicate_invitation(): ) assert response.status_code == status.HTTP_400_BAD_REQUEST - assert response.json()["__all__"] == [ + assert response.json() == [ "Document invitation with this Email address and Document already exists." ] @@ -278,9 +279,7 @@ def test_api_document_invitations__create__cannot_invite_existing_users(): ) assert response.status_code == status.HTTP_400_BAD_REQUEST - assert response.json()["email"] == [ - "This email is already associated to a registered user." - ] + assert response.json() == ["This email is already associated to a registered user."] def test_api_document_invitations__list__anonymous_user(): @@ -567,8 +566,9 @@ def test_api_document_invitations__update__forbidden__not_authenticated( client = APIClient() client.force_login(user) url = f"/api/v1.0/documents/{invitation.document.id}/invitations/{invitation.id}/" - if method == "put": - response = client.put(url) + + response = client.put(url) + if method == "patch": response = client.patch(url) diff --git a/src/backend/core/tests/documents/test_api_document_versions.py b/src/backend/core/tests/documents/test_api_document_versions.py index e9805081..066f3997 100644 --- a/src/backend/core/tests/documents/test_api_document_versions.py +++ b/src/backend/core/tests/documents/test_api_document_versions.py @@ -1,6 +1,7 @@ """ Test document versions API endpoints for users in impress's core app. """ + import random import time diff --git a/src/backend/core/tests/documents/test_api_documents_create.py b/src/backend/core/tests/documents/test_api_documents_create.py index c4bd11b1..4f3673f9 100644 --- a/src/backend/core/tests/documents/test_api_documents_create.py +++ b/src/backend/core/tests/documents/test_api_documents_create.py @@ -1,6 +1,7 @@ """ Tests for Documents API endpoint in impress's core app: create """ + import uuid import pytest diff --git a/src/backend/core/tests/documents/test_api_documents_delete.py b/src/backend/core/tests/documents/test_api_documents_delete.py index 7cf67bd2..0831b93a 100644 --- a/src/backend/core/tests/documents/test_api_documents_delete.py +++ b/src/backend/core/tests/documents/test_api_documents_delete.py @@ -1,6 +1,7 @@ """ Tests for Documents API endpoint in impress's core app: delete """ + import random import pytest diff --git a/src/backend/core/tests/documents/test_api_documents_list.py b/src/backend/core/tests/documents/test_api_documents_list.py index aefc0749..30d8febd 100644 --- a/src/backend/core/tests/documents/test_api_documents_list.py +++ b/src/backend/core/tests/documents/test_api_documents_list.py @@ -1,6 +1,7 @@ """ Tests for Documents API endpoint in impress's core app: list """ + from unittest import mock import pytest diff --git a/src/backend/core/tests/documents/test_api_documents_retrieve.py b/src/backend/core/tests/documents/test_api_documents_retrieve.py index b34119c3..2ec46605 100644 --- a/src/backend/core/tests/documents/test_api_documents_retrieve.py +++ b/src/backend/core/tests/documents/test_api_documents_retrieve.py @@ -1,6 +1,7 @@ """ Tests for Documents API endpoint in impress's core app: retrieve """ + import pytest from rest_framework.test import APIClient @@ -228,6 +229,8 @@ def test_api_documents_retrieve_authenticated_related_team_members( factories.TeamDocumentAccessFactory() response = client.get(f"/api/v1.0/documents/{document.id!s}/") + + # pylint: disable=R0801 assert response.status_code == 200 content = response.json() expected_abilities = { diff --git a/src/backend/core/tests/documents/test_api_documents_update.py b/src/backend/core/tests/documents/test_api_documents_update.py index 866a8ba9..7b3ee965 100644 --- a/src/backend/core/tests/documents/test_api_documents_update.py +++ b/src/backend/core/tests/documents/test_api_documents_update.py @@ -1,6 +1,7 @@ """ Tests for Documents API endpoint in impress's core app: update """ + import random import pytest diff --git a/src/backend/core/tests/swagger/test_openapi_schema.py b/src/backend/core/tests/swagger/test_openapi_schema.py index 26b58b71..9e0919a8 100644 --- a/src/backend/core/tests/swagger/test_openapi_schema.py +++ b/src/backend/core/tests/swagger/test_openapi_schema.py @@ -1,6 +1,7 @@ """ Test suite for generated openapi schema. """ + import json from io import StringIO diff --git a/src/backend/core/tests/templates/test_api_templates_create.py b/src/backend/core/tests/templates/test_api_templates_create.py index e26a5a75..75dddc82 100644 --- a/src/backend/core/tests/templates/test_api_templates_create.py +++ b/src/backend/core/tests/templates/test_api_templates_create.py @@ -1,6 +1,7 @@ """ Tests for Templates API endpoint in impress's core app: create """ + import pytest from rest_framework.test import APIClient diff --git a/src/backend/core/tests/templates/test_api_templates_delete.py b/src/backend/core/tests/templates/test_api_templates_delete.py index 5a8f32cd..0c0bd161 100644 --- a/src/backend/core/tests/templates/test_api_templates_delete.py +++ b/src/backend/core/tests/templates/test_api_templates_delete.py @@ -1,6 +1,7 @@ """ Tests for Templates API endpoint in impress's core app: delete """ + import random import pytest diff --git a/src/backend/core/tests/templates/test_api_templates_generate_document.py b/src/backend/core/tests/templates/test_api_templates_generate_document.py index 1edfddb1..bfc30161 100644 --- a/src/backend/core/tests/templates/test_api_templates_generate_document.py +++ b/src/backend/core/tests/templates/test_api_templates_generate_document.py @@ -1,6 +1,7 @@ """ Test users API endpoints in the impress core app. """ + import pytest from rest_framework.test import APIClient @@ -97,7 +98,7 @@ def test_api_templates_generate_document_related(via, mock_user_get_teams): client = APIClient() client.force_login(user) - + access = None if via == USER: access = factories.UserTemplateAccessFactory(user=user) elif via == TEAM: diff --git a/src/backend/core/tests/templates/test_api_templates_list.py b/src/backend/core/tests/templates/test_api_templates_list.py index 4b8a39f4..2e6eb329 100644 --- a/src/backend/core/tests/templates/test_api_templates_list.py +++ b/src/backend/core/tests/templates/test_api_templates_list.py @@ -1,6 +1,7 @@ """ Tests for Templates API endpoint in impress's core app: list """ + from unittest import mock import pytest diff --git a/src/backend/core/tests/templates/test_api_templates_retrieve.py b/src/backend/core/tests/templates/test_api_templates_retrieve.py index 1027ebcc..e6ea96d1 100644 --- a/src/backend/core/tests/templates/test_api_templates_retrieve.py +++ b/src/backend/core/tests/templates/test_api_templates_retrieve.py @@ -1,6 +1,7 @@ """ Tests for Templates API endpoint in impress's core app: retrieve """ + import pytest from rest_framework.test import APIClient diff --git a/src/backend/core/tests/templates/test_api_templates_update.py b/src/backend/core/tests/templates/test_api_templates_update.py index 0735cba1..56e582ea 100644 --- a/src/backend/core/tests/templates/test_api_templates_update.py +++ b/src/backend/core/tests/templates/test_api_templates_update.py @@ -1,6 +1,7 @@ """ Tests for Templates API endpoint in impress's core app: update """ + import random import pytest diff --git a/src/backend/core/tests/test_api_template_accesses.py b/src/backend/core/tests/test_api_template_accesses.py index a27ff7cd..7b8f8eb4 100644 --- a/src/backend/core/tests/test_api_template_accesses.py +++ b/src/backend/core/tests/test_api_template_accesses.py @@ -1,6 +1,7 @@ """ Test template accesses API endpoints for users in impress's core app. """ + import random from uuid import uuid4 @@ -67,6 +68,7 @@ def test_api_template_accesses_list_authenticated_related(via, mock_user_get_tea client.force_login(user) template = factories.TemplateFactory() + user_access = None if via == USER: user_access = models.TemplateAccess.objects.create( template=template, @@ -733,6 +735,7 @@ def test_api_template_accesses_update_owner_self(via, mock_user_get_teams): client.force_login(user) template = factories.TemplateFactory() + access = None if via == USER: access = factories.UserTemplateAccessFactory( template=template, user=user, role="owner" @@ -957,6 +960,7 @@ def test_api_template_accesses_delete_owners_last_owner(via, mock_user_get_teams client.force_login(user) template = factories.TemplateFactory() + access = None if via == USER: access = factories.UserTemplateAccessFactory( template=template, user=user, role="owner" diff --git a/src/backend/core/tests/test_api_users.py b/src/backend/core/tests/test_api_users.py index 2e006ab7..79eda932 100644 --- a/src/backend/core/tests/test_api_users.py +++ b/src/backend/core/tests/test_api_users.py @@ -1,6 +1,7 @@ """ Test users API endpoints in the impress core app. """ + import pytest from rest_framework.test import APIClient diff --git a/src/backend/core/tests/test_models_document_accesses.py b/src/backend/core/tests/test_models_document_accesses.py index 4e94423b..62c03665 100644 --- a/src/backend/core/tests/test_models_document_accesses.py +++ b/src/backend/core/tests/test_models_document_accesses.py @@ -1,6 +1,7 @@ """ Unit tests for the DocumentAccess model """ + from django.contrib.auth.models import AnonymousUser from django.core.exceptions import ValidationError @@ -318,7 +319,7 @@ def test_models_document_access_get_abilities_for_editor_of_administrator(): def test_models_document_access_get_abilities_for_editor_of_editor_user( - django_assert_num_queries + django_assert_num_queries, ): """Check abilities of editor access for the editor of a document.""" access = factories.UserDocumentAccessFactory(role="editor") @@ -377,7 +378,7 @@ def test_models_document_access_get_abilities_for_reader_of_administrator(): def test_models_document_access_get_abilities_for_reader_of_reader_user( - django_assert_num_queries + django_assert_num_queries, ): """Check abilities of reader access for the reader of a document.""" access = factories.UserDocumentAccessFactory(role="reader") diff --git a/src/backend/core/tests/test_models_documents.py b/src/backend/core/tests/test_models_documents.py index c7462353..e47ba1a2 100644 --- a/src/backend/core/tests/test_models_documents.py +++ b/src/backend/core/tests/test_models_documents.py @@ -1,6 +1,7 @@ """ Unit tests for the Document model """ + from django.contrib.auth.models import AnonymousUser from django.core.exceptions import ValidationError from django.core.files.storage import default_storage diff --git a/src/backend/core/tests/test_models_invitations.py b/src/backend/core/tests/test_models_invitations.py index 38c99939..2ed88571 100644 --- a/src/backend/core/tests/test_models_invitations.py +++ b/src/backend/core/tests/test_models_invitations.py @@ -1,6 +1,7 @@ """ Unit tests for the Invitation model """ + import time from django.contrib.auth.models import AnonymousUser diff --git a/src/backend/core/tests/test_models_template_accesses.py b/src/backend/core/tests/test_models_template_accesses.py index e3ebd340..70a24164 100644 --- a/src/backend/core/tests/test_models_template_accesses.py +++ b/src/backend/core/tests/test_models_template_accesses.py @@ -1,6 +1,7 @@ """ Unit tests for the TemplateAccess model """ + from django.contrib.auth.models import AnonymousUser from django.core.exceptions import ValidationError @@ -318,7 +319,7 @@ def test_models_template_access_get_abilities_for_editor_of_administrator(): def test_models_template_access_get_abilities_for_editor_of_editor_user( - django_assert_num_queries + django_assert_num_queries, ): """Check abilities of editor access for the editor of a template.""" access = factories.UserTemplateAccessFactory(role="editor") @@ -377,7 +378,7 @@ def test_models_template_access_get_abilities_for_reader_of_administrator(): def test_models_template_access_get_abilities_for_reader_of_reader_user( - django_assert_num_queries + django_assert_num_queries, ): """Check abilities of reader access for the reader of a template.""" access = factories.UserTemplateAccessFactory(role="reader") diff --git a/src/backend/core/tests/test_models_templates.py b/src/backend/core/tests/test_models_templates.py index bd2269e8..c086b063 100644 --- a/src/backend/core/tests/test_models_templates.py +++ b/src/backend/core/tests/test_models_templates.py @@ -1,6 +1,7 @@ """ Unit tests for the Template model """ + from django.contrib.auth.models import AnonymousUser from django.core.exceptions import ValidationError diff --git a/src/backend/core/tests/test_models_users.py b/src/backend/core/tests/test_models_users.py index f3e808c4..edea5bb9 100644 --- a/src/backend/core/tests/test_models_users.py +++ b/src/backend/core/tests/test_models_users.py @@ -1,6 +1,7 @@ """ Unit tests for the User model """ + from unittest import mock from django.core.exceptions import ValidationError diff --git a/src/backend/core/tests/test_utils.py b/src/backend/core/tests/test_utils.py index 68c6148f..288d3197 100644 --- a/src/backend/core/tests/test_utils.py +++ b/src/backend/core/tests/test_utils.py @@ -1,6 +1,7 @@ """ Unit tests for the Invitation model """ + import smtplib from logging import Logger from unittest import mock diff --git a/src/backend/core/urls.py b/src/backend/core/urls.py index 07e2bb8b..d16e3ee0 100644 --- a/src/backend/core/urls.py +++ b/src/backend/core/urls.py @@ -1,4 +1,5 @@ """URL configuration for the core app.""" + from django.conf import settings from django.urls import include, path, re_path diff --git a/src/backend/core/utils.py b/src/backend/core/utils.py index 58ed6764..b3767eaf 100644 --- a/src/backend/core/utils.py +++ b/src/backend/core/utils.py @@ -1,6 +1,7 @@ """ Utilities for the core app. """ + import smtplib from logging import getLogger diff --git a/src/backend/demo/management/commands/createsuperuser.py b/src/backend/demo/management/commands/createsuperuser.py index 6ac7cf5e..9c5ab786 100644 --- a/src/backend/demo/management/commands/createsuperuser.py +++ b/src/backend/demo/management/commands/createsuperuser.py @@ -1,4 +1,5 @@ """Management user to create a superuser.""" + from django.contrib.auth import get_user_model from django.core.management.base import BaseCommand diff --git a/src/backend/impress/celery_app.py b/src/backend/impress/celery_app.py index 1cf11953..37d7a70d 100644 --- a/src/backend/impress/celery_app.py +++ b/src/backend/impress/celery_app.py @@ -1,4 +1,5 @@ """Impress celery configuration file.""" + import os from celery import Celery diff --git a/src/backend/impress/settings.py b/src/backend/impress/settings.py index f91fd667..4f5ec723 100755 --- a/src/backend/impress/settings.py +++ b/src/backend/impress/settings.py @@ -9,6 +9,7 @@ https://docs.djangoproject.com/en/3.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.1/ref/settings/ """ + import json import os diff --git a/src/backend/manage.py b/src/backend/manage.py index 78b98ee5..ab643f93 100644 --- a/src/backend/manage.py +++ b/src/backend/manage.py @@ -2,6 +2,7 @@ """ impress's sandbox management script. """ + import os import sys diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index 097b3711..fa5dcb51 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -100,11 +100,11 @@ exclude = [ "__pycache__", "*/migrations/*", ] -ignore= ["DJ001", "PLR2004"] line-length = 88 [tool.ruff.lint] +ignore = ["DJ001", "PLR2004"] select = [ "B", # flake8-bugbear "BLE", # flake8-blind-except @@ -126,7 +126,7 @@ select = [ section-order = ["future","standard-library","django","third-party","impress","first-party","local-folder"] sections = { impress=["core"], django=["django"] } -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "**/tests/*" = ["S", "SLF"] [tool.pytest.ini_options]