Giter Site home page Giter Site logo

mansenfranzen / autodoc_pydantic Goto Github PK

View Code? Open in Web Editor NEW
141.0 6.0 23.0 2.81 MB

Seamlessly integrate pydantic models in your Sphinx documentation.

License: MIT License

Python 99.95% CSS 0.05%
pydantic sphinx autodoc python sphinx-extension documentation

autodoc_pydantic's Introduction

Autodoc Pydantic

PyPI - Version Python PyPI - Downloads

GitHub Actions Workflow Status Codecov Read the Docs (stable)

GitHub License linting - ruff types - Mypy All Contributors

You love pydantic ❀ and you want to document your models and configuration settings with sphinx?

Perfect, let's go. But wait, sphinx' autodoc does not integrate too well with pydantic models πŸ˜•.

Don't worry - just pip install autodoc_pydantic ☺.

🌟 Features

  • πŸ’¬ provides default values, alias and constraints for model fields
  • πŸ”— adds hyperlinks between validators and corresponding fields
  • πŸ“ƒ includes collapsable model json schema
  • πŸ„ natively integrates with autodoc and autosummary extensions
  • πŸ“Ž defines explicit pydantic prefixes for models, settings, fields, validators and model config
  • πŸ“‹ shows summary section for model configuration, fields and validators
  • πŸ‘€ hides overloaded and redundant model class signature
  • πŸ”± visualizes entity-relationship-diagrams for class hierarchies
  • πŸ”¨ allows complete configurability on global and per-model level
  • πŸ€ supports pydantic >= 1.5.0 and sphinx >= 4.0.0

πŸ“„ Documentation

Section Description
πŸ“‘ Landing Page Guides and detailed information.
πŸ› οΈ Installation Setup and installation procedures.
πŸ”§ Configuration System or application settings.
πŸ’‘ Usage How to use the application or tool.
🌐 Examples Showcase and usage examples.
πŸ‘¨β€πŸ’» Developer Guide In-depth guide for developers.

πŸ™ Acknowledgements

Thanks to great open source projects sphinx, pydantic and poetry (and so many more) ❀ in addition to the following contributors:

Franz WΓΆllert
Franz WΓΆllert

🚧 πŸ“– ⚠️ πŸ–‹
Yves Renier
Yves Renier

πŸ“– ⚠️ πŸ–‹
TheBeardedBerserkr
TheBeardedBerserkr

πŸ€”
Jan Vlčinský
Jan Vlčinský

πŸ›‘οΈ
antvig
antvig

πŸ› πŸ““
Hugo O Rivera
Hugo O Rivera

πŸ€”
yura bondarenko
yura bondarenko

πŸ› πŸ““
Trevor Howard
Trevor Howard

πŸ› πŸ““
thomas-pedot
thomas-pedot

πŸ› πŸ““
Mat Utter
Mat Utter

πŸ› πŸ““
David C Hall
David C Hall

πŸ€” πŸ““
Josh A. Mitchell
Josh A. Mitchell

πŸ€” ⚠️
Roderick Go
Roderick Go

⚠️
Lily Wang
Lily Wang

πŸ“– πŸ–‹
j-carson
j-carson

πŸ› πŸ’» ⚠️
Jakob Lykke Andersen
Jakob Lykke Andersen

πŸ’»
Juan Luis Cano RodrΓ­guez
Juan Luis Cano RodrΓ­guez

πŸ–‹
Mikalai Chaly
Mikalai Chaly

πŸ› ⚠️
Stig Korsnes
Stig Korsnes

πŸ› πŸ€”
Ilia Kurenkov
Ilia Kurenkov

πŸ›
Grzegorz Bokota
Grzegorz Bokota

πŸ›
jgunstone
jgunstone

πŸ›
iwyrkore
iwyrkore

πŸ’»
spacemanspiff2007
spacemanspiff2007

πŸ› πŸ€”
Luke Hsiao
Luke Hsiao

πŸ›
Daniel Walker
Daniel Walker

πŸ›
Evgeniy Lupashin
Evgeniy Lupashin

πŸ›
Jan-Hendrik Ewers
Jan-Hendrik Ewers

πŸ›
Jonny Saunders
Jonny Saunders

πŸ›
Charles Machalow
Charles Machalow

πŸ’¬
Thomas Karaouzene
Thomas Karaouzene

πŸ›
caseyzak24
caseyzak24

πŸ“–
Priscila Oliveira
Priscila Oliveira

πŸ‘€ πŸ““
Arthur WoimbΓ©e
Arthur WoimbΓ©e

πŸ‘€ πŸ““ πŸ’» ⚠️
Chris Markiewicz
Chris Markiewicz

πŸ›
David B. Nagle
David B. Nagle

πŸ›
JerryJia
JerryJia

πŸ’»
Mike D
Mike D

πŸ’» πŸ› ⚠️
Dario Quintero (Flexcompute)
Dario Quintero (Flexcompute)

πŸ‘€
Rafael Guedes
Rafael Guedes

πŸ’»
Andrew Linzie
Andrew Linzie

πŸ’»
Altay Sansal
Altay Sansal

πŸ€”
Tony Narlock
Tony Narlock

πŸ’» πŸ“–
Xuan (Sean) Hu
Xuan (Sean) Hu

πŸ›
Christian Riedel
Christian Riedel

πŸ›
morcef
morcef

πŸ›
alejandro-yousef
alejandro-yousef

πŸ€”
exs-dwoodward
exs-dwoodward

πŸ’»
Leah Wasser
Leah Wasser

πŸ›
Allan Galarza
Allan Galarza

πŸ›
Carson-Shaar
Carson-Shaar

πŸ›
Kyle Finley
Kyle Finley

πŸ›
brunocruz
brunocruz

πŸ›
Anne Rademacher
Anne Rademacher

πŸ’΅
Γ‰loi Rivard
Γ‰loi Rivard

πŸ›

This project follows the all-contributors specification. Contributions of any kind welcome!

autodoc_pydantic's People

Contributors

allcontributors[bot] avatar awoimbee avatar caerulescens avatar caseyzak24 avatar devmonkey22 avatar j-carson avatar lilyminium avatar mansenfranzen avatar rafa-guedes avatar renovate[bot] avatar spacemanspiff2007 avatar tony avatar yves-renier avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

autodoc_pydantic's Issues

No Hyperlinks for Pydantic Types

Running Sphinx 4.1.1 and pydantic 1.8.2.

Enabled extensions:

    'sphinx.ext.autodoc',
    'sphinxcontrib.autodoc_pydantic',
    'sphinx.ext.viewcode',
    'sphinx.ext.todo',
    'sphinx.ext.napoleon',
    'sphinx_autodoc_typehints'

Sample:

from pydantic import BaseModel


class TestClass:
    """Test

    Attributes:
        model (TestModel): Model
    """

    def __init__(self):
        self.model = TestModel()


class TestModel(BaseModel):
    pass

The generated document will not have a hyperlink for the TestModel data type reference. Removing the BaseModel class from TestModel renders the type references with hyperlinks again.

AttributeError: 'NoneType' object has no attribute 'Config'

autodoc_pydantic failing builds without much information or which model is causing the issue.

Exception occurred:
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 352, in __init__
    self.attribute: Dict = self.model.Config
