Skip to content

fix: catch recursion in Alias.resolved - #115

Closed
tlambert03 wants to merge 2 commits into
mkdocstrings:masterfrom
tlambert03:recursion
Closed

fix: catch recursion in Alias.resolved#115
tlambert03 wants to merge 2 commits into
mkdocstrings:masterfrom
tlambert03:recursion

Conversation

@tlambert03

@tlambert03tlambert03 commented Nov 19, 2022

Copy link
Copy Markdown
Contributor

hey @pawamoy

I'm sure this is probably your least favorite bug at this point 😂 ... but I ran into an Alias resolution recursion error, similar to #83

Full traceback:
Traceback (most recent call last):
File "/Users/talley/mambaforge/envs/mmcore/bin/mkdocs", line 8, in <module>
sys.exit(cli())
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/click/core.py", line 1130, in __call__returnself.main(*args, **kwargs)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/click/core.py", line 1055, in main
rv =self.invoke(ctx)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/click/core.py", line 1657, in invokereturn _process_result(sub_ctx.command.invoke(sub_ctx))
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/click/core.py", line 1404, in invokereturn ctx.invoke(self.callback, **ctx.params)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/click/core.py", line 760, in invokereturn __callback(*args, **kwargs)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/mkdocs/__main__.py", line 234, in serve_command
serve.serve(dev_addr=dev_addr, livereload=livereload, watch=watch, **kwargs)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 83, in serve
builder(config)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/mkdocs/commands/serve.py", line 76, in builder
build(config, live_server=live_server, dirty=dirty)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/mkdocs/commands/build.py", line 308, in build
_populate_page(file.page, config, files, dirty)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/mkdocs/commands/build.py", line 181, in _populate_page
page.render(config, files)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/mkdocs/structure/pages.py", line 270, in renderself.content = md.convert(self.markdown)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/markdown/core.py", line 264, in convert
root =self.parser.parseDocument(self.lines).getroot()
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/markdown/blockparser.py", line 90, in parseDocumentself.parseChunk(self.root, '\n'.join(lines))
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/markdown/blockparser.py", line 105, in parseChunkself.parseBlocks(parent, text.split('\n\n'))
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/markdown/blockparser.py", line 123, in parseBlocksif processor.run(parent, blocks) isnotFalse:
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/mkdocstrings/extension.py", line 121, in run
html, handler, data =self._process_block(identifier, block, heading_level)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/mkdocstrings/extension.py", line 195, in _process_block
data: CollectorItem = handler.collect(identifier, options)
File "/Users/talley/mambaforge/envs/mmcore/lib/python3.10/site-packages/mkdocstrings_handlers/python/handler.py", line 199, in collect
unresolved, iterations = loader.resolve_aliases(implicit=False, external=False)
File "/Users/talley/dev/forks/griffe/src/griffe/loader.py", line 217, in resolve_aliases
next_resolved, next_unresolved =self.resolve_module_aliases(module, implicit, external)
File "/Users/talley/dev/forks/griffe/src/griffe/loader.py", line 357, in resolve_module_aliases
sub_resolved, sub_unresolved =self.resolve_module_aliases(
File "/Users/talley/dev/forks/griffe/src/griffe/loader.py", line 338, in resolve_module_aliases
member.resolve_target() # type:ignore[union-attr]
File "/Users/talley/dev/forks/griffe/src/griffe/dataclasses.py", line 967, in resolve_targetself._target.aliases[self.path] =self# type:ignore[union-attr]# we just set the target
File "/Users/talley/dev/forks/griffe/src/griffe/dataclasses.py", line 827, in __getattr__
attr =getattr(self.target, name)
File "/Users/talley/dev/forks/griffe/src/griffe/dataclasses.py", line 935, in targetifnotself.resolved:
File "/Users/talley/dev/forks/griffe/src/griffe/dataclasses.py", line 976, in resolvedreturnself._target isnotNoneand (notself._target.is_alias orself._target.resolved) # type:ignore[union-attr]
File "/Users/talley/dev/forks/griffe/src/griffe/dataclasses.py", line 976, in resolvedreturnself._target isnotNoneand (notself._target.is_alias orself._target.resolved) # type:ignore[union-attr]
File "/Users/talley/dev/forks/griffe/src/griffe/dataclasses.py", line 976, in resolvedreturnself._target isnotNoneand (notself._target.is_alias orself._target.resolved) # type:ignore[union-attr]
[Previous line repeated 971 more times]
RecursionError: maximum recursion depth exceeded

In this case, it does appear to be a legitimate Cyclic Alias... that is self._target._target is self.

For what it's worth, the class I was trying to document with mkdocstrings is from pymmcore (pip install pymmcore)

::: pymmcore.CMMCore

... and that class is a SWIG wrapper with a .pyi type stub providing the signatures and docstring. And the cyclic aliases look like:

<Alias('CMMCore', 'pymmcore.pymmcore_swig.CMMCore')>
<Alias('CMMCore', 'pymmcore._pymmcore_swig.CMMCore')>
<Alias('CMMCore', 'pymmcore.pymmcore_swig.CMMCore')>
<Alias('CMMCore', 'pymmcore._pymmcore_swig.CMMCore')>
...

I opened this as a PR rather than an issue, since this does fix the docs building (the page looks exactly how I'd expect it to)... but I'm not sure what the actual best fix is. Feel free to close or suggest a better approach here for me to implement

@tlambert03tlambert03 changed the title catch recursioncatch recursion in Alias.resolvedNov 19, 2022
@pawamoy

Copy link
Copy Markdown
Member

least favorite bug

Not agaaaaaaaaaaaaaaaaaaain 😂
Yeah I hate this error, but that's entirely my fault 👐
I'm working on fixing the design (implicitness triggering alias errors all the time), but I struggle to find something explicit
that would also not require wrapping every attribute access in a try/except or contextlib.suppress block 🤔

For now I'll continue to apply bandages on this poor project 😢

Thanks for the report and PR!

Catching recursion errors is like the absolute last resort haha.

I read SWIG wrapper + type stubs, I understand compiled module?
I recall having dealt with a similar case in Numpy. Here's the special case:

orparent_module_name=="numpy.core._multiarray_umath"
andchild_module_name=="numpy.core.multiarray"

Maybe a similar situation here.

@tlambert03

Copy link
Copy Markdown
ContributorAuthor

Catching recursion errors is like the absolute last resort haha.

yep. I changed this PR to an attribute check, and that also fixes mkdocs build for me. But if you'd prefer to close it and look into a different fix, I won't be offended in the least :) and can open a bug issue as a reminder.

I read SWIG wrapper + type stubs, I understand compiled module?

yep, compiled module.

Maybe a similar situation here.

yeah I think so (pymmcore.pymmcore_swig.CMMCore -> pymmcore._pymmcore_swig.CMMCore -> pymmcore.pymmcore_swig.CMMCore)

@tlambert03tlambert03 changed the title catch recursion in Alias.resolvedfix: catch recursion in Alias.resolvedNov 19, 2022
pawamoy added a commit that referenced this pull request Nov 30, 2022
Also add support for the `pymmcore` project.
PR #115: #115
@pawamoy

Copy link
Copy Markdown
Member

Closing in favor of 9a2a711 🙂

@pawamoypawamoy closed this Nov 30, 2022
@tlambert03

Copy link
Copy Markdown
ContributorAuthor

wow 😮 ... special casing it huh? don't think it's gonna happen again?

@pawamoy

Copy link
Copy Markdown
Member

It will probably happen again, but I want to improve the alias resolution mechanism, and maybe provide a way for registering cycles in this new "cyclic relationships" map, so that project suffering from it can fix it themselves.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@tlambert03@pawamoy