PyO3 v0.27 and earlier did not exhibit this behavior.
Traceback (most recent call last):
File "/home/raven/pyo3-recursive-enum/.venv/bin/pdoc", line 7, in <module>
sys.exit(cli())
~~~^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/__main__.py", line 198, in cli
pdoc.pdoc(
~~~~~~~~~^
*opts.modules,
^^^^^^^^^^^^^^
output_directory=opts.output_directory,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/__init__.py", line 548, in pdoc
out = render.html_module(module, all_modules)
File "/usr/lib/python3.14/contextlib.py", line 85, in inner
return func(*args, **kwds)
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/render.py", line 106, in html_module
return env.get_template("module.html.jinja2").render(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
module=module,
^^^^^^^^^^^^^^
...<7 lines>...
mtime=mtime,
^^^^^^^^^^^^
)
^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/jinja2/environment.py", line 1295, in render
self.environment.handle_exception()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/jinja2/environment.py", line 942, in handle_exception
raise rewrite_traceback_stack(source=source)
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/templates/default/module.html.jinja2", line 315, in top-level template code
{%- if loop.nextitem -%}
^^^^^^^^^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/templates/default/frame.html.jinja2", line 36, in top-level template code
{% block body %}
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/templates/default/frame.html.jinja2", line 40, in block 'body'
<div>{% block nav %}{% endblock %}</div>
^^^^^^^^^^^^^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/templates/default/module.html.jinja2", line 56, in block 'nav'
{% block nav_members %}
^^^^^^^^^^^^^^^^^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/templates/default/module.html.jinja2", line 57, in block 'nav_members'
{% if module.members %}
^^^^^^^^^^^^^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/jinja2/environment.py", line 490, in getattr
return getattr(obj, attribute)
File "/usr/lib/python3.14/functools.py", line 1126, in __get__
val = self.func(instance)
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc.py", line 342, in members
doc_pyi.include_typeinfo_from_stub_files(self)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc_pyi.py", line 140, in include_typeinfo_from_stub_files
_prepare_module(module)
~~~~~~~~~~~~~~~^^^^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc_pyi.py", line 81, in _prepare_module
_prepare_module(member)
~~~~~~~~~~~~~~~^^^^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc_pyi.py", line 81, in _prepare_module
_prepare_module(member)
~~~~~~~~~~~~~~~^^^^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc_pyi.py", line 81, in _prepare_module
_prepare_module(member)
~~~~~~~~~~~~~~~^^^^^^^^
[Previous line repeated 973 more times]
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc_pyi.py", line 79, in _prepare_module
for member in ns.members.values():
^^^^^^^^^^
File "/usr/lib/python3.14/functools.py", line 1126, in __get__
val = self.func(instance)
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc.py", line 261, in members
for name, obj in self._member_objects.items():
^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/functools.py", line 1126, in __get__
val = self.func(instance)
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc.py", line 737, in _member_objects
for name in self._var_docstrings:
^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/functools.py", line 1126, in __get__
val = self.func(instance)
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc.py", line 621, in _var_docstrings
for name, docstr in doc_ast.walk_tree(cls).var_docstrings.items():
~~~~~~~~~~~~~~~~~^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc_ast.py", line 104, in walk_tree
return _walk_tree(parse(obj))
~~~~~^^^^^
File "/home/raven/pyo3-recursive-enum/.venv/lib/python3.14/site-packages/pdoc/doc_ast.py", line 71, in parse
src = get_source(obj)
RecursionError: maximum recursion depth exceeded
pdoc: 16.0.0
Python: 3.14.2
Platform: Linux-6.18.7-arch1-1-x86_64-with-glibc2.43
Problem Description
pdocenters infinite recursion when documenting extension modules created with PyO3 v0.28+, when the modulecontains "complex enums" (Rust sum types translated into nested Python classes). The bug is only triggered when a
.pyityping stubs file is also present. The contents of this.pyifile does not matter, it may even be empty.PyO3 v0.27 and earlier did not exhibit this behavior.
Steps to reproduce the behavior:
maturin develop. I've created a test extension module that is sufficient to reproduce the problem: pyo3-recursive-enum.pdoc -o html complex_enum.RecursionError: maximum recursion depth exceededexception is thrown.Full backtrace:
System Information