Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leverage importlib.reload for reloading modules #11679

Merged
merged 8 commits into from Sep 13, 2023

Conversation

godlygeek
Copy link
Contributor

Feature or Bugfix

  • Bugfix

Purpose

Rather than directly manipulating sys.modules ourselves, rely on importlib.reload to do it, as it works in more cases (particularly for Rust extension modules built with PyO3).

Also, import modules with typing.TYPE_CHECKING set to False first, and reload them with it set to true. This way, if the reload fails, things are likely to still be in a valid state from the first, successful import.

Relates

Rather than directly manipulating `sys.modules` ourselves, rely on
`importlib.reload` to do it, as it works in more cases (particularly for
Rust extension modules built with PyO3).

Also, import modules with `typing.TYPE_CHECKING` set to `False` first,
and reload them with it set to `True`. This way, if the reload fails,
things are likely to still be in a valid state from the first,
successful import.
typing.TYPE_CHECKING = False
module = import_module(modname, warningiserror=warningiserror)
# Ignore failures; we've already successfully loaded these modules.
with contextlib.suppress(Exception):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a narrower exception type than Exception?

Copy link
Contributor Author

@godlygeek godlygeek Sep 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so -- at least, not without sacrificing correctness. If I change this to just catch ImportError, then doing:

.. automodule:: pydantic

fails with::

>       _PartialClsOrStaticMethod: TypeAlias = Union[classmethod[Any, Any, Any], staticmethod[Any, Any], partialmethod[Any]]
E       TypeError: type 'classmethod' is not subscriptable

Let me flip the question around on you: given that the module was already imported successfully with typing.TYPE_CHECKING == False, which sorts of exceptions encountered while reloading the module with typing.TYPE_CHECKING == True should cause import_object to fail instead of using the already successfully imported module?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I take it from your testing that e.g. if pydantic is successfully imported, and then fails on the reload, the initial imported module is still usable, coherent, etc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's my expectation, and it seems to be the case for pydantic, at least up to the point where a basic .. automodule:: pydantic succeeds. I'm not sure how to test it more thoroughly, though. I do suspect that this is still going to be fragile in ways that we can't predict, the hope is just that it works for more cases than both what's in #11511 and what's in #11645

@godlygeek godlygeek marked this pull request as draft September 8, 2023 00:26
@godlygeek
Copy link
Contributor Author

I'm gonna mark this as draft for now, and investigate the report in #11662 (comment) that this still isn't enough for some modules...

@AA-Turner
Copy link
Member

Matt -- I've added a basic escape hatch through SPHINX_AUTODOC_DO_NOT_RELOAD_MODULES.

@AA-Turner AA-Turner marked this pull request as ready for review September 13, 2023 01:46
@AA-Turner
Copy link
Member

I'd like to merge this as it is an improvement over the status quo, even if not perfect -- @godlygeek did you make any progress in your investigations, or any other observations that would halt merging this?

A

@godlygeek
Copy link
Contributor Author

Nothing beyond what I noted in #11662 (comment)

I still think this is probably more correct than both what shipped in 7.2.0 and what shipped in 7.2.5, but I also think that this entire approach of setting typing.TYPE_CHECKING = True is fundamentally unwise. I think adding an escape hatch is a very good idea, but given that we know this still doesn't work successfully for some modules (even some that worked with 7.2.4!), I really think that this should be opt-in rather than opt-out.

@AA-Turner AA-Turner merged commit 43d6975 into sphinx-doc:master Sep 13, 2023
27 checks passed
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants