@@ -142,7 +142,7 @@ class B(metaclass=ABCMeta):
142
142
@abstractmethod
143
143
def f(self): pass
144
144
A() # OK
145
- B() # E: Cannot instantiate abstract class 'B' with abstract method 'f'
145
+ B() # E: Cannot instantiate abstract class 'B' with abstract attribute 'f'
146
146
[out]
147
147
148
148
[case testInstantiatingClassWithInheritedAbstractMethod]
@@ -154,7 +154,7 @@ class A(metaclass=ABCMeta):
154
154
@abstractmethod
155
155
def g(self): pass
156
156
class B(A): pass
157
- B()# E: Cannot instantiate abstract class 'B' with abstract methods 'f' and 'g'
157
+ B()# E: Cannot instantiate abstract class 'B' with abstract attributes 'f' and 'g'
158
158
[out]
159
159
160
160
@@ -376,8 +376,8 @@ class D(A, B):
376
376
class E(A, B):
377
377
def f(self) -> None: pass
378
378
def g(self) -> None: pass
379
- C() # E: Cannot instantiate abstract class 'C' with abstract method 'g'
380
- D() # E: Cannot instantiate abstract class 'D' with abstract method 'f'
379
+ C() # E: Cannot instantiate abstract class 'C' with abstract attribute 'g'
380
+ D() # E: Cannot instantiate abstract class 'D' with abstract attribute 'f'
381
381
E()
382
382
383
383
[case testInconsistentMro]
@@ -405,7 +405,7 @@ class B(A):
405
405
def f(self, x: int) -> int: pass
406
406
@overload
407
407
def f(self, x: str) -> str: pass
408
- A() # E: Cannot instantiate abstract class 'A' with abstract method 'f'
408
+ A() # E: Cannot instantiate abstract class 'A' with abstract attribute 'f'
409
409
B()
410
410
B().f(1)
411
411
a = B() # type: A
@@ -430,7 +430,7 @@ class B(A):
430
430
def f(self, x: int) -> int: pass
431
431
@overload
432
432
def f(self, x: str) -> str: pass
433
- A() # E: Cannot instantiate abstract class 'A' with abstract method 'f'
433
+ A() # E: Cannot instantiate abstract class 'A' with abstract attribute 'f'
434
434
B()
435
435
B().f(1)
436
436
a = B() # type: A
@@ -521,3 +521,211 @@ class B:
521
521
class C:
522
522
def __add__(self, other: int) -> B: pass
523
523
[out]
524
+
525
+
526
+ -- Abstract properties
527
+ -- -------------------
528
+
529
+
530
+ [case testReadOnlyAbstractProperty]
531
+ from abc import abstractproperty, ABCMeta
532
+ class A(metaclass=ABCMeta):
533
+ @abstractproperty
534
+ def x(self) -> int: pass
535
+ def f(a: A) -> None:
536
+ a.x() # E: "int" not callable
537
+ a.x = 1 # E: Property "x" defined in "A" is read-only
538
+ [out]
539
+ main: note: In function "f":
540
+
541
+ [case testReadOnlyAbstractPropertyForwardRef]
542
+ from abc import abstractproperty, ABCMeta
543
+ def f(a: A) -> None:
544
+ a.x() # E: "int" not callable
545
+ a.x = 1 # E: Property "x" defined in "A" is read-only
546
+ class A(metaclass=ABCMeta):
547
+ @abstractproperty
548
+ def x(self) -> int: pass
549
+ [out]
550
+ main: note: In function "f":
551
+
552
+ [case testReadWriteAbstractProperty]
553
+ from abc import abstractproperty, ABCMeta
554
+ def f(a: A) -> None:
555
+ a.x.y # E: "int" has no attribute "y"
556
+ a.x = 1
557
+ class A(metaclass=ABCMeta):
558
+ @abstractproperty
559
+ def x(self) -> int: pass
560
+ @x.setter
561
+ def x(self, x: int) -> None: pass
562
+ [out]
563
+ main: note: In function "f":
564
+
565
+ [case testInstantiateClassWithReadOnlyAbstractProperty]
566
+ from abc import abstractproperty, ABCMeta
567
+ class A(metaclass=ABCMeta):
568
+ @abstractproperty
569
+ def x(self) -> int: pass
570
+ class B(A): pass
571
+ b = B() # E: Cannot instantiate abstract class 'B' with abstract attribute 'x'
572
+
573
+ [case testInstantiateClassWithReadWriteAbstractProperty]
574
+ from abc import abstractproperty, ABCMeta
575
+ class A(metaclass=ABCMeta):
576
+ @abstractproperty
577
+ def x(self) -> int: pass
578
+ @x.setter
579
+ def x(self, x: int) -> None: pass
580
+ class B(A): pass
581
+ b = B() # E: Cannot instantiate abstract class 'B' with abstract attribute 'x'
582
+
583
+ [case testImplementAbstractPropertyViaProperty]
584
+ from abc import abstractproperty, ABCMeta
585
+ class A(metaclass=ABCMeta):
586
+ @abstractproperty
587
+ def x(self) -> int: pass
588
+ class B(A):
589
+ @property
590
+ def x(self) -> int: pass
591
+ b = B()
592
+ b.x() # E: "int" not callable
593
+ [builtins fixtures/property.py]
594
+
595
+ [case testImplementReradWriteAbstractPropertyViaProperty]
596
+ from abc import abstractproperty, ABCMeta
597
+ class A(metaclass=ABCMeta):
598
+ @abstractproperty
599
+ def x(self) -> int: pass
600
+ @x.setter
601
+ def x(self, v: int) -> None: pass
602
+ class B(A):
603
+ @property
604
+ def x(self) -> int: pass
605
+ @x.setter
606
+ def x(self, v: int) -> None: pass
607
+ b = B()
608
+ b.x.y # E: "int" has no attribute "y"
609
+ [builtins fixtures/property.py]
610
+
611
+ [case testImplementAbstractPropertyViaPropertyInvalidType]
612
+ from abc import abstractproperty, ABCMeta
613
+ class A(metaclass=ABCMeta):
614
+ @abstractproperty
615
+ def x(self) -> int: pass
616
+ class B(A):
617
+ @property
618
+ def x(self) -> str: pass # E
619
+ b = B()
620
+ b.x() # E
621
+ [builtins fixtures/property.py]
622
+ [out]
623
+ main: note: In class "B":
624
+ main:7: error: Return type of "x" incompatible with supertype "A"
625
+ main: note: At top level:
626
+ main:9: error: "str" not callable
627
+
628
+ [case testCantImplementAbstractPropertyViaInstanceVariable]
629
+ from abc import abstractproperty, ABCMeta
630
+ class A(metaclass=ABCMeta):
631
+ @abstractproperty
632
+ def x(self) -> int: pass
633
+ class B(A):
634
+ def __init__(self) -> None:
635
+ self.x = 1 # E
636
+ b = B() # E
637
+ b.x.y # E
638
+ [builtins fixtures/property.py]
639
+ [out]
640
+ main: note: In member "__init__" of class "B":
641
+ main:7: error: Property "x" defined in "B" is read-only
642
+ main: note: At top level:
643
+ main:8: error: Cannot instantiate abstract class 'B' with abstract attribute 'x'
644
+ main:9: error: "int" has no attribute "y"
645
+
646
+ [case testSuperWithAbstractProperty]
647
+ from abc import abstractproperty, ABCMeta
648
+ class A(metaclass=ABCMeta):
649
+ @abstractproperty
650
+ def x(self) -> int: pass
651
+ class B(A):
652
+ @property
653
+ def x(self) -> int:
654
+ return super().x.y # E: "int" has no attribute "y"
655
+ [builtins fixtures/property.py]
656
+ [out]
657
+ main: note: In member "x" of class "B":
658
+
659
+ [case testSuperWithReadWriteAbstractProperty]
660
+ from abc import abstractproperty, ABCMeta
661
+ class A(metaclass=ABCMeta):
662
+ @abstractproperty
663
+ def x(self) -> int: pass
664
+ @x.setter
665
+ def x(self, v: int) -> None: pass
666
+ class B(A):
667
+ @property
668
+ def x(self) -> int:
669
+ return super().x.y # E
670
+ @x.setter
671
+ def x(self, v: int) -> None:
672
+ super().x = '' # E
673
+ [builtins fixtures/property.py]
674
+ [out]
675
+ main: note: In member "x" of class "B":
676
+ main:10: error: "int" has no attribute "y"
677
+ main: note: In function "x":
678
+ main:13: error: Invalid assignment target
679
+
680
+ [case testOnlyImplementGetterOfReadWriteAbstractProperty]
681
+ from abc import abstractproperty, ABCMeta
682
+ class A(metaclass=ABCMeta):
683
+ @abstractproperty
684
+ def x(self) -> int: pass
685
+ @x.setter
686
+ def x(self, v: int) -> None: pass
687
+ class B(A):
688
+ @property # E
689
+ def x(self) -> int: pass
690
+ b = B()
691
+ b.x.y # E
692
+ [builtins fixtures/property.py]
693
+ [out]
694
+ main: note: In class "B":
695
+ main:8: error: Read-only property cannot override read-write property
696
+ main: note: At top level:
697
+ main:11: error: "int" has no attribute "y"
698
+
699
+ [case testDynamicallyTypedReadOnlyAbstractProperty]
700
+ from abc import abstractproperty, ABCMeta
701
+ class A(metaclass=ABCMeta):
702
+ @abstractproperty
703
+ def x(self): pass
704
+ def f(a: A) -> None:
705
+ a.x.y
706
+ a.x = 1 # E: Property "x" defined in "A" is read-only
707
+ [out]
708
+ main: note: In function "f":
709
+
710
+ [case testDynamicallyTypedReadOnlyAbstractPropertyForwardRef]
711
+ from abc import abstractproperty, ABCMeta
712
+ def f(a: A) -> None:
713
+ a.x.y
714
+ a.x = 1 # E: Property "x" defined in "A" is read-only
715
+ class A(metaclass=ABCMeta):
716
+ @abstractproperty
717
+ def x(self): pass
718
+ [out]
719
+ main: note: In function "f":
720
+
721
+ [case testDynamicallyTypedReadWriteAbstractProperty]
722
+ from abc import abstractproperty, ABCMeta
723
+ def f(a: A) -> None:
724
+ a.x.y
725
+ a.x = 1
726
+ class A(metaclass=ABCMeta):
727
+ @abstractproperty
728
+ def x(self): pass
729
+ @x.setter
730
+ def x(self, x): pass
731
+ [out]
0 commit comments