Skip to content

Commit 895c6d7

Browse files
Support attrs decorators even if they are imported from attrs (#2059) (#2073)
Use inference to determine membership of ``attr(s)`` module Co-authored-by: Daniël van Noord <[email protected]> (cherry picked from commit 489c90f) Co-authored-by: alm <[email protected]>
1 parent 1bc3e76 commit 895c6d7

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in astroid 2.15.2?
1212
=============================
1313
Release date: TBA
1414

15+
* Support more possible usages of ``attrs`` decorators.
16+
17+
Closes pylint-dev/pylint#7884
1518

1619

1720
What's New in astroid 2.15.1?

astroid/brain/brain_attrs.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
Without this hook pylint reports unsupported-assignment-operation
99
for attrs classes
1010
"""
11+
from astroid.helpers import safe_infer
1112
from astroid.manager import AstroidManager
1213
from astroid.nodes.node_classes import AnnAssign, Assign, AssignName, Call, Unknown
1314
from astroid.nodes.scoped_nodes import ClassDef
@@ -40,6 +41,10 @@ def is_decorated_with_attrs(node, decorator_names=ATTRS_NAMES) -> bool:
4041
decorator_attribute = decorator_attribute.func
4142
if decorator_attribute.as_string() in decorator_names:
4243
return True
44+
45+
inferred = safe_infer(decorator_attribute)
46+
if inferred and inferred.root().name == "attr._next_gen":
47+
return True
4348
return False
4449

4550

tests/brain/test_attr.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ def test_attrs_transform(self) -> None:
9090
module = astroid.parse(
9191
"""
9292
import attrs
93-
from attrs import field, mutable, frozen
93+
from attrs import field, mutable, frozen, define
94+
from attrs import mutable as my_mutable
9495
9596
@attrs.define
9697
class Foo:
@@ -141,10 +142,39 @@ class Eggs:
141142
142143
l = Eggs(d=1)
143144
l.d['answer'] = 42
145+
146+
147+
@frozen
148+
class Legs:
149+
d = attrs.field(default=attrs.Factory(dict))
150+
151+
m = Legs(d=1)
152+
m.d['answer'] = 42
153+
154+
@define
155+
class FooBar:
156+
d = attrs.field(default=attrs.Factory(dict))
157+
158+
n = FooBar(d=1)
159+
n.d['answer'] = 42
160+
161+
@mutable
162+
class BarFoo:
163+
d = attrs.field(default=attrs.Factory(dict))
164+
165+
o = BarFoo(d=1)
166+
o.d['answer'] = 42
167+
168+
@my_mutable
169+
class FooFoo:
170+
d = attrs.field(default=attrs.Factory(dict))
171+
172+
p = FooFoo(d=1)
173+
p.d['answer'] = 42
144174
"""
145175
)
146176

147-
for name in ("f", "g", "h", "i", "j", "k", "l"):
177+
for name in ("f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"):
148178
should_be_unknown = next(module.getattr(name)[0].infer()).getattr("d")[0]
149179
self.assertIsInstance(should_be_unknown, astroid.Unknown)
150180

0 commit comments

Comments
 (0)