Skip to content

bug: RecursionError when subclass is attribute #368

@patrick-kidger

Description

@patrick-kidger

Description of the bug

Code of the following form produces a RecursionError in griffe:

class X:
    pass

class Y(X):
    pass

X.Y = Y

To Reproduce

https://github.com/patrick-kidger/griffe-error

FWIW I'm providing this via mkdocs, as I didn't quite piece together the correct griffe.load(...) invocation to obtain this error. A simple griffe.load("mylib", force_inspection=True) does not raise the error.

Full traceback

Full traceback
INFO    -  Building documentation...
INFO    -  Cleaning site directory
ERROR   -  Error reading page 'foo.md': maximum recursion depth exceeded
Traceback (most recent call last):
  File ".../.venv/lib/python3.12/site-packages/click/core.py", line 1161, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/click/core.py", line 1082, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/click/core.py", line 1697, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/click/core.py", line 1443, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/click/core.py", line 788, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/mkdocs/__main__.py", line 272, in serve_command
    serve.serve(**kwargs)
  File ".../.venv/lib/python3.12/site-packages/mkdocs/commands/serve.py", line 85, in serve
    builder(config)
  File ".../.venv/lib/python3.12/site-packages/mkdocs/commands/serve.py", line 67, in builder
    build(config, serve_url=None if is_clean else serve_url, dirty=is_dirty)
  File ".../.venv/lib/python3.12/site-packages/mkdocs/commands/build.py", line 310, in build
    _populate_page(file.page, config, files, dirty)
  File ".../.venv/lib/python3.12/site-packages/mkdocs/commands/build.py", line 167, in _populate_page
    page.render(config, files)
  File ".../.venv/lib/python3.12/site-packages/mkdocs/structure/pages.py", line 285, in render
    self.content = md.convert(self.markdown)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/markdown/core.py", line 357, in convert
    root = self.parser.parseDocument(self.lines).getroot()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/markdown/blockparser.py", line 117, in parseDocument
    self.parseChunk(self.root, '\n'.join(lines))
  File ".../.venv/lib/python3.12/site-packages/markdown/blockparser.py", line 136, in parseChunk
    self.parseBlocks(parent, text.split('\n\n'))
  File ".../.venv/lib/python3.12/site-packages/markdown/blockparser.py", line 158, in parseBlocks
    if processor.run(parent, blocks) is not False:
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/mkdocstrings/_internal/extension.py", line 126, in run
    html, handler, data = self._process_block(identifier, block, heading_level)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/mkdocstrings/_internal/extension.py", line 201, in _process_block
    rendered = handler.render(data, options)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/mkdocstrings_handlers/python/_internal/handler.py", line 294, in render
    return template.render(
           ^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/jinja2/environment.py", line 1295, in render
    self.environment.handle_exception()
  File ".../.venv/lib/python3.12/site-packages/jinja2/environment.py", line 942, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File ".../.venv/lib/python3.12/site-packages/mkdocstrings_handlers/python/templates/material/class.html.jinja", line 1, in top-level template code
    {% extends "_base/class.html.jinja" %}
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja", line 120, in top-level template code
    {% block contents scoped %}
^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja", line 220, in block 'contents'
    {% block children scoped %}


... some thousand lines from jinja templating removed for brevity ...


  File ".../.venv/lib/python3.12/site-packages/mkdocstrings_handlers/python/templates/material/children.html.jinja", line 1, in top-level template code
    {% extends "_base/children.html.jinja" %}
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja", line 13, in top-level template code
    {% if obj.all_members %}
    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/jinja2/environment.py", line 490, in getattr
    return getattr(obj, attribute)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/mixins.py", line 299, in all_members
    if self.is_class:  # type: ignore[attr-defined]
       ^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 1345, in is_class
    return self.final_target.is_class
           ^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 1693, in final_target
    if target.path in paths_seen:
       ^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 1152, in path
    return f"{self.parent.path}.{self.name}"  # type: ignore[union-attr]
              ^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 1152, in path
    return f"{self.parent.path}.{self.name}"  # type: ignore[union-attr]
              ^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 1152, in path
    return f"{self.parent.path}.{self.name}"  # type: ignore[union-attr]
              ^^^^^^^^^^^^^^^^
  [Previous line repeated 134 more times]
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 856, in path
    return self.canonical_path
           ^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 868, in canonical_path
    return f"{self.parent.path}.{self.name}"
              ^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 856, in path
    return self.canonical_path
           ^^^^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 868, in canonical_path
    return f"{self.parent.path}.{self.name}"
              ^^^^^^^^^^^^^^^^
  File ".../.venv/lib/python3.12/site-packages/_griffe/models.py", line 856, in path
    return self.canonical_path
           ^^^^^^^^^^^^^^^^^^^
RecursionError: maximum recursion depth exceeded

Expected behavior

No crash :)

Environment information

- __System__: macOS-15.3.2-arm64-arm-64bit
- __Python__: cpython 3.12.0 (.../.venv/bin/python3)
- __Environment variables__:
- __Installed packages__:
  - `griffe` v1.6.2

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy