microsoft / microsoft/pyright

Recognize valid pattern of dataclasses with @property

Open
#11,361 3 comments 0 reactions 1 assignee Claimed by @StellaHuang95 View on GitHub
Dominant language
Python
Stars
15.6k
Forks
1.8k
Avg merge
12h 13m
Merged PRs (30d)
52

Description

I tried a pattern which is absolutely fine in runtime and should be valid code, but pylance is complaining a lot:

```python
from dataclasses import InitVar, dataclass, field

@dataclass
class Animal:
name: str

def alive(self) -> str:
return f"{self.name} is alive"

@dataclass
class Duck(Animal):
age: InitVar[int]
_age: int = field(init=False, repr=False) # do not initialize, only register datafield

def __post_init__(self, age: int):
self.age = age # uses setter!

@property
def age(self) -> int:
return self._age

@age.setter
def age(self, value: int):
if value < 0:
raise ValueError("Age cannot be negative!")
self._age = value

def fly(self) -> str:
return f"{self.name} flies"

def swim(self) -> str:
return f"{self.name} swims"

def main() -> None:
duck = Duck(name="Daisy", age=2)
print(duck.alive())
print(duck.fly())
print(duck.swim())
print(duck.age)

if __name__ == "__main__":
main()
```

problem detected by pylance:
```
[{
"resource": "/d:/dev/python_oop/src/python_oop/1_4_simple_inherritance_init_dataclass.py",
"owner": "Pylance5",
"code": {
"value": "reportRedeclaration",
"target": {
"$mid": 1,
"path": "/microsoft/pylance-release/blob/main/docs/diagnostics/reportRedeclaration.md",
"scheme": "https",
"authority": "github.com"
}
},
"severity": 8,
"message": "Declaration \"age\" is obscured by a declaration of the same name",
"source": "Pylance",
"startLineNumber": 23,
"startColumn": 5,
"endLineNumber": 23,
"endColumn": 8,
"relatedInformation": [
{
"startLineNumber": 34,
"startColumn": 9,
"endLineNumber": 34,
"endColumn": 12,
"message": "See method declaration",
"resource": "/d:/dev/python_oop/src/python_oop/1_4_simple_inherritance_init_dataclass.py"
}
],
"modelVersionId": 565,
"origin": "extHost1"
},{
"resource": "/d:/dev/python_oop/src/python_oop/1_4_simple_inherritance_init_dataclass.py",
"owner": "Pylance5",
"code": {
"value": "reportGeneralTypeIssues",
"target": {
"$mid": 1,
"path": "/microsoft/pylance-release/blob/main/docs/diagnostics/reportGeneralTypeIssues.md",
"scheme": "https",
"authority": "github.com"
}
},
"severity": 8,
"message": "Dataclass __post_init__ method parameter type mismatch for field \"age\"\n  \"property\" is not assignable to \"int\"",
"source": "Pylance",
"startLineNumber": 26,
"startColumn": 34,
"endLineNumber": 26,
"endColumn": 37,
"relatedInformation": [
{
"startLineNumber": 23,
"startColumn": 5,
"endLineNumber": 23,
"endColumn": 8,
"message": "Field declaration",
"resource": "/d:/dev/python_oop/src/python_oop/1_4_simple_inherritance_init_dataclass.py"
}
],
"modelVersionId": 565,
"origin": "extHost1"
},{
"resource": "/d:/dev/python_oop/src/python_oop/1_4_simple_inherritance_init_dataclass.py",
"owner": "Pylance5",
"code": {
"value": "reportAttributeAccessIssue",
"target": {
"$mid": 1,
"path": "/microsoft/pylance-release/blob/main/docs/diagnostics/reportAttributeAccessIssue.md",
"scheme": "https",
"authority": "github.com"
}
},
"severity": 8,
"message": "Cannot assign to attribute \"age\" for class \"Duck*\"\n  \"age\" is an init-only field",
"source": "Pylance",
"startLineNumber": 27,
"startColumn": 14,
"endLineNumber": 27,
"endColumn": 17,
"modelVersionId": 565,
"origin": "extHost1"
},{
"resource": "/d:/dev/python_oop/src/python_oop/1_4_simple_inherritance_init_dataclass.py",
"owner": "Pylance5",
"code": {
"value": "reportUnknownMemberType",
"target": {
"$mid": 1,
"path": "/microsoft/pylance-release/blob/main/docs/diagnostics/reportUnknownMemberType.md",
"scheme": "https",
"authority": "github.com"
}
},
"severity": 8,
"message": "Type of \"age\" is unknown",
"source": "Pylance",
"startLineNumber": 51,
"startColumn": 11,
"endLineNumber": 51,
"endColumn": 19,
"modelVersionId": 565,
"origin": "extHost1"
},{
"resource": "/d:/dev/python_oop/src/python_oop/1_4_simple_inherritance_init_dataclass.py",
"owner": "Pylance5",
"code": {
"value": "reportUnknownArgumentType",
"target": {
"$mid": 1,
"path": "/microsoft/pylance-release/blob/main/docs/diagnostics/reportUnknownArgumentType.md",
"scheme": "https",
"authority": "github.com"
}
},
"severity": 8,
"message": "Argument type is unknown\n  Argument corresponds to parameter \"values\" in function \"print\"",
"source": "Pylance",
"startLineNumber": 51,
"startColumn": 11,
"endLineNumber": 51,
"endColumn": 19,
"modelVersionId": 565,
"origin": "extHost1"
},{
"resource": "/d:/dev/python_oop/src/python_oop/1_4_simple_inherritance_init_dataclass.py",
"owner": "Pylance5",
"code": {
"value": "reportAttributeAccessIssue",
"target": {
"$mid": 1,
"path": "/microsoft/pylance-release/blob/main/docs/diagnostics/reportAttributeAccessIssue.md",
"scheme": "https",
"authority": "github.com"
}
},
"severity": 8,
"message": "Cannot access attribute \"age\" for class \"Duck\"\n  \"age\" is an init-only field",
"source": "Pylance",
"startLineNumber": 51,
"startColumn": 16,
"endLineNumber": 51,
"endColumn": 19,
"modelVersionId": 565,
"origin": "extHost1"
}]
```

This pattern should be recognized and have no type errors.
Thanks!

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.