gh-144957: Add test for lazy imports with __getattr__#145330
gh-144957: Add test for lazy imports with __getattr__#145330gourijain029-del wants to merge 2 commits intopython:mainfrom
Conversation
|
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 |
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.
Your test doesn't pass locally for me: ❯ ./python.exe -m unittest Lib.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)
Lazy imports work with module __getattr__ (gh-144957).
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/bartosz.slawecki/Python/cpython/Lib/test/test_import/test_lazy_imports.py", line 101, in test_lazy_import_with_getattr
self.assertEqual(result.returncode, 0, result.stderr)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 1 != 0 : Traceback (most recent call last):
File "<string>", line 4, in <module>
ImportError: deferred import of 'typing.Match' raised an exception during resolution
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<string>", line 5, in <module>
print(Match)
^^^^^
ImportError: cannot import name 'Match' from 'typing' (/Users/bartosz.slawecki/Python/cpython/Lib/typing.py)Presumably there's something with CI, needs investigation. |
122ad9f to
3e63300
Compare
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.
| 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) |
There was a problem hiding this comment.
Less prone to false positives:
| 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) | |
| code = textwrap.dedent(""" | |
| import sys | |
| sys.set_lazy_imports("normal") | |
| lazy from test.test_import.data.lazy_imports.module_with_getattr import dynamic_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) |
Adds a regression test for lazy imports working with modules that use
__getattr__.The issue reported that
lazy from typing import Matchwould fail sinceMatchis provided bytyping.__getattr__rather than being in the module dict. Testing shows this works correctly in current main - the existing code inregister_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.
__getattr__when reifying #144957