@@ -390,29 +390,6 @@ assert c.a == 13
390
390
assert type(c) == C
391
391
assert not hasattr(c, 'b')
392
392
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
-
416
393
[case testCastUserClass]
417
394
from typing import List
418
395
@@ -1466,3 +1443,328 @@ with patch("interp.Bar.spam", lambda self: 20):
1466
1443
1467
1444
with assertRaises(TypeError, "int object expected; got str"):
1468
1445
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