pdoc icon indicating copy to clipboard operation
pdoc copied to clipboard

Type annotation parsing warning for Pydantic BaseModel private attributes

Open DawnEver opened this issue 9 months ago • 3 comments

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:

  1. Install pdoc and pydantic
  2. 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
  1. 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

DawnEver avatar Mar 27 '25 06:03 DawnEver

I think pydantic is mainstream enough that it's worth to support this - contributions welcome!

mhils avatar Apr 09 '25 07:04 mhils

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.

jinnovation avatar May 02 '25 18:05 jinnovation

I note also the following:

  1. Both of the problematic fields that @DawnEver cites are dicts
  2. There is this very relevant-sounding disclaimer in Pydantic code regarding dict being in the namespace of BaseModel -- namely, as a deprecated dict() 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.

jinnovation avatar May 02 '25 18:05 jinnovation