Skip to content

Commit 1fbbf25

Browse files
Make igetattr() idempotent (#2208)
This addresses some reports of varying results when running pylint with ``--jobs. The original inconsistency was due to a performance optimization in 2d7a87b for a pathological case, but we have no source for the original bug report it targeted.
1 parent b08166b commit 1fbbf25

File tree

3 files changed

+21
-9
lines changed

3 files changed

+21
-9
lines changed

ChangeLog

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ Release date: TBA
1717

1818
* Reduce file system access in ``ast_from_file()``.
1919

20+
* Make ``igetattr()`` idempotent. This addresses some reports of varying results
21+
when running pylint with ``--jobs``.
22+
23+
Closes pylint-dev/pylint#4356
24+
Refs #7
25+
2026
* Fix incorrect cache keys for inference results, thereby correctly inferring types
2127
for calls instantiating types dynamically.
2228

astroid/bases.py

-8
Original file line numberDiff line numberDiff line change
@@ -277,14 +277,6 @@ def igetattr(
277277
context = InferenceContext()
278278
try:
279279
context.lookupname = name
280-
# avoid recursively inferring the same attr on the same class
281-
if context.push(self._proxied):
282-
raise InferenceError(
283-
message="Cannot infer the same attribute again",
284-
node=self,
285-
context=context,
286-
)
287-
288280
# XXX frame should be self._proxied, or not ?
289281
get_attr = self.getattr(name, context, lookupclass=False)
290282
yield from _infer_stmts(

tests/test_inference.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -4024,7 +4024,7 @@ def __getitem__(self, name):
40244024
flow['app']['config']['doffing'] = AttributeDict() #@
40254025
"""
40264026
)
4027-
self.assertIsNone(helpers.safe_infer(ast_node.targets[0]))
4027+
self.assertIsInstance(helpers.safe_infer(ast_node.targets[0]), Instance)
40284028

40294029
def test_classmethod_inferred_by_context(self) -> None:
40304030
ast_node = extract_node(
@@ -6120,6 +6120,20 @@ def __exit__(self, ex_type, ex_value, ex_tb):
61206120
next(node.infer())
61216121

61226122

6123+
def test_igetattr_idempotent() -> None:
6124+
code = """
6125+
class InferMeTwice:
6126+
item = 10
6127+
6128+
InferMeTwice()
6129+
"""
6130+
call = extract_node(code)
6131+
instance = call.inferred()[0]
6132+
context_to_be_used_twice = InferenceContext()
6133+
assert util.Uninferable not in instance.igetattr("item", context_to_be_used_twice)
6134+
assert util.Uninferable not in instance.igetattr("item", context_to_be_used_twice)
6135+
6136+
61236137
def test_infer_context_manager_with_unknown_args() -> None:
61246138
code = """
61256139
class client_log(object):

0 commit comments

Comments
 (0)