AttributeError: 'NoneType' object has no attribute 'Config'
Full log
# Sphinx version: 4.5.0
# Python version: 3.9.12 (CPython)
# Docutils version: 0.17.1 release
# Jinja2 version: 3.1.2
# Last messages:
...
# Loaded extensions:
#   sphinx.ext.mathjax (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/mathjax.py
#   sphinxcontrib.applehelp (1.0.2) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/applehelp/__init__.py
#   sphinxcontrib.devhelp (1.0.2) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/devhelp/__init__.py
#   sphinxcontrib.htmlhelp (2.0.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/htmlhelp/__init__.py
#   sphinxcontrib.serializinghtml (1.1.5) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/serializinghtml/__init__.py
#   sphinxcontrib.qthelp (1.0.3) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/qthelp/__init__.py
#   alabaster (0.7.12) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/alabaster/__init__.py
#   sphinx.ext.autodoc.preserve_defaults (1.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/autodoc/preserve_defaults.py
#   sphinx.ext.autodoc.type_comment (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/autodoc/type_comment.py
#   sphinx.ext.autodoc (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py
#   sphinx.ext.intersphinx (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/intersphinx.py
#   sphinx.ext.todo (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/todo.py
#   sphinx.ext.autosummary (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/autosummary/__init__.py
#   sphinx.ext.viewcode (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/viewcode.py
#   sphinx.ext.coverage (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/coverage.py
#   sphinx.ext.doctest (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/doctest.py
#   sphinx.ext.ifconfig (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/ifconfig.py
#   sphinx.ext.napoleon (4.5.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/napoleon/__init__.py
#   sphinx_rtd_theme (unknown version) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx_rtd_theme/__init__.py
#   nbsphinx (0.8.8) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/nbsphinx.py
#   sphinxcontrib.autodoc_pydantic (1.7.0) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/__init__.py
#   recommonmark (0.7.1) from /home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/recommonmark/__init__.py
Traceback (most recent call last):
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/cmd/build.py", line 276, in build_main
    app.build(args.force_all, filenames)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/application.py", line 330, in build
    self.builder.build_update()
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 286, in build_update
    self.build(to_build,
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 300, in build
    updated_docnames = set(self.read())
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 407, in read
    self._read_serial(docnames)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 428, in _read_serial
    self.read_doc(docname)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 468, in read_doc
    doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/io.py", line 181, in read_doc
    pub.publish()
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/core.py", line 217, in publish
    self.document = self.reader.read(self.source, self.parser,
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/io.py", line 101, in read
    self.parse()
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/readers/__init__.py", line 78, in parse
    self.parser.parse(self.input, document)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/parsers.py", line 89, in parse
    self.statemachine.run(inputlines, document, inliner=self.inliner)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 170, in run
    results = StateMachineWS.run(self, input_lines, input_offset,
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
    newabsoffset = self.nested_parse(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
    newabsoffset = self.nested_parse(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2342, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
    return method(self, expmatch)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2096, in directive
    return self.run_directive(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/autodoc/directive.py", line 165, in run
    result = parse_generated_content(self.state, params.result, documenter)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/ext/autodoc/directive.py", line 108, in parse_generated_content
    nested_parse_with_titles(state, content, node)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/util/nodes.py", line 340, in nested_parse_with_titles
    return state.nested_parse(content, 0, node, match_titles=1)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2342, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
    return method(self, expmatch)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2096, in directive
    return self.run_directive(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/domains/__init__.py", line 281, in run
    return super().run()
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/directives/__init__.py", line 200, in run
    self.state.nested_parse(self.content, self.content_offset, contentnode)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2344, in explicit_markup
    self.explicit_list(blank_finish)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2369, in explicit_list
    newline_offset, blank_finish = self.nested_list_parse(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 318, in nested_list_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2647, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
    return method(self, expmatch)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2096, in directive
    return self.run_directive(
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/domains/__init__.py", line 281, in run
    return super().run()
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinx/directives/__init__.py", line 181, in run
    name = self.handle_signature(sig, signode)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/directives/directives.py", line 266, in handle_signature
    self.replace_return_node(signode)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/directives/directives.py", line 247, in replace_return_node
    inspector = ModelInspector.from_signode(signode)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 547, in from_signode
    return cls(model)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 533, in __init__
    self.config = ConfigInspector(self)
  File "/home/jhewers/Documents/projects/jpdmgen/.tox/docs/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 352, in __init__
    self.attribute: Dict = self.model.Config
AttributeError: 'NoneType' object has no attribute 'Config'

`.. currentmodule::` breaks with `autopydantic_model`

When using the .. currentmodule:: directive in conjunction with autopydantic_model and certain options like :model-show-validator-members: False raise a value error:

.. py:currentmodule:: target.example_autosummary

.. autopydantic_model:: AutoSummaryModel
   :model-show-validator-members: False

This occurs because autodoc_pydantic uses a custom method to locate objects. Instead, it should rely on autdoc's object import methods.

JSON serialization with custom json encoder

Hi there,

I have a Pydantic class that inherits another Pydantic class that allows for custom handling of function serialization:

class ConfigModel(BaseModel):
    class Config:
        extra = Extra.forbid
        use_enum_values = True
        json_encoders = {
            Callable: lambda fn: ".".join(
                [fn.__module__, fn.__name__]
            ),
            FunctionType: lambda fn: ".".join(
                [fn.__module__, fn.__name__]
            ),
        }
class TextConfig(ConfigModel):
    symbols: Symbols = Field(default_factory=Symbols)
    cleaners: List[Callable] = [lower, collapse_whitespace, nfc_normalize]

    def __init__(self, **data) -> None:
        """Custom init to process cleaners"""
        with contextlib.suppress(KeyError):
            cleaners = data["cleaners"]
            for i, c in enumerate(cleaners):
                cleaners[i] = string_to_callable(c)
        super().__init__(**data)

With this configuration, I can do the following:

>>> tc = TextConfig()
>>> tc.json()
'{"symbols": {"silence": ["<SIL>"], "pad": "_", "punctuation": "-\';:,.!?\\u00a1\\u00bf\\u2014\\u2026\\"\\u00ab\\u00bb\\u201c\\u201d "}, "cleaners": ["smts.utils.lower", "smts.utils.collapse_whitespace", "smts.utils.nfc_normalize"]}'

But when I try to autodoc TextConfig, I get the following:

Exception occurred:
  File "pydantic/json.py", line 90, in pydantic.json.pydantic_encoder
TypeError: Object of type 'function' is not JSON serializable
The full traceback has been saved in /home/aip000/aip000/tmp/sphinx-err-u13_waob.log, if you want to report the issue to the developers.

There are ways to ignore this seemingly, but how can I get autodoc_pydantic to just use the models json serialization?

`pd.DataFrame` breaks JSON schema generation

When using Arbitrary type we cannot serialize to a JSON Schema.

Work

PandasDataFrame = TypeVar('pd.DataFrame')

class Model(BaseModel):
    pandasDF:  PandasDataFrame 

Doesnot work

class Model(BaseModel):
    pandasDF:  pd.DataFrame
    class Config:
        arbitrary_types_allowed = True # pd.DataFrame allowed

Following error is raised when building the docs:

ValueError: Value not declarable with JSON Schema, field: name='inputs_DataFrame' type=DataFrame required=True

Support sphinx 4.0 and drop dependency on myst-parser

Sphinx 4.0 was released just today. autodoc_pydantic should work with newest sphinx version. Additionally, the dependency on myst-parser is really not required since it is only used to convert the changelog, written in markdown, to reST. Instead, the changelog can be written in reST right away.

Move CI test matrix to tox

Currently, the varying versions to be tested (e.g. python, sphinx, pydantic) are completely defined within github actions yaml. To support local and other remote CI/CD pipelines, move the version definitions and test environment execution into tox.

Broken CI for sphinx 3.4

The CI builds for sphinx 3.4 are currently broken. This probably occurs to newer versions of unpinned dependencies (e.g. docutils). The actual error is of minor significance and does not impact correct behavior but still breaks the CI. This needs to be fixed.

Handle Ellipsis default value

pydantic uses Field(default = ...) to indicate that a field is required (see docs).

Currently autodoc_pydantic will output things like:

field name: str = Ellipsis

which can be a bit confusing. Perhaps it could instead output something like:

field name: str [Required]

Model Field Output

When I generate the html for a my model none of the fields are populating.

The docs just generate something along the lines of:

pydantic model MyModel [source]
This is my doc string.
Show Json Schema

I'm generating the page with the
..automodule:: package.MyModel :members:

Am I supposed to have a setting marked for field population?

Add option to show only the alias for a field

I'm loading the application configuration from a yaml file and want to use autodoc-pydantic to document the available settings.
It's really great that there are so many configuration options so everything can be tailored to ones needs.

However I'm missing one more thing:
Since I load from file I load the corresponding values by alias and not by name.
Would it be possible to add a configuration option which shows the alias instead of the field name?
My users have to enter the alias in the configuration file - the field name is of no use for them and might be confusing.

Example:

class General(BaseModel):
    listen_only: bool = Field(False, alias='listen only')

Valid entry in yaml file

listen only: True

Support pydantic dataclass models

I am using pydantic.dataclasses.dataclass because I need the __post_init__ dunder. However, I noticed that automodule does not generate the pydantic model documentation for these data classes. Looking at pydantic's docs, I can access the model using __pydantic_model__, but I'm not sure how to get this to happen automatically with automodule?

TypeError: '<' not supported between instances of 'NoneType' and 'NoneType'

Hi,

I have encountered a simmilar issue as discussed in #78.
My Pydantic models have fields with type of other Pydantic models, and when using autodoc_pydantic_model_summary_list_order = 'bysource' I still seem to get the same error.

Is there any other way to find the exact model that fails, except for the elimination method?

I am not sure what more should be provided to find my edge case, but here is the Sphinx traceback:

# Sphinx version: 5.1.1
# Python version: 3.6.8 (CPython)
# Docutils version: 0.17.1 release
# Jinja2 version: 3.0.3
# Last messages:
#   reading sources... [ 56%] index
#   
#   reading sources... [ 62%] reference/api
#   
# Loaded extensions:
#   sphinx.ext.mathjax (5.1.1) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\mathjax.py
#   sphinxcontrib.applehelp (1.0.2) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\applehelp\__init__.py
#   sphinxcontrib.devhelp (1.0.2) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\devhelp\__init__.py
#   sphinxcontrib.htmlhelp (2.0.0) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\htmlhelp\__init__.py
#   sphinxcontrib.serializinghtml (1.1.5) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\serializinghtml\__init__.py
#   sphinxcontrib.qthelp (1.0.3) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\qthelp\__init__.py
#   alabaster (0.7.12) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\alabaster\__init__.py
#   sphinx.ext.autodoc.preserve_defaults (1.0) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\autodoc\preserve_defaults.py
#   sphinx.ext.autodoc.type_comment (5.1.1) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\autodoc\type_comment.py
#   sphinx.ext.autodoc (5.1.1) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\autodoc\__init__.py
#   sphinx.ext.intersphinx (5.1.1) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\intersphinx.py
#   sphinx_autodoc_typehints (unknown version) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx_autodoc_typehints.py
#   sphinx_click (unknown version) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx_click\__init__.py
#   sphinx_rtd_dark_mode (1.2.4) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx_rtd_dark_mode\__init__.py
#   sphinxcontrib.autodoc_pydantic (1.7.2) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\autodoc_pydantic\__init__.py
#   sphinx_rtd_theme (unknown version) from C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx_rtd_theme\__init__.py
Traceback (most recent call last):
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\cmd\build.py", line 277, in build_main
    app.build(args.force_all, filenames)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\application.py", line 349, in build
    self.builder.build_update()
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\builders\__init__.py", line 303, in build_update
    len(to_build))
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\builders\__init__.py", line 317, in build
    updated_docnames = set(self.read())
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\builders\__init__.py", line 424, in read
    self._read_serial(docnames)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\builders\__init__.py", line 445, in _read_serial
    self.read_doc(docname)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\builders\__init__.py", line 498, in read_doc
    publisher.publish()
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\core.py", line 218, in publish
    self.settings)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\io.py", line 104, in read
    self.parse()
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\readers\__init__.py", line 78, in parse
    self.parser.parse(self.input, document)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\parsers.py", line 78, in parse
    self.statemachine.run(inputlines, document, inliner=self.inliner)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 171, in run
    input_source=document['source'])
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 240, in run
    context, state, transitions)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 3008, in text
    self.section(title.lstrip(), source, style, lineno + 1, messages)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 240, in run
    context, state, transitions)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 3008, in text
    self.section(title.lstrip(), source, style, lineno + 1, messages)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 240, in run
    context, state, transitions)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 240, in run
    context, state, transitions)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 395, in new_subsection
    node=section_node, match_titles=True)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 282, in nested_parse
    node=node, match_titles=match_titles)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 240, in run
    context, state, transitions)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 2342, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 2354, in explicit_construct
    return method(self, expmatch)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 2097, in directive
    directive_class, match, type_name, option_presets)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\docutils\parsers\rst\states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\autodoc\directive.py", line 148, in run
    documenter.generate(more_content=self.content)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 954, in generate
    self.document_members(all_members)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 832, in document_members
    check_module=members_check_module and not isattr)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 1790, in generate
    all_members=all_members)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinx\ext\autodoc\__init__.py", line 951, in generate
    self.add_content(more_content)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\autodoc_pydantic\directives\autodocumenters.py", line 221, in add_content
    self.add_validators_summary()
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\autodoc_pydantic\directives\autodocumenters.py", line 344, in add_validators_summary
    sorted_references = self._get_validator_summary_references()
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\autodoc_pydantic\directives\autodocumenters.py", line 316, in _get_validator_summary_references
    sort_func = self._get_reference_sort_func()
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\autodoc_pydantic\directives\autodocumenters.py", line 295, in _get_reference_sort_func
    idx_fields = self._get_idx_mappings(all_fields)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\autodoc_pydantic\directives\autodocumenters.py", line 280, in _get_idx_mappings
    sorted_members = self._sort_summary_list(members)
  File "C:\venvs\poetry\virtualenvs\prog-vnI5qaYb-py3.6\lib\site-packages\sphinxcontrib\autodoc_pydantic\directives\autodocumenters.py", line 405, in _sort_summary_list
    return sorted(names, key=sort_func)
