Skip to content

Commit

Permalink
Strict typing, py.typed and link issues
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasam committed Sep 18, 2024
1 parent a8b6f12 commit fd0c7b9
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 31 deletions.
17 changes: 10 additions & 7 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,6 @@
nitpicky = True
nitpick_ignore: list[tuple[str, str]] = []

nitpick_ignore = [
('py:class', '_pytest.nodes.Item'),
('py:class', 'Config'),
('py:class', 'Path'),
('py:class', 'Session'),
]

# Include Python intersphinx mapping to prevent failures
# jaraco/skeleton#51
extensions += ['sphinx.ext.intersphinx']
Expand All @@ -65,3 +58,13 @@
intersphinx_mapping.update(
pytest=('https://docs.pytest.org/en/latest/', None),
)

# local

nitpick_ignore += [
('py:class', 'Config'),
('py:class', 'Session'),
# jaraco/pytest-checkdocs#25
('py:class', 'PackageMetadata'),
('py:class', 'Node'),
]
6 changes: 5 additions & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[mypy]
# Is the project well-typed?
strict = False
strict = True

# Early opt-in even when strict = False
warn_unused_ignores = True
Expand All @@ -13,3 +13,7 @@ explicit_package_bases = True
disable_error_code =
# Disable due to many false positives
overload-overlap,

# jaraco/jaraco.packaging#20
[mypy-jaraco.packaging.*]
ignore_missing_imports = True
1 change: 1 addition & 0 deletions newsfragments/25.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Complete annotations and add ``py.typed`` marker -- by :user:`Avasam`
6 changes: 2 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ type = [

# local
"types-docutils", # pytest-checkdocs#13
"importlib_metadata; python_version < '3.12'", # Only used for annotations, not at runtime
"pytest>=8.3.3" # Typing fixes not necessary at runtime
]


Expand All @@ -73,7 +75,3 @@ pytest11 = {checkdocs = "pytest_checkdocs"}


[tool.setuptools_scm]


[tool.pytest-enabler.mypy]
# Disabled due to jaraco/skeleton#143
58 changes: 39 additions & 19 deletions pytest_checkdocs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,72 @@
from __future__ import annotations

import contextlib
import pathlib
import re
import sys
from collections.abc import Iterator
from typing import TYPE_CHECKING, Any, cast

import pytest
import docutils.core
import docutils.nodes
import docutils.utils
import pytest
from jaraco.packaging import metadata

if TYPE_CHECKING:
if sys.version_info >= (3, 12):
from importlib.metadata import PackageMetadata
else:
from importlib_metadata import PackageMetadata

from _pytest.nodes import Node
from typing_extensions import Self

project_files = 'setup.py', 'setup.cfg', 'pyproject.toml'


def pytest_collect_file(file_path: pathlib.Path, parent):
def pytest_collect_file(file_path: pathlib.Path, parent: Node) -> CheckdocsItem | None:
if file_path.name not in project_files:
return
return None
return CheckdocsItem.from_parent(parent, name='project')


class Description(str):
content_type: str = ""

@classmethod
def from_md(cls, md):
def from_md(cls, md: PackageMetadata) -> Self:
desc = cls(md.get('Description'))
desc.content_type = md.get('Description-Content-Type', 'text/x-rst')
return desc


class CheckdocsItem(pytest.Item):
def runtest(self):
def runtest(self) -> None:
desc = self.get_long_description()
method_name = f"run_{re.sub('[-/]', '_', desc.content_type)}"
getattr(self, method_name)(desc)

def run_text_markdown(self, desc):
def run_text_markdown(self, desc: str) -> None:
"stubbed"

def run_text_x_rst(self, desc):
def run_text_x_rst(self, desc: str) -> None:
with self.monkey_patch_system_message() as reports:
self.rst2html(desc)
assert not reports

@contextlib.contextmanager
def monkey_patch_system_message(self):
reports = []
def monkey_patch_system_message(self) -> Iterator[list[str | Exception]]:
reports: list[str | Exception] = []
orig = docutils.utils.Reporter.system_message

def system_message(reporter, level, message, *children, **kwargs):
def system_message(
reporter: docutils.utils.Reporter,
level: int,
message: str | Exception,
*children: docutils.nodes.Node,
**kwargs: Any,
) -> docutils.nodes.system_message:
result = orig(reporter, level, message, *children, **kwargs)
if level >= reporter.WARNING_LEVEL:
# All reST failures preventing doc publishing go to reports
Expand All @@ -52,17 +75,14 @@ def system_message(reporter, level, message, *children, **kwargs):

return result

docutils.utils.Reporter.system_message = system_message
docutils.utils.Reporter.system_message = system_message # type: ignore[assignment] # type-stubs expands the kwargs
yield reports
docutils.utils.Reporter.system_message = orig
docutils.utils.Reporter.system_message = orig # type: ignore[method-assign]

def get_long_description(self):
def get_long_description(self) -> Description:
return Description.from_md(metadata.load('.'))

@staticmethod
def rst2html(value):
docutils_settings = {}
parts = docutils.core.publish_parts(
source=value, writer_name="html4css1", settings_overrides=docutils_settings
)
return parts['whole']
def rst2html(value: str) -> str:
parts = docutils.core.publish_parts(source=value, writer_name="html4css1")
return parts['whole'] # type: ignore[no-any-return] # python/typeshed#12595
Empty file added pytest_checkdocs/py.typed
Empty file.

0 comments on commit fd0c7b9

Please sign in to comment.