From 309ca8dd7b4d0c95cb3cbb25180857f44050b672 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Sat, 15 Apr 2023 15:26:51 -0400 Subject: [PATCH] Fix infer_call_result() crash on methods called with_metaclass() (#2118) --- ChangeLog | 3 +++ astroid/nodes/scoped_nodes/scoped_nodes.py | 10 +++++++++- tests/test_inference.py | 5 +++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5b35cfdf6c..a9b26f1386 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,9 @@ What's New in astroid 2.15.3? ============================= Release date: TBA +* Fix ``infer_call_result()`` crash on methods called ``with_metaclass()``. + + Closes #1735 What's New in astroid 2.15.2? diff --git a/astroid/nodes/scoped_nodes/scoped_nodes.py b/astroid/nodes/scoped_nodes/scoped_nodes.py index 530d9e6d34..5945f05de2 100644 --- a/astroid/nodes/scoped_nodes/scoped_nodes.py +++ b/astroid/nodes/scoped_nodes/scoped_nodes.py @@ -1697,10 +1697,18 @@ def infer_call_result(self, caller=None, context: InferenceContext | None = None # generators, and filter it out later. if ( self.name == "with_metaclass" + and caller is not None and len(self.args.args) == 1 and self.args.vararg is not None ): - metaclass = next(caller.args[0].infer(context), None) + if isinstance(caller.args, Arguments): + metaclass = next(caller.args.args[0].infer(context), None) + elif isinstance(caller.args, list): + metaclass = next(caller.args[0].infer(context), None) + else: + raise TypeError( # pragma: no cover + f"caller.args was neither Arguments nor list; got {type(caller.args)}" + ) if isinstance(metaclass, ClassDef): try: class_bases = [ diff --git a/tests/test_inference.py b/tests/test_inference.py index ef99e03136..86fdbcf4ae 100644 --- a/tests/test_inference.py +++ b/tests/test_inference.py @@ -4048,6 +4048,11 @@ class C: inferred = next(node.infer()) self.assertRaises(InferenceError, next, inferred.infer_call_result(node)) + def test_infer_call_result_with_metaclass(self) -> None: + node = extract_node("def with_metaclass(meta, *bases): return 42") + inferred = next(node.infer_call_result(caller=node)) + self.assertIsInstance(inferred, nodes.Const) + def test_context_call_for_context_managers(self) -> None: ast_nodes = extract_node( """