TypeError: '<' not supported between instances of 'NoneType' and 'NoneType'

automodule error with nested BaseModel

I have the following MRE:

'''Blah module'''

import typing

import pydantic

class Foo:
    '''Foo class'''

    class Bar(pydantic.BaseModel):
        '''Bar class'''

        x: str = pydantic.Field(description='The x.')

        @pydantic.validator('x')
        def do_nothing(cls, value: typing.Any) -> typing.Any:
            return value

In my .rst file, I have

.. automodule:: blah.blah
    :members:

make html produces

  File ".../autodoc_pydantic/inspection.py", line 352, in __init__
    self.attribute: Dict = self.model.Config
AttributeError: type object 'Foo' has no attribute 'Config'

So, autodoc_pydantic has somehow been led to believe that Foo is a pydantic.BaseModel. What's interesting is, if I remove the validator, then the error goes away.

I'm using Python 3.8.10 and autodoc_pydantic 1.7.1.

Styling lost with Jupyter Book

Hello Sir,
To be honest, I'm not sure whether or not this question belong in Jupyter-Book or here. I`m facing an issue, and in a hurry to solve it. I'm using Jupyter-Book to document a library for a client. I have some bakground material/examples which I have produced with markdown/python-code (.md and ipynb), and I have the "API reference" in the last chapter using an rst-file. All works fine, except when I tried using autodoc_pydantic. All pydantic models loose their styling. I.e if I have a module containing say a regular Exception, and another class derived from a Pydantic BaseModel, the Exception will turn out like your examples, but all pydantic models look pretty wierd. They get idented properly, and I can toogle JSON schema on/off in configs, but all styling such as the blue background on the signature is lost. Have tried both automodule and autopydantic_ with same results. Any idea what is going on?
Great project, btw :)

