diff options
Diffstat (limited to 'astroid')
-rw-r--r-- | astroid/arguments.py | 2 | ||||
-rw-r--r-- | astroid/brain/brain_builtin_inference.py | 60 | ||||
-rw-r--r-- | astroid/brain/brain_namedtuple_enum.py | 20 | ||||
-rw-r--r-- | astroid/inference.py | 14 | ||||
-rw-r--r-- | astroid/interpreter/objectmodel.py | 40 | ||||
-rw-r--r-- | astroid/nodes/node_classes.py | 114 |
6 files changed, 154 insertions, 96 deletions
diff --git a/astroid/arguments.py b/astroid/arguments.py index f2630416..c92a5ffe 100644 --- a/astroid/arguments.py +++ b/astroid/arguments.py @@ -254,6 +254,8 @@ class CallSite: lineno=funcnode.args.lineno, col_offset=funcnode.args.col_offset, parent=funcnode.args, + end_lineno=funcnode.args.end_lineno, + end_col_offset=funcnode.args.end_col_offset, ) kwarg.postinit( [(nodes.const_factory(key), value) for key, value in kwargs.items()] diff --git a/astroid/brain/brain_builtin_inference.py b/astroid/brain/brain_builtin_inference.py index 6da11eda..efca0c5e 100644 --- a/astroid/brain/brain_builtin_inference.py +++ b/astroid/brain/brain_builtin_inference.py @@ -7,10 +7,11 @@ from __future__ import annotations import itertools -from collections.abc import Iterator +from collections.abc import Callable, Iterable, Iterator from functools import partial +from typing import Any -from astroid import arguments, helpers, inference_tip, nodes, objects, util +from astroid import arguments, bases, helpers, inference_tip, nodes, objects, util from astroid.builder import AstroidBuilder from astroid.context import InferenceContext from astroid.exceptions import ( @@ -22,7 +23,7 @@ from astroid.exceptions import ( ) from astroid.manager import AstroidManager from astroid.nodes import scoped_nodes -from astroid.typing import InferenceResult +from astroid.typing import InferenceResult, SuccessfulInferenceResult OBJECT_DUNDER_NEW = "object.__new__" @@ -196,10 +197,21 @@ def register_builtin_transform(transform, builtin_name) -> None: ) -def _container_generic_inference(node, context, node_type, transform): +def _container_generic_inference( + node: nodes.Call, + context: InferenceContext | None, + node_type: type[nodes.BaseContainer], + transform: Callable[[SuccessfulInferenceResult], nodes.BaseContainer | None], +) -> nodes.BaseContainer: args = node.args if not args: - return node_type() + return node_type( + lineno=node.lineno, + col_offset=node.col_offset, + parent=node.parent, + end_lineno=node.end_lineno, + end_col_offset=node.end_col_offset, + ) if len(node.args) > 1: raise UseInferenceDefault() @@ -219,8 +231,12 @@ def _container_generic_inference(node, context, node_type, transform): def _container_generic_transform( # pylint: disable=inconsistent-return-statements - arg, context, klass, iterables, build_elts -): + arg: SuccessfulInferenceResult, + context: InferenceContext | None, + klass: type[nodes.BaseContainer], + iterables: tuple[type[nodes.NodeNG] | type[bases.Proxy], ...], + build_elts: type[Iterable[Any]], +) -> nodes.BaseContainer | None: if isinstance(arg, klass): return arg if isinstance(arg, iterables): @@ -251,8 +267,12 @@ def _container_generic_transform( # pylint: disable=inconsistent-return-stateme def _infer_builtin_container( - node, context, klass=None, iterables=None, build_elts=None -): + node: nodes.Call, + context: InferenceContext | None, + klass: type[nodes.BaseContainer], + iterables: tuple[type[nodes.NodeNG] | type[bases.Proxy], ...], + build_elts: type[Iterable[Any]], +) -> nodes.BaseContainer: transform_func = partial( _container_generic_transform, context=context, @@ -337,7 +357,7 @@ def _get_elts(arg, context): return items -def infer_dict(node, context: InferenceContext | None = None): +def infer_dict(node: nodes.Call, context: InferenceContext | None = None) -> nodes.Dict: """Try to infer a dict call to a Dict node. The function treats the following cases: @@ -360,7 +380,13 @@ def infer_dict(node, context: InferenceContext | None = None): if not args and not kwargs: # dict() - return nodes.Dict() + return nodes.Dict( + lineno=node.lineno, + col_offset=node.col_offset, + parent=node.parent, + end_lineno=node.end_lineno, + end_col_offset=node.end_col_offset, + ) if kwargs and not args: # dict(a=1, b=2, c=4) items = [(nodes.Const(key), value) for key, value in kwargs] @@ -374,7 +400,11 @@ def infer_dict(node, context: InferenceContext | None = None): else: raise UseInferenceDefault() value = nodes.Dict( - col_offset=node.col_offset, lineno=node.lineno, parent=node.parent + col_offset=node.col_offset, + lineno=node.lineno, + parent=node.parent, + end_lineno=node.end_lineno, + end_col_offset=node.end_col_offset, ) value.postinit(items) return value @@ -853,7 +883,11 @@ def infer_dict_fromkeys(node, context: InferenceContext | None = None): def _build_dict_with_elements(elements): new_node = nodes.Dict( - col_offset=node.col_offset, lineno=node.lineno, parent=node.parent + col_offset=node.col_offset, + lineno=node.lineno, + parent=node.parent, + end_lineno=node.end_lineno, + end_col_offset=node.end_col_offset, ) new_node.postinit(elements) return new_node diff --git a/astroid/brain/brain_namedtuple_enum.py b/astroid/brain/brain_namedtuple_enum.py index 18aedcb3..84bb0fcd 100644 --- a/astroid/brain/brain_namedtuple_enum.py +++ b/astroid/brain/brain_namedtuple_enum.py @@ -466,9 +466,23 @@ def infer_enum_class(node: nodes.ClassDef) -> nodes.ClassDef: node.locals[local] = new_targets # The undocumented `_value2member_map_` member: - node.locals["_value2member_map_"] = [nodes.Dict(parent=node)] - - members = nodes.Dict(parent=node) + node.locals["_value2member_map_"] = [ + nodes.Dict( + parent=node, + lineno=node.lineno, + col_offset=node.col_offset, + end_lineno=node.end_lineno, + end_col_offset=node.end_col_offset, + ) + ] + + members = nodes.Dict( + parent=node, + lineno=node.lineno, + col_offset=node.col_offset, + end_lineno=node.end_lineno, + end_col_offset=node.end_col_offset, + ) members.postinit( [ ( diff --git a/astroid/inference.py b/astroid/inference.py index 1729d81d..6dcfa49f 100644 --- a/astroid/inference.py +++ b/astroid/inference.py @@ -130,7 +130,11 @@ def infer_sequence( if has_starred_named_expr: values = _infer_sequence_helper(self, context) new_seq = type(self)( - lineno=self.lineno, col_offset=self.col_offset, parent=self.parent + lineno=self.lineno, + col_offset=self.col_offset, + parent=self.parent, + end_lineno=self.end_lineno, + end_col_offset=self.end_col_offset, ) new_seq.postinit(values) @@ -151,7 +155,13 @@ def infer_map( yield self else: items = _infer_map(self, context) - new_seq = type(self)(self.lineno, self.col_offset, self.parent) + new_seq = type(self)( + self.lineno, + self.col_offset, + self.parent, + end_lineno=self.end_lineno, + end_col_offset=self.end_col_offset, + ) new_seq.postinit(list(items.items())) yield new_seq diff --git a/astroid/interpreter/objectmodel.py b/astroid/interpreter/objectmodel.py index fbc454bf..a095f0cd 100644 --- a/astroid/interpreter/objectmodel.py +++ b/astroid/interpreter/objectmodel.py @@ -47,7 +47,13 @@ LEN_OF_IMPL_PREFIX = len(IMPL_PREFIX) def _dunder_dict(instance, attributes): - obj = node_classes.Dict(parent=instance) + obj = node_classes.Dict( + parent=instance, + lineno=instance.lineno, + col_offset=instance.col_offset, + end_lineno=instance.end_lineno, + end_col_offset=instance.end_col_offset, + ) # Convert the keys to node strings keys = [ @@ -263,7 +269,13 @@ class FunctionModel(ObjectModel): @property def attr___annotations__(self): - obj = node_classes.Dict(parent=self._instance) + obj = node_classes.Dict( + parent=self._instance, + lineno=self._instance.lineno, + col_offset=self._instance.col_offset, + end_lineno=self._instance.end_lineno, + end_col_offset=self._instance.end_col_offset, + ) if not self._instance.returns: returns = None @@ -297,7 +309,13 @@ class FunctionModel(ObjectModel): @property def attr___dict__(self): - return node_classes.Dict(parent=self._instance) + return node_classes.Dict( + parent=self._instance, + lineno=self._instance.lineno, + col_offset=self._instance.col_offset, + end_lineno=self._instance.end_lineno, + end_col_offset=self._instance.end_col_offset, + ) attr___globals__ = attr___dict__ @@ -314,7 +332,13 @@ class FunctionModel(ObjectModel): yield name, default args = self._instance.args - obj = node_classes.Dict(parent=self._instance) + obj = node_classes.Dict( + parent=self._instance, + lineno=self._instance.lineno, + col_offset=self._instance.col_offset, + end_lineno=self._instance.end_lineno, + end_col_offset=self._instance.end_col_offset, + ) defaults = dict(_default_args(args, obj)) obj.postinit(list(defaults.items())) @@ -567,7 +591,13 @@ class ClassModel(ObjectModel): @property def attr___dict__(self): - return node_classes.Dict(parent=self._instance) + return node_classes.Dict( + parent=self._instance, + lineno=self._instance.lineno, + col_offset=self._instance.col_offset, + end_lineno=self._instance.end_lineno, + end_col_offset=self._instance.end_col_offset, + ) @property def attr___call__(self): diff --git a/astroid/nodes/node_classes.py b/astroid/nodes/node_classes.py index 787fbc5f..5afb3659 100644 --- a/astroid/nodes/node_classes.py +++ b/astroid/nodes/node_classes.py @@ -8,6 +8,7 @@ from __future__ import annotations import abc import itertools +import sys import typing from collections.abc import Generator, Iterable, Iterator, Mapping from functools import cached_property, lru_cache @@ -46,6 +47,12 @@ from astroid.typing import ( SuccessfulInferenceResult, ) +if sys.version_info >= (3, 11): + from typing import Self +else: + from typing_extensions import Self + + if TYPE_CHECKING: from astroid import nodes from astroid.nodes import LocalsDictNodeNG @@ -266,26 +273,13 @@ class BaseContainer(_base_nodes.ParentAssignNode, Instance, metaclass=abc.ABCMet def __init__( self, - lineno: int | None = None, - col_offset: int | None = None, - parent: NodeNG | None = None, + lineno: int | None, + col_offset: int | None, + parent: NodeNG | None, *, - end_lineno: int | None = None, - end_col_offset: int | None = None, + end_lineno: int | None, + end_col_offset: int | None, ) -> None: - """ - :param lineno: The line that this node appears on in the source code. - - :param col_offset: The column that this node appears on in the - source code. - - :param parent: The parent node in the syntax tree. - - :param end_lineno: The last line this node appears on in the source code. - - :param end_col_offset: The end column this node appears on in the - source code. Note: This is after the last symbol. - """ self.elts: list[SuccessfulInferenceResult] = [] """The elements in the node.""" @@ -297,28 +291,25 @@ class BaseContainer(_base_nodes.ParentAssignNode, Instance, metaclass=abc.ABCMet parent=parent, ) - def postinit(self, elts: list[NodeNG]) -> None: - """Do some setup after initialisation. - - :param elts: The list of elements the that node contains. - """ + def postinit(self, elts: list[SuccessfulInferenceResult]) -> None: self.elts = elts @classmethod - def from_elements(cls, elts=None): + def from_elements(cls, elts: Iterable[Any]) -> Self: """Create a node of this type from the given list of elements. :param elts: The list of elements that the node should contain. - :type elts: list(NodeNG) :returns: A new node containing the given elements. - :rtype: NodeNG """ - node = cls() - if elts is None: - node.elts = [] - else: - node.elts = [const_factory(e) if _is_const(e) else e for e in elts] + node = cls( + lineno=None, + col_offset=None, + parent=None, + end_lineno=None, + end_col_offset=None, + ) + node.elts = [const_factory(e) if _is_const(e) else e for e in elts] return node def itered(self): @@ -1855,26 +1846,13 @@ class Dict(NodeNG, Instance): def __init__( self, - lineno: int | None = None, - col_offset: int | None = None, - parent: NodeNG | None = None, + lineno: int | None, + col_offset: int | None, + parent: NodeNG | None, *, - end_lineno: int | None = None, - end_col_offset: int | None = None, + end_lineno: int | None, + end_col_offset: int | None, ) -> None: - """ - :param lineno: The line that this node appears on in the source code. - - :param col_offset: The column that this node appears on in the - source code. - - :param parent: The parent node in the syntax tree. - - :param end_lineno: The last line this node appears on in the source code. - - :param end_col_offset: The end column this node appears on in the - source code. Note: This is after the last symbol. - """ self.items: list[tuple[InferenceResult, InferenceResult]] = [] """The key-value pairs contained in the dictionary.""" @@ -1897,28 +1875,6 @@ class Dict(NodeNG, Instance): infer_unary_op: ClassVar[InferUnaryOp[Dict]] - @classmethod - def from_elements(cls, items=None): - """Create a :class:`Dict` of constants from a live dictionary. - - :param items: The items to store in the node. - :type items: dict - - :returns: The created dictionary node. - :rtype: Dict - """ - node = cls() - if items is None: - node.items = [] - else: - node.items = [ - (const_factory(k), const_factory(v) if _is_const(v) else v) - for k, v in items.items() - # The keys need to be constants - if _is_const(k) - ] - return node - def pytype(self) -> Literal["builtins.dict"]: """Get the name of the type that this node represents. @@ -4528,11 +4484,23 @@ def const_factory(value: Any) -> ConstFactoryResult: instance: List | Set | Tuple | Dict initializer_cls = CONST_CLS[value.__class__] if issubclass(initializer_cls, (List, Set, Tuple)): - instance = initializer_cls() + instance = initializer_cls( + lineno=None, + col_offset=None, + parent=None, + end_lineno=None, + end_col_offset=None, + ) instance.postinit(_create_basic_elements(value, instance)) return instance if issubclass(initializer_cls, Dict): - instance = initializer_cls() + instance = initializer_cls( + lineno=None, + col_offset=None, + parent=None, + end_lineno=None, + end_col_offset=None, + ) instance.postinit(_create_dict_items(value, instance)) return instance return Const(value) |