Skip to content

Commit c6b7cd9

Browse files
committed
Conformance: drop questionable non-data-descriptor dataclass tests
The DC2 portion of dataclasses_descriptors.py asserted types for a non-data descriptor (only __get__) used as a dataclass field that do not match the runtime: DC2.x/DC2.y raise AttributeError, and dc2.x/y/z are the descriptor objects themselves (a non-data descriptor is shadowed by the instance dict), not the __get__ return type. This behavior is under-specified, and type checkers disagree. Remove the DC2 cases, keeping the well-defined data descriptor (DC1) test. mypy, pycroscope, and ty no longer fail on the spurious assertions. Closes #2259
1 parent 94514b1 commit c6b7cd9

6 files changed

Lines changed: 21 additions & 95 deletions

File tree

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
1-
conformant = "Partial"
2-
notes = """
3-
Assumes descriptor behavior only when field is assigned in class body.
4-
Does not correctly evaluate type of descriptor access.
5-
"""
1+
conformant = "Pass"
62
output = """
7-
dataclasses_descriptors.py:61: error: Cannot access instance-only attribute "x" on class object [misc]
8-
dataclasses_descriptors.py:62: error: Cannot access instance-only attribute "y" on class object [misc]
9-
dataclasses_descriptors.py:66: error: Expression is of type "Desc2[int]", not "int" [assert-type]
10-
dataclasses_descriptors.py:67: error: Expression is of type "Desc2[str]", not "str" [assert-type]
113
"""
12-
conformance_automated = "Fail"
4+
conformance_automated = "Pass"
135
errors_diff = """
14-
Line 61: Unexpected errors ['dataclasses_descriptors.py:61: error: Cannot access instance-only attribute "x" on class object [misc]']
15-
Line 62: Unexpected errors ['dataclasses_descriptors.py:62: error: Cannot access instance-only attribute "y" on class object [misc]']
16-
Line 66: Unexpected errors ['dataclasses_descriptors.py:66: error: Expression is of type "Desc2[int]", not "int" [assert-type]']
17-
Line 67: Unexpected errors ['dataclasses_descriptors.py:67: error: Expression is of type "Desc2[str]", not "str" [assert-type]']
186
"""
Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,6 @@
1-
conformant = "Partial"
2-
notes = """
3-
Conformance suite is questionable; see https://github.com/python/typing/issues/2259
4-
"""
5-
conformance_automated = "Fail"
1+
conformant = "Pass"
2+
conformance_automated = "Pass"
63
errors_diff = """
7-
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]"]
8-
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]"]
9-
Line 63: Unexpected errors ['./dataclasses_descriptors.py:63:12: list[Any[generic_argument]] is not equivalent to list[str]']
10-
Line 66: Unexpected errors ['./dataclasses_descriptors.py:66:12: ./dataclasses_descriptors.py.Desc2[int] is not equivalent to int']
11-
Line 67: Unexpected errors ['./dataclasses_descriptors.py:67:12: ./dataclasses_descriptors.py.Desc2[str] is not equivalent to str']
12-
Line 68: Unexpected errors ['./dataclasses_descriptors.py:68:12: Any[generic_argument] is not equivalent to str']
134
"""
145
output = """
15-
./dataclasses_descriptors.py:61:12: Any[error] is not equivalent to list[int]
16-
./dataclasses_descriptors.py:61:12: <class 'DC2'> has no attribute 'x' [undefined_attribute]
17-
./dataclasses_descriptors.py:62:12: Any[error] is not equivalent to list[str]
18-
./dataclasses_descriptors.py:62:12: <class 'DC2'> has no attribute 'y' [undefined_attribute]
19-
./dataclasses_descriptors.py:63:12: list[Any[generic_argument]] is not equivalent to list[str]
20-
./dataclasses_descriptors.py:66:12: ./dataclasses_descriptors.py.Desc2[int] is not equivalent to int
21-
./dataclasses_descriptors.py:67:12: ./dataclasses_descriptors.py.Desc2[str] is not equivalent to str
22-
./dataclasses_descriptors.py:68:12: Any[generic_argument] is not equivalent to str
236
"""
Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,11 @@
11
conformant = "Partial"
22
notes = """
3-
* Assumes descriptor behavior only when field is assigned in class body
4-
* Doesn't allow non-data descriptors or data descriptors with differing `__get__` and `__set__` types
3+
Rejects a data descriptor field whose `__get__` and `__set__` have differing types.
54
"""
65
conformance_automated = "Fail"
76
errors_diff = """
8-
Line 32: Unexpected errors ['Cannot set field `y` to data descriptor `Desc1` with inconsistent types [bad-class-definition]']
9-
Line 58: Unexpected errors ['Cannot set field `z` to non-data descriptor `Desc2` [bad-class-definition]']
10-
Line 61: Unexpected errors ['assert_type(Desc2[int], list[int]) failed [assert-type]']
11-
Line 62: Unexpected errors ['assert_type(Desc2[str], list[str]) failed [assert-type]']
12-
Line 66: Unexpected errors ['assert_type(Desc2[int], int) failed [assert-type]']
13-
Line 67: Unexpected errors ['assert_type(Desc2[str], str) failed [assert-type]']
7+
Line 35: Unexpected errors ['Cannot set field `y` to data descriptor `Desc1` with inconsistent types [bad-class-definition]']
148
"""
159
output = """
16-
ERROR dataclasses_descriptors.py:32:5-6: Cannot set field `y` to data descriptor `Desc1` with inconsistent types [bad-class-definition]
17-
ERROR dataclasses_descriptors.py:58:5-6: Cannot set field `z` to non-data descriptor `Desc2` [bad-class-definition]
18-
ERROR dataclasses_descriptors.py:61:12-30: assert_type(Desc2[int], list[int]) failed [assert-type]
19-
ERROR dataclasses_descriptors.py:62:12-30: assert_type(Desc2[str], list[str]) failed [assert-type]
20-
ERROR dataclasses_descriptors.py:66:12-24: assert_type(Desc2[int], int) failed [assert-type]
21-
ERROR dataclasses_descriptors.py:67:12-24: assert_type(Desc2[str], str) failed [assert-type]
10+
ERROR dataclasses_descriptors.py:35:5-6: Cannot set field `y` to data descriptor `Desc1` with inconsistent types [bad-class-definition]
2211
"""

