Skip to content

gh-144957: Add test for lazy imports with __getattr__ - #145330

Closed
gourijain029-del wants to merge 3 commits into
python:mainfrom
gourijain029-del:gh-144957-lazy-import-test
Closed

gh-144957: Add test for lazy imports with __getattr__#145330
gourijain029-del wants to merge 3 commits into
python:mainfrom
gourijain029-del:gh-144957-lazy-import-test

Conversation

@gourijain029-del

@gourijain029-delgourijain029-del commented Feb 27, 2026

Copy link
Copy Markdown

Adds a regression test for lazy imports working with modules that use __getattr__.

The issue reported that lazy from typing import Match would fail since Match is provided by typing.__getattr__ rather than being in the module dict. Testing shows this works correctly in current main - the existing code in register_lazy_on_parent() already checks for __getattr__ and skips adding lazy import objects to those modules.

This test documents the expected behavior and prevents future regressions.

@bedevere-app

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

Adds regression test to verify lazy imports work correctly with
modules that use __getattr__ for dynamic attributes (e.g. typing.Match).
The issue appears to be already fixed in current main branch.
@johnslavik

johnslavik commented Feb 27, 2026

Copy link
Copy Markdown
Member

Testing shows this works correctly in current main - the existing code in register_lazy_on_parent() already checks for __getattr__ and skips adding lazy import objects to those modules.

Your test doesn't pass locally for me:

❯ ./python.exe-munittestLib.test.test_import.test_lazy_imports
....................................................F............BAR_MODULE_LOADED
...........................
======================================================================FAIL: test_lazy_import_with_getattr (Lib.test.test_import.test_lazy_imports.LazyImportTests.test_lazy_import_with_getattr)
Lazyimportsworkwithmodule__getattr__ (gh-144957).
----------------------------------------------------------------------Traceback (mostrecentcalllast):
File"/Users/bartosz.slawecki/Python/cpython/Lib/test/test_import/test_lazy_imports.py", line101, intest_lazy_import_with_getattrself.assertEqual(result.returncode, 0, result.stderr)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^AssertionError: 1!=0 : Traceback (mostrecentcalllast):
File"<string>", line4, in<module>ImportError: deferredimportof'typing.Match'raisedanexceptionduringresolutionTheaboveexceptionwasthedirectcauseofthefollowingexception:
Traceback (mostrecentcalllast):
File"<string>", line5, in<module>print(Match)
^^^^^ImportError: cannotimportname'Match'from'typing' (/Users/bartosz.slawecki/Python/cpython/Lib/typing.py)

Presumably there's something with CI, needs investigation.
EDIT: See #145334.

@gourijain029-del
gourijain029-delforce-pushed the gh-144957-lazy-import-test branch from 122ad9f to 3e63300CompareFebruary 27, 2026 20:59
When resolving lazy imports, check if a lazy import object was found
and the module has __getattr__. If so, try calling __getattr__ first
before using the lazy import object.
Comment on lines +90 to +103
code = textwrap.dedent("""
import sys
sys.set_lazy_imports("normal")
lazy from test.test_import.data.lazy_imports.module_with_getattr import dynamic_attr
assert dynamic_attr == "from_getattr"
print("OK")
""")
result = subprocess.run(
[sys.executable, "-c", code],
capture_output=True,
text=True
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("OK", result.stdout)

@johnslavikjohnslavikFeb 27, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Less prone to false positives:

Suggested change
code=textwrap.dedent("""
importsys
sys.set_lazy_imports("normal")
lazyfromtest.test_import.data.lazy_imports.module_with_getattrimportdynamic_attr
assertdynamic_attr=="from_getattr"
print("OK")
""")
result=subprocess.run(
[sys.executable, "-c", code],
capture_output=True,
text=True
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("OK", result.stdout)
code=textwrap.dedent("""
importsys
sys.set_lazy_imports("normal")
lazyfromtest.test_lazy_import.data.module_with_getattrimportdynamic_attr
print(repr(dynamic_attr))
""")
result=subprocess.run(
[sys.executable, "-c", code],
capture_output=True,
text=True
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("'from_getattr'", result.stdout)

@pythonpython deleted a comment from bedevere-appBotFeb 27, 2026
@pythonpython deleted a comment from bedevere-appBotFeb 27, 2026
@pablogsal

Copy link
Copy Markdown
Member

This user is creating a lot of AI generated PRs see #145276

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@gourijain029-del@johnslavik@pablogsal@Yhg1s