Very best,
Stig

Show fields from parent model

In the following case

class Foo(pydantic.BaseModel):
    '''Foo class'''

    x: str = pydantic.Field(description='The x.')

class Bar(Foo):
    '''Bar class'''

    y: int = pydantic.Field(description='The y.')

is there a way to have the documentation for Bar show both x and y as the fields?

Add Licence

I did not find any licence terms within the project.

Consider adding some (what about MIT? BSD? - you are the author).

Thanks for your plugin - seems very practical and looks great.

Optional[float] displays as [Required]

Hi,
I have a pydantic model where a field is defined as myvalue:Optional[float] , this renders as Optional[float] [Required] in my docs. The json schema does not list it as a required field either. Ref this section of the docs .

Another small issue I have is how to deal with derived models. (Might be in the docs, but could not find it) Ex:

class IdBase(BaseModel):
    id:int
    name:str

class MyOtherModels(IdBase):
    somefield:float

I have a few of these that resemble tables in a relational db. MyOtherModels does not include the fields id,name in the docs using automodule. As id is a primary key in the db, the field is kind of important :) Any guidance on how to solve this?

Btw, using directive :inherited-members: does include the fields, but introduces a lot of noise int the docs. (classmethods etc from pydantic)

Support for autosummary :recursive: documentation of entire API

Hi! Thanks for this package, I love the results it produces!

I've been experimenting with ways to fully automate the generation of API reference documentation from source code and docstrings, a la rustdoc. I know you're aware of this, but there's no easy way to include autodoc_pydantic output in a fully automated API reference.

The following works, of course:

.. autosummary::
   :toctree: _autosummary

   module_with_lots_of_stuff.AutoSummaryModel
   module_with_lots_of_stuff.AutoSummarySettings
   module_with_lots_of_stuff.another_module

But I would like the following:

.. autosummary::
   :toctree: _autosummary
   :recursive:

   module_with_lots_of_stuff

