gh-143469: enable LOAD_ATTR_MODULE specialization even if __getattr__ is defined (#143470)

This commit is contained in:
Kumar Aditya 2026-01-06 22:09:18 +05:30 committed by GitHub
parent 05406b221d
commit faa3dc7c64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 40 additions and 7 deletions

View File

@ -1909,6 +1909,44 @@ class TestSpecializer(TestBase):
self.assert_no_opcode(my_list_append, "CALL_LIST_APPEND")
self.assert_no_opcode(my_list_append, "CALL")
@cpython_only
@requires_specialization_ft
def test_load_attr_module_with_getattr(self):
module = types.ModuleType("test_module_with_getattr")
module.__dict__["some_attr"] = "foo"
def module_getattr(name):
if name == "missing_attr":
return 42
raise AttributeError(f"module has no attribute {name}")
module.__dict__["__getattr__"] = module_getattr
import sys
sys.modules.pop("test_module_with_getattr", None)
sys.modules["test_module_with_getattr"] = module
try:
def load_module_attr_present():
import test_module_with_getattr
return test_module_with_getattr.some_attr
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
self.assertEqual(load_module_attr_present(), "foo")
self.assert_specialized(load_module_attr_present, "LOAD_ATTR_MODULE")
self.assert_no_opcode(load_module_attr_present, "LOAD_ATTR")
def load_module_attr_missing():
import test_module_with_getattr
return test_module_with_getattr.missing_attr
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
self.assertEqual(load_module_attr_missing(), 42)
self.assert_no_opcode(load_module_attr_missing, "LOAD_ATTR_MODULE")
finally:
sys.modules.pop("test_module_with_getattr", None)
if __name__ == "__main__":
unittest.main()

View File

@ -0,0 +1 @@
Enable :opcode:`!LOAD_ATTR_MODULE` specialization even if :func:`!__getattr__` is defined in module.

View File

@ -366,14 +366,8 @@ specialize_module_load_attr_lock_held(PyDictObject *dict, _Py_CODEUNIT *instr, P
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_STRING);
return -1;
}
Py_ssize_t index = _PyDict_LookupIndex(dict, &_Py_ID(__getattr__));
Py_ssize_t index = _PyDict_LookupIndex(dict, name);
assert(index != DKIX_ERROR);
if (index != DKIX_EMPTY) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND);
return -1;
}
index = _PyDict_LookupIndex(dict, name);
assert (index != DKIX_ERROR);
if (index != (uint16_t)index) {
SPECIALIZATION_FAIL(LOAD_ATTR,
index == DKIX_EMPTY ?