GithubHelp home page GithubHelp logo

mkdocstrings / griffe-pydantic Goto Github PK

View Code? Open in Web Editor NEW
3.0 3.0 0.0 695 KB

Griffe extension for Pydantic. Only available to sponsors.

Home Page: https://mkdocstrings.github.io/griffe-pydantic/

griffe griffe-extension mkdocstrings pydantic

griffe-pydantic's Issues

bug: griffe-pydantic crashes when mode='before' is added to field_validator

Description of the bug

When the example model is modified to have a field_validator with keyword argument mode='before' griffe crashes.

To Reproduce

class ExampleModel(BaseModel):
    """An example {info}."""

    model_config = ConfigDict(frozen=False)

    field_without_default: str
    """Shows the *[Required]* marker in the signature."""

    field_plain_with_validator: int = 100
    """Show standard field with type annotation."""

    field_with_validator_and_alias: str = Field("FooBar", alias="BarFoo", validation_alias="BarFoo")
    """Shows corresponding validator with link/anchor."""

    field_with_constraints_and_description: int = Field(
        default=5, ge=0, le=100, description="Shows constraints within doc string."
    )

    @field_validator("field_with_validator_and_alias", "field_without_default", mode="before") # <<-- mind the 'mode='before'
    @classmethod
    def check_max_length_ten(cls, v) -> str:
        """Show corresponding field with link/anchor."""
        if len(v) >= 10:
            raise ValueError("No more than 10 characters allowed")
        return v

Full traceback

