summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniël van Noord <13665637+DanielNoord@users.noreply.github.com>2023-05-08 12:12:38 +0200
committerDaniël van Noord <13665637+DanielNoord@users.noreply.github.com>2023-05-08 16:46:51 +0200
commit351c8de32ae64d05dd958cfe812b6adbca380829 (patch)
tree9fd815374acf7d0ee95798d91d14a6a32f7127d1
parentfb238f11210238dca01f321d65307639b1248594 (diff)
downloadastroid-git-351c8de32ae64d05dd958cfe812b6adbca380829.tar.gz
Fix constructors of ``BaseContainer`` and ``Dict``
-rw-r--r--ChangeLog2
-rw-r--r--astroid/arguments.py2
-rw-r--r--astroid/brain/brain_builtin_inference.py60
-rw-r--r--astroid/brain/brain_namedtuple_enum.py20
-rw-r--r--astroid/inference.py14
-rw-r--r--astroid/interpreter/objectmodel.py40
-rw-r--r--astroid/nodes/node_classes.py114
7 files changed, 156 insertions, 96 deletions
diff --git a/ChangeLog b/ChangeLog
index faccda68..aab86832 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -58,6 +58,7 @@ Release date: TBA
- ``nodes.Attribute``
- ``nodes.AugAssign``
- ``nodes.Await``
+ - ``nodes.BaseContainer``
- ``nodes.BinOp``
- ``nodes.Call``
- ``nodes.ClassDef``
@@ -67,6 +68,7 @@ Release date: TBA
- ``nodes.Delete``
- ``nodes.DelAttr``
- ``nodes.DelName``
+ - ``nodes.Dict``
- ``nodes.DictComp``
- ``nodes.ExceptHandler``
- ``nodes.Expr``
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)