Skip to content

Commit c6db291

Browse files
avhzatzander_aautofix-ci[bot]avhz
authored
feat: support Pydantic descriptions (#855)
* feat: support Pydantic descriptions * fix: move Pydantic logic from pdoc.doc to pdoc._pydantic * [autofix.ci] apply automated fixes * fix: mypy computed_field on property error (see: https://docs.pydantic.dev/2.0/usage/computed_fields/) * docs: add `computed_field` docs to `__init__.py` * Update CHANGELOG.md --------- Co-authored-by: atzander_a <[email protected]> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: avhz <[email protected]>
1 parent 76c8e84 commit c6db291

File tree

4 files changed

+24
-2
lines changed

4 files changed

+24
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
## Unreleased: pdoc next
66

7+
- Support Pydantic [`computed_field`](https://docs.pydantic.dev/2.0/usage/computed_fields/) descriptions ([#855](https://github.com/mitmproxy/pdoc/pull/855), @avhz)
78

89
## 2025-10-27: pdoc 16.0.0
910

pdoc/__init__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,11 +265,11 @@ class GoldenRetriever(Dog):
265265
For [Pydantic models](https://docs.pydantic.dev/latest/concepts/models/), pdoc
266266
will extract [field](https://docs.pydantic.dev/latest/concepts/fields/)
267267
descriptions and treat them just like [documented
268-
variables](#document-variables). For example, the following two Pydantic models
268+
variables](#document-variables). For example, the following Pydantic models
269269
would have identical pdoc-rendered documentation:
270270
271271
```python
272-
from pydantic import BaseModel, Field
272+
from pydantic import BaseModel, Field, computed_field
273273
274274
class Foo(BaseModel):
275275
a: int = Field(description="Docs for field a.")
@@ -278,6 +278,11 @@ class OtherFoo(BaseModel):
278278
a: int
279279
"""Docs for field a."""
280280
281+
class ComputedFoo(BaseModel):
282+
@computed_field(description="Docs for field a.")
283+
@property
284+
def a(self) -> int:
285+
...
281286
```
282287
283288
## ...render math formulas?

pdoc/_pydantic.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,6 @@ def get_field_docstring(parent: ClassOrModule, field_name: str) -> str | None:
5151
if is_pydantic_model(parent):
5252
if field := parent.__pydantic_fields__.get(field_name, None):
5353
return field.description
54+
if computed := parent.__pydantic_computed_fields__.get(field_name, None):
55+
return computed.description
5456
return None

test/test__pydantic.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from functools import cached_property
2+
13
import pydantic
24

35
from pdoc import _pydantic
@@ -16,10 +18,22 @@ class ExampleModel(pydantic.BaseModel):
1618
id: int
1719
name: str = pydantic.Field(description="desc", default="Jane Doe")
1820

21+
@pydantic.computed_field(description="computed") # type: ignore[misc]
22+
@property
23+
def computed(self) -> str:
24+
return "computed_value"
25+
26+
@pydantic.computed_field(description="cached") # type: ignore[misc]
27+
@cached_property
28+
def cached(self) -> str:
29+
return "computed_value"
30+
1931

2032
def test_with_pydantic(monkeypatch):
2133
assert _pydantic.is_pydantic_model(ExampleModel)
2234
assert _pydantic.get_field_docstring(ExampleModel, "name") == "desc"
35+
assert _pydantic.get_field_docstring(ExampleModel, "computed") == "computed"
36+
assert _pydantic.get_field_docstring(ExampleModel, "cached") == "cached"
2337
assert _pydantic.default_value(ExampleModel, "name", None) == "Jane Doe"
2438

2539
assert not _pydantic.is_pydantic_model(pdoc.doc.Module)

0 commit comments

Comments
 (0)