Skip to content

Commit 239cc7b

Browse files
fajpunkaeisenbarthpre-commit-ci[bot]
authored
Warning types and subtypes (#562)
Co-authored-by: aeisenbarth <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 22ccfb9 commit 239cc7b

File tree

3 files changed

+74
-16
lines changed

3 files changed

+74
-16
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ The following configuration options are accepted:
8989
code or `None` to fall back to the default formatter.
9090
- `typehints_use_signature` (default: `False`): If `True`, typehints for parameters in the signature are shown.
9191
- `typehints_use_signature_return` (default: `False`): If `True`, return annotations in the signature are shown.
92+
- `suppress_warnings`: sphinx-autodoc-typehints supports to suppress warning messages via Sphinx's `suppress_warnings`. It allows following additional warning types:
93+
- `sphinx_autodoc_typehints`
94+
- `sphinx_autodoc_typehints.comment`
95+
- `sphinx_autodoc_typehints.forward_reference`
96+
- `sphinx_autodoc_typehints.guarded_import`
97+
- `sphinx_autodoc_typehints.local_function`
98+
- `sphinx_autodoc_typehints.multiple_ast_nodes`
9299

93100
## How it works
94101

src/sphinx_autodoc_typehints/__init__.py

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,12 @@ def _get_formatted_annotation(annotation: TypeVar) -> TypeVar:
407407
elif what == "method":
408408
# bail if it is a local method as we cannot determine if first argument needs to be deleted or not
409409
if "<locals>" in obj.__qualname__ and not _is_dataclass(name, what, obj.__qualname__):
410-
_LOGGER.warning('Cannot handle as a local function: "%s" (use @functools.wraps)', name)
410+
_LOGGER.warning(
411+
'Cannot handle as a local function: "%s" (use @functools.wraps)',
412+
name,
413+
type="sphinx_autodoc_typehints",
414+
subtype="local_function",
415+
)
411416
return None
412417
outer = inspect.getmodule(obj)
413418
for class_name in obj.__qualname__.split(".")[:-1]:
@@ -500,7 +505,9 @@ def _execute_guarded_code(autodoc_mock_imports: list[str], obj: Any, module_code
500505
with mock(autodoc_mock_imports):
501506
exec(guarded_code, getattr(obj, "__globals__", obj.__dict__)) # noqa: S102
502507
except Exception as exc: # noqa: BLE001
503-
_LOGGER.warning("Failed guarded type import with %r", exc)
508+
_LOGGER.warning(
509+
"Failed guarded type import with %r", exc, type="sphinx_autodoc_typehints", subtype="guarded_import"
510+
)
504511

505512

506513
def _resolve_type_guarded_imports(autodoc_mock_imports: list[str], obj: Any) -> None:
@@ -536,7 +543,13 @@ def _get_type_hint(
536543
else:
537544
result = {}
538545
except NameError as exc:
539-
_LOGGER.warning('Cannot resolve forward reference in type annotations of "%s": %s', name, exc)
546+
_LOGGER.warning(
547+
'Cannot resolve forward reference in type annotations of "%s": %s',
548+
name,
549+
exc,
550+
type="sphinx_autodoc_typehints",
551+
subtype="forward_reference",
552+
)
540553
result = obj.__annotations__
541554
return result
542555

@@ -554,7 +567,13 @@ def backfill_type_hints(obj: Any, name: str) -> dict[str, Any]: # noqa: C901, P
554567
def _one_child(module: Module) -> stmt | None:
555568
children = module.body # use the body to ignore type comments
556569
if len(children) != 1:
557-
_LOGGER.warning('Did not get exactly one node from AST for "%s", got %s', name, len(children))
570+
_LOGGER.warning(
571+
'Did not get exactly one node from AST for "%s", got %s',
572+
name,
573+
len(children),
574+
type="sphinx_autodoc_typehints",
575+
subtype="multiple_ast_nodes",
576+
)
558577
return None
559578
return children[0]
560579

@@ -579,7 +598,12 @@ def _one_child(module: Module) -> stmt | None:
579598
try:
580599
comment_args_str, comment_returns = type_comment.split(" -> ")
581600
except ValueError:
582-
_LOGGER.warning('Unparseable type hint comment for "%s": Expected to contain ` -> `', name)
601+
_LOGGER.warning(
602+
'Unparseable type hint comment for "%s": Expected to contain ` -> `',
603+
name,
604+
type="sphinx_autodoc_typehints",
605+
subtype="comment",
606+
)
583607
return {}
584608

585609
rv = {}
@@ -594,7 +618,9 @@ def _one_child(module: Module) -> stmt | None:
594618
comment_args.insert(0, None) # self/cls may be omitted in type comments, insert blank
595619

596620
if len(args) != len(comment_args):
597-
_LOGGER.warning('Not enough type comments found on "%s"', name)
621+
_LOGGER.warning(
622+
'Not enough type comments found on "%s"', name, type="sphinx_autodoc_typehints", subtype="comment"
623+
)
598624
return rv
599625

600626
for at, arg in enumerate(args):

tests/test_integration.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,28 @@
3131
W = NewType("W", str)
3232

3333

34+
@dataclass
35+
class WarningInfo:
36+
"""Properties and assertion methods for warnings."""
37+
38+
regexp: str
39+
type: str
40+
41+
def assert_regexp(self, message: str) -> None:
42+
regexp = self.regexp
43+
msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {message!r}"
44+
assert re.search(regexp, message), msg
45+
46+
def assert_type(self, message: str) -> None:
47+
expected = f"[{self.type}]"
48+
msg = f"Warning did not contain type and subtype.\n Expected: {expected}\n Input: {message}"
49+
assert expected in message, msg
50+
51+
def assert_warning(self, message: str) -> None:
52+
self.assert_regexp(message)
53+
self.assert_type(message)
54+
55+
3456
def expected(expected: str, **options: dict[str, Any]) -> Callable[[T], T]:
3557
def dec(val: T) -> T:
3658
val.EXPECTED = expected
@@ -40,9 +62,9 @@ def dec(val: T) -> T:
4062
return dec
4163

4264

43-
def warns(pattern: str) -> Callable[[T], T]:
65+
def warns(info: WarningInfo) -> Callable[[T], T]:
4466
def dec(val: T) -> T:
45-
val.WARNING = pattern
67+
val.WARNING = info
4668
return val
4769

4870
return dec
@@ -58,7 +80,7 @@ def wrapper(self) -> str: # noqa: ANN001
5880
return wrapper
5981

6082

61-
@warns("Cannot handle as a local function")
83+
@warns(WarningInfo(regexp="Cannot handle as a local function", type="sphinx_autodoc_typehints.local_function"))
6284
@expected(
6385
"""\
6486
class mod.Class(x, y, z=None)
@@ -330,7 +352,11 @@ def function_with_escaped_default(x: str = "\b"): # noqa: ANN201
330352
"""
331353

332354

333-
@warns("Cannot resolve forward reference in type annotations")
355+
@warns(
356+
WarningInfo(
357+
regexp="Cannot resolve forward reference in type annotations", type="sphinx_autodoc_typehints.forward_reference"
358+
)
359+
)
334360
@expected(
335361
"""\
336362
mod.function_with_unresolvable_annotation(x)
@@ -1196,7 +1222,7 @@ def docstring_with_enum_list_after_params(param: int) -> None:
11961222
"""
11971223

11981224

1199-
@warns("Definition list ends without a blank line")
1225+
@warns(WarningInfo(regexp="Definition list ends without a blank line", type="docutils"))
12001226
@expected(
12011227
"""
12021228
mod.docstring_with_definition_list_after_params_no_blank_line(param)
@@ -1457,7 +1483,7 @@ def has_doctest1() -> None:
14571483
Unformatted = TypeVar("Unformatted")
14581484

14591485

1460-
@warns("cannot cache unpickleable configuration value: 'typehints_formatter'")
1486+
@warns(WarningInfo(regexp="cannot cache unpickleable configuration value: 'typehints_formatter'", type="config.cache"))
14611487
@expected(
14621488
"""
14631489
mod.typehints_formatter_applied_to_signature(param: Formatted) -> Formatted
@@ -1525,11 +1551,10 @@ def test_integration(
15251551
app.build()
15261552
assert "build succeeded" in status.getvalue() # Build succeeded
15271553

1528-
regexp = getattr(val, "WARNING", None)
1554+
warning_info: Union[WarningInfo, None] = getattr(val, "WARNING", None)
15291555
value = warning.getvalue().strip()
1530-
if regexp:
1531-
msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}"
1532-
assert re.search(regexp, value), msg
1556+
if warning_info:
1557+
warning_info.assert_warning(value)
15331558
else:
15341559
assert not value
15351560

0 commit comments

Comments
 (0)