diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2019-09-26 09:19:40 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2019-09-26 09:19:40 +0200 |
commit | 3e4eac76e9abfa0400fa07b58c61973ac5495bd2 (patch) | |
tree | 79eec3d7ae47e882c2793ad1073c0467ba14c0ac /astroid/brain/brain_dataclasses.py | |
parent | da1a1d70b8a3668a59de863d32132db6eaffadb6 (diff) | |
download | astroid-git-3e4eac76e9abfa0400fa07b58c61973ac5495bd2.tar.gz |
A transform for the builtin `dataclasses` module was added.
This should address various `dataclasses` issues that were surfaced
even more after the release of pylint 2.4.0.
In the previous versions of `astroid`, annotated assign nodes were
allowed to be retrieved via `getattr()` but that no longer happens
with the latest `astroid` release, as those attribute are not actual
attributes, but rather virtual ones, thus an operation such as `getattr()`
does not make sense for them.
Diffstat (limited to 'astroid/brain/brain_dataclasses.py')
-rw-r--r-- | astroid/brain/brain_dataclasses.py | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/astroid/brain/brain_dataclasses.py b/astroid/brain/brain_dataclasses.py new file mode 100644 index 00000000..7a25e0c6 --- /dev/null +++ b/astroid/brain/brain_dataclasses.py @@ -0,0 +1,50 @@ +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER +""" +Astroid hook for the dataclasses library +""" + +import astroid +from astroid import MANAGER + + +DATACLASSES_DECORATORS = frozenset(("dataclasses.dataclass", "dataclass")) + + +def is_decorated_with_dataclass(node, decorator_names=DATACLASSES_DECORATORS): + """Return True if a decorated node has a `dataclass` decorator applied.""" + if not node.decorators: + return False + for decorator_attribute in node.decorators.nodes: + if isinstance(decorator_attribute, astroid.Call): # decorator with arguments + decorator_attribute = decorator_attribute.func + if decorator_attribute.as_string() in decorator_names: + return True + return False + + +def dataclass_transform(node): + """Rewrite a dataclass to be easily understood by pylint""" + + for assign_node in node.body: + if not isinstance(assign_node, (astroid.AnnAssign, astroid.Assign)): + continue + + targets = ( + assign_node.targets + if hasattr(assign_node, "targets") + else [assign_node.target] + ) + for target in targets: + rhs_node = astroid.Unknown( + lineno=assign_node.lineno, + col_offset=assign_node.col_offset, + parent=assign_node, + ) + node.instance_attrs[target.name] = [rhs_node] + node.locals[target.name] = [rhs_node] + + +MANAGER.register_transform( + astroid.ClassDef, dataclass_transform, is_decorated_with_dataclass +) |