summaryrefslogtreecommitdiff
path: root/astroid/brain/brain_dataclasses.py
diff options
context:
space:
mode:
authorDavid Liu <david@cs.toronto.edu>2021-08-16 13:18:50 -0400
committerGitHub <noreply@github.com>2021-08-16 19:18:50 +0200
commit212990793f7182881c4583eb82bb7b071b1b1731 (patch)
tree548ce92a895405a48eff35a795ef5745e59a1a15 /astroid/brain/brain_dataclasses.py
parent02a4c266534fb473da07ea5b905726281d06cbde (diff)
downloadastroid-git-212990793f7182881c4583eb82bb7b071b1b1731.tar.gz
Restrict type inference of dataclass attributes. (#1130)
For now, from the typing module only generic collection types are inferred: Dict, FrozenSet, List, Set, Tuple. Astroid proxies these to the built-in collection types (e.g., dict). Other type annotations from typing like Callable and Union yield Uninferable; these would need to be handled on a case by case basis. Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
Diffstat (limited to 'astroid/brain/brain_dataclasses.py')
-rw-r--r--astroid/brain/brain_dataclasses.py49
1 files changed, 39 insertions, 10 deletions
diff --git a/astroid/brain/brain_dataclasses.py b/astroid/brain/brain_dataclasses.py
index f42c981c..b4be357f 100644
--- a/astroid/brain/brain_dataclasses.py
+++ b/astroid/brain/brain_dataclasses.py
@@ -97,16 +97,7 @@ def infer_dataclass_attribute(
if value is not None:
yield from value.infer(context=ctx)
if annotation is not None:
- klass = None
- try:
- klass = next(annotation.infer())
- except (InferenceError, StopIteration):
- yield Uninferable
-
- if not isinstance(klass, ClassDef):
- yield Uninferable
- else:
- yield klass.instantiate_class()
+ yield from _infer_instance_from_annotation(annotation, ctx=ctx)
else:
yield Uninferable
@@ -229,6 +220,44 @@ def _is_init_var(node: NodeNG) -> bool:
return getattr(inferred, "name", "") == "InitVar"
+# Allowed typing classes for which we support inferring instances
+_INFERABLE_TYPING_TYPES = frozenset(
+ (
+ "Dict",
+ "FrozenSet",
+ "List",
+ "Set",
+ "Tuple",
+ )
+)
+
+
+def _infer_instance_from_annotation(
+ node: NodeNG, ctx: context.InferenceContext = None
+) -> Generator:
+ """Infer an instance corresponding to the type annotation represented by node.
+
+ Currently has limited support for the typing module.
+ """
+ klass = None
+ try:
+ klass = next(node.infer(context=ctx))
+ except (InferenceError, StopIteration):
+ yield Uninferable
+ if not isinstance(klass, ClassDef):
+ yield Uninferable
+ elif klass.root().name in (
+ "typing",
+ "",
+ ): # "" because of synthetic nodes in brain_typing.py
+ if klass.name in _INFERABLE_TYPING_TYPES:
+ yield klass.instantiate_class()
+ else:
+ yield Uninferable
+ else:
+ yield klass.instantiate_class()
+
+
if PY37_PLUS:
AstroidManager().register_transform(
ClassDef, dataclass_transform, is_decorated_with_dataclass