diff options
author | David Liu <david@cs.toronto.edu> | 2021-08-16 13:18:50 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-16 19:18:50 +0200 |
commit | 212990793f7182881c4583eb82bb7b071b1b1731 (patch) | |
tree | 548ce92a895405a48eff35a795ef5745e59a1a15 /astroid/brain/brain_dataclasses.py | |
parent | 02a4c266534fb473da07ea5b905726281d06cbde (diff) | |
download | astroid-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.py | 49 |
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 |