mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -05:00
Removes support for Python 3.8 and lower from the code base
This commit is contained in:

committed by
Trenton H

parent
c8bfbb9315
commit
650c816a7b
@@ -2,9 +2,7 @@ import logging
|
||||
import tempfile
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
from typing import Final
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
from django.conf import settings
|
||||
@@ -53,7 +51,7 @@ class BarcodeReader:
|
||||
self.file: Final[Path] = filepath
|
||||
self.mime: Final[str] = mime_type
|
||||
self.pdf_file: Path = self.file
|
||||
self.barcodes: List[Barcode] = []
|
||||
self.barcodes: list[Barcode] = []
|
||||
self.temp_dir: Optional[tempfile.TemporaryDirectory] = None
|
||||
|
||||
if settings.CONSUMER_BARCODE_TIFF_SUPPORT:
|
||||
@@ -111,7 +109,7 @@ class BarcodeReader:
|
||||
return asn
|
||||
|
||||
@staticmethod
|
||||
def read_barcodes_zxing(image: Image) -> List[str]:
|
||||
def read_barcodes_zxing(image: Image) -> list[str]:
|
||||
barcodes = []
|
||||
|
||||
import zxingcpp
|
||||
@@ -127,7 +125,7 @@ class BarcodeReader:
|
||||
return barcodes
|
||||
|
||||
@staticmethod
|
||||
def read_barcodes_pyzbar(image: Image) -> List[str]:
|
||||
def read_barcodes_pyzbar(image: Image) -> list[str]:
|
||||
barcodes = []
|
||||
|
||||
from pyzbar import pyzbar
|
||||
@@ -209,7 +207,7 @@ class BarcodeReader:
|
||||
f"Exception during barcode scanning: {e}",
|
||||
)
|
||||
|
||||
def get_separation_pages(self) -> Dict[int, bool]:
|
||||
def get_separation_pages(self) -> dict[int, bool]:
|
||||
"""
|
||||
Search the parsed barcodes for separators and returns a dict of page
|
||||
numbers, which separate the file into new files, together with the
|
||||
@@ -228,7 +226,7 @@ class BarcodeReader:
|
||||
**{bc.page: True for bc in self.barcodes if bc.is_asn and bc.page != 0},
|
||||
}
|
||||
|
||||
def separate_pages(self, pages_to_split_on: Dict[int, bool]) -> List[Path]:
|
||||
def separate_pages(self, pages_to_split_on: dict[int, bool]) -> list[Path]:
|
||||
"""
|
||||
Separate the provided pdf file on the pages_to_split_on.
|
||||
The pages which are defined by the keys in page_numbers
|
||||
@@ -241,9 +239,9 @@ class BarcodeReader:
|
||||
fname = self.file.with_suffix("").name
|
||||
with Pdf.open(self.pdf_file) as input_pdf:
|
||||
# Start with an empty document
|
||||
current_document: List[Page] = []
|
||||
current_document: list[Page] = []
|
||||
# A list of documents, ie a list of lists of pages
|
||||
documents: List[List[Page]] = [current_document]
|
||||
documents: list[list[Page]] = [current_document]
|
||||
|
||||
for idx, page in enumerate(input_pdf.pages):
|
||||
# Keep building the new PDF as long as it is not a
|
||||
|
@@ -3,11 +3,10 @@ import os
|
||||
import pickle
|
||||
import re
|
||||
import warnings
|
||||
from collections.abc import Iterator
|
||||
from datetime import datetime
|
||||
from hashlib import sha256
|
||||
from pathlib import Path
|
||||
from typing import Iterator
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
from django.conf import settings
|
||||
@@ -357,7 +356,7 @@ class DocumentClassifier:
|
||||
|
||||
# Tokenize
|
||||
# This splits the content into tokens, roughly words
|
||||
words: List[str] = word_tokenize(
|
||||
words: list[str] = word_tokenize(
|
||||
content,
|
||||
language=settings.NLTK_LANGUAGE,
|
||||
)
|
||||
@@ -404,7 +403,7 @@ class DocumentClassifier:
|
||||
else:
|
||||
return None
|
||||
|
||||
def predict_tags(self, content: str) -> List[int]:
|
||||
def predict_tags(self, content: str) -> list[int]:
|
||||
from sklearn.utils.multiclass import type_of_target
|
||||
|
||||
if self.tags_classifier:
|
||||
|
@@ -8,7 +8,6 @@ from pathlib import Path
|
||||
from subprocess import CompletedProcess
|
||||
from subprocess import run
|
||||
from typing import Optional
|
||||
from typing import Type
|
||||
|
||||
import magic
|
||||
from asgiref.sync import async_to_sync
|
||||
@@ -372,7 +371,7 @@ class Consumer(LoggingMixin):
|
||||
self.log.debug(f"Detected mime type: {mime_type}")
|
||||
|
||||
# Based on the mime type, get the parser for that type
|
||||
parser_class: Optional[Type[DocumentParser]] = get_parser_class_for_mime_type(
|
||||
parser_class: Optional[type[DocumentParser]] = get_parser_class_for_mime_type(
|
||||
mime_type,
|
||||
)
|
||||
if not parser_class:
|
||||
|
@@ -2,7 +2,6 @@ import dataclasses
|
||||
import datetime
|
||||
import enum
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
import magic
|
||||
@@ -20,7 +19,7 @@ class DocumentMetadataOverrides:
|
||||
title: Optional[str] = None
|
||||
correspondent_id: Optional[int] = None
|
||||
document_type_id: Optional[int] = None
|
||||
tag_ids: Optional[List[int]] = None
|
||||
tag_ids: Optional[list[int]] = None
|
||||
created: Optional[datetime.datetime] = None
|
||||
asn: Optional[int] = None
|
||||
owner_id: Optional[int] = None
|
||||
|
@@ -115,12 +115,10 @@ def collate(input_doc: ConsumableDocument) -> str:
|
||||
staging.unlink()
|
||||
|
||||
else:
|
||||
# In Python 3.9 move supports Path objects directly,
|
||||
# but for now we have to be compatible with 3.8
|
||||
shutil.move(str(pdf_file), str(staging))
|
||||
shutil.move(pdf_file, staging)
|
||||
# update access to modification time so we know if the file
|
||||
# is outdated when another file gets uploaded
|
||||
os.utime(str(staging), (dt.datetime.now().timestamp(),) * 2)
|
||||
os.utime(staging, (dt.datetime.now().timestamp(),) * 2)
|
||||
logger.info(
|
||||
"Got scan with odd numbered pages of double-sided scan, moved it to %s",
|
||||
staging,
|
||||
|
@@ -8,7 +8,6 @@ from threading import Event
|
||||
from time import monotonic
|
||||
from time import sleep
|
||||
from typing import Final
|
||||
from typing import Set
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
@@ -32,7 +31,7 @@ except ImportError: # pragma: nocover
|
||||
logger = logging.getLogger("paperless.management.consumer")
|
||||
|
||||
|
||||
def _tags_from_path(filepath) -> Set[Tag]:
|
||||
def _tags_from_path(filepath) -> set[Tag]:
|
||||
"""
|
||||
Walk up the directory tree from filepath to CONSUMPTION_DIR
|
||||
and get or create Tag IDs for every directory.
|
||||
|
@@ -5,8 +5,6 @@ import shutil
|
||||
import tempfile
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
from typing import Set
|
||||
|
||||
import tqdm
|
||||
from django.conf import settings
|
||||
@@ -138,8 +136,8 @@ class Command(BaseCommand):
|
||||
BaseCommand.__init__(self, *args, **kwargs)
|
||||
self.target: Path = None
|
||||
self.split_manifest = False
|
||||
self.files_in_export_dir: Set[Path] = set()
|
||||
self.exported_files: List[Path] = []
|
||||
self.files_in_export_dir: set[Path] = set()
|
||||
self.exported_files: list[Path] = []
|
||||
self.compare_checksums = False
|
||||
self.use_filename_format = False
|
||||
self.use_folder_prefix = False
|
||||
|
@@ -6,12 +6,11 @@ import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
from collections.abc import Iterator
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Iterator
|
||||
from typing import Match
|
||||
from re import Match
|
||||
from typing import Optional
|
||||
from typing import Set
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
@@ -90,7 +89,7 @@ def is_file_ext_supported(ext: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def get_supported_file_extensions() -> Set[str]:
|
||||
def get_supported_file_extensions() -> set[str]:
|
||||
extensions = set()
|
||||
for response in document_consumer_declaration.send(None):
|
||||
parser_declaration = response[1]
|
||||
|
@@ -1,14 +1,10 @@
|
||||
import datetime
|
||||
import math
|
||||
import re
|
||||
import zoneinfo
|
||||
|
||||
from celery import states
|
||||
|
||||
try:
|
||||
import zoneinfo
|
||||
except ImportError:
|
||||
from backports import zoneinfo
|
||||
import magic
|
||||
from celery import states
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import Group
|
||||
from django.contrib.auth.models import User
|
||||
|
@@ -3,7 +3,6 @@ import logging
|
||||
import shutil
|
||||
import uuid
|
||||
from typing import Optional
|
||||
from typing import Type
|
||||
|
||||
import tqdm
|
||||
from asgiref.sync import async_to_sync
|
||||
@@ -216,7 +215,7 @@ def update_document_archive_file(document_id):
|
||||
|
||||
mime_type = document.mime_type
|
||||
|
||||
parser_class: Type[DocumentParser] = get_parser_class_for_mime_type(mime_type)
|
||||
parser_class: type[DocumentParser] = get_parser_class_for_mime_type(mime_type)
|
||||
|
||||
if not parser_class:
|
||||
logger.error(
|
||||
|
@@ -7,18 +7,13 @@ import tempfile
|
||||
import urllib.request
|
||||
import uuid
|
||||
import zipfile
|
||||
import zoneinfo
|
||||
from datetime import timedelta
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import celery
|
||||
|
||||
try:
|
||||
import zoneinfo
|
||||
except ImportError:
|
||||
from backports import zoneinfo
|
||||
|
||||
import pytest
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from django.conf import settings
|
||||
|
@@ -5,16 +5,11 @@ import shutil
|
||||
import stat
|
||||
import tempfile
|
||||
import uuid
|
||||
import zoneinfo
|
||||
from unittest import mock
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from dateutil import tz
|
||||
|
||||
try:
|
||||
import zoneinfo
|
||||
except ImportError:
|
||||
from backports import zoneinfo
|
||||
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.test import override_settings
|
||||
|
@@ -1,13 +1,9 @@
|
||||
import shutil
|
||||
import tempfile
|
||||
import zoneinfo
|
||||
from pathlib import Path
|
||||
from unittest import mock
|
||||
|
||||
try:
|
||||
import zoneinfo
|
||||
except ImportError:
|
||||
from backports import zoneinfo
|
||||
|
||||
from django.test import TestCase
|
||||
from django.test import override_settings
|
||||
from django.utils import timezone
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import shutil
|
||||
import tempfile
|
||||
from collections.abc import Iterable
|
||||
from random import randint
|
||||
from typing import Iterable
|
||||
|
||||
from django.contrib.admin.models import LogEntry
|
||||
from django.contrib.auth.models import User
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import importlib
|
||||
import shutil
|
||||
import tempfile
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
from typing import Iterable
|
||||
from typing import Union
|
||||
from unittest import mock
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
import importlib
|
||||
import shutil
|
||||
import tempfile
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
from typing import Iterable
|
||||
from typing import Union
|
||||
from unittest import mock
|
||||
|
||||
|
@@ -3,14 +3,12 @@ import tempfile
|
||||
import time
|
||||
import warnings
|
||||
from collections import namedtuple
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
from os import PathLike
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Callable
|
||||
from typing import Iterator
|
||||
from typing import List
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
from unittest import mock
|
||||
|
||||
@@ -88,10 +86,10 @@ def paperless_environment():
|
||||
|
||||
def util_call_with_backoff(
|
||||
method_or_callable: Callable,
|
||||
args: Union[List, Tuple],
|
||||
args: Union[list, tuple],
|
||||
*,
|
||||
skip_on_50x_err=True,
|
||||
) -> Tuple[bool, Any]:
|
||||
) -> tuple[bool, Any]:
|
||||
"""
|
||||
For whatever reason, the images started during the test pipeline like to
|
||||
segfault sometimes, crash and otherwise fail randomly, when run with the
|
||||
@@ -219,7 +217,7 @@ class DocumentConsumeDelayMixin:
|
||||
|
||||
def get_last_consume_delay_call_args(
|
||||
self,
|
||||
) -> Tuple[ConsumableDocument, DocumentMetadataOverrides]:
|
||||
) -> tuple[ConsumableDocument, DocumentMetadataOverrides]:
|
||||
"""
|
||||
Returns the most recent arguments to the async task
|
||||
"""
|
||||
@@ -233,7 +231,7 @@ class DocumentConsumeDelayMixin:
|
||||
|
||||
def get_all_consume_delay_call_args(
|
||||
self,
|
||||
) -> Iterator[Tuple[ConsumableDocument, DocumentMetadataOverrides]]:
|
||||
) -> Iterator[tuple[ConsumableDocument, DocumentMetadataOverrides]]:
|
||||
"""
|
||||
Iterates over all calls to the async task and returns the arguments
|
||||
"""
|
||||
@@ -246,7 +244,7 @@ class DocumentConsumeDelayMixin:
|
||||
def get_specific_consume_delay_call_args(
|
||||
self,
|
||||
index: int,
|
||||
) -> Iterator[Tuple[ConsumableDocument, DocumentMetadataOverrides]]:
|
||||
) -> Iterator[tuple[ConsumableDocument, DocumentMetadataOverrides]]:
|
||||
"""
|
||||
Returns the arguments of a specific call to the async task
|
||||
"""
|
||||
|
@@ -1,14 +1,13 @@
|
||||
import shutil
|
||||
from os import utime
|
||||
from pathlib import Path
|
||||
from typing import Tuple
|
||||
from typing import Union
|
||||
|
||||
|
||||
def _coerce_to_path(
|
||||
source: Union[Path, str],
|
||||
dest: Union[Path, str],
|
||||
) -> Tuple[Path, Path]:
|
||||
) -> tuple[Path, Path]:
|
||||
return Path(source).resolve(), Path(dest).resolve()
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user