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]
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"

View File

@@ -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(

View File

@@ -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)