Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for attrs v21.3.0+ #1331

Merged
merged 9 commits into from Jan 20, 2022
5 changes: 4 additions & 1 deletion astroid/brain/brain_attrs.py
Expand Up @@ -10,7 +10,7 @@
from astroid.nodes.node_classes import AnnAssign, Assign, AssignName, Call, Unknown
from astroid.nodes.scoped_nodes import ClassDef

ATTRIB_NAMES = frozenset(("attr.ib", "attrib", "attr.attrib", "attr.field", "field"))
ATTRIB_NAMES = frozenset(("attr.ib", "attr.attrib", "attr.field", "attrs.field"))
Pierre-Sassoulas marked this conversation as resolved.
Show resolved Hide resolved
ATTRS_NAMES = frozenset(
(
"attr.s",
Expand All @@ -20,6 +20,9 @@
"attr.define",
"attr.mutable",
"attr.frozen",
"attrs.define",
"attrs.mutable",
"attrs.frozen",
)
)

Expand Down
67 changes: 67 additions & 0 deletions tests/unittest_brain.py
Expand Up @@ -2211,6 +2211,73 @@ class Eggs:
should_be_unknown = next(module.getattr(name)[0].infer()).getattr("d")[0]
self.assertIsInstance(should_be_unknown, astroid.Unknown)

def test_attrs_transform(self) -> None:
jacobbogdanov marked this conversation as resolved.
Show resolved Hide resolved
"""Test brain for decorators of the 'attrs' package.

Package added support for 'attrs' a long side 'attr' in v21.3.0.
See: https://github.com/python-attrs/attrs/releases/tag/21.3.0
"""
module = astroid.parse(
"""
import attrs
from attrs import field, mutable, frozen

@attrs.define
class Foo:

d = attrs.field(attrs.Factory(dict))

f = Foo()
f.d['answer'] = 42

@attrs.define(slots=True)
class Bar:
d = field(attrs.Factory(dict))

g = Bar()
g.d['answer'] = 42

@attrs.mutable
class Bah:
d = field(attrs.Factory(dict))

h = Bah()
h.d['answer'] = 42

@attrs.frozen
class Bai:
d = attrs.field(attrs.Factory(dict))

i = Bai()
i.d['answer'] = 42

@attrs.define
class Spam:
d = field(default=attrs.Factory(dict))

j = Spam(d=1)
j.d['answer'] = 42

@attrs.mutable
class Eggs:
d = attrs.field(default=attrs.Factory(dict))

k = Eggs(d=1)
k.d['answer'] = 42

@attrs.frozen
class Eggs:
d = attrs.field(default=attrs.Factory(dict))

l = Eggs(d=1)
l.d['answer'] = 42
"""
)

for name in ("f", "g", "h", "i", "j", "k", "l"):
should_be_unknown = next(module.getattr(name)[0].infer()).getattr("d")[0]
self.assertIsInstance(should_be_unknown, astroid.Unknown)

def test_special_attributes(self) -> None:
"""Make sure special attrs attributes exist"""

Expand Down