summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel van Noord <13665637+DanielNoord@users.noreply.github.com>2023-04-25 13:32:28 +0200
committerDaniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>2023-04-25 13:52:45 +0200
commitf13b247d617de36f44d7e825566f134174723c28 (patch)
tree2bed6354c5e96263f2cdbca0adda8d7dad6c47d4
parent82f62c26038b12466e075a235427f73d073f8362 (diff)
downloadastroid-git-f13b247d617de36f44d7e825566f134174723c28.tar.gz
Fix the signature of ``infer_call_result``
-rw-r--r--ChangeLog13
-rw-r--r--astroid/bases.py18
-rw-r--r--astroid/brain/brain_dataclasses.py4
-rw-r--r--astroid/brain/brain_functools.py11
-rw-r--r--astroid/interpreter/objectmodel.py38
-rw-r--r--astroid/nodes/scoped_nodes/scoped_nodes.py30
-rw-r--r--astroid/objects.py14
-rw-r--r--tests/test_scoped_nodes.py2
-rw-r--r--tests/test_transforms.py2
9 files changed, 94 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index ab360b6c..78e65f4b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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