conformance/results/results.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -900,12 +900,12 @@ <h3>Python Type System Conformance Test Results</h3>
900900
<a class="test_group" href="https://typing.readthedocs.io/en/latest/spec/dataclasses.html">Dataclasses</a>
901901
</th></tr>
902902
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataclasses_descriptors</th>
903-
<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>
904903
<th class="column col2 conformant">Pass</th>
905904
<th class="column col2 conformant">Pass</th>
906-
<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>
907-
<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>
908-
<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>
905+
<th class="column col2 conformant">Pass</th>
906+
<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>
907+
<th class="column col2 conformant">Pass</th>
908+
<th class="column col2 conformant">Pass</th>
909909
</tr>
910910
<tr><th class="column col1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dataclasses_final</th>
911911
<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>
Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
1-
conformance_automated = "Fail"
2-
conformant = "Partial"
3-
notes = """
4-
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.
5-
"""
1+
conformance_automated = "Pass"
2+
conformant = "Pass"
63
errors_diff = """
7-
Line 66: Unexpected errors ['dataclasses_descriptors.py:66:1: error[type-assertion-failure] Type `int | Desc2[int]` does not match asserted type `int`']
8-
Line 67: Unexpected errors ['dataclasses_descriptors.py:67:1: error[type-assertion-failure] Type `str | Desc2[str]` does not match asserted type `str`']
94
"""
105
output = """
11-
dataclasses_descriptors.py:66:1: error[type-assertion-failure] Type `int | Desc2[int]` does not match asserted type `int`
12-
dataclasses_descriptors.py:67:1: error[type-assertion-failure] Type `str | Desc2[str]` does not match asserted type `str`
136
"""

conformance/tests/dataclasses_descriptors.py

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22
Tests the handling of descriptors within a dataclass.
33
"""
44

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

813
from dataclasses import dataclass
9-
from typing import Any, Generic, TypeVar, assert_type, overload
10-
11-
T = TypeVar("T")
14+
from typing import Any, assert_type, overload
1215

1316

1417
class Desc1:
@@ -36,33 +39,3 @@ class DC1:
3639

3740
assert_type(dc1.y, int)
3841
assert_type(DC1.y, Desc1)
39-
40-
41-
class Desc2(Generic[T]):
42-
@overload
43-
def __get__(self, instance: None, owner: Any) -> list[T]:
44-
...
45-
46-
@overload
47-
def __get__(self, instance: object, owner: Any) -> T:
48-
...
49-
50-
def __get__(self, instance: object | None, owner: Any) -> list[T] | T:
51-
raise NotImplementedError
52-
53-
54-
@dataclass
55-
class DC2:
56-
x: Desc2[int]
57-
y: Desc2[str]
58-
z: Desc2[str] = Desc2()
59-
60-
61-
assert_type(DC2.x, list[int])
62-
assert_type(DC2.y, list[str])
63-
assert_type(DC2.z, list[str])
64-
65-
dc2 = DC2(Desc2(), Desc2(), Desc2())
66-
assert_type(dc2.x, int)
67-
assert_type(dc2.y, str)
68-
assert_type(dc2.z, str)

0 commit comments

Comments
 (0)