Skip to content

Commit

Permalink
Did a cleanup pass for the dataclass test cases. Renamed and reordere…
Browse files Browse the repository at this point in the history
…d test cases for maintainability.
  • Loading branch information
msfterictraut committed Jun 19, 2023
1 parent b7df200 commit 96e03aa
Show file tree
Hide file tree
Showing 33 changed files with 594 additions and 581 deletions.
87 changes: 54 additions & 33 deletions packages/pyright-internal/src/tests/samples/dataclass1.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,71 @@
# This sample validates the Python 3.7 data class feature.
# This sample tests the handling of the @dataclass decorator.

from typing import ClassVar, Final, Hashable, NamedTuple, Optional
from dataclasses import dataclass, InitVar


class Other:
pass
@dataclass
class Bar:
bbb: int
ccc: str
aaa: str = "string"


def standalone(obj: object) -> None:
print(obj)
bar1 = Bar(bbb=5, ccc="hello")
bar2 = Bar(5, "hello")
bar3 = Bar(5, "hello", "hello2")
print(bar3.bbb)
print(bar3.ccc)
print(bar3.aaa)

class DataTuple(NamedTuple):
def _m(self):
pass
# This should generate an error because ddd
# isn't a declared value.
bar = Bar(bbb=5, ddd=5, ccc="hello")

# This should generate an error because the
# parameter types don't match.
bar = Bar("hello", "goodbye")

# ClassVar variables should not be included.
class_var: ClassVar[int] = 4
# This should generate an error because a parameter
# is missing.
bar = [Bar(2)]

id: int
aid: Other
value: str = ""
# This should generate an error because there are
# too many parameters.
bar = Bar(2, "hello", "hello", 4)

# Unannotated variables should not be included.
not_annotated = 5

name: Optional[str] = None
@dataclass
class Baz1:
bbb: int
aaa: str = "string"

name2: Final[Optional[str]] = None
# This should generate an error because variables
# with no default cannot come after those with
# defaults.
ccc: str

def __init__(self) -> None:
pass

not_a_method = standalone

d1 = DataTuple(id=1, aid=Other(), name2="hi")
d1.not_a_method()
@dataclass
class Baz2:
aaa: str
ddd: InitVar[int] = 3

d2 = DataTuple(id=1, aid=Other(), value="v")
d3 = DataTuple(id=1, aid=Other(), name="hello")
d4 = DataTuple(id=1, aid=Other(), name=None)
id = d1.id

h4: Hashable = d4
v = d3 == d4
@dataclass(init=False)
class Baz3:
bbb: int
aaa: str = "string"
# This should not generate an error because
# the ordering requirement is not enforced when
# init=False.
ccc: str

# This should generate an error because the name argument
# is the incorrect type.
d5 = DataTuple(id=1, aid=Other(), name=3)

# This should generate an error because aid is a required
# parameter and is missing an argument here.
d6 = DataTuple(id=1, name=None)
@dataclass
class Baz4:
# Private names are not allowed, so this should
# generate an error.
__private: int
46 changes: 11 additions & 35 deletions packages/pyright-internal/src/tests/samples/dataclass10.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,21 @@
# This sample tests the case where a dataclass entry is
# initialized with a "field" that uses "init=False". This
# case needs to be handled specially because it means
# that the synthesized __init__ method shouldn't include
# this field in its parameter list.
# This sample verifies that a generic dataclass works.

from dataclasses import dataclass, field
from dataclasses import dataclass
from typing import Generic, TypeVar, Union


@dataclass
class Parent:
prop_1: str = field(init=False)
prop_2: str = field(default="hello")
prop_3: str = field(default_factory=lambda: "hello")

# This should generate an error because it appears after
# a property with a default value.
prop_4: str = field()

def __post_init__(self):
self.prop_1 = "test"
T = TypeVar("T")


@dataclass
class Child(Parent):
prop_2: str
class Foo(Generic[T]):
value: Union[str, T]


test = Child(prop_2="test", prop_4="hi")
reveal_type(Foo(""), expected_text="Foo[Unknown]")

assert test.prop_1 == "test"
assert test.prop_2 == "test"

class Bar(Foo[int]):
pass

@dataclass
class HandshakeMessage:
reset_reason_hex: str
reset_data_hex: str
device_id: str = field(default="")
reset_reason: str = field(init=False)
reset_data: str = field(init=False)

def __post_init__(self):
reset_reason = "calculated value"
reset_data = "calculated value"

reveal_type(Bar(123), expected_text="Bar")
65 changes: 22 additions & 43 deletions packages/pyright-internal/src/tests/samples/dataclass11.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,32 @@
# This sample tests the synthesized comparison operators for dataclasses.
# This sample tests the case where an inheritance chain of
# dataclasses use generic types.

