Skip to content

Commit 22dacff

Browse files
Fix a regression in 2.13.2 where a RunTimeError could be raised unexpectedly (#1959) (#1962)
* Add a unit test for broken __getattr__ in extension modules Co-authored-by: Florian Bruhin <[email protected]> Closes #1958 (cherry picked from commit 9eb8c47) Co-authored-by: Pierre Sassoulas <[email protected]>
1 parent fe058bf commit 22dacff

File tree

4 files changed

+36
-2
lines changed

4 files changed

+36
-2
lines changed

ChangeLog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ What's New in astroid 2.13.3?
1212
=============================
1313
Release date: TBA
1414

15+
* Fix a regression in 2.13.2 where a RunTimeError could be raised unexpectedly.
1516

17+
Closes #1958
1618

1719
What's New in astroid 2.13.2?
1820
=============================

astroid/raw_building.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,17 @@ def _build_from_function(
324324
object_build_function(node, member, name)
325325

326326

327+
def _safe_has_attribute(obj, member: str) -> bool:
328+
"""Required because unexpected RunTimeError can be raised.
329+
330+
See https://github.com/PyCQA/astroid/issues/1958
331+
"""
332+
try:
333+
return hasattr(obj, member)
334+
except Exception: # pylint: disable=broad-except
335+
return False
336+
337+
327338
class InspectBuilder:
328339
"""class for building nodes from living object
329340
@@ -419,7 +430,7 @@ def object_build(
419430
# This should be called for Jython, where some builtin
420431
# methods aren't caught by isbuiltin branch.
421432
_build_from_function(node, name, member, self._module)
422-
elif hasattr(member, "__all__"):
433+
elif _safe_has_attribute(member, "__all__"):
423434
module = build_module(name)
424435
_attach_local_node(node, module, name)
425436
# recursion
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Broken:
2+
3+
def __getattr__(self, name):
4+
raise Exception("boom")
5+
6+
7+
broken = Broken()

tests/unittest_raw_building.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
"""
2+
'tests.testdata.python3.data.fake_module_with_warnings' and
3+
'tests.testdata.python3.data.fake_module_with_warnings' are fake modules
4+
to simulate issues in unittest below
5+
"""
6+
17
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
28
# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
39
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt
@@ -8,7 +14,7 @@
814
import _io
915
import pytest
1016

11-
# A fake module to simulate pandas in unittest below
17+
import tests.testdata.python3.data.fake_module_with_broken_getattr as fm_getattr
1218
import tests.testdata.python3.data.fake_module_with_warnings as fm
1319
from astroid.builder import AstroidBuilder
1420
from astroid.const import IS_PYPY
@@ -102,6 +108,14 @@ def test_build_function_deepinspect_deprecation(self) -> None:
102108
# This should not raise an exception
103109
AstroidBuilder().module_build(m, "test")
104110

111+
def test_module_object_with_broken_getattr(self) -> None:
112+
# Tests https://github.com/PyCQA/astroid/issues/1958
113+
# When astroid deep inspection of modules raises
114+
# errors when using hasattr().
115+
116+
# This should not raise an exception
117+
AstroidBuilder().inspect_build(fm_getattr, "test")
118+
105119

106120
if __name__ == "__main__":
107121
unittest.main()

0 commit comments

Comments
 (0)