diff options
author | Daniel van Noord <13665637+DanielNoord@users.noreply.github.com> | 2023-04-25 13:32:28 +0200 |
---|---|---|
committer | Daniƫl van Noord <13665637+DanielNoord@users.noreply.github.com> | 2023-04-25 13:52:45 +0200 |
commit | f13b247d617de36f44d7e825566f134174723c28 (patch) | |
tree | 2bed6354c5e96263f2cdbca0adda8d7dad6c47d4 | |
parent | 82f62c26038b12466e075a235427f73d073f8362 (diff) | |
download | astroid-git-f13b247d617de36f44d7e825566f134174723c28.tar.gz |
Fix the signature of ``infer_call_result``
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | astroid/bases.py | 18 | ||||
-rw-r--r-- | astroid/brain/brain_dataclasses.py | 4 | ||||
-rw-r--r-- | astroid/brain/brain_functools.py | 11 | ||||
-rw-r--r-- | astroid/interpreter/objectmodel.py | 38 | ||||
-rw-r--r-- | astroid/nodes/scoped_nodes/scoped_nodes.py | 30 | ||||
-rw-r--r-- | astroid/objects.py | 14 | ||||
-rw-r--r-- | tests/test_scoped_nodes.py | 2 | ||||
-rw-r--r-- | tests/test_transforms.py | 2 |
9 files changed, 94 insertions, 38 deletions
@@ -24,6 +24,19 @@ Release date: TBA We have tried to minimize the amount of breaking changes caused by this change but some are unavoidable. +* ``infer_call_result`` now shares the same interface across all implemenations. Namely: + ```python + def infer_call_result( + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: + ``` + + This is a breaking change for ``nodes.FunctionDef`` where previously ``caller`` had a default of + ``None``. Passing ``None`` again will not create a behaviour change. + The breaking change allows us to better type and re-use the method within ``astroid``. + * Improved signature of the ``__init__`` and ``__postinit__`` methods of most nodes. This includes makes ``lineno``, ``col_offset``, ``end_lineno``, ``end_col_offset`` and ``parent`` required arguments for ``nodes.NodeNG`` and its subclasses. diff --git a/astroid/bases.py b/astroid/bases.py index 52884f6d..f1fa7b3d 100644 --- a/astroid/bases.py +++ b/astroid/bases.py @@ -306,8 +306,10 @@ class BaseInstance(Proxy): yield attr def infer_call_result( - self, caller: nodes.Call | Proxy, context: InferenceContext | None = None - ): + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: """Infer what a class instance is returning when called.""" context = bind_context_to_node(context, self) inferred = False @@ -441,7 +443,11 @@ class UnboundMethod(Proxy): return iter((self.special_attributes.lookup(name),)) return self._proxied.igetattr(name, context) - def infer_call_result(self, caller, context): + def infer_call_result( + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: """ The boundnode of the regular context with a function called on ``object.__new__`` will be of type ``object``, @@ -614,7 +620,11 @@ class BoundMethod(UnboundMethod): cls.locals = cls_locals return cls - def infer_call_result(self, caller, context: InferenceContext | None = None): + def infer_call_result( + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: context = bind_context_to_node(context, self.bound) if ( self.bound.__class__.__name__ == "ClassDef" diff --git a/astroid/brain/brain_dataclasses.py b/astroid/brain/brain_dataclasses.py index 49f47b67..29e8d6f6 100644 --- a/astroid/brain/brain_dataclasses.py +++ b/astroid/brain/brain_dataclasses.py @@ -314,7 +314,9 @@ def _generate_dataclass_init( # pylint: disable=too-many-locals # But we can't represent those as string try: # Call str to make sure also Uninferable gets stringified - default_str = str(next(property_node.infer_call_result()).as_string()) + default_str = str( + next(property_node.infer_call_result(None)).as_string() + ) except (InferenceError, StopIteration): pass else: diff --git a/astroid/brain/brain_functools.py b/astroid/brain/brain_functools.py index 9393b886..ded1da3a 100644 --- a/astroid/brain/brain_functools.py +++ b/astroid/brain/brain_functools.py @@ -18,6 +18,7 @@ from astroid.interpreter import objectmodel from astroid.manager import AstroidManager from astroid.nodes.node_classes import AssignName, Attribute, Call, Name from astroid.nodes.scoped_nodes import FunctionDef +from astroid.typing import InferenceResult, SuccessfulInferenceResult from astroid.util import UninferableBase LRU_CACHE = "functools.lru_cache" @@ -45,9 +46,13 @@ class LruWrappedModel(objectmodel.FunctionModel): class CacheInfoBoundMethod(BoundMethod): def infer_call_result( - self, caller, context: InferenceContext | None = None - ): - yield helpers.safe_infer(cache_info) + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: + res = helpers.safe_infer(cache_info) + assert res is not None + yield res return CacheInfoBoundMethod(proxy=self._instance, bound=self._instance) diff --git a/astroid/interpreter/objectmodel.py b/astroid/interpreter/objectmodel.py index 12405684..fbc454bf 100644 --- a/astroid/interpreter/objectmodel.py +++ b/astroid/interpreter/objectmodel.py @@ -27,6 +27,7 @@ import itertools import os import pprint import types +from collections.abc import Iterator from functools import lru_cache from typing import TYPE_CHECKING, Any, Literal @@ -36,6 +37,7 @@ from astroid.context import InferenceContext, copy_context from astroid.exceptions import AttributeInferenceError, InferenceError, NoDefault from astroid.manager import AstroidManager from astroid.nodes import node_classes +from astroid.typing import InferenceResult, SuccessfulInferenceResult if TYPE_CHECKING: from astroid.objects import Property @@ -337,8 +339,10 @@ class FunctionModel(ObjectModel): return 0 def infer_call_result( - self, caller, context: InferenceContext | None = None - ): + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[bases.BoundMethod]: if len(caller.args) > 2 or len(caller.args) < 1: raise InferenceError( "Invalid arguments for descriptor binding", @@ -501,8 +505,10 @@ class ClassModel(ObjectModel): # The method we're returning is capable of inferring the underlying MRO though. class MroBoundMethod(bases.BoundMethod): def infer_call_result( - self, caller, context: InferenceContext | None = None - ): + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[node_classes.Tuple]: yield other_self.attr___mro__ implicit_metaclass = self._instance.implicit_metaclass() @@ -549,8 +555,10 @@ class ClassModel(ObjectModel): class SubclassesBoundMethod(bases.BoundMethod): def infer_call_result( - self, caller, context: InferenceContext | None = None - ): + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[node_classes.List]: yield obj implicit_metaclass = self._instance.implicit_metaclass() @@ -817,8 +825,10 @@ class DictModel(ObjectModel): class DictMethodBoundMethod(astroid.BoundMethod): def infer_call_result( - self, caller, context: InferenceContext | None = None - ): + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: yield obj meth = next(self._instance._proxied.igetattr(name), None) @@ -896,8 +906,10 @@ class PropertyModel(ObjectModel): class PropertyFuncAccessor(nodes.FunctionDef): def infer_call_result( - self, caller=None, context: InferenceContext | None = None - ): + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: nonlocal func if caller and len(caller.args) != 1: raise InferenceError( @@ -946,8 +958,10 @@ class PropertyModel(ObjectModel): class PropertyFuncAccessor(nodes.FunctionDef): def infer_call_result( - self, caller=None, context: InferenceContext | None = None - ): + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: nonlocal func_setter if caller and len(caller.args) != 2: raise InferenceError( diff --git a/astroid/nodes/scoped_nodes/scoped_nodes.py b/astroid/nodes/scoped_nodes/scoped_nodes.py index ef25c2b7..caed9f0b 100644 --- a/astroid/nodes/scoped_nodes/scoped_nodes.py +++ b/astroid/nodes/scoped_nodes/scoped_nodes.py @@ -991,12 +991,12 @@ class Lambda(_base_nodes.FilterStmtsBaseNode, LocalsDictNodeNG): names.append(self.args.kwarg) return names - def infer_call_result(self, caller, context: InferenceContext | None = None): - """Infer what the function returns when called. - - :param caller: Unused - :type caller: object - """ + def infer_call_result( + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: + """Infer what the function returns when called.""" return self.body.infer(context) def scope_lookup( @@ -1540,12 +1540,12 @@ class FunctionDef( elif yield_.scope() == self: yield from yield_.value.infer(context=context) - def infer_call_result(self, caller=None, context: InferenceContext | None = None): - """Infer what the function returns when called. - - :returns: What the function returns. - :rtype: iterable(NodeNG or Uninferable) or None - """ + def infer_call_result( + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: + """Infer what the function returns when called.""" if self.is_generator(): if isinstance(self, AsyncFunctionDef): generator_cls: type[bases.Generator] = bases.AsyncGenerator @@ -2127,7 +2127,11 @@ class ClassDef( result.parent = caller.parent return result - def infer_call_result(self, caller, context: InferenceContext | None = None): + def infer_call_result( + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: """infer what a class is returning when called""" if self.is_subtype_of("builtins.type", context) and len(caller.args) == 3: result = self._infer_type_call(caller, context) diff --git a/astroid/objects.py b/astroid/objects.py index 784881be..f1e4cb69 100644 --- a/astroid/objects.py +++ b/astroid/objects.py @@ -15,7 +15,7 @@ from __future__ import annotations from collections.abc import Generator, Iterator from functools import cached_property -from typing import Any, Literal, TypeVar +from typing import Any, Literal, NoReturn, TypeVar from astroid import bases, decorators, util from astroid.context import InferenceContext @@ -308,7 +308,11 @@ class PartialFunction(scoped_nodes.FunctionDef): self.filled_positionals = len(self.filled_args) - def infer_call_result(self, caller=None, context: InferenceContext | None = None): + def infer_call_result( + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> Iterator[InferenceResult]: if context: current_passed_keywords = { keyword for (keyword, _) in context.callcontext.keywords @@ -356,7 +360,11 @@ class Property(scoped_nodes.FunctionDef): def pytype(self) -> Literal["builtins.property"]: return "builtins.property" - def infer_call_result(self, caller=None, context: InferenceContext | None = None): + def infer_call_result( + self, + caller: SuccessfulInferenceResult | None, + context: InferenceContext | None = None, + ) -> NoReturn: raise InferenceError("Properties are not callable") def _infer( diff --git a/tests/test_scoped_nodes.py b/tests/test_scoped_nodes.py index 9f409582..e169dc66 100644 --- a/tests/test_scoped_nodes.py +++ b/tests/test_scoped_nodes.py @@ -1986,7 +1986,7 @@ class ClassNodeTest(ModuleLoader, unittest.TestCase): """ ) assert isinstance(func, nodes.FunctionDef) - result = next(func.infer_call_result()) + result = next(func.infer_call_result(None)) self.assertIsInstance(result, Generator) self.assertEqual(result.parent, func) diff --git a/tests/test_transforms.py b/tests/test_transforms.py index fd9aeb62..59aaf210 100644 --- a/tests/test_transforms.py +++ b/tests/test_transforms.py @@ -164,7 +164,7 @@ class TestTransforms(unittest.TestCase): for decorator in node.decorators.nodes: inferred = next(decorator.infer()) if inferred.qname() == "abc.abstractmethod": - return next(node.infer_call_result()) + return next(node.infer_call_result(None)) return None manager = MANAGER |