Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 2 additions & 14 deletions conformance/results/mypy/dataclasses_descriptors.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
conformant = "Partial"
notes = """
Assumes descriptor behavior only when field is assigned in class body.
Does not correctly evaluate type of descriptor access.
"""
conformant = "Pass"
output = """
dataclasses_descriptors.py:61: error: Cannot access instance-only attribute "x" on class object [misc]
dataclasses_descriptors.py:62: error: Cannot access instance-only attribute "y" on class object [misc]
dataclasses_descriptors.py:66: error: Expression is of type "Desc2[int]", not "int" [assert-type]
dataclasses_descriptors.py:67: error: Expression is of type "Desc2[str]", not "str" [assert-type]
"""
conformance_automated = "Fail"
conformance_automated = "Pass"
errors_diff = """
Line 61: Unexpected errors ['dataclasses_descriptors.py:61: error: Cannot access instance-only attribute "x" on class object [misc]']
Line 62: Unexpected errors ['dataclasses_descriptors.py:62: error: Cannot access instance-only attribute "y" on class object [misc]']
Line 66: Unexpected errors ['dataclasses_descriptors.py:66: error: Expression is of type "Desc2[int]", not "int" [assert-type]']
Line 67: Unexpected errors ['dataclasses_descriptors.py:67: error: Expression is of type "Desc2[str]", not "str" [assert-type]']
"""
21 changes: 2 additions & 19 deletions conformance/results/pycroscope/dataclasses_descriptors.toml
Original file line number Diff line number Diff line change
@@ -1,23 +1,6 @@
conformant = "Partial"
notes = """
Conformance suite is questionable; see https://github.com/python/typing/issues/2259
"""
conformance_automated = "Fail"
conformant = "Pass"
conformance_automated = "Pass"
errors_diff = """
Line 61: Unexpected errors ['./dataclasses_descriptors.py:61:12: Any[error] is not equivalent to list[int]', "./dataclasses_descriptors.py:61:12: <class 'DC2'> has no attribute 'x' [undefined_attribute]"]
Line 62: Unexpected errors ['./dataclasses_descriptors.py:62:12: Any[error] is not equivalent to list[str]', "./dataclasses_descriptors.py:62:12: <class 'DC2'> has no attribute 'y' [undefined_attribute]"]
Line 63: Unexpected errors ['./dataclasses_descriptors.py:63:12: list[Any[generic_argument]] is not equivalent to list[str]']
Line 66: Unexpected errors ['./dataclasses_descriptors.py:66:12: ./dataclasses_descriptors.py.Desc2[int] is not equivalent to int']
Line 67: Unexpected errors ['./dataclasses_descriptors.py:67:12: ./dataclasses_descriptors.py.Desc2[str] is not equivalent to str']
Line 68: Unexpected errors ['./dataclasses_descriptors.py:68:12: Any[generic_argument] is not equivalent to str']
"""
output = """
./dataclasses_descriptors.py:61:12: Any[error] is not equivalent to list[int]
./dataclasses_descriptors.py:61:12: <class 'DC2'> has no attribute 'x' [undefined_attribute]
./dataclasses_descriptors.py:62:12: Any[error] is not equivalent to list[str]
./dataclasses_descriptors.py:62:12: <class 'DC2'> has no attribute 'y' [undefined_attribute]
./dataclasses_descriptors.py:63:12: list[Any[generic_argument]] is not equivalent to list[str]
./dataclasses_descriptors.py:66:12: ./dataclasses_descriptors.py.Desc2[int] is not equivalent to int
./dataclasses_descriptors.py:67:12: ./dataclasses_descriptors.py.Desc2[str] is not equivalent to str
./dataclasses_descriptors.py:68:12: Any[generic_argument] is not equivalent to str
"""
17 changes: 3 additions & 14 deletions conformance/results/pyrefly/dataclasses_descriptors.toml
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
conformant = "Partial"
notes = """
* Assumes descriptor behavior only when field is assigned in class body
* Doesn't allow non-data descriptors or data descriptors with differing `__get__` and `__set__` types
Rejects a data descriptor field whose `__get__` and `__set__` have differing types.
"""
conformance_automated = "Fail"
errors_diff = """
Line 32: Unexpected errors ['Cannot set field `y` to data descriptor `Desc1` with inconsistent types [bad-class-definition]']
Line 58: Unexpected errors ['Cannot set field `z` to non-data descriptor `Desc2` [bad-class-definition]']
Line 61: Unexpected errors ['assert_type(Desc2[int], list[int]) failed [assert-type]']
Line 62: Unexpected errors ['assert_type(Desc2[str], list[str]) failed [assert-type]']
Line 66: Unexpected errors ['assert_type(Desc2[int], int) failed [assert-type]']
Line 67: Unexpected errors ['assert_type(Desc2[str], str) failed [assert-type]']
Line 35: Unexpected errors ['Cannot set field `y` to data descriptor `Desc1` with inconsistent types [bad-class-definition]']
"""
output = """
ERROR dataclasses_descriptors.py:32:5-6: Cannot set field `y` to data descriptor `Desc1` with inconsistent types [bad-class-definition]
ERROR dataclasses_descriptors.py:58:5-6: Cannot set field `z` to non-data descriptor `Desc2` [bad-class-definition]
ERROR dataclasses_descriptors.py:61:12-30: assert_type(Desc2[int], list[int]) failed [assert-type]
ERROR dataclasses_descriptors.py:62:12-30: assert_type(Desc2[str], list[str]) failed [assert-type]
ERROR dataclasses_descriptors.py:66:12-24: assert_type(Desc2[int], int) failed [assert-type]
ERROR dataclasses_descriptors.py:67:12-24: assert_type(Desc2[str], str) failed [assert-type]
ERROR dataclasses_descriptors.py:35:5-6: Cannot set field `y` to data descriptor `Desc1` with inconsistent types [bad-class-definition]
"""
8 changes: 4 additions & 4 deletions conformance/results/results.html
Original file line number Diff line number Diff line change
Expand Up @@ -900,12 +900,12 @@ <h3>Python Type System Conformance Test Results</h3>
<a class="test_group" href="https://typing.readthedocs.io/en/latest/spec/dataclasses.html">Dataclasses</a>
</th></tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataclasses_descriptors</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Assumes descriptor behavior only when field is assigned in class body.</p><p>Does not correctly evaluate type of descriptor access.</p></span></div></th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>* Assumes descriptor behavior only when field is assigned in class body</p><p>* Doesn't allow non-data descriptors or data descriptors with differing `__get__` and `__set__` types</p></span></div></th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Conformance suite is questionable; see https://github.com/python/typing/issues/2259</p></span></div></th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Only infers a descriptor `__get__` method as being called when a descriptor attribute is accessed on an instance if the descriptor attribute is present in the class namespace.</p></span></div></th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Rejects a data descriptor field whose `__get__` and `__set__` have differing types.</p></span></div></th>
<th class="column col2 conformant">Pass</th>
<th class="column col2 conformant">Pass</th>
</tr>
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataclasses_final</th>
<th class="column col2 partially-conformant"><div class="hover-text">Partial<span class="tooltip-text" id="bottom"><p>Wrongly requires a Final dataclass field to be initialized at class level.</p><p>Doesn't support Final nested inside ClassVar.</p></span></div></th>
Expand Down
11 changes: 2 additions & 9 deletions conformance/results/ty/dataclasses_descriptors.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
conformance_automated = "Fail"
conformant = "Partial"
notes = """
Only infers a descriptor `__get__` method as being called when a descriptor attribute is accessed on an instance if the descriptor attribute is present in the class namespace.
"""
conformance_automated = "Pass"
conformant = "Pass"
errors_diff = """
Line 66: Unexpected errors ['dataclasses_descriptors.py:66:1: error[type-assertion-failure] Type `int | Desc2[int]` does not match asserted type `int`']
Line 67: Unexpected errors ['dataclasses_descriptors.py:67:1: error[type-assertion-failure] Type `str | Desc2[str]` does not match asserted type `str`']
"""
output = """
dataclasses_descriptors.py:66:1: error[type-assertion-failure] Type `int | Desc2[int]` does not match asserted type `int`
dataclasses_descriptors.py:67:1: error[type-assertion-failure] Type `str | Desc2[str]` does not match asserted type `str`
"""
43 changes: 8 additions & 35 deletions conformance/tests/dataclasses_descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
Tests the handling of descriptors within a dataclass.
"""

# This portion of the dataclass spec is under-specified in the documentation,
# but its behavior can be determined from the runtime implementation.
# A data descriptor used as a dataclass field is handled according to the
# runtime implementation: the field type is the type returned by ``__get__``.
#
# The behavior of non-data descriptors (descriptors with only ``__get__``) used
# as dataclass fields is under-specified and type checkers disagree, so those
# cases are intentionally omitted here. See
# https://github.com/python/typing/issues/2259.

from dataclasses import dataclass
from typing import Any, Generic, TypeVar, assert_type, overload

T = TypeVar("T")
from typing import Any, assert_type, overload


class Desc1:
Expand Down Expand Up @@ -36,33 +39,3 @@ class DC1:

assert_type(dc1.y, int)
assert_type(DC1.y, Desc1)


class Desc2(Generic[T]):
@overload
def __get__(self, instance: None, owner: Any) -> list[T]:
...

@overload
def __get__(self, instance: object, owner: Any) -> T:
...

def __get__(self, instance: object | None, owner: Any) -> list[T] | T:
raise NotImplementedError


@dataclass
class DC2:
x: Desc2[int]
y: Desc2[str]
z: Desc2[str] = Desc2()


assert_type(DC2.x, list[int])
assert_type(DC2.y, list[str])
assert_type(DC2.z, list[str])

dc2 = DC2(Desc2(), Desc2(), Desc2())
assert_type(dc2.x, int)
assert_type(dc2.y, str)
assert_type(dc2.z, str)