diff --git a/pdoc/_pydantic.py b/pdoc/_pydantic.py index 945537a5..402cb88f 100644 --- a/pdoc/_pydantic.py +++ b/pdoc/_pydantic.py @@ -41,7 +41,9 @@ def default_value(parent: ClassOrModule, name: str, obj: Any) -> Any: For all other objects, return `obj` as-is. """ if is_pydantic_model(parent): - pydantic_fields = parent.__pydantic_fields__ + pydantic_fields = getattr(parent, "__pydantic_fields__", None) + if pydantic_fields is None: + pydantic_fields = parent.__fields__ return pydantic_fields[name].default if name in pydantic_fields else obj return obj @@ -49,7 +51,12 @@ def default_value(parent: ClassOrModule, name: str, obj: Any) -> Any: def get_field_docstring(parent: ClassOrModule, field_name: str) -> str | None: if is_pydantic_model(parent): - if field := parent.__pydantic_fields__.get(field_name, None): + pydantic_fields = getattr(parent, "__pydantic_fields__", None) + if pydantic_fields is None: + if field := parent.__fields__.get(field_name): + return getattr(field, "field_info", field).description + return None + if field := pydantic_fields.get(field_name): return field.description if computed := parent.__pydantic_computed_fields__.get(field_name, None): return computed.description diff --git a/test/test__pydantic.py b/test/test__pydantic.py index 34aa0e74..d5a1a5ea 100644 --- a/test/test__pydantic.py +++ b/test/test__pydantic.py @@ -1,8 +1,10 @@ from functools import cached_property import pydantic +import pydantic.v1 as pydantic_v1 from pdoc import _pydantic +from pdoc import extract import pdoc.doc @@ -39,3 +41,28 @@ def test_with_pydantic(monkeypatch): assert not _pydantic.is_pydantic_model(pdoc.doc.Module) assert _pydantic.get_field_docstring(pdoc.doc.Module, "kind") is None assert _pydantic.default_value(pdoc.doc.Module, "kind", "module") == "module" + + +def test_with_pydantic_v1(monkeypatch, tmp_path): + monkeypatch.setattr(_pydantic, "pydantic", pydantic_v1) + + class LegacyModel(pydantic_v1.BaseModel): + name: str = pydantic_v1.Field( + default="Jane Doe", description="legacy description" + ) + + assert _pydantic.is_pydantic_model(LegacyModel) + assert _pydantic.get_field_docstring(LegacyModel, "name") == "legacy description" + assert _pydantic.get_field_docstring(LegacyModel, "unknown") is None + assert _pydantic.default_value(LegacyModel, "name", None) == "Jane Doe" + assert _pydantic.default_value(LegacyModel, "unknown", "fallback") == "fallback" + + module_file = tmp_path / "legacy_model.py" + module_file.write_text( + "from pydantic.v1 import BaseModel, Field\n" + "class LegacyModel(BaseModel):\n" + " name: str = Field(default='Jane Doe', description='legacy description')\n" + ) + module = extract.load_module(extract.parse_spec(module_file)) + assert "LegacyModel" in pdoc.doc.Module(module).members + assert "legacy description" in pdoc.pdoc(str(module_file))