I faced with problem linting dataclasses with list and dict properties
from dataclasses import dataclass, field
@dataclass
class Item:
list_prop: list = field(default_factory=list)
dict_prop: dict = field(default_factory=dict)
obj = Item()
for i in obj.list_prop:
print(i)
obj.dict_prop["key"] = "value"
I got:
test.py:10:9: E1133: Non-iterable value obj.list_prop is used in an iterating context (not-an-iterable)
test.py:13:0: E1137: 'obj.dict_prop' does not support item assignment (unsupported-assignment-operation)
It should report no errors.
$ pylint --version
pylint 2.2.2
astroid 2.1.0
Python 3.6.3 (default, Oct 6 2017, 08:44:35)
[GCC 5.4.0 20160609]
Thanks for the report! Right now we don't fully understand the dataclasses module, which will require an astroid brain transform for better inference results.
Looks like this somehow got worse when we moved from 2.3.1 -> 2.4.0. Used to get no errors on our class (which is a non-dataclass derived from a dataclass) ... now we're flooded with "no-member". Also, it seems to "lose context" ... it recognizes some derived classes from dataclass... but not all? I'm going to try to make a tight example.
I've just got the no-member flood with no change in code, and no pylint version bump (fixed at 2.3.1), just pipeline's environment has been reinstalled once again. Seems like the 2.3.1 version has been overridden on PyPI server. I have no other reason, why it suddenly started to raise warnings.
My dataclasses are canonical, as this:
@dataclass
class InventoryItem:
name: str
unit_price: float
And pylint complains about name and unit_price. Even # pylint: disable=no-member at top of the file doesn't help.
Bumping to 2.4.1 solves the problem.
Seems like the 2.3.1 version has been overridden on PyPI server. I have no other reason, why it suddenly started to raise warnings.
@kamichal I believe the breakage is in astroid (the AST library). If I pin pylint==2.3.1 and astroid==2.2.5, I no longer see the flood of no-member errors.
@jacebrowning Some evidence of that is that mypy is also failing for the same classes unless we tag them up with types.
Seems closed in #3133
As hinted by the previous commenter, it seems fixed. I cannot reproduce the error with pylint 2.6.0 (and astroid 2.4.2).
Shall we close this issue?
test/check and close if not reproducible.
The following minimal example still triggers the not-an-iterable lint:
import dataclasses as dc
@dc.dataclass
class Foo:
bar = dc.field(default_factory=list)
foo = Foo()
for _ in foo.bar:
pass
$ pylint --version
pylint 2.6.0
astroid 2.4.2
Python 3.7.0 (default, Oct 9 2018, 10:31:47)
[GCC 7.3.0]
$ pylint foo.py
************* Module foo
foo.py:1: [C0102(blacklisted-name), ] Black listed name "foo"
foo.py:1: [C0114(missing-module-docstring), ] Missing module docstring
foo.py:4: [C0115(missing-class-docstring), Foo] Missing class docstring
foo.py:6: [C0102(blacklisted-name), Foo] Black listed name "bar"
foo.py:4: [R0903(too-few-public-methods), Foo] Too few public methods (0/2)
foo.py:10: [E1133(not-an-iterable), ] Non-iterable value foo.bar is used in an iterating context
@troiganto It's probably because it's not using the dataclass plugin when you import it like that. Try:
from dataclasses import dataclass, field
@dataclass
class Foo:
bar = field(default_factory=list)
foo = Foo()
for _ in foo.bar:
pass
This works fine for me.
Ah, that indeed fixes it! Just import dataclasses without a rename works as well.
Is it realistic to support renamed imports as well? Should I open a separate issue about it? I checked a few other issues to learn more about this problem and I don't seem to be the only one who prefers import dataclasses as dc.
@troiganto Sorry, but I have no idea how it works actually. Perhaps someone better-informed can comment.
Most helpful comment
Looks like this somehow got worse when we moved from 2.3.1 -> 2.4.0. Used to get no errors on our class (which is a non-dataclass derived from a dataclass) ... now we're flooded with "no-member". Also, it seems to "lose context" ... it recognizes some derived classes from dataclass... but not all? I'm going to try to make a tight example.