(c:\gitlab\mkdocs_experiments\.conda) PS C:\gitlab\mkdocs_experiments> mkdocs serve
INFO    -  Building documentation...
INFO    -  Cleaning site directory
INFO    -  mkdocstrings_handlers: .conda\Lib\site-packages\griffe_pydantic\templates\material\pydantic_model.html: DeprecationWarning: Extending '_base/class.html' is deprecated, extend '_base/class.html.jinja'           instead. After some time, this message will be logged as a warning, causing strict builds to fail.
INFO    -  Documentation built in 0.88 seconds
INFO    -  [21:16:41] Watching paths for changes: 'docs', 'mkdocs.yml'
INFO    -  [21:16:41] Serving on http://127.0.0.1:8000/
INFO    -  [21:17:11] Detected file changes
INFO    -  Building documentation...
INFO    -  mkdocstrings_handlers: .conda\Lib\site-packages\griffe_pydantic\templates\material\pydantic_model.html: DeprecationWarning: Extending '_base/class.html' is deprecated, extend '_base/class.html.jinja'           instead. After some time, this message will be logged as a warning, causing strict builds to fail.
INFO    -  Documentation built in 1.03 seconds
INFO    -  [21:17:12] Reloading browsers
INFO    -  [21:17:29] Detected file changes
INFO    -  Building documentation...
ERROR   -  Error reading page 'index.md': malformed node or string: ExprKeyword(name='mode', value="'before'", function=ExprName(name='field_validator', parent=Class('ExampleModel', 37, 61)))
Traceback (most recent call last):
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\mkdocs\livereload\__init__.py", line 211, in _build_loop
    self.builder()
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\mkdocs\commands\serve.py", line 67, in builder
    build(config, serve_url=None if is_clean else serve_url, dirty=is_dirty)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\mkdocs\commands\build.py", line 310, in build
    _populate_page(file.page, config, files, dirty)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\mkdocs\commands\build.py", line 167, in _populate_page
    page.render(config, files)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\mkdocs\structure\pages.py", line 285, in render
    self.content = md.convert(self.markdown)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\markdown\core.py", line 357, in convert
    root = self.parser.parseDocument(self.lines).getroot()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\markdown\blockparser.py", line 117, in parseDocument
    self.parseChunk(self.root, '\n'.join(lines))
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\markdown\blockparser.py", line 136, in parseChunk
    self.parseBlocks(parent, text.split('\n\n'))
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\markdown\blockparser.py", line 158, in parseBlocks
    if processor.run(parent, blocks) is not False:
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\mkdocstrings\extension.py", line 128, in run
    html, handler, data = self._process_block(identifier, block, heading_level)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\mkdocstrings\extension.py", line 210, in _process_block
    data: CollectorItem = handler.collect(identifier, options)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\mkdocstrings_handlers\python\handler.py", line 315, in collect
    loader.load(
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\griffe\loader.py", line 233, in load
    self.extensions.call("on_package_loaded", pkg=obj)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\griffe\extensions\base.py", line 345, in call
    getattr(extension, event)(**kwargs)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\griffe_pydantic\extension.py", line 42, in on_package_loaded
    static.process_module(pkg, processed=self.processed, schema=self.schema)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\griffe_pydantic\static.py", line 165, in process_module
    process_module(submodule, processed=processed, schema=schema)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\griffe_pydantic\static.py", line 162, in process_module
    process_class(cls, processed=processed, schema=schema)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\griffe_pydantic\static.py", line 145, in process_class
    process_function(member, cls, processed=processed)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\griffe_pydantic\static.py", line 111, in process_function
    fields = [ast.literal_eval(field) for field in decorator.arguments]  # type: ignore[arg-type]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\site-packages\griffe_pydantic\static.py", line 111, in <listcomp>
    fields = [ast.literal_eval(field) for field in decorator.arguments]  # type: ignore[arg-type]
              ^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\ast.py", line 110, in literal_eval
    return _convert(node_or_string)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\ast.py", line 109, in _convert
    return _convert_signed_num(node)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\ast.py", line 83, in _convert_signed_num
    return _convert_num(node)
           ^^^^^^^^^^^^^^^^^^
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\ast.py", line 74, in _convert_num
    _raise_malformed_node(node)
  File "c:\gitlab\mkdocs_experiments\.conda\Lib\ast.py", line 71, in _raise_malformed_node
    raise ValueError(msg + f': {node!r}')
ValueError: malformed node or string: ExprKeyword(name='mode', value="'before'", function=ExprName(name='field_validator', parent=Class('ExampleModel', 37, 61)))
ERROR   -  [21:17:30] An error happened during the rebuild. The server will appear stuck until build errors are resolved.

Expected behavior

render correctly

Environment information

[tool.poetry.dependencies]
python = "^3.11"
pydantic = "^2.7.1"
griffe = "0.45.2"
mkdocs = "^1.6.0"
mkdocs-material = "^9.5.24"
mkdocstrings = "^0.25.1"
mkdocstrings-python = "^1.10.3"
ruamel-yaml = "^0.18.6"
pydantic-yaml = "^1.3.0"

bug: griffe-pydantic doesn't support subclassed pydantic models

Description of the bug

When the class which is to be rendered as a pydantic model is not directly inheriting from pydantic.BaseModel the rendering fails

To Reproduce

# other file content:
from pydantic.main import BaseModel


class InheritedBaseModel(BaseModel):
    """"""

When trying to render the example model:

from other_file import InheritedBaseModel

class ExampleModel(InheritedBaseModel):
    """An example model."""

    model_config = ConfigDict(frozen=False)

    field_without_default: str
    """Shows the *[Required]* marker in the signature."""

    field_plain_with_validator: int = 100
    """Show standard field with type annotation."""

    field_with_validator_and_alias: str = Field("FooBar", alias="BarFoo", validation_alias="BarFoo")
    """Shows corresponding validator with link/anchor."""

    field_with_constraints_and_description: int = Field(
        default=5, ge=0, le=100, description="Shows constraints within doc string."
    )

    @field_validator("field_with_validator_and_alias", "field_without_default")
    @classmethod
    def check_max_length_ten(cls, v) -> str:
        """Show corresponding field with link/anchor."""
        if len(v) >= 10:
            raise ValueError("No more than 10 characters allowed")
        return v

Using these mkdocs.yml settings:

site_name: "My Library"

theme:
  name: "material"

plugins:
- mkdocstrings:
    handlers:
      python:
        paths: [.]
        options:
          extensions:
          - griffe_pydantic:
              schema: true
$ mkdocs serve
INFO    -  Building documentation...
INFO    -  Cleaning site directory
INFO    -  mkdocstrings_handlers: .conda\Lib\site-packages\griffe_pydantic\templates\material\pydantic_model.html: DeprecationWarning: Extending '_base/class.html' is deprecated, extend '_base/class.html.jinja'           instead. After some time, this message will be logged as a warning, causing strict builds to fail.
INFO    -  Documentation built in 0.91 seconds
INFO    -  [20:39:57] Watching paths for changes: 'docs', 'mkdocs.yml'
INFO    -  [20:39:57] Serving on http://127.0.0.1:8000/

Expected behavior

I expect the model to render just fine.

Environment information

[tool.poetry.dependencies]
python = "^3.11"
pydantic = "^2.7.1"
griffe = "0.45.2"
mkdocs = "^1.6.0"
mkdocs-material = "^9.5.24"
mkdocstrings = "^0.25.1"
mkdocstrings-python = "^1.10.3"
ruamel-yaml = "^0.18.6"
pydantic-yaml = "^1.3.0"

Additional context

The result:
image

When the InheritedBaseModel is replaced with the pydantic.BaseModel the result is as expected:
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.