From e0fdf1caa9229901a07f56f622bdb5105302ed1a Mon Sep 17 00:00:00 2001 From: Trenton H <797416+stumpylog@users.noreply.github.com> Date: Wed, 28 Jan 2026 15:19:22 -0800 Subject: [PATCH] Adds example type checking configuration, with a default broard ignore and a tight scoped check --- pyproject.toml | 31 ++++++++++++++++--- .../test_date_parser_plugin_loading.py | 19 +++--------- .../tests/date_parsing/test_date_parsing.py | 19 ++++++++++-- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 17ca25b8c..612636dfb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -154,10 +154,6 @@ typing = [ [tool.uv] required-version = ">=0.9.0" package = false -environments = [ - "sys_platform == 'darwin'", - "sys_platform == 'linux'", -] [tool.uv.sources] # Markers are chosen to select these almost exclusively when building the Docker image @@ -333,6 +329,10 @@ exclude_also = [ [tool.mypy] mypy_path = "src" +files = [ + "src/documents/plugins/date_parsing", + "src/documents/tests/date_parsing", +] plugins = [ "mypy_django_plugin.main", "mypy_drf_plugin.main", @@ -344,5 +344,28 @@ disallow_untyped_defs = true warn_redundant_casts = true warn_unused_ignores = true +# This prevents errors from imports, but allows type-checking logic to work +follow_imports = "silent" + +[[tool.mypy.overrides]] +module = [ + "documents.*", + "paperless.*", + "paperless_ai.*", + "paperless_mail.*", + "paperless_tesseract.*", + "paperless_remote.*", + "paperless_text.*", + "paperless_tika.*", +] +ignore_errors = true + +[[tool.mypy.overrides]] +module = [ + "documents.plugins.date_parsing.*", + "documents.tests.date_parsing.*", +] +ignore_errors = false + [tool.django-stubs] django_settings_module = "paperless.settings" diff --git a/src/documents/tests/date_parsing/test_date_parser_plugin_loading.py b/src/documents/tests/date_parsing/test_date_parser_plugin_loading.py index 9da939a76..cc9411d52 100644 --- a/src/documents/tests/date_parsing/test_date_parser_plugin_loading.py +++ b/src/documents/tests/date_parsing/test_date_parser_plugin_loading.py @@ -2,7 +2,6 @@ import datetime import logging from collections.abc import Iterator from importlib.metadata import EntryPoint -from pathlib import Path import pytest import pytest_mock @@ -17,12 +16,12 @@ from documents.plugins.date_parsing.regex_parser import RegexDateParserPlugin class AlphaParser(DateParserPluginBase): - def parse(self, filename: Path, content: str) -> Iterator[datetime.datetime]: + def parse(self, filename: str, content: str) -> Iterator[datetime.datetime]: yield timezone.now() class BetaParser(DateParserPluginBase): - def parse(self, filename: Path, content: str) -> Iterator[datetime.datetime]: + def parse(self, filename: str, content: str) -> Iterator[datetime.datetime]: yield timezone.now() @@ -98,17 +97,9 @@ class TestDiscoverParserClass: ) -> None: """If exactly one valid plugin is discovered, it should be returned without logging a warning.""" - class AlphaPlugin(DateParserPluginBase): - def parse( - self, - filename: Path, - content: str, - ) -> Iterator[datetime.datetime]: - yield timezone.now() - ep = mocker.MagicMock(spec=EntryPoint) ep.name = "alpha" - ep.load.return_value = AlphaPlugin + ep.load.return_value = AlphaParser mock_entry_points = mocker.patch( "documents.plugins.date_parsing.entry_points", @@ -124,8 +115,8 @@ class TestDiscoverParserClass: # It should have called entry_points with the correct group mock_entry_points.assert_called_once_with(group=DATE_PARSER_ENTRY_POINT_GROUP) - # The discovered class should be exactly our AlphaPlugin - assert result is AlphaPlugin + # The discovered class should be exactly our AlphaParser + assert result is AlphaParser # No warnings should have been logged assert not any( diff --git a/src/documents/tests/date_parsing/test_date_parsing.py b/src/documents/tests/date_parsing/test_date_parsing.py index 24002cc9b..a587b32cc 100644 --- a/src/documents/tests/date_parsing/test_date_parsing.py +++ b/src/documents/tests/date_parsing/test_date_parsing.py @@ -1,5 +1,6 @@ import datetime import logging +from typing import Any import pytest import pytest_mock @@ -261,7 +262,11 @@ class TestRegexDateParser: # Patch the dateparser.parse target = "documents.plugins.date_parsing.base.dateparser.parse" - def fake_parse(date_string: str, settings=None, locales=None): + def fake_parse( + date_string: str, + settings: dict[str, Any] | None = None, + locales: None = None, + ) -> datetime.datetime | None: date_order = settings.get("DATE_ORDER") if settings else None # Filename-style YYYY-MM-DD / YYYY.MM.DD @@ -332,7 +337,11 @@ class TestRegexDateParser: target = "documents.plugins.date_parsing.base.dateparser.parse" - def fake_parse(date_string: str, settings=None, locales=None): + def fake_parse( + date_string: str, + settings: dict[str, Any] | None = None, + locales: None = None, + ) -> datetime.datetime | None: if "10/12/2023" in date_string or "10-12-2023" in date_string: # ignored date return datetime.datetime(2023, 12, 10, tzinfo=datetime.timezone.utc) @@ -393,7 +402,11 @@ class TestRegexDateParser: # Patch the module's dateparser.parse so we can inspect calls target = "documents.plugins.date_parsing.base.dateparser.parse" - def fake_parse(date_string: str, settings=None, locales=None): + def fake_parse( + date_string: str, + settings: dict[str, Any] | None = None, + locales: None = None, + ) -> datetime.datetime | None: # return distinct datetimes so we can tell which source was parsed if "25/12/2022" in date_string: return datetime.datetime(2022, 12, 25, tzinfo=datetime.timezone.utc)