I understand that the reason this doesn't work is that Sphinx doesn't let you expose new variables to the autosummary templates (as you discuss in #11). I've worked around this to some extent in the project I'm working on by adding an autosummary table with all the members not documented elsewhere in the template to the end of the module template, but it's not very good and we probably won't end up using it.

My suggestion would be to workaround the bug in Sphinx by adding a Jinja2 filter along the lines of "keep_pydantic_models" that takes an iterator of names of objects and filters out those that aren't models. So a block like the following could be added to an Autosummary template:

{% set models = members | keep_pydantic_models(module=fullname) | list %}

{% if models %}
Models
---------

{% for item in models %}
.. autopydantic_model:: item
{% endfor %}

I think you should be able to add such a filter to all templates, but I'm not super familiar. Sorry if this isn't helpful.

Thanks!

Make error handling for non serializable objects configureable

One may show the nodel JSON schema within class doc string as a collapsable code block via :model-show-json:. This depends on the model to be completely JSON serializable. However, users may provide custom fields that are not serializable by default. This breaks the schema generation.

Currently, this is handled by intercepting such non serializable fields and replacing their types and default values to indicate an error. This is rather implicit even though there is an explicit remark in the documentation.

To improve, let's make the error handling configureable, like autodoc_pydantic_model_show_json_error_handling to be one of:

  • raise: Do not handle the error. Propagate it.
  • ignore: Drop all fields from the schema that are not JSON serializable and provide warning in the sphinx output.
  • coerce: Keep violating field names (and types?) but replace default (None?) and provide warning in the sphinx output.

Add autosummary-like table to model/settings doc string

Since autosummary is currently not very well suited for custom autodocumenters (see #11), its functionality can't be properly used. Hence, it would make sense to provide a autosummary-like table of contents for largish models/settings to get a brief overview of all existing fields and validators instead of scrolling all over the page.

Ideally it would be possible to reuse some of the existing autosummary codebase. The new configuration could be called model-show-autosummary or something similar.

Links behave unexpectedly in the Example - ExampleSettings on the readthedocs

this looks like a great package!

I was just looking at the documentation and when you hit "source":
image

it behaves as expected taking you to the source code... but then when you hit the equivalent "docs" link to go back:
image

it takes you to the "Usage" section rather than the "Examples" section you came from:
image

otherwise looks great - can't wait to use it in my next package

KeyError: 'created_by' when building documentation

Full error trace:

# Sphinx version: 5.0.0
# Python version: 3.8.13 (CPython)
# Docutils version: 0.17.1 release
# Jinja2 version: 3.1.2
# Last messages:
#   reading sources... [ 50%] reference/app.crud.crud_role
#   reading sources... [ 51%] reference/app.crud.crud_team
#   reading sources... [ 53%] reference/app.crud.crud_user
#   reading sources... [ 54%] reference/app.db
#   reading sources... [ 56%] reference/app.db.init_db
#   reading sources... [ 57%] reference/app.db.session
#   reading sources... [ 59%] reference/app.initial_data
#   reading sources... [ 60%] reference/app.main
#   reading sources... [ 62%] reference/app.models
#   reading sources... [ 63%] reference/app.models.group
# Loaded extensions:
#   sphinx.ext.mathjax (5.0.0) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/mathjax.py
#   sphinxcontrib.applehelp (1.0.2) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/applehelp/__init__.py
#   sphinxcontrib.devhelp (1.0.2) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/devhelp/__init__.py
#   sphinxcontrib.htmlhelp (2.0.0) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/htmlhelp/__init__.py
#   sphinxcontrib.serializinghtml (1.1.5) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/serializinghtml/__init__.py
#   sphinxcontrib.qthelp (1.0.3) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/qthelp/__init__.py
#   alabaster (0.7.12) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/alabaster/__init__.py
#   sphinx.ext.todo (5.0.0) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/todo.py
#   sphinx.ext.viewcode (5.0.0) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/viewcode.py
#   sphinx.ext.autodoc.preserve_defaults (1.0) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/preserve_defaults.py
#   sphinx.ext.autodoc.type_comment (5.0.0) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/type_comment.py
#   sphinx.ext.autodoc (5.0.0) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py
#   sphinx.ext.napoleon (5.0.0) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/napoleon/__init__.py
#   sphinxcontrib.apidoc (0.3.0) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/apidoc/__init__.py
#   sphinxcontrib.autodoc_pydantic (1.7.1) from /Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/autodoc_pydantic/__init__.py
Traceback (most recent call last):
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/cmd/build.py", line 276, in build_main
    app.build(args.force_all, filenames)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/application.py", line 329, in build
    self.builder.build_update()
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 288, in build_update
    self.build(to_build,
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 302, in build
    updated_docnames = set(self.read())
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 409, in read
    self._read_serial(docnames)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 430, in _read_serial
    self.read_doc(docname)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/builders/__init__.py", line 483, in read_doc
    publisher.publish()
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/core.py", line 217, in publish
    self.document = self.reader.read(self.source, self.parser,
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/io.py", line 103, in read
    self.parse()
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/readers/__init__.py", line 78, in parse
    self.parser.parse(self.input, document)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/parsers.py", line 78, in parse
    self.statemachine.run(inputlines, document, inliner=self.inliner)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 170, in run
    results = StateMachineWS.run(self, input_lines, input_offset,
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
    newabsoffset = self.nested_parse(
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2342, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
    return method(self, expmatch)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2096, in directive
    return self.run_directive(
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/directive.py", line 148, in run
    documenter.generate(more_content=self.content)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 955, in generate
    self.document_members(all_members)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 831, in document_members
    documenter.generate(
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 1788, in generate
    return super().generate(more_content=more_content,
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 955, in generate
    self.document_members(all_members)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/autodoc_pydantic/directives/autodocumenters.py", line 164, in document_members
    super().document_members(*args, **kwargs)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 1779, in document_members
    super().document_members(all_members)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 831, in document_members
    documenter.generate(
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinx/ext/autodoc/__init__.py", line 945, in generate
    self.add_directive_header(sig)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/autodoc_pydantic/directives/options/composites.py", line 259, in wrapped
    result = func(*args, **kwargs)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/autodoc_pydantic/directives/autodocumenters.py", line 539, in add_directive_header
    self.add_default_value_or_marker()
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/autodoc_pydantic/directives/autodocumenters.py", line 586, in add_default_value_or_marker
    if self.needs_required_marker:
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/autodoc_pydantic/directives/autodocumenters.py", line 549, in needs_required_marker
    is_required = self.pydantic.inspect.fields.is_required(field_name)
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 188, in is_required
    return self.get(field_name).required
  File "/Users/pipeknight/.pyenv/versions/3.8.13/lib/python3.8/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 137, in get
    return self.attribute[name]
KeyError: 'created_by'

My conf file:

# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
import os
import sys

# Also we may load a dotenv file here
sys.path.insert(0, os.path.abspath('.'))


# -- Project information -----------------------------------------------------

project = 'fastapi-alembic-sqlmodel-async'
copyright = '2022, -'
author = '-'


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    'sphinx.ext.todo',
    'sphinx.ext.viewcode',
    'sphinx.ext.autodoc',
    'sphinx.ext.napoleon',
    'sphinxcontrib.apidoc',
    'sphinxcontrib.autodoc_pydantic',
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

# Apidoc options
apidoc_module_dir = '../fastapi-alembic-sqlmodel-async'
apidoc_output_dir = 'reference'
apidoc_excluded_paths = ['tests', 'kafka_test']
apidoc_separate_modules = True
# apidoc_extra_args = ['-d 2']

# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
html_theme = 'alabaster'
# html_theme = 'sphinx-rtd-theme'

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

I have several models in my app with field named created_by, for example:

from sqlmodel import Field, Relationship, SQLModel

class Group(SQLModel, table=True):
    id: Optional[int] = Field(default=None, nullable=False, primary_key=True)
    updated_at: Optional[datetime]
    created_at: Optional[datetime]
    created_by_id: Optional[UUID] = Field(default=None, foreign_key="user.id")
    created_by: "User" = Relationship(  # noqa: F821
        sa_relationship_kwargs={
            "lazy": "select",
            "primaryjoin": "Group.created_by_id==User.id",
        }
    )

And for some reason this broke my docs generation. If I comment 'sphinxcontrib.autodoc_pydantic' in conf.py extensions, than everything works

autosummary does not seem to work with autodoc_pydantic

Hi

First, my doc and I would like to thank you a lot for this great lib !

I face an issue : I'm using autosummary to have a clean doc but using autodoc_pydantic seem not compatible with autosummary

.. currentmodule:: my_module

API Reference
=============

This page gives an overview of all public :mod:`my_module` objects, functions and methods. 

all classes
+++++++++++

.. autosummary::
   :toctree: temp
   :nosignatures:
   :inherited-members:

   ForecastingConfig

the results is

image

While the results before using autodoc_pydantic was :

image

Support for Union with ForwardRef

for code:

Node = ForwardRef('Node')

class Node(BaseModel):
    left: Union[Node, Leaf]
    op: str
    right: Union[Node, Leaf]

there was warning /home/czaki/Projekty/PartSeg/docs/autodoc_pydantic.rst: WARNING: JSON schema can't be generated for 'PartSegCore.analysis.measurement_base.Node' because the following pydantic fields can't be serialized properly: ['left', 'right'].

in this code

try:
field_args = (field.type_, field.default)
model = create_model("_", test_field=field_args, Config=Cfg)
model.schema()
return True
except Exception:
return False

there is no check for sub_fields:
https://github.com/samuelcolvin/pydantic/blob/fbf8002cefd1ba7b263f63545fff2e48a378189d/pydantic/typing.py#L445-L458

in my case field.type_ is typing.Union[ForwardRef('Node'), PartSegCore.analysis.measurement_base.Leaf] but field.sub_fields is [ModelField(name="left_ForwardRef('Node')", type=Node, required=True), ModelField(name='left_Leaf', type=Leaf, required=True)]

So all data are available in data structures.

Additional field arguments appear as constraints

Additional keyword arguments of fields automatically appear under constraints even when they are not a constraint.

I use an additional keyword argument to specify whether the field will be created in the yaml file.
This argument is automatically documented as a constraint when it is more of a general field information.
grafik

From the pydantic docs:
grafik
It seems that these kwargs are indeed intended for other purposes.
Is the documentation under constraints the intended behavior or is this something that is/was just out of scope?

Feature request: render sphinx markup in description attributes of fields

Hi!

Thanks for this very nice tool! It's so nice, that I'm wondering if we can make it even more powerful :)

Would it be a challenge to render any sphinx markup in the description attribute of a Field?

I'd love to help, but afraid that I'm a bit low on free time for the next month or two.

Support/respect autodoc's `autodoc_preserve_defaults` and `autodoc_typehints_format` settings

In the last few releases, autodoc has added two settings to conf.py that are very useful:

  • autodoc_preserve_defaults: Preserves default argument values as they are in code, rather than evaluating them
  • autodoc_typehints_format: Suppresses the module names of type hints

By turning each of these on, a field signature could be transformed from something like this:

target_templates: List[Union[openff.bespokefit.schema.targets.TorsionProfileTargetSchema, openff.bespokefit.schema.targets.AbInitioTargetSchema, openff.bespokefit.schema.targets.VibrationTargetSchema, openff.bespokefit.schema.targets.OptGeoTargetSchema]] = [TorsionProfileTargetSchema(weight=1.0, reference_data=None, extras={}, type='TorsionProfile', attenuate_weights=True, energy_denominator=1.0, energy_cutoff=10.0)]

to

target_templates: List[Union[TorsionProfileTargetSchema, AbInitioTargetSchema, VibrationTargetSchema, OptGeoTargetSchema]] = [TorsionProfileTargetSchema()]

Which is much less intimidating and easier to read.

It would be amazing if autodoc_pydantic could support these options in pydantic models etc.

TypeError with Sphinx 5.0

When using autodoc_pydantic with the just-released Sphinix v5.0.0, we get a TypeError:

  File "/home/redacted/.venv/lib/python3.8/site-packages/sphinxcontrib/autodoc_pydantic/directives/autodocumenters.py", line 205, in add_content
    super().add_content(more_content, no_docstring)
TypeError: add_content() takes 2 positional arguments but 3 were given

This appears to be changed in sphinx's autodoc extension here: sphinx-doc/sphinx@267954e#diff-e43bdd6f8f37a12d2536e09e57c5e8999cb8de18b9c7ba49126f90576c4328acR2666

It seems that autodoc_pydantic will also need to adjust accordingly.

Does `autodoc_pydantic` work with autoapi?

I'm not fully initiated into sphinx so some terms may be slightly off so bear with me :)

I have a project that uses sphinx autoapi to build some rst files from code for docs. I figured adding sphinxcontrib.autodoc_pydantic" as an extension in conf.py would be enough to get the description from pydantic fields in the documentation... but alas it doesn't seem to make a difference.

Does this generally work with projects that generate docs via autoapi?

In my conf.py:

..
extensions = [
    "autoapi.extension",
    "sphinxcontrib.autodoc_pydantic",
    "sphinx_rtd_theme",
]
...
html_theme = "sphinx_rtd_theme"

autoapi_type = "python"
autoapi_dirs = ["../src"]
autoapi_keep_files = True
autoapi_python_class_content = 'both'
autoapi_options = ['members', 'undoc-members', 'show-inheritance', 'show-module-summary', 'special-members', 'imported-members']

TypeError: '<' not supported between instances of 'NoneType' and 'NoneType' in `_sort_summary_list`

Hey all, I've encountered exception while trying to generate a pydantic models documentation. I believe it is related to a combination of factors (most likely it is related to 'bysource' sorting and usage of pydantic model as a class field):

class DataTransformer:
    """Transformer"""

    PARAMS_CLS = DataTransformerConfig  # DataTransformerConfig is a pydantic model

conf.py settings:

  autodoc_pydantic_model_show_json = True
  autodoc_pydantic_model_show_config = False
  autodoc_pydantic_model_show_config_summary = False
  autodoc_pydantic_model_show_config_member = False
  autodoc_pydantic_model_show_validator_summary = False
  autodoc_pydantic_model_show_validator_members = False
  autodoc_pydantic_model_summary_list_order = 'bysource'  # exception disappears after commenting this line
  autodoc_pydantic_model_member_order = 'bysource'
  autodoc_pydantic_model_signature_prefix = ''
  autodoc_pydantic_validator_list_fields = False
  autodoc_pydantic_settings_show_config_summary = False
  autodoc_pydantic_settings_show_config_member = False
  autodoc_pydantic_field_list_validators = False                               

Probably there are other factors, so 've put the complete code base to github: https://github.com/nchaly/autodoc-pydantic-
bug

Versions installed:

  • sphinx 4.3.0
  • autodoc-pydantic 1.5.1

Build command: sphinx-build -b html docs docs/_build/html -a -E -T

Sphinx trace file:

    # Sphinx version: 4.3.0
    # Python version: 3.9.7 (CPython)
    # Docutils version: 0.16 release
    # Jinja2 version: 3.0.3
    # Last messages:
    #   updating environment:
    #   [new config]
    #   4 added, 0 changed, 0 removed
    #   reading sources... [ 25%] index
    #   reading sources... [ 50%] pages/generated_refs/app
    #   reading sources... [ 75%] pages/generated_refs/app.data_module
    #   
    #   ====================== slowest reading durations =======================
    #   0.020 index
    #   0.009 pages/generated_refs/app
    # Loaded extensions:
    #   sphinx.ext.mathjax (4.3.0) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/mathjax.py
    #   sphinxcontrib.applehelp (1.0.2) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinxcontrib/applehelp/__init__.py
    #   sphinxcontrib.devhelp (1.0.2) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinxcontrib/devhelp/__init__.py
    #   sphinxcontrib.htmlhelp (2.0.0) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinxcontrib/htmlhelp/__init__.py
    #   sphinxcontrib.serializinghtml (1.1.5) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinxcontrib/serializinghtml/__init__.py
    #   sphinxcontrib.qthelp (1.0.3) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinxcontrib/qthelp/__init__.py
    #   alabaster (0.7.12) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/alabaster/__init__.py
    #   sphinx.ext.doctest (4.3.0) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/doctest.py
    #   sphinx.ext.autodoc.preserve_defaults (1.0) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/preserve_defaults.py
    #   sphinx.ext.autodoc.type_comment (4.3.0) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/type_comment.py
    #   sphinx.ext.autodoc (4.3.0) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py
    #   sphinx.ext.autosummary (4.3.0) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autosummary/__init__.py
    #   sphinx.ext.napoleon (4.3.0) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/napoleon/__init__.py
    #   sphinxcontrib.autodoc_pydantic (1.5.1) from /usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/__init__.py
    Traceback (most recent call last):
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/cmd/build.py", line 280, in build_main
        app.build(args.force_all, filenames)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/application.py", line 338, in build
        self.builder.build_all()
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 258, in build_all
        self.build(None, summary=__('all source files'), method='all')
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 308, in build
        updated_docnames = set(self.read())
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 415, in read
        self._read_serial(docnames)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 436, in _read_serial
        self.read_doc(docname)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 476, in read_doc
        doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/io.py", line 189, in read_doc
        pub.publish()
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/core.py", line 217, in publish
        self.document = self.reader.read(self.source, self.parser,
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/io.py", line 109, in read
        self.parse()
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/readers/__init__.py", line 77, in parse
        self.parser.parse(self.input, document)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/parsers.py", line 101, in parse
        self.statemachine.run(inputlines, document, inliner=self.inliner)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 170, in run
        results = StateMachineWS.run(self, input_lines, input_offset,
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/statemachine.py", line 241, in run
        context, next_state, result = self.check_line(
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/statemachine.py", line 459, in check_line
        return method(match, context, next_state)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
        self.section(title, source, style, lineno - 1, messages)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 327, in section
        self.new_subsection(title, lineno, messages)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
        newabsoffset = self.nested_parse(
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
        state_machine.run(block, input_offset, memo=self.memo,
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 196, in run
        results = StateMachineWS.run(self, input_lines, input_offset)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/statemachine.py", line 241, in run
        context, next_state, result = self.check_line(
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/statemachine.py", line 459, in check_line
        return method(match, context, next_state)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2342, in explicit_markup
        nodelist, blank_finish = self.explicit_construct(match)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
        return method(self, expmatch)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2096, in directive
        return self.run_directive(
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
        result = directive_instance.run()
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/directive.py", line 162, in run
        documenter.generate(more_content=self.content)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 984, in generate
        self.document_members(all_members)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 860, in document_members
        documenter.generate(
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 1774, in generate
        return super().generate(more_content=more_content,
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 984, in generate
        self.document_members(all_members)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 1765, in document_members
        super().document_members(all_members)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 860, in document_members
        documenter.generate(
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 1774, in generate
        return super().generate(more_content=more_content,
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 981, in generate
        self.add_content(more_content)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/directives/autodocumenters.py", line 201, in add_content
        self.add_field_summary()
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/directives/autodocumenters.py", line 300, in add_field_summary
        sorted_fields = self._sort_summary_list(filtered_fields)
      File "/usr/local/Caskroom/miniconda/base/envs/logml/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/directives/autodocumenters.py", line 333, in _sort_summary_list
        return sorted(names, key=sort_func)
    TypeError: '<' not supported between instances of 'NoneType' and 'NoneType'

Sphinx 4.3 will include a breaking change for autodoc_pydantic

Hi! I've been lending a hand to contributing to Sphinx itself and discovered that my project no longer built on the upcoming release's branch. I bisected and reported this issue as sphinx-doc/sphinx#9832 and the wonderful Jakob Andersen has tracked the problem down to a change in signature for get_signature_prefix (https://www.sphinx-doc.org/en/master/changes.html#id2), which is apparently overwritten by autodoc_pydantic.

His comment is here: sphinx-doc/sphinx#9832 (comment)

He's written a mitigation but the behaviour will still be broken, just with a clearer error message. The release is expected to come out in the next few days. Thought you'd want a heads up!

Docstring of base class' `__init__` included

Thanks for creating this package, @mansenfranzen -- it's the missing link between the self-documenting objects of Pydantic and, well, actual documentation!

However, I'm not sure I've set it up correctly. Might you know why the class docstrings I'm getting have the Pydantic BaseModel docstring attached? e.g. here: https://psiresp.readthedocs.io/en/latest/_autosummary/psiresp.job.Job.html#psiresp.job.Job

If you look at the source, it includes the first part only:

https://psiresp.readthedocs.io/en/latest/_modules/psiresp/job.html#Job

Is it because I'm using autosummary instead of autopydantic_model or similar?

Support reused validators

I notice that this extension doesn't work with reused validators, i.e. Pydantic's Reuse validators section

from pydantic import BaseModel, validator


def normalize(name: str) -> str:
    """Normalize docstring."""
    return ' '.join((word.capitalize()) for word in name.split(' '))


class Producer(BaseModel):
    name: str

    # validators
    _normalize_name = validator('name', allow_reuse=True)(normalize)


class Consumer(BaseModel):
    name: str

    # validators
    _normalize_name = validator('name', allow_reuse=True)(normalize)


jane_doe = Producer(name='JaNe DOE')
john_doe = Consumer(name='joHN dOe')
assert jane_doe.name == 'Jane Doe'
assert john_doe.name == 'John Doe'

It looks like there is a warning. Note that below is not exactly the above case but just slightly modified from the example I'm messing with:

docstring of example.Consumer.name:1: WARNING: py:obj reference target not found: example.Consumer.normalize

The only problem is the docs don't contain a link to that function.

EDIT: Added simple docstring to normalize for later replies to make sense.

PydanticUndefined is shown even if there is a default_factory

Currently PydanticUndefined is shown if there is a default factory.

Source

habapp: HABAppConfig = Field(default_factory=HABAppConfig, in_file=False)

Output
grafik

I think PydanticUndefined is a bit misleading since the default is not undefined.
How about [has default] (so it's the same as with [required]) so it's clear that the field will have a default when created.

Possible output:

grafik

Config value autodoc_member_order gets ignored

Looks like autodoc_pydantic causes autodoc to ignore the autodoc_member_order config value

  • I've got it set to "bysource"
  • When building with autodoc_pydantic the ordering falls back to the default (alphabetical)
  • Without it, everything works as expected

p.s.: Awesome plugin! I was looking for an alternative for my hacky workaround to hide pydantic model signatures and got so much more 😊

`ClassVar` not supported?

Hello! Wondering if i'm doing something wrong.

I have a model with typing.ClassVars to indicate class, rather than instance attributes:

eg:

from pydantic import BaseModel
from abc import ABC
from typing import ClassVar, Type
from PySide2 import QtWidgets

class Input(BaseModel, ABC):
    """
    Metaclass to parametrically spawn a Qt Input widget for a given type.
   """
    # class variables set by subtypes
    widget: ClassVar[Type[QtWidgets.QWidget]] = None

This throws the following stack:

  File "./autodoc_pydantic/directives/options/composites.py", line 259, in wrapped
    result = func(*args, **kwargs)
  File "./autodoc_pydantic/directives/autodocumenters.py", line 539, in add_directive_header
    self.add_default_value_or_marker()
  File "./autodoc_pydantic/directives/autodocumenters.py", line 586, in add_default_value_or_marker
    if self.needs_required_marker:
  File "./autodoc_pydantic/directives/autodocumenters.py", line 549, in needs_required_marker
    is_required = self.pydantic.inspect.fields.is_required(field_name)
  File "./autodoc_pydantic/inspection.py", line 188, in is_required
    return self.get(field_name).required
  File "./autodoc_pydantic/inspection.py", line 137, in get
    return self.attribute[name]
KeyError: 'widget'

So it seems like it's being seen by the fields list, but not populated into the attributes dictionary? Not sure if this is a me thing, but if not lmk how I can help with a PR :)

Improve CI for pull request

Currently forks trigger the complete CI including code coverage reports. Due to security constraints, environment secrets are not available for foreign pull requests which leads to a failure in code coverage. Hence, code coverage should be excluded from the CI for foreign pull requests.

Model subclasses do not show superclass fields

I cannot find a way to show all fields of a model if it subclasses another BaseModel.

class MyBase(BaseModel):
  field_on_base: str

class MySubclass(MyBase):
  field_on_subclass: str

When generate the model's docs with autopydantic_model both field_on_base and field_on_subclass is shown in the field list however only the docstring of field_on_subclass is shown.

.. currentmodule:: tests

.. autopydantic_model:: MySubclass

Add possible callback to process type and default

I load a str from a yaml file and convert it into a path object.
It's possible to change certain paths so e.g. logfiles get generated in a different folder.

Currently this

logging: Path = Field(Path('log'), description='Folder where the logs will be written to')

renders like that

field logging: Optional[pathlib.Path] = WindowsPath('log')

However since the user is editing a yaml file I'd like to process both the type and the default value to be a string.
E.g. so it looks like that.

field logging: Optional[str] = 'log'

I'm aware that this is a rather special use case.
So how about a configurable callback that gets inserted here.
The callback would get the PydanticFieldDocumenter and the default passed in. If it returns a string that's the value for documentation, otherwise object_description would be called.
For the type I have not yet found the code part where it happens - could you provide me with a hint?

What do you think? Is this something where I can create a PR and you see it getting merged or do you have a better idea how this can achieved?
Thank you for your help!

Support pydantic 1.9

Currently 3 tests fail with pydantic 1.9 release half an hour ago. Those tests do not seem critical however should be fixed anyway.

Generics not supported?

invalid signature for autopydantic_model ('saf.collect.beacons::PipelineRunContext[BeaconsConfig]')
make: *** [Makefile:20: coverage] Error 2
class BeaconsConfig(CollectConfigBase):
    """
    Configuration schema for the beacons collect plugin.
    """

    beacons: List[str]

async def collect(*, ctx: PipelineRunContext[BeaconsConfig]) -> AsyncIterator[BeaconCollectedEvent]:
    """
    Method called to collect events.
    """
PipelineRunContextConfigType = TypeVar("PipelineRunContextConfigType", bound=NonMutableConfig)


class PipelineRunContext(GenericModel, Generic[PipelineRunContextConfigType]):
    """
    Class representing a pipeline run context.
    """

    config: PipelineRunContextConfigType

Numpy NDArray breaks inspection module

Thanks so much for this library! I've just discovered it.

autodoc_pydantic is crashing for me in inspection.py, where checking to see if "obj" is a subclass of "BaseModel"

All of the crashes are from checking various objects from numpy. The simplest reproducible example I found is:

import numpy as np
from numpy.typing import NDArray

>> issinstance(NDArray, type)  # returns True
>> issubclass(NDArray, BaseModel) # throws TypeError

As a workaround, I edited the file to put a try/except in is_pydantic_model:

459     @staticmethod                                                                                   
460     def is_pydantic_model(obj: Any) -> bool:                                                        
461         """Determine if object is a valid pydantic model.                                           
462                                                                                                     
463         """                                                                                         
464         try:                                                                                        
465             if isinstance(obj, type):                                                               
466                 return issubclass(obj, BaseModel)                                                   
467         except TypeError:                                                                                     
468             pass                                                                                    
469         return False         

The fallback behavior of returning False seems to work.

Error parsing root validators

Hello all,

I really appreciate this Sphinx extension, but recently I've been running into some issues getting my docs to build. Would appreciate any guidance on what may be going onβ€”from the traceback, it seems like my installation is getting tripped up trying to parse root validators. I tested a few versions of autodoc_pydantic, and it seems to appear in β‰₯ v.1.3

Here's the full traceback that Sphinx provided:

# Sphinx version: 4.2.0
# Python version: 3.9.7 (CPython)
# Docutils version: 0.17.1 release
# Jinja2 version: 3.0.1
# Last messages:
#   failed: <lambda>() missing 1 required positional argument: 'aliased'
#   building [mo]: targets for 0 po files that are out of date
#   building [html]: targets for 14 source files that are out of date
#   updating environment:
#   [new config]
#   14 added, 0 changed, 0 removed
#   reading sources... [  7%] index
#   reading sources... [ 14%] modules
#   reading sources... [ 21%] nmt
#   reading sources... [ 28%] nmt.common
# Loaded extensions:
#   sphinx.ext.mathjax (4.2.0) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/mathjax.py
#   sphinxcontrib.applehelp (1.0.2) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/applehelp/__init__.py
#   sphinxcontrib.devhelp (1.0.2) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/devhelp/__init__.py
#   sphinxcontrib.htmlhelp (2.0.0) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/htmlhelp/__init__.py
#   sphinxcontrib.serializinghtml (1.1.5) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/serializinghtml/__init__.py
#   sphinxcontrib.qthelp (1.0.3) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/qthelp/__init__.py
#   alabaster (0.7.12) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/alabaster/__init__.py
#   sphinx.ext.autodoc.preserve_defaults (1.0) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/autodoc/preserve_defaults.py
#   sphinx.ext.autodoc.type_comment (4.2.0) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/autodoc/type_comment.py
#   sphinx.ext.autodoc (4.2.0) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py
#   sphinx.ext.graphviz (4.2.0) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/graphviz.py
#   sphinx.ext.imgmath (4.2.0) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/imgmath.py
#   sphinxcontrib.napoleon (0.7) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/napoleon/__init__.py
#   sphinxcontrib.autodoc_pydantic (1.4.0) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/__init__.py
#   furo (2021.09.22) from /opt/miniconda3/envs/nmt/lib/python3.9/site-packages/furo/__init__.py
Traceback (most recent call last):
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/cmd/build.py", line 280, in build_main
    app.build(args.force_all, filenames)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/application.py", line 343, in build
    self.builder.build_update()
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 293, in build_update
    self.build(to_build,
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 307, in build
    updated_docnames = set(self.read())
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 414, in read
    self._read_serial(docnames)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 435, in _read_serial
    self.read_doc(docname)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/builders/__init__.py", line 475, in read_doc
    doctree = read_doc(self.app, self.env, self.env.doc2path(docname))
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/io.py", line 189, in read_doc
    pub.publish()
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/core.py", line 217, in publish
    self.document = self.reader.read(self.source, self.parser,
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/io.py", line 109, in read
    self.parse()
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/readers/__init__.py", line 78, in parse
    self.parser.parse(self.input, document)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/parsers.py", line 101, in parse
    self.statemachine.run(inputlines, document, inliner=self.inliner)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 170, in run
    results = StateMachineWS.run(self, input_lines, input_offset,
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
    newabsoffset = self.nested_parse(
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2769, in underline
    self.section(title, source, style, lineno - 1, messages)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 327, in section
    self.new_subsection(title, lineno, messages)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 393, in new_subsection
    newabsoffset = self.nested_parse(
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 281, in nested_parse
    state_machine.run(block, input_offset, memo=self.memo,
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 196, in run
    results = StateMachineWS.run(self, input_lines, input_offset)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/statemachine.py", line 239, in run
    context, next_state, result = self.check_line(
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/statemachine.py", line 451, in check_line
    return method(match, context, next_state)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2342, in explicit_markup
    nodelist, blank_finish = self.explicit_construct(match)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2354, in explicit_construct
    return method(self, expmatch)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2096, in directive
    return self.run_directive(
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/docutils/parsers/rst/states.py", line 2146, in run_directive
    result = directive_instance.run()
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/autodoc/directive.py", line 162, in run
    documenter.generate(more_content=self.content)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 983, in generate
    self.document_members(all_members)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 860, in document_members
    documenter.generate(
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 1773, in generate
    return super().generate(more_content=more_content,
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinx/ext/autodoc/__init__.py", line 980, in generate
    self.add_content(more_content)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/autodoc.py", line 241, in add_content
    self.add_field_summary()
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/autodoc.py", line 331, in add_field_summary
    wrapper = ModelWrapper(self.object)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 87, in __init__
    self.field_validator_names = self.get_field_validator_names()
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 110, in get_field_validator_names
    field_names["*"].extend(self.get_names_from_root_validators())
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 121, in get_names_from_root_validators
    pre_root = get_name(self.model.__pre_root_validators__)
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 119, in get_name
    return [validator[1].__name__ for validator in validators]
  File "/opt/miniconda3/envs/nmt/lib/python3.9/site-packages/sphinxcontrib/autodoc_pydantic/inspection.py", line 119, in <listcomp>
    return [validator[1].__name__ for validator in validators]
TypeError: 'function' object is not subscriptable

Add support for root validators.

Hello! Thank you for the great work.

I was wondering if you were planning on adding support for documenting root validators, like you do field validators.

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.