bug: False positive "Parameter does not appear in function signature" with typing.dataclass_transform
Description of the bug
PEP681 introduced dataclass_transform, a decorator for marking objects with dataclass-like behavior, available in python3.11+.
Griffe incorrectly warns about missing parameters of such objects' docstrings.
To Reproduce
# helloclass.py
from dataclasses import dataclass
from typing import dataclass_transform
@dataclass_transform()
class HelloDataClass:
"""A dataclass which says 'Hello' on creation."""
def __init_subclass__(cls) -> None:
"""Say hello."""
print("Hello")
dataclass(cls)
class HelloPerson(HelloDataClass):
"""A person with name and age.
Parameters
----------
name : str
age : int
"""
name: str
age: int
# mkdocs.yaml
site_name: hello
nav:
- Home: index.md
plugins:
- mkdocstrings:
default_handler: python
handlers:
python:
options:
docstring_style: numpy
<!-- docs/index.md -->
::: helloclass
Full traceback
$ mkdocs build
INFO - Cleaning site directory
INFO - Building documentation to directory: /tmp/site
WARNING - griffe: helloclass.py:21: Parameter 'name' does not appear in the
function signature
WARNING - griffe: helloclass.py:21: Parameter 'age' does not appear in the
function signature
INFO - Documentation built in 0.21 seconds
Expected behavior
A class which inherits from a base decorated with dataclass_transform, or itself decorated by a decorator decorated by dataclass_transform, should not warn about missing parameters in function signature.
Hi @bessman, thanks for the report!
Aahhh... more dynamic stuff to handle statically :sweat_smile:
In this case, things get hairy. This will probably require a new built-in extension. The extension will have to:
- find classes decorated with
@dataclass_transform - then find classes that inherit from such classes (directly or indirectly)
- and run the built-in
dataclassesextension onto them somehow
Well, it would be nice if we could reuse code, but that might prove difficult.
Also, I see you call dataclasses.dataclass(cls): what if you called pydantic.dataclasses.dataclass(cls) instead, or any other dataclass-like transform? This will be impossible to detect statically unfortunately. So, what should we do? Always default to considering the inheriting classes to be standard dataclasses.dataclass? What else can we do without forcing devs to add additional metadata just for Griffe?
The alternative is always to fallback onto dynamic analysis for these objects: https://mkdocstrings.github.io/griffe/guide/users/how-to/selectively-inspect/.
I'll mark this as a feature rather than a bug. Griffe does not claim to support the whole standard library or all PEPs: that's only a goal :slightly_smiling_face: