@@ -390,29 +390,6 @@ assert c.a == 13
390390assert type(c) == C
391391assert not hasattr(c, 'b')
392392
393- [case testListOfUserDefinedClass]
394- class C:
395- x: int
396-
397- def f() -> int:
398- c = C()
399- c.x = 5
400- a = [c]
401- d = a[0]
402- return d.x + 1
403-
404- def g() -> int:
405- a = [C()]
406- a[0].x = 3
407- return a[0].x + 4
408- [file driver.py]
409- from native import f, g
410- print(f())
411- print(g())
412- [out]
413- 6
414- 7
415-
416393[case testCastUserClass]
417394from typing import List
418395
@@ -1466,3 +1443,328 @@ with patch("interp.Bar.spam", lambda self: 20):
14661443
14671444with assertRaises(TypeError, "int object expected; got str"):
14681445 y.x = "test"
1446+
1447+ [case testProperty]
1448+ from typing import Callable
1449+ from mypy_extensions import trait
1450+ class Temperature:
1451+ @property
1452+ def celsius(self) -> float:
1453+ return 5.0 * (self.farenheit - 32.0) / 9.0
1454+
1455+ def __init__(self, farenheit: float) -> None:
1456+ self.farenheit = farenheit
1457+
1458+ def print_temp(self) -> None:
1459+ print("F:", self.farenheit, "C:", self.celsius)
1460+
1461+ @property
1462+ def rankine(self) -> float:
1463+ raise NotImplementedError
1464+
1465+ class Access:
1466+ @property
1467+ def number_of_accesses(self) -> int:
1468+ self._count += 1
1469+ return self._count
1470+ def __init__(self) -> None:
1471+ self._count = 0
1472+
1473+ from typing import Callable
1474+ class BaseProperty:
1475+ @property
1476+ def doc(self) -> str:
1477+ return "Represents a sequence of values. Updates itself by next, which is a new value."
1478+
1479+ @property
1480+ def value(self) -> object:
1481+ return self._incrementer
1482+
1483+ @property
1484+ def bad_value(self) -> object:
1485+ return self._incrementer
1486+
1487+ @property
1488+ def next(self) -> BaseProperty:
1489+ return BaseProperty(self._incrementer + 1)
1490+
1491+ def __init__(self, value: int) -> None:
1492+ self._incrementer = value
1493+
1494+ class DerivedProperty(BaseProperty):
1495+ @property
1496+ def value(self) -> int:
1497+ return self._incrementer
1498+
1499+ @property
1500+ def bad_value(self) -> object:
1501+ return self._incrementer
1502+
1503+ def __init__(self, incr_func: Callable[[int], int], value: int) -> None:
1504+ BaseProperty.__init__(self, value)
1505+ self._incr_func = incr_func
1506+
1507+ @property
1508+ def next(self) -> DerivedProperty:
1509+ return DerivedProperty(self._incr_func, self._incr_func(self.value))
1510+
1511+ class AgainProperty(DerivedProperty):
1512+ @property
1513+ def next(self) -> AgainProperty:
1514+ return AgainProperty(self._incr_func, self._incr_func(self._incr_func(self.value)))
1515+
1516+ @property
1517+ def bad_value(self) -> int:
1518+ return self._incrementer
1519+
1520+ def print_first_n(n: int, thing: BaseProperty) -> None:
1521+ vals = []
1522+ cur_thing = thing
1523+ for _ in range(n):
1524+ vals.append(cur_thing.value)
1525+ cur_thing = cur_thing.next
1526+ print ('', vals)
1527+
1528+ @trait
1529+ class Trait:
1530+ @property
1531+ def value(self) -> int:
1532+ return 3
1533+
1534+ class Printer(Trait):
1535+ def print_value(self) -> None:
1536+ print(self.value)
1537+
1538+ [file driver.py]
1539+ from native import Temperature, Access
1540+ import traceback
1541+ x = Temperature(32.0)
1542+ try:
1543+ print (x.rankine)
1544+ except NotImplementedError as e:
1545+ traceback.print_exc()
1546+ print (x.celsius)
1547+ x.print_temp()
1548+
1549+ y = Temperature(212.0)
1550+ print (y.celsius)
1551+ y.print_temp()
1552+
1553+ z = Access()
1554+ print (z.number_of_accesses)
1555+ print (z.number_of_accesses)
1556+ print (z.number_of_accesses)
1557+ print (z.number_of_accesses)
1558+
1559+ from native import BaseProperty, DerivedProperty, AgainProperty, print_first_n
1560+ a = BaseProperty(7)
1561+ b = DerivedProperty((lambda x: x // 2 if (x % 2 == 0) else 3 * x + 1), 7)
1562+ c = AgainProperty((lambda x: x // 2 if (x % 2 == 0) else 3 * x + 1), 7)
1563+
1564+ def py_print_first_n(n: int, thing: BaseProperty) -> None:
1565+ vals = []
1566+ cur_thing = thing
1567+ for _ in range(n):
1568+ vals.append(cur_thing.value)
1569+ cur_thing = cur_thing.next
1570+ print ('', vals)
1571+
1572+ py_print_first_n(20, a)
1573+ py_print_first_n(20, b)
1574+ py_print_first_n(20, c)
1575+
1576+ print(a.next.next.next.bad_value)
1577+ print(b.next.next.next.bad_value)
1578+ print(c.next.next.next.bad_value)
1579+
1580+ print_first_n(20, a)
1581+ print_first_n(20, b)
1582+ print_first_n(20, c)
1583+
1584+ print (a.doc)
1585+ print (b.doc)
1586+ print (c.doc)
1587+
1588+ from native import Printer
1589+ Printer().print_value()
1590+ print (Printer().value)
1591+ [out]
1592+ Traceback (most recent call last):
1593+ File "driver.py", line 5, in <module>
1594+ print (x.rankine)
1595+ File "native.py", line 16, in rankine
1596+ raise NotImplementedError
1597+ NotImplementedError
1598+ 0.0
1599+ F: 32.0 C: 0.0
1600+ 100.0
1601+ F: 212.0 C: 100.0
1602+ 1
1603+ 2
1604+ 3
1605+ 4
1606+ [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
1607+ [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1]
1608+ [7, 11, 17, 26, 40, 10, 16, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4]
1609+ 10
1610+ 34
1611+ 26
1612+ [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
1613+ [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1]
1614+ [7, 11, 17, 26, 40, 10, 16, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4, 1, 2, 4]
1615+ Represents a sequence of values. Updates itself by next, which is a new value.
1616+ Represents a sequence of values. Updates itself by next, which is a new value.
1617+ Represents a sequence of values. Updates itself by next, which is a new value.
1618+ 3
1619+ 3
1620+
1621+ [case testPropertySetters]
1622+
1623+ from mypy_extensions import trait
1624+
1625+ class Foo():
1626+ def __init__(self) -> None:
1627+ self.attr = "unmodified"
1628+
1629+ class A:
1630+ def __init__(self) -> None:
1631+ self._x = 0
1632+ self._foo = Foo()
1633+
1634+ @property
1635+ def x(self) -> int:
1636+ return self._x
1637+
1638+ @x.setter
1639+ def x(self, val : int) -> None:
1640+ self._x = val
1641+
1642+ @property
1643+ def foo(self) -> Foo:
1644+ return self._foo
1645+
1646+ @foo.setter
1647+ def foo(self, val : Foo) -> None:
1648+ self._foo = val
1649+
1650+ # Overrides base property setters and getters
1651+ class B(A):
1652+ def __init__(self) -> None:
1653+ self._x = 10
1654+
1655+ @property
1656+ def x(self) -> int:
1657+ return self._x + 1
1658+
1659+ @x.setter
1660+ def x(self, val : int) -> None:
1661+ self._x = val + 1
1662+
1663+ #Inerits base property setters and getters
1664+ class C(A):
1665+ def __init__(self) -> None:
1666+ A.__init__(self)
1667+
1668+ @trait
1669+ class D():
1670+ def __init__(self) -> None:
1671+ self._x = 0
1672+
1673+ @property
1674+ def x(self) -> int:
1675+ return self._x
1676+
1677+ @x.setter
1678+ def x(self, val : int) -> None:
1679+ self._x = val
1680+
1681+ #Inherits trait property setters and getters
1682+ class E(D):
1683+ def __init__(self) -> None:
1684+ D.__init__(self)
1685+
1686+ #Overrides trait property setters and getters
1687+ class F(D):
1688+ def __init__(self) -> None:
1689+ self._x = 10
1690+
1691+ @property
1692+ def x(self) -> int:
1693+ return self._x + 10
1694+
1695+ @x.setter
1696+ def x(self, val : int) -> None:
1697+ self._x = val + 10
1698+
1699+ # # Property setter and getter are subtypes of base property setters and getters
1700+ # # class G(A):
1701+ # # def __init__(self) -> None:
1702+ # # A.__init__(self)
1703+
1704+ # # @property
1705+ # # def y(self) -> int:
1706+ # # return self._y
1707+
1708+ # # @y.setter
1709+ # # def y(self, val : object) -> None:
1710+ # # self._y = val
1711+
1712+ [file other.py]
1713+ # Run in both interpreted and compiled mode
1714+
1715+ from native import A, B, C, D, E, F
1716+
1717+ a = A()
1718+ assert a.x == 0
1719+ assert a._x == 0
1720+ a.x = 1
1721+ assert a.x == 1
1722+ assert a._x == 1
1723+ a._x = 0
1724+ assert a.x == 0
1725+ assert a._x == 0
1726+ b = B()
1727+ assert b.x == 11
1728+ assert b._x == 10
1729+ b.x = 11
1730+ assert b.x == 13
1731+ b._x = 11
1732+ assert b.x == 12
1733+ c = C()
1734+ assert c.x == 0
1735+ c.x = 1000
1736+ assert c.x == 1000
1737+ e = E()
1738+ assert e.x == 0
1739+ e.x = 1000
1740+ assert e.x == 1000
1741+ f = F()
1742+ assert f.x == 20
1743+ f.x = 30
1744+ assert f.x == 50
1745+
1746+ [file driver.py]
1747+ # Run the tests in both interpreted and compiled mode
1748+ import other
1749+ import other_interpreted
1750+
1751+ [out]
1752+
1753+ [case testSubclassAttributeAccess]
1754+ from mypy_extensions import trait
1755+
1756+ class A:
1757+ v = 0
1758+
1759+ class B(A):
1760+ v = 1
1761+
1762+ class C(B):
1763+ v = 2
1764+
1765+ [file driver.py]
1766+ from native import A, B, C
1767+
1768+ a = A()
1769+ b = B()
1770+ c = C()
0 commit comments