Adds example type checking configuration, with a default broard ignore and a tight scoped check

This commit is contained in:
Trenton H
2026-01-28 15:19:22 -08:00
parent f80ae51a7d
commit e0fdf1caa9
3 changed files with 48 additions and 21 deletions

View File

@@ -154,10 +154,6 @@ typing = [
[tool.uv] [tool.uv]
required-version = ">=0.9.0" required-version = ">=0.9.0"
package = false package = false
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
]
[tool.uv.sources] [tool.uv.sources]
# Markers are chosen to select these almost exclusively when building the Docker image # Markers are chosen to select these almost exclusively when building the Docker image
@@ -333,6 +329,10 @@ exclude_also = [
[tool.mypy] [tool.mypy]
mypy_path = "src" mypy_path = "src"
files = [
"src/documents/plugins/date_parsing",
"src/documents/tests/date_parsing",
]
plugins = [ plugins = [
"mypy_django_plugin.main", "mypy_django_plugin.main",
"mypy_drf_plugin.main", "mypy_drf_plugin.main",
@@ -344,5 +344,28 @@ disallow_untyped_defs = true
warn_redundant_casts = true warn_redundant_casts = true
warn_unused_ignores = 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] [tool.django-stubs]
django_settings_module = "paperless.settings" django_settings_module = "paperless.settings"

View File

@@ -2,7 +2,6 @@ import datetime
import logging import logging
from collections.abc import Iterator from collections.abc import Iterator
from importlib.metadata import EntryPoint from importlib.metadata import EntryPoint
from pathlib import Path
import pytest import pytest
import pytest_mock import pytest_mock
@@ -17,12 +16,12 @@ from documents.plugins.date_parsing.regex_parser import RegexDateParserPlugin
class AlphaParser(DateParserPluginBase): 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() yield timezone.now()
class BetaParser(DateParserPluginBase): 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() yield timezone.now()
@@ -98,17 +97,9 @@ class TestDiscoverParserClass:
) -> None: ) -> None:
"""If exactly one valid plugin is discovered, it should be returned without logging a warning.""" """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 = mocker.MagicMock(spec=EntryPoint)
ep.name = "alpha" ep.name = "alpha"
ep.load.return_value = AlphaPlugin ep.load.return_value = AlphaParser
mock_entry_points = mocker.patch( mock_entry_points = mocker.patch(
"documents.plugins.date_parsing.entry_points", "documents.plugins.date_parsing.entry_points",
@@ -124,8 +115,8 @@ class TestDiscoverParserClass:
# It should have called entry_points with the correct group # It should have called entry_points with the correct group
mock_entry_points.assert_called_once_with(group=DATE_PARSER_ENTRY_POINT_GROUP) mock_entry_points.assert_called_once_with(group=DATE_PARSER_ENTRY_POINT_GROUP)
# The discovered class should be exactly our AlphaPlugin # The discovered class should be exactly our AlphaParser
assert result is AlphaPlugin assert result is AlphaParser
# No warnings should have been logged # No warnings should have been logged
assert not any( assert not any(

View File

@@ -1,5 +1,6 @@
import datetime import datetime
import logging import logging
from typing import Any
import pytest import pytest
import pytest_mock import pytest_mock
@@ -261,7 +262,11 @@ class TestRegexDateParser:
# Patch the dateparser.parse # Patch the dateparser.parse
target = "documents.plugins.date_parsing.base.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 date_order = settings.get("DATE_ORDER") if settings else None
# Filename-style YYYY-MM-DD / YYYY.MM.DD # Filename-style YYYY-MM-DD / YYYY.MM.DD
@@ -332,7 +337,11 @@ class TestRegexDateParser:
target = "documents.plugins.date_parsing.base.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:
if "10/12/2023" in date_string or "10-12-2023" in date_string: if "10/12/2023" in date_string or "10-12-2023" in date_string:
# ignored date # ignored date
return datetime.datetime(2023, 12, 10, tzinfo=datetime.timezone.utc) 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 # Patch the module's dateparser.parse so we can inspect calls
target = "documents.plugins.date_parsing.base.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:
# return distinct datetimes so we can tell which source was parsed # return distinct datetimes so we can tell which source was parsed
if "25/12/2022" in date_string: if "25/12/2022" in date_string:
return datetime.datetime(2022, 12, 25, tzinfo=datetime.timezone.utc) return datetime.datetime(2022, 12, 25, tzinfo=datetime.timezone.utc)