From 3003bdd50792dc116c5c3b1df46a17ea23b7bfdf Mon Sep 17 00:00:00 2001 From: Trenton Holmes Date: Fri, 6 May 2022 09:04:08 -0700 Subject: [PATCH] Runs pyupgrade to Python 3.8+ and adds a hook for it --- .pre-commit-config.yaml | 9 +++- gunicorn.conf.py | 2 +- src/documents/admin.py | 6 +-- src/documents/bulk_download.py | 2 +- src/documents/classifier.py | 14 +++--- src/documents/consumer.py | 8 +-- src/documents/file_handling.py | 2 +- src/documents/filters.py | 2 +- .../management/commands/decrypt_documents.py | 2 +- .../management/commands/loaddata_stdin.py | 2 +- src/documents/models.py | 9 ++-- src/documents/parsers.py | 8 +-- src/documents/serialisers.py | 4 +- src/documents/tasks.py | 12 ++--- src/documents/tests/test_admin.py | 2 +- src/documents/tests/test_api.py | 50 +++++++++---------- src/documents/tests/test_classifier.py | 2 +- src/documents/tests/test_consumer.py | 10 ++-- src/documents/tests/test_date_parsing.py | 2 +- src/documents/tests/test_file_handling.py | 6 +-- .../tests/test_management_consumer.py | 4 +- .../tests/test_management_exporter.py | 2 +- .../tests/test_management_retagger.py | 2 +- .../tests/test_management_thumbnails.py | 2 +- src/documents/tests/test_matchables.py | 4 +- .../tests/test_migration_archive_files.py | 6 +-- .../tests/test_migration_mime_type.py | 4 +- src/documents/tests/test_parsers.py | 6 +-- src/documents/tests/utils.py | 6 +-- src/documents/views.py | 16 +++--- src/paperless/auth.py | 2 +- src/paperless_mail/tests/test_mail.py | 8 +-- src/paperless_tesseract/parsers.py | 2 +- src/paperless_text/parsers.py | 4 +- 34 files changed, 113 insertions(+), 109 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f0bf9bace..b9d7e5f22 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: exclude: "(^Pipfile\\.lock$)" # Python hooks - repo: https://github.com/asottile/reorder_python_imports - rev: v3.0.1 + rev: v3.1.0 hooks: - id: reorder-python-imports exclude: "(migrations)" @@ -62,6 +62,13 @@ repos: rev: 22.3.0 hooks: - id: black + - repo: https://github.com/asottile/pyupgrade + rev: v2.32.1 + hooks: + - id: pyupgrade + exclude: "(migrations)" + args: + - "--py38-plus" # Dockerfile hooks - repo: https://github.com/AleksaC/hadolint-py rev: v2.10.0 diff --git a/gunicorn.conf.py b/gunicorn.conf.py index f00e62c36..7bfaef43e 100644 --- a/gunicorn.conf.py +++ b/gunicorn.conf.py @@ -24,7 +24,7 @@ def worker_int(worker): ## get traceback info import threading, sys, traceback - id2name = dict([(th.ident, th.name) for th in threading.enumerate()]) + id2name = {th.ident: th.name for th in threading.enumerate()} code = [] for threadId, stack in sys._current_frames().items(): code.append("\n# Thread: %s(%d)" % (id2name.get(threadId, ""), threadId)) diff --git a/src/documents/admin.py b/src/documents/admin.py index 0551278ef..37a45bb8f 100644 --- a/src/documents/admin.py +++ b/src/documents/admin.py @@ -74,19 +74,19 @@ class DocumentAdmin(admin.ModelAdmin): for o in queryset: index.remove_document(writer, o) - super(DocumentAdmin, self).delete_queryset(request, queryset) + super().delete_queryset(request, queryset) def delete_model(self, request, obj): from documents import index index.remove_document_from_index(obj) - super(DocumentAdmin, self).delete_model(request, obj) + super().delete_model(request, obj) def save_model(self, request, obj, form, change): from documents import index index.add_or_update_document(obj) - super(DocumentAdmin, self).save_model(request, obj, form, change) + super().save_model(request, obj, form, change) class RuleInline(admin.TabularInline): diff --git a/src/documents/bulk_download.py b/src/documents/bulk_download.py index cf0b8949f..6beefa23b 100644 --- a/src/documents/bulk_download.py +++ b/src/documents/bulk_download.py @@ -32,7 +32,7 @@ class OriginalsOnlyStrategy(BulkArchiveStrategy): class ArchiveOnlyStrategy(BulkArchiveStrategy): def __init__(self, zipf): - super(ArchiveOnlyStrategy, self).__init__(zipf) + super().__init__(zipf) def add_document(self, doc: Document): if doc.has_archive_version: diff --git a/src/documents/classifier.py b/src/documents/classifier.py index be2256297..562afff52 100644 --- a/src/documents/classifier.py +++ b/src/documents/classifier.py @@ -57,7 +57,7 @@ def load_classifier(): return classifier -class DocumentClassifier(object): +class DocumentClassifier: # v7 - Updated scikit-learn package version FORMAT_VERSION = 7 @@ -144,12 +144,10 @@ class DocumentClassifier(object): labels_correspondent.append(y) tags = sorted( - [ - tag.pk - for tag in doc.tags.filter( - matching_algorithm=MatchingModel.MATCH_AUTO, - ) - ], + tag.pk + for tag in doc.tags.filter( + matching_algorithm=MatchingModel.MATCH_AUTO, + ) ) for tag in tags: m.update(tag.to_bytes(4, "little", signed=True)) @@ -163,7 +161,7 @@ class DocumentClassifier(object): if self.data_hash and new_data_hash == self.data_hash: return False - labels_tags_unique = set([tag for tags in labels_tags for tag in tags]) + labels_tags_unique = {tag for tags in labels_tags for tag in tags} num_tags = len(labels_tags_unique) diff --git a/src/documents/consumer.py b/src/documents/consumer.py index 4fe6b02ed..a59f0bfd7 100644 --- a/src/documents/consumer.py +++ b/src/documents/consumer.py @@ -257,7 +257,7 @@ class Consumer(LoggingMixin): try: self._send_progress(20, 100, "WORKING", MESSAGE_PARSING_DOCUMENT) - self.log("debug", "Parsing {}...".format(self.filename)) + self.log("debug", f"Parsing {self.filename}...") document_parser.parse(self.path, mime_type, self.filename) self.log("debug", f"Generating thumbnail for {self.filename}...") @@ -346,7 +346,7 @@ class Consumer(LoggingMixin): document.save() # Delete the file only if it was successfully consumed - self.log("debug", "Deleting file {}".format(self.path)) + self.log("debug", f"Deleting file {self.path}") os.unlink(self.path) # https://github.com/jonaswinkler/paperless-ng/discussions/1037 @@ -356,7 +356,7 @@ class Consumer(LoggingMixin): ) if os.path.isfile(shadow_file): - self.log("debug", "Deleting file {}".format(shadow_file)) + self.log("debug", f"Deleting file {shadow_file}") os.unlink(shadow_file) except Exception as e: @@ -370,7 +370,7 @@ class Consumer(LoggingMixin): self.run_post_consume_script(document) - self.log("info", "Document {} consumption finished".format(document)) + self.log("info", f"Document {document} consumption finished") self._send_progress(100, 100, "SUCCESS", MESSAGE_FINISHED, document.id) diff --git a/src/documents/file_handling.py b/src/documents/file_handling.py index 132825e0e..cf165d31d 100644 --- a/src/documents/file_handling.py +++ b/src/documents/file_handling.py @@ -133,7 +133,7 @@ def generate_filename(doc, counter=0, append_gpg=True, archive_filename=False): tags = defaultdictNoStr(lambda: slugify(None), many_to_dictionary(doc.tags)) tag_list = pathvalidate.sanitize_filename( - ",".join(sorted([tag.name for tag in doc.tags.all()])), + ",".join(sorted(tag.name for tag in doc.tags.all())), replacement_text="-", ) diff --git a/src/documents/filters.py b/src/documents/filters.py index 6451bea35..642241044 100644 --- a/src/documents/filters.py +++ b/src/documents/filters.py @@ -35,7 +35,7 @@ class DocumentTypeFilterSet(FilterSet): class TagsFilter(Filter): def __init__(self, exclude=False, in_list=False): - super(TagsFilter, self).__init__() + super().__init__() self.exclude = exclude self.in_list = in_list diff --git a/src/documents/management/commands/decrypt_documents.py b/src/documents/management/commands/decrypt_documents.py index 861bfa2cc..2cb98c4e1 100644 --- a/src/documents/management/commands/decrypt_documents.py +++ b/src/documents/management/commands/decrypt_documents.py @@ -55,7 +55,7 @@ class Command(BaseCommand): for document in encrypted_files: - print("Decrypting {}".format(document).encode("utf-8")) + print(f"Decrypting {document}".encode()) old_paths = [document.source_path, document.thumbnail_path] diff --git a/src/documents/management/commands/loaddata_stdin.py b/src/documents/management/commands/loaddata_stdin.py index 23f75769b..39b598674 100644 --- a/src/documents/management/commands/loaddata_stdin.py +++ b/src/documents/management/commands/loaddata_stdin.py @@ -17,4 +17,4 @@ class Command(LoadDataCommand): def find_fixtures(self, fixture_label): if fixture_label == "-": return [("-", None, "-")] - return super(Command, self).find_fixtures(fixture_label) + return super().find_fixtures(fixture_label) diff --git a/src/documents/models.py b/src/documents/models.py index 8f531e401..fcb4be382 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -1,4 +1,3 @@ -# coding=utf-8 import datetime import logging import os @@ -221,7 +220,7 @@ class Document(models.Model): if self.filename: fname = str(self.filename) else: - fname = "{:07}{}".format(self.pk, self.file_type) + fname = f"{self.pk:07}{self.file_type}" if self.storage_type == self.STORAGE_TYPE_GPG: fname += ".gpg" # pragma: no cover @@ -268,7 +267,7 @@ class Document(models.Model): @property def thumbnail_path(self): - file_name = "{:07}.png".format(self.pk) + file_name = f"{self.pk:07}.png" if self.storage_type == self.STORAGE_TYPE_GPG: file_name += ".gpg" @@ -414,7 +413,7 @@ class FileInfo: @classmethod def _get_created(cls, created): try: - return dateutil.parser.parse("{:0<14}Z".format(created[:-1])) + return dateutil.parser.parse(f"{created[:-1]:0<14}Z") except ValueError: return None @@ -425,7 +424,7 @@ class FileInfo: @classmethod def _mangle_property(cls, properties, name): if name in properties: - properties[name] = getattr(cls, "_get_{}".format(name))(properties[name]) + properties[name] = getattr(cls, f"_get_{name}")(properties[name]) @classmethod def from_filename(cls, filename): diff --git a/src/documents/parsers.py b/src/documents/parsers.py index 269fddbb4..be4db1e71 100644 --- a/src/documents/parsers.py +++ b/src/documents/parsers.py @@ -143,7 +143,7 @@ def run_convert( logger.debug("Execute: " + " ".join(args), extra={"group": logging_group}) if not subprocess.Popen(args, env=environment).wait() == 0: - raise ParseError("Convert failed at {}".format(args)) + raise ParseError(f"Convert failed at {args}") def get_default_thumbnail(): @@ -164,7 +164,7 @@ def make_thumbnail_from_pdf_gs_fallback(in_path, temp_dir, logging_group=None): cmd = [settings.GS_BINARY, "-q", "-sDEVICE=pngalpha", "-o", gs_out_path, in_path] try: if not subprocess.Popen(cmd).wait() == 0: - raise ParseError("Thumbnail (gs) failed at {}".format(cmd)) + raise ParseError(f"Thumbnail (gs) failed at {cmd}") # then run convert on the output from gs run_convert( density=300, @@ -199,7 +199,7 @@ def make_thumbnail_from_pdf(in_path, temp_dir, logging_group=None): strip=True, trim=False, auto_orient=True, - input_file="{}[0]".format(in_path), + input_file=f"{in_path}[0]", output_file=out_path, logging_group=logging_group, ) @@ -333,7 +333,7 @@ class DocumentParser(LoggingMixin): self.log("debug", f"Execute: {' '.join(args)}") if not subprocess.Popen(args).wait() == 0: - raise ParseError("Optipng failed at {}".format(args)) + raise ParseError(f"Optipng failed at {args}") return out_path else: diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index 5e295f537..a257a1dd6 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -30,7 +30,7 @@ class DynamicFieldsModelSerializer(serializers.ModelSerializer): fields = kwargs.pop("fields", None) # Instantiate the superclass normally - super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if fields is not None: # Drop any fields that are not specified in the `fields` argument. @@ -263,7 +263,7 @@ class SavedViewSerializer(serializers.ModelSerializer): rules_data = validated_data.pop("filter_rules") else: rules_data = None - super(SavedViewSerializer, self).update(instance, validated_data) + super().update(instance, validated_data) if rules_data is not None: SavedViewFilterRule.objects.filter(saved_view=instance).delete() for rule_data in rules_data: diff --git a/src/documents/tasks.py b/src/documents/tasks.py index 9fe58b325..10a1ad671 100644 --- a/src/documents/tasks.py +++ b/src/documents/tasks.py @@ -64,7 +64,7 @@ def train_classifier(): try: if classifier.train(): logger.info( - "Saving updated classifier model to {}...".format(settings.MODEL_FILE), + f"Saving updated classifier model to {settings.MODEL_FILE}...", ) classifier.save() else: @@ -165,7 +165,7 @@ def separate_pages(filepath: str, pages_to_split_on: List[int]) -> List[str]: for n, page in enumerate(pdf.pages): if n < pages_to_split_on[0]: dst.pages.append(page) - output_filename = "{}_document_0.pdf".format(fname) + output_filename = f"{fname}_document_0.pdf" savepath = os.path.join(tempdir, output_filename) with open(savepath, "wb") as out: dst.save(out) @@ -185,7 +185,7 @@ def separate_pages(filepath: str, pages_to_split_on: List[int]) -> List[str]: f"page_number: {str(page_number)} next_page: {str(next_page)}", ) dst.pages.append(pdf.pages[page]) - output_filename = "{}_document_{}.pdf".format(fname, str(count + 1)) + output_filename = f"{fname}_document_{str(count + 1)}.pdf" logger.debug(f"pdf no:{str(count)} has {str(len(dst.pages))} pages") savepath = os.path.join(tempdir, output_filename) with open(savepath, "wb") as out: @@ -266,9 +266,9 @@ def consume_file( # if we got here, the document was successfully split # and can safely be deleted if converted_tiff: - logger.debug("Deleting file {}".format(file_to_process)) + logger.debug(f"Deleting file {file_to_process}") os.unlink(file_to_process) - logger.debug("Deleting file {}".format(path)) + logger.debug(f"Deleting file {path}") os.unlink(path) # notify the sender, otherwise the progress bar # in the UI stays stuck @@ -306,7 +306,7 @@ def consume_file( ) if document: - return "Success. New document id {} created".format(document.pk) + return f"Success. New document id {document.pk} created" else: raise ConsumerError( "Unknown error: Returned document was null, but " diff --git a/src/documents/tests/test_admin.py b/src/documents/tests/test_admin.py index 92e2d1f95..edbeb6f4c 100644 --- a/src/documents/tests/test_admin.py +++ b/src/documents/tests/test_admin.py @@ -16,7 +16,7 @@ class TestDocumentAdmin(DirectoriesMixin, TestCase): return searcher.document(id=doc.id) def setUp(self) -> None: - super(TestDocumentAdmin, self).setUp() + super().setUp() self.doc_admin = DocumentAdmin(model=Document, admin_site=AdminSite()) def test_save_model(self): diff --git a/src/documents/tests/test_api.py b/src/documents/tests/test_api.py index 9c43f174a..21d53be9d 100644 --- a/src/documents/tests/test_api.py +++ b/src/documents/tests/test_api.py @@ -27,7 +27,7 @@ from whoosh.writing import AsyncWriter class TestDocumentApi(DirectoriesMixin, APITestCase): def setUp(self): - super(TestDocumentApi, self).setUp() + super().setUp() self.user = User.objects.create_superuser(username="temp_admin") self.client.force_login(user=self.user) @@ -70,7 +70,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): returned_doc["title"] = "the new title" response = self.client.put( - "/api/documents/{}/".format(doc.pk), + f"/api/documents/{doc.pk}/", returned_doc, format="json", ) @@ -82,7 +82,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): self.assertEqual(doc_after_save.correspondent, c2) self.assertEqual(doc_after_save.title, "the new title") - self.client.delete("/api/documents/{}/".format(doc_after_save.pk)) + self.client.delete(f"/api/documents/{doc_after_save.pk}/") self.assertEqual(len(Document.objects.all()), 0) @@ -163,22 +163,22 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): ) with open( - os.path.join(self.dirs.thumbnail_dir, "{:07d}.png".format(doc.pk)), + os.path.join(self.dirs.thumbnail_dir, f"{doc.pk:07d}.png"), "wb", ) as f: f.write(content_thumbnail) - response = self.client.get("/api/documents/{}/download/".format(doc.pk)) + response = self.client.get(f"/api/documents/{doc.pk}/download/") self.assertEqual(response.status_code, 200) self.assertEqual(response.content, content) - response = self.client.get("/api/documents/{}/preview/".format(doc.pk)) + response = self.client.get(f"/api/documents/{doc.pk}/preview/") self.assertEqual(response.status_code, 200) self.assertEqual(response.content, content) - response = self.client.get("/api/documents/{}/thumb/".format(doc.pk)) + response = self.client.get(f"/api/documents/{doc.pk}/thumb/") self.assertEqual(response.status_code, 200) self.assertEqual(response.content, content_thumbnail) @@ -202,25 +202,25 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): with open(doc.archive_path, "wb") as f: f.write(content_archive) - response = self.client.get("/api/documents/{}/download/".format(doc.pk)) + response = self.client.get(f"/api/documents/{doc.pk}/download/") self.assertEqual(response.status_code, 200) self.assertEqual(response.content, content_archive) response = self.client.get( - "/api/documents/{}/download/?original=true".format(doc.pk), + f"/api/documents/{doc.pk}/download/?original=true", ) self.assertEqual(response.status_code, 200) self.assertEqual(response.content, content) - response = self.client.get("/api/documents/{}/preview/".format(doc.pk)) + response = self.client.get(f"/api/documents/{doc.pk}/preview/") self.assertEqual(response.status_code, 200) self.assertEqual(response.content, content_archive) response = self.client.get( - "/api/documents/{}/preview/?original=true".format(doc.pk), + f"/api/documents/{doc.pk}/preview/?original=true", ) self.assertEqual(response.status_code, 200) @@ -234,13 +234,13 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): mime_type="application/pdf", ) - response = self.client.get("/api/documents/{}/download/".format(doc.pk)) + response = self.client.get(f"/api/documents/{doc.pk}/download/") self.assertEqual(response.status_code, 404) - response = self.client.get("/api/documents/{}/preview/".format(doc.pk)) + response = self.client.get(f"/api/documents/{doc.pk}/preview/") self.assertEqual(response.status_code, 404) - response = self.client.get("/api/documents/{}/thumb/".format(doc.pk)) + response = self.client.get(f"/api/documents/{doc.pk}/thumb/") self.assertEqual(response.status_code, 404) def test_document_filters(self): @@ -283,7 +283,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): self.assertCountEqual([results[0]["id"], results[1]["id"]], [doc2.id, doc3.id]) response = self.client.get( - "/api/documents/?tags__id__in={},{}".format(tag_inbox.id, tag_3.id), + f"/api/documents/?tags__id__in={tag_inbox.id},{tag_3.id}", ) self.assertEqual(response.status_code, 200) results = response.data["results"] @@ -291,7 +291,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): self.assertCountEqual([results[0]["id"], results[1]["id"]], [doc1.id, doc3.id]) response = self.client.get( - "/api/documents/?tags__id__in={},{}".format(tag_2.id, tag_3.id), + f"/api/documents/?tags__id__in={tag_2.id},{tag_3.id}", ) self.assertEqual(response.status_code, 200) results = response.data["results"] @@ -299,7 +299,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): self.assertCountEqual([results[0]["id"], results[1]["id"]], [doc2.id, doc3.id]) response = self.client.get( - "/api/documents/?tags__id__all={},{}".format(tag_2.id, tag_3.id), + f"/api/documents/?tags__id__all={tag_2.id},{tag_3.id}", ) self.assertEqual(response.status_code, 200) results = response.data["results"] @@ -307,27 +307,27 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): self.assertEqual(results[0]["id"], doc3.id) response = self.client.get( - "/api/documents/?tags__id__all={},{}".format(tag_inbox.id, tag_3.id), + f"/api/documents/?tags__id__all={tag_inbox.id},{tag_3.id}", ) self.assertEqual(response.status_code, 200) results = response.data["results"] self.assertEqual(len(results), 0) response = self.client.get( - "/api/documents/?tags__id__all={}a{}".format(tag_inbox.id, tag_3.id), + f"/api/documents/?tags__id__all={tag_inbox.id}a{tag_3.id}", ) self.assertEqual(response.status_code, 200) results = response.data["results"] self.assertEqual(len(results), 3) - response = self.client.get("/api/documents/?tags__id__none={}".format(tag_3.id)) + response = self.client.get(f"/api/documents/?tags__id__none={tag_3.id}") self.assertEqual(response.status_code, 200) results = response.data["results"] self.assertEqual(len(results), 2) self.assertCountEqual([results[0]["id"], results[1]["id"]], [doc1.id, doc2.id]) response = self.client.get( - "/api/documents/?tags__id__none={},{}".format(tag_3.id, tag_2.id), + f"/api/documents/?tags__id__none={tag_3.id},{tag_2.id}", ) self.assertEqual(response.status_code, 200) results = response.data["results"] @@ -335,7 +335,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): self.assertEqual(results[0]["id"], doc1.id) response = self.client.get( - "/api/documents/?tags__id__none={},{}".format(tag_2.id, tag_inbox.id), + f"/api/documents/?tags__id__none={tag_2.id},{tag_inbox.id}", ) self.assertEqual(response.status_code, 200) results = response.data["results"] @@ -1284,7 +1284,7 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): class TestDocumentApiV2(DirectoriesMixin, APITestCase): def setUp(self): - super(TestDocumentApiV2, self).setUp() + super().setUp() self.user = User.objects.create_superuser(username="temp_admin") @@ -1365,7 +1365,7 @@ class TestDocumentApiV2(DirectoriesMixin, APITestCase): class TestBulkEdit(DirectoriesMixin, APITestCase): def setUp(self): - super(TestBulkEdit, self).setUp() + super().setUp() user = User.objects.create_superuser(username="temp_admin") self.client.force_login(user=user) @@ -1886,7 +1886,7 @@ class TestBulkEdit(DirectoriesMixin, APITestCase): class TestBulkDownload(DirectoriesMixin, APITestCase): def setUp(self): - super(TestBulkDownload, self).setUp() + super().setUp() user = User.objects.create_superuser(username="temp_admin") self.client.force_login(user=user) diff --git a/src/documents/tests/test_classifier.py b/src/documents/tests/test_classifier.py index b03ecf7d3..331618b94 100644 --- a/src/documents/tests/test_classifier.py +++ b/src/documents/tests/test_classifier.py @@ -19,7 +19,7 @@ from documents.tests.utils import DirectoriesMixin class TestClassifier(DirectoriesMixin, TestCase): def setUp(self): - super(TestClassifier, self).setUp() + super().setUp() self.classifier = DocumentClassifier() def generate_test_data(self): diff --git a/src/documents/tests/test_consumer.py b/src/documents/tests/test_consumer.py index af54255e0..5592d74d7 100644 --- a/src/documents/tests/test_consumer.py +++ b/src/documents/tests/test_consumer.py @@ -41,7 +41,7 @@ class TestAttributes(TestCase): self.assertEqual(file_info.title, title, filename) - self.assertEqual(tuple([t.name for t in file_info.tags]), tags, filename) + self.assertEqual(tuple(t.name for t in file_info.tags), tags, filename) def test_guess_attributes_from_name_when_title_starts_with_dash(self): self._test_guess_attributes_from_name( @@ -176,7 +176,7 @@ class DummyParser(DocumentParser): raise NotImplementedError() def __init__(self, logging_group, scratch_dir, archive_path): - super(DummyParser, self).__init__(logging_group, None) + super().__init__(logging_group, None) _, self.fake_thumb = tempfile.mkstemp(suffix=".png", dir=scratch_dir) self.archive_path = archive_path @@ -195,7 +195,7 @@ class CopyParser(DocumentParser): return self.fake_thumb def __init__(self, logging_group, progress_callback=None): - super(CopyParser, self).__init__(logging_group, progress_callback) + super().__init__(logging_group, progress_callback) _, self.fake_thumb = tempfile.mkstemp(suffix=".png", dir=self.tempdir) def parse(self, document_path, mime_type, file_name=None): @@ -210,7 +210,7 @@ class FaultyParser(DocumentParser): raise NotImplementedError() def __init__(self, logging_group, scratch_dir): - super(FaultyParser, self).__init__(logging_group) + super().__init__(logging_group) _, self.fake_thumb = tempfile.mkstemp(suffix=".png", dir=scratch_dir) def get_optimised_thumbnail(self, document_path, mime_type, file_name=None): @@ -270,7 +270,7 @@ class TestConsumer(DirectoriesMixin, TestCase): return FaultyParser(logging_group, self.dirs.scratch_dir) def setUp(self): - super(TestConsumer, self).setUp() + super().setUp() patcher = mock.patch("documents.parsers.document_consumer_declaration.send") m = patcher.start() diff --git a/src/documents/tests/test_date_parsing.py b/src/documents/tests/test_date_parsing.py index 06ad9876c..ae9589ad7 100644 --- a/src/documents/tests/test_date_parsing.py +++ b/src/documents/tests/test_date_parsing.py @@ -16,7 +16,7 @@ class TestDate(TestCase): os.path.dirname(__file__), "../../paperless_tesseract/tests/samples", ) - SCRATCH = "/tmp/paperless-tests-{}".format(str(uuid4())[:8]) + SCRATCH = f"/tmp/paperless-tests-{str(uuid4())[:8]}" def setUp(self): os.makedirs(self.SCRATCH, exist_ok=True) diff --git a/src/documents/tests/test_file_handling.py b/src/documents/tests/test_file_handling.py index 7743458b4..3293d188c 100644 --- a/src/documents/tests/test_file_handling.py +++ b/src/documents/tests/test_file_handling.py @@ -32,12 +32,12 @@ class TestFileHandling(DirectoriesMixin, TestCase): document.storage_type = Document.STORAGE_TYPE_UNENCRYPTED document.save() - self.assertEqual(generate_filename(document), "{:07d}.pdf".format(document.pk)) + self.assertEqual(generate_filename(document), f"{document.pk:07d}.pdf") document.storage_type = Document.STORAGE_TYPE_GPG self.assertEqual( generate_filename(document), - "{:07d}.pdf.gpg".format(document.pk), + f"{document.pk:07d}.pdf.gpg", ) @override_settings(PAPERLESS_FILENAME_FORMAT="{correspondent}/{correspondent}") @@ -50,7 +50,7 @@ class TestFileHandling(DirectoriesMixin, TestCase): # Test default source_path self.assertEqual( document.source_path, - settings.ORIGINALS_DIR + "/{:07d}.pdf".format(document.pk), + settings.ORIGINALS_DIR + f"/{document.pk:07d}.pdf", ) document.filename = generate_filename(document) diff --git a/src/documents/tests/test_management_consumer.py b/src/documents/tests/test_management_consumer.py index d99b01e66..e8463ab64 100644 --- a/src/documents/tests/test_management_consumer.py +++ b/src/documents/tests/test_management_consumer.py @@ -39,7 +39,7 @@ class ConsumerMixin: sample_file = os.path.join(os.path.dirname(__file__), "samples", "simple.pdf") def setUp(self) -> None: - super(ConsumerMixin, self).setUp() + super().setUp() self.t = None patcher = mock.patch( "documents.management.commands.document_consumer.async_task", @@ -60,7 +60,7 @@ class ConsumerMixin: # wait for the consumer to exit. self.t.join() - super(ConsumerMixin, self).tearDown() + super().tearDown() def wait_for_task_mock_call(self, excpeted_call_count=1): n = 0 diff --git a/src/documents/tests/test_management_exporter.py b/src/documents/tests/test_management_exporter.py index 23cf1f225..74e8d8af7 100644 --- a/src/documents/tests/test_management_exporter.py +++ b/src/documents/tests/test_management_exporter.py @@ -65,7 +65,7 @@ class TestExportImport(DirectoriesMixin, TestCase): self.d1.correspondent = self.c1 self.d1.document_type = self.dt1 self.d1.save() - super(TestExportImport, self).setUp() + super().setUp() def _get_document_from_manifest(self, manifest, id): f = list( diff --git a/src/documents/tests/test_management_retagger.py b/src/documents/tests/test_management_retagger.py index 18b55626f..c31462855 100644 --- a/src/documents/tests/test_management_retagger.py +++ b/src/documents/tests/test_management_retagger.py @@ -82,7 +82,7 @@ class TestRetagger(DirectoriesMixin, TestCase): ) def setUp(self) -> None: - super(TestRetagger, self).setUp() + super().setUp() self.make_models() def test_add_tags(self): diff --git a/src/documents/tests/test_management_thumbnails.py b/src/documents/tests/test_management_thumbnails.py index daf56c586..0e643c354 100644 --- a/src/documents/tests/test_management_thumbnails.py +++ b/src/documents/tests/test_management_thumbnails.py @@ -39,7 +39,7 @@ class TestMakeThumbnails(DirectoriesMixin, TestCase): ) def setUp(self) -> None: - super(TestMakeThumbnails, self).setUp() + super().setUp() self.make_models() def test_process_document(self): diff --git a/src/documents/tests/test_matchables.py b/src/documents/tests/test_matchables.py index c12883c1f..8dc629b0b 100644 --- a/src/documents/tests/test_matchables.py +++ b/src/documents/tests/test_matchables.py @@ -36,13 +36,13 @@ class _TestMatchingBase(TestCase): doc = Document(content=string) self.assertTrue( matching.matches(instance, doc), - '"%s" should match "%s" but it does not' % (match_text, string), + f'"{match_text}" should match "{string}" but it does not', ) for string in no_match: doc = Document(content=string) self.assertFalse( matching.matches(instance, doc), - '"%s" should not match "%s" but it does' % (match_text, string), + f'"{match_text}" should not match "{string}" but it does', ) diff --git a/src/documents/tests/test_migration_archive_files.py b/src/documents/tests/test_migration_archive_files.py index 1cb088185..ae76f0f81 100644 --- a/src/documents/tests/test_migration_archive_files.py +++ b/src/documents/tests/test_migration_archive_files.py @@ -22,7 +22,7 @@ def archive_path_old(self): if self.filename: fname = archive_name_from_filename(self.filename) else: - fname = "{:07}.pdf".format(self.pk) + fname = f"{self.pk:07}.pdf" return os.path.join(settings.ARCHIVE_DIR, fname) @@ -38,7 +38,7 @@ def source_path(doc): if doc.filename: fname = str(doc.filename) else: - fname = "{:07}{}".format(doc.pk, doc.file_type) + fname = f"{doc.pk:07}{doc.file_type}" if doc.storage_type == STORAGE_TYPE_GPG: fname += ".gpg" # pragma: no cover @@ -46,7 +46,7 @@ def source_path(doc): def thumbnail_path(doc): - file_name = "{:07}.png".format(doc.pk) + file_name = f"{doc.pk:07}.png" if doc.storage_type == STORAGE_TYPE_GPG: file_name += ".gpg" diff --git a/src/documents/tests/test_migration_mime_type.py b/src/documents/tests/test_migration_mime_type.py index a08c3d74d..7b607a0cf 100644 --- a/src/documents/tests/test_migration_mime_type.py +++ b/src/documents/tests/test_migration_mime_type.py @@ -15,7 +15,7 @@ def source_path_before(self): if self.filename: fname = str(self.filename) else: - fname = "{:07}.{}".format(self.pk, self.file_type) + fname = f"{self.pk:07}.{self.file_type}" if self.storage_type == STORAGE_TYPE_GPG: fname += ".gpg" @@ -30,7 +30,7 @@ def source_path_after(doc): if doc.filename: fname = str(doc.filename) else: - fname = "{:07}{}".format(doc.pk, file_type_after(doc)) + fname = f"{doc.pk:07}{file_type_after(doc)}" if doc.storage_type == STORAGE_TYPE_GPG: fname += ".gpg" # pragma: no cover diff --git a/src/documents/tests/test_parsers.py b/src/documents/tests/test_parsers.py index ab0311783..34711bca8 100644 --- a/src/documents/tests/test_parsers.py +++ b/src/documents/tests/test_parsers.py @@ -31,7 +31,7 @@ def fake_magic_from_file(file, mime=False): class TestParserDiscovery(TestCase): @mock.patch("documents.parsers.document_consumer_declaration.send") def test__get_parser_class_1_parser(self, m, *args): - class DummyParser(object): + class DummyParser: pass m.return_value = ( @@ -49,10 +49,10 @@ class TestParserDiscovery(TestCase): @mock.patch("documents.parsers.document_consumer_declaration.send") def test__get_parser_class_n_parsers(self, m, *args): - class DummyParser1(object): + class DummyParser1: pass - class DummyParser2(object): + class DummyParser2: pass m.return_value = ( diff --git a/src/documents/tests/utils.py b/src/documents/tests/utils.py index f4d3bee87..26ccf4991 100644 --- a/src/documents/tests/utils.py +++ b/src/documents/tests/utils.py @@ -76,10 +76,10 @@ class DirectoriesMixin: def setUp(self) -> None: self.dirs = setup_directories() - super(DirectoriesMixin, self).setUp() + super().setUp() def tearDown(self) -> None: - super(DirectoriesMixin, self).tearDown() + super().tearDown() remove_dirs(self.dirs) @@ -93,7 +93,7 @@ class TestMigrations(TransactionTestCase): auto_migrate = True def setUp(self): - super(TestMigrations, self).setUp() + super().setUp() assert ( self.migrate_from and self.migrate_to diff --git a/src/documents/views.py b/src/documents/views.py index d29802394..f43581550 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -210,7 +210,7 @@ class DocumentViewSet( return serializer_class(*args, **kwargs) def update(self, request, *args, **kwargs): - response = super(DocumentViewSet, self).update(request, *args, **kwargs) + response = super().update(request, *args, **kwargs) from documents import index index.add_or_update_document(self.get_object()) @@ -220,7 +220,7 @@ class DocumentViewSet( from documents import index index.remove_document_from_index(self.get_object()) - return super(DocumentViewSet, self).destroy(request, *args, **kwargs) + return super().destroy(request, *args, **kwargs) @staticmethod def original_requested(request): @@ -362,7 +362,7 @@ class DocumentViewSet( class SearchResultSerializer(DocumentSerializer): def to_representation(self, instance): doc = Document.objects.get(id=instance["id"]) - r = super(SearchResultSerializer, self).to_representation(doc) + r = super().to_representation(doc) r["__search_hit__"] = { "score": instance.score, "highlights": instance.highlights("content", text=doc.content) @@ -376,7 +376,7 @@ class SearchResultSerializer(DocumentSerializer): class UnifiedSearchViewSet(DocumentViewSet): def __init__(self, *args, **kwargs): - super(UnifiedSearchViewSet, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.searcher = None def get_serializer_class(self): @@ -408,7 +408,7 @@ class UnifiedSearchViewSet(DocumentViewSet): self.paginator.get_page_size(self.request), ) else: - return super(UnifiedSearchViewSet, self).filter_queryset(queryset) + return super().filter_queryset(queryset) def list(self, request, *args, **kwargs): if self._is_search_request(): @@ -417,13 +417,13 @@ class UnifiedSearchViewSet(DocumentViewSet): try: with index.open_index_searcher() as s: self.searcher = s - return super(UnifiedSearchViewSet, self).list(request) + return super().list(request) except NotFound: raise except Exception as e: return HttpResponseBadRequest(str(e)) else: - return super(UnifiedSearchViewSet, self).list(request) + return super().list(request) class LogViewSet(ViewSet): @@ -441,7 +441,7 @@ class LogViewSet(ViewSet): if not os.path.isfile(filename): raise Http404() - with open(filename, "r") as f: + with open(filename) as f: lines = [line.rstrip() for line in f.readlines()] return Response(lines) diff --git a/src/paperless/auth.py b/src/paperless/auth.py index 86f428518..368d3e47b 100644 --- a/src/paperless/auth.py +++ b/src/paperless/auth.py @@ -27,7 +27,7 @@ class AngularApiAuthenticationOverride(authentication.BaseAuthentication): and request.headers["Referer"].startswith("http://localhost:4200/") ): user = User.objects.filter(is_staff=True).first() - print("Auto-Login with user {}".format(user)) + print(f"Auto-Login with user {user}") return (user, None) else: return None diff --git a/src/paperless_mail/tests/test_mail.py b/src/paperless_mail/tests/test_mail.py index b076d9e30..24014b4dc 100644 --- a/src/paperless_mail/tests/test_mail.py +++ b/src/paperless_mail/tests/test_mail.py @@ -28,7 +28,7 @@ from paperless_mail.models import MailRule @dataclasses.dataclass -class _AttachmentDef(object): +class _AttachmentDef: filename: str = "a_file.pdf" maintype: str = "application/pdf" subtype: str = "pdf" @@ -45,7 +45,7 @@ class BogusFolderManager: self.current_folder = new_folder -class BogusClient(object): +class BogusClient: def authenticate(self, mechanism, authobject): # authobject must be a callable object auth_bytes = authobject(None) @@ -205,7 +205,7 @@ class TestMail(DirectoriesMixin, TestCase): self.reset_bogus_mailbox() self.mail_account_handler = MailAccountHandler() - super(TestMail, self).setUp() + super().setUp() def reset_bogus_mailbox(self): self.bogus_mailbox.messages = [] @@ -473,7 +473,7 @@ class TestMail(DirectoriesMixin, TestCase): self.assertEqual(result, len(matches), f"Error with pattern: {pattern}") filenames = sorted( - [a[1]["override_filename"] for a in self.async_task.call_args_list], + a[1]["override_filename"] for a in self.async_task.call_args_list ) self.assertListEqual(filenames, matches) diff --git a/src/paperless_tesseract/parsers.py b/src/paperless_tesseract/parsers.py index 4b1049566..56313c5b4 100644 --- a/src/paperless_tesseract/parsers.py +++ b/src/paperless_tesseract/parsers.py @@ -98,7 +98,7 @@ class RasterisedDocumentParser(DocumentParser): def extract_text(self, sidecar_file, pdf_file): if sidecar_file and os.path.isfile(sidecar_file): - with open(sidecar_file, "r") as f: + with open(sidecar_file) as f: text = f.read() if "[OCR skipped on page" not in text: diff --git a/src/paperless_text/parsers.py b/src/paperless_text/parsers.py index 2e002457e..9ef5fec40 100644 --- a/src/paperless_text/parsers.py +++ b/src/paperless_text/parsers.py @@ -18,7 +18,7 @@ class TextDocumentParser(DocumentParser): def get_thumbnail(self, document_path, mime_type, file_name=None): def read_text(): - with open(document_path, "r") as src: + with open(document_path) as src: lines = [line.strip() for line in src.readlines()] text = "\n".join(lines[:50]) return text @@ -38,5 +38,5 @@ class TextDocumentParser(DocumentParser): return out_path def parse(self, document_path, mime_type, file_name=None): - with open(document_path, "r") as f: + with open(document_path) as f: self.text = f.read()