File: _pydantic.py

package info (click to toggle)
python-pdoc 16.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,080 kB
  • sloc: python: 5,260; javascript: 1,156; makefile: 18; sh: 3
file content (54 lines) | stat: -rw-r--r-- 1,812 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
"""Work with Pydantic models."""

from __future__ import annotations

import types
from typing import Any
from typing import TypeAlias
from typing import TypeGuard

try:
    import pydantic
except ImportError:  # pragma: no cover
    pydantic = None  # type: ignore

ClassOrModule: TypeAlias = type | types.ModuleType
"""Type alias for the type of `Namespace.obj`."""

IGNORED_FIELDS: frozenset[str] = frozenset(
    (["__fields__"] + list(pydantic.BaseModel.__dict__.keys()))
    if pydantic is not None
    else []
)
"""Fields to ignore when generating docs, e.g. those that emit deprecation
warnings or that are not relevant to users of BaseModel-derived classes."""


def is_pydantic_model(obj: ClassOrModule) -> TypeGuard[pydantic.BaseModel]:
    """Returns whether an object is a Pydantic model."""
    if pydantic is None:  # pragma: no cover
        # classes that subclass pydantic.BaseModel can only be instantiated if pydantic is importable
        # => if we cannot import pydantic, the passed object cannot be a subclass of BaseModel.
        return False

    return isinstance(obj, type) and issubclass(obj, pydantic.BaseModel)


def default_value(parent: ClassOrModule, name: str, obj: Any) -> Any:
    """Determine the default value of obj.

    For pydantic BaseModels, extract the default value from field metadata.
    For all other objects, return `obj` as-is.
    """
    if is_pydantic_model(parent):
        pydantic_fields = parent.__pydantic_fields__
        return pydantic_fields[name].default if name in pydantic_fields else obj

    return obj


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):
            return field.description
    return None