from dataclasses import dataclass
from typing import Generic, TypeVar

Key0 = TypeVar("Key0")
Key1 = TypeVar("Key1")
Key2 = TypeVar("Key2")
Value = TypeVar("Value")

@dataclass(order=True)
class DC1:
a: str
b: int

@dataclass
class MapTreeLeaf(Generic[Key0, Value]):
key: Key0
value: Value

@dataclass(order=True)
class DC2:
a: str
b: int

@dataclass
class MapTreeNode(MapTreeLeaf[Key1, Value]):
pass

dc1_1 = DC1("hi", 2)
dc1_2 = DC1("hi", 2)

if dc1_1 < dc1_2:
print("")
class Foo(Generic[Key2, Value]):
def add(self, key: Key2, value: Value):
return MapTreeNode(key=key, value=value)

if dc1_1 <= dc1_2:
print("")

if dc1_1 > dc1_2:
print("")

if dc1_1 >= dc1_2:
print("")

if dc1_1 == dc1_2:
print("")

if dc1_1 != dc1_2:
print("")

if dc1_1 == None:
print("")

if dc1_1 != None:
print("")

dc2_1 = DC2("hi", 2)

# This should generate an error because the types are
# incompatible.
if dc1_1 < dc2_1:
print("")

if dc1_1 != dc2_1:
print("")
def test1(self, a: Key2, b: Value):
v1 = self.add(a, b)
reveal_type(v1, expected_text="MapTreeNode[Key2@Foo, Value@Foo]")
reveal_type(v1.key, expected_text="Key2@Foo")
reveal_type(v1.value, expected_text="Value@Foo")
46 changes: 26 additions & 20 deletions packages/pyright-internal/src/tests/samples/dataclass12.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
# This sample tests the case where an inheritance chain of
# dataclasses use generic types.
# This sample tests the case where a dataclass declares an instance
# variable and a subclass redeclares it as a class variable.

from dataclasses import dataclass
from typing import Generic, TypeVar
from typing import ClassVar

Key0 = TypeVar("Key0")
Key1 = TypeVar("Key1")
Key2 = TypeVar("Key2")
Value = TypeVar("Value")

@dataclass
class Base:
x: int
y: int


@dataclass
class MapTreeLeaf(Generic[Key0, Value]):
key: Key0
value: Value
class Special(Base):
x: ClassVar[int] = 1
z: int


@dataclass
class MapTreeNode(MapTreeLeaf[Key1, Value]):
pass
class VerySpecial(Special):
y: ClassVar[int] = 2


Base(x=1, y=2)
Special(y=2, z=3)
Special(2, 3)

# This should generate an error
Special(x=1, y=2, z=3)

# This should generate an error
Special(1, 2, 3)

class Foo(Generic[Key2, Value]):
def add(self, key: Key2, value: Value):
return MapTreeNode(key=key, value=value)
VerySpecial(z=3)

def test1(self, a: Key2, b: Value):
v1 = self.add(a, b)
reveal_type(v1, expected_text="MapTreeNode[Key2@Foo, Value@Foo]")
reveal_type(v1.key, expected_text="Key2@Foo")
reveal_type(v1.value, expected_text="Value@Foo")
# This should generate an error
VerySpecial(x=1, z=3)
54 changes: 9 additions & 45 deletions packages/pyright-internal/src/tests/samples/dataclass13.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,13 @@
# This sample tests the handling of frozen dataclass types.
# This sample tests that a dataclass member without a type annotation
# but with a field descriptor assignment results in an error.

from dataclasses import dataclass
from typing import ClassVar
from dataclasses import dataclass, field


@dataclass(frozen=False)
class DC1:
val1: int = 6
@dataclass
class MyClass:
id: int
x: int = field()


@dataclass(frozen=True)
class DC2:
val2: int = 4


# This should generate an error because a frozen dataclass
# cannot inherit from a non-frozen dataclass.
@dataclass(frozen=True)
class DC3(DC1):
val3: int = 4


@dataclass(frozen=True)
class DC4(DC2):
val4: int = 4

val5: ClassVar[int]


# This should generate an error because a non-frozen dataclass
# cannot inherit from a frozen dataclass.
@dataclass(frozen=False)
class DC5(DC2):
val4: int = 5


a = DC1(val1=3)
a.val1 = 3

b = DC4(val2=3, val4=5)

DC4.val5 = 3

# This should generate an error because the dataclass is frozen.
b.val2 = 3

# This should generate an error because the dataclass is frozen.
b.val4 = 3
# This should generate an error because it will result in a runtime exception
y = field()
Loading

0 comments on commit 96e03aa

Please sign in to comment.