Type annotation parsing warning for Pydantic BaseModel private attributes
Problem Description
When using pdoc to generate documentation for Pydantic BaseModel classes, warnings appear about parsing type annotations for __pydantic_private__ and __pydantic_extra__ attributes. The warning indicates that a 'function' object is not subscriptable when trying to parse the type annotations dict[str, Any] | None.
This occurs even with simple Pydantic model definitions and affects the documentation generation process.
Steps to reproduce the behavior:
- Install pdoc and pydantic
- Create a Python file with the following content:
from pydantic import BaseModel
class Foo(BaseModel):
"""Test model"""
bar: int
class Bar(BaseModel):
"""Another test model"""
foo: Foo
- Run
pdoc foobar.py, warning appears:
Warn: Error parsing type annotation dict[str, Any] | None for pydantic.main.BaseModel.__pydantic_private__: 'function' object is
not subscriptable(.../lib/python3.13/site-packages/pdoc/doc_types.py:123)
Warn: Error parsing type annotation dict[str, Any] | None for pydantic.main.BaseModel.__pydantic_extra__: 'function' object is not subscriptable(.../lib/python3.13/site-packages/pdoc/doc_types.py:123)
System Information
pdoc: 15.0.1 Python: 3.13.2 Platform: macOS-10.16-x86_64-i386-64bit-Mach-O pydantic: 2.10.6
I think pydantic is mainstream enough that it's worth to support this - contributions welcome!
I notice that "normal" annotations like dict[str, Any] | None in pydantic.BaseModel-inherited classes get converted into ForwardRefs as part of pdoc.doc_types._eval_type(). This is, itself, related to the annotation getting passed into _eval_type() as a string rather than as the type-annotation type itself, e.g. <class 'types.UnionType'>.
Notably, this does not happen with, for example, with vanilla Python dataclasses.
Could be worth looking into why the annotations for Pydantic classes get handled as though they were strings.
I note also the following:
- Both of the problematic fields that @DawnEver cites are
dicts - There is this very relevant-sounding disclaimer in Pydantic code regarding
dictbeing in the namespace ofBaseModel-- namely, as a deprecateddict()method
Rewriting both of the offending annotations as typing.Dict[str, Any] rather than the current dict[str, Any] seems to do the trick. This suggests that the fix here should be a PR to Pydantic itself.