-- Test cases for dataclasses based on the attrs library, where auto_attribs=True [case testRunAttrsclass] import attr from typing import Set, List, Callable, Any @attr.s(auto_attribs=True) class Person1: age : int name : str def __bool__(self) -> bool: return self.name == 'robot' def testBool(p: Person1) -> bool: if p: return True else: return False @attr.s(auto_attribs=True) class Person1b(Person1): id: str = '000' @attr.s(auto_attribs=True) class Person2: age : int name : str = attr.ib(default='robot') @attr.s(auto_attribs=True, order=True) class Person3: age : int = attr.ib(default = 6) friendIDs : List[int] = attr.ib(factory = list) def get_age(self) -> int: return (self.age) def set_age(self, new_age : int) -> None: self.age = new_age def add_friendID(self, fid : int) -> None: self.friendIDs.append(fid) def get_friendIDs(self) -> List[int]: return self.friendIDs def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]: def f(a: Any) -> int: return g(a) + 1 return f @attr.s(auto_attribs=True) class Person4: age : int _name : str = 'Bot' @get_next_age def get_age(self) -> int: return self.age @property def name(self) -> str: return self._name @attr.s(auto_attribs=True) class Point: x : int = attr.ib(converter=int) y : int = attr.ib(init=False) def __attrs_post_init__(self): self.y = self.x + 1 [file other.py] from native import Person1, Person1b, Person2, Person3, Person4, testBool, Point i1 = Person1(age = 5, name = 'robot') assert i1.age == 5 assert i1.name == 'robot' assert testBool(i1) == True assert testBool(Person1(age = 5, name = 'robo')) == False i1b = Person1b(age = 5, name = 'robot') assert i1b.age == 5 assert i1b.name == 'robot' assert i1b.id == '000' assert testBool(i1b) == True assert testBool(Person1b(age = 5, name = 'robo')) == False i1c = Person1b(age = 20, name = 'robot', id = 'test') assert i1c.age == 20 assert i1c.id == 'test' i2 = Person2(age = 5) assert i2.age == 5 assert i2.name == 'robot' i3 = Person2(age = 5, name = 'new_robot') assert i3.age == 5 assert i3.name == 'new_robot' i4 = Person3() assert i4.age == 6 assert i4.friendIDs == [] i5 = Person3(age = 5) assert i5.age == 5 assert i5.friendIDs == [] i6 = Person3(age = 5, friendIDs = [1,2,3]) assert i6.age == 5 assert i6.friendIDs == [1,2,3] assert i6.get_age() == 5 i6.set_age(10) assert i6.get_age() == 10 i6.add_friendID(4) assert i6.get_friendIDs() == [1,2,3,4] i7 = Person4(age = 5) assert i7.get_age() == 6 i7.age += 3 assert i7.age == 8 assert i7.name == 'Bot' i8 = Person3(age = 1, friendIDs = [1,2]) i9 = Person3(age = 1, friendIDs = [1,2]) assert i8 == i9 i8.age = 2 assert i8 > i9 assert Person1.__annotations__ == {'age': int, 'name': str} assert Person2.__annotations__ == {'age': int, 'name': str} p1 = Point(2) assert p1.x == 2 assert p1.y == 3 p2 = Point('2') assert p2.x == 2 assert p2.y == 3 assert Point.__annotations__ == {'x': int, 'y': int} [file driver.py] import sys # PEP 526 introduced in 3.6 version = sys.version_info[:2] if version[0] < 3 or version[1] < 6: exit() # Run the tests in both interpreted and compiled mode import other import other_interpreted # Test for an exceptional cases from testutil import assertRaises from native import Person1, Person1b, Person3 from types import BuiltinMethodType with assertRaises(TypeError, "missing 1 required positional argument"): Person1(0) with assertRaises(TypeError, "missing 2 required positional arguments"): Person1b() with assertRaises(TypeError, "int object expected; got str"): Person1('nope', 'test') p = Person1(0, 'test') with assertRaises(TypeError, "int object expected; got str"): p.age = 'nope' assert isinstance(Person3().get_age, BuiltinMethodType) [case testRunAttrsclassNonAuto] import attr from typing import Set, List, Callable, Any @attr.s class Person1: age = attr.ib(type=int) name = attr.ib(type=str) def __bool__(self) -> bool: return self.name == 'robot' def testBool(p: Person1) -> bool: if p: return True else: return False @attr.s class Person1b(Person1): id = attr.ib(type=str, default='000') @attr.s class Person2: age = attr.ib(type=int) name = attr.ib(type=str, default='robot') @attr.s(order=True) class Person3: age = attr.ib(type=int, default=6) friendIDs = attr.ib(factory=list, type=List[int]) def get_age(self) -> int: return (self.age) def set_age(self, new_age : int) -> None: self.age = new_age def add_friendID(self, fid : int) -> None: self.friendIDs.append(fid) def get_friendIDs(self) -> List[int]: return self.friendIDs def get_next_age(g: Callable[[Any], int]) -> Callable[[Any], int]: def f(a: Any) -> int: return g(a) + 1 return f @attr.s class Person4: age = attr.ib(type=int) _name = attr.ib(type=str, default='Bot') @get_next_age def get_age(self) -> int: return self.age @property def name(self) -> str: return self._name @attr.s class Point: x = attr.ib(type=int, converter=int) y = attr.ib(type=int, init=False) def __attrs_post_init__(self): self.y = self.x + 1 [file other.py] from native import Person1, Person1b, Person2, Person3, Person4, testBool, Point i1 = Person1(age = 5, name = 'robot') assert i1.age == 5 assert i1.name == 'robot' assert testBool(i1) == True assert testBool(Person1(age = 5, name = 'robo')) == False i1b = Person1b(age = 5, name = 'robot') assert i1b.age == 5 assert i1b.name == 'robot' assert i1b.id == '000' assert testBool(i1b) == True assert testBool(Person1b(age = 5, name = 'robo')) == False i1c = Person1b(age = 20, name = 'robot', id = 'test') assert i1c.age == 20 assert i1c.id == 'test' i2 = Person2(age = 5) assert i2.age == 5 assert i2.name == 'robot' i3 = Person2(age = 5, name = 'new_robot') assert i3.age == 5 assert i3.name == 'new_robot' i4 = Person3() assert i4.age == 6 assert i4.friendIDs == [] i5 = Person3(age = 5) assert i5.age == 5 assert i5.friendIDs == [] i6 = Person3(age = 5, friendIDs = [1,2,3]) assert i6.age == 5 assert i6.friendIDs == [1,2,3] assert i6.get_age() == 5 i6.set_age(10) assert i6.get_age() == 10 i6.add_friendID(4) assert i6.get_friendIDs() == [1,2,3,4] i7 = Person4(age = 5) assert i7.get_age() == 6 i7.age += 3 assert i7.age == 8 assert i7.name == 'Bot' i8 = Person3(age = 1, friendIDs = [1,2]) i9 = Person3(age = 1, friendIDs = [1,2]) assert i8 == i9 i8.age = 2 assert i8 > i9 p1 = Point(2) assert p1.x == 2 assert p1.y == 3 p2 = Point('2') assert p2.x == 2 assert p2.y == 3 [file driver.py] import sys # Run the tests in both interpreted and compiled mode import other import other_interpreted # Test for an exceptional cases from testutil import assertRaises from native import Person1, Person1b, Person3 from types import BuiltinMethodType with assertRaises(TypeError, "missing 1 required positional argument"): Person1(0) with assertRaises(TypeError, "missing 2 required positional arguments"): Person1b() with assertRaises(TypeError, "int object expected; got str"): Person1('nope', 'test') p = Person1(0, 'test') with assertRaises(TypeError, "int object expected; got str"): p.age = 'nope' assert isinstance(Person3().get_age, BuiltinMethodType)