@@ -157,8 +157,25 @@ def foo(): return 4
157
157
self .assertEqual (D .foo (), 4 )
158
158
self .assertEqual (D ().foo (), 4 )
159
159
160
- # TODO: RUSTPYTHON
161
- @unittest .expectedFailure
160
+ def test_object_new_with_one_abstractmethod (self ):
161
+ class C (metaclass = abc_ABCMeta ):
162
+ @abc .abstractmethod
163
+ def method_one (self ):
164
+ pass
165
+ msg = r"class C with abstract method method_one"
166
+ self .assertRaisesRegex (TypeError , msg , C )
167
+
168
+ def test_object_new_with_many_abstractmethods (self ):
169
+ class C (metaclass = abc_ABCMeta ):
170
+ @abc .abstractmethod
171
+ def method_one (self ):
172
+ pass
173
+ @abc .abstractmethod
174
+ def method_two (self ):
175
+ pass
176
+ msg = r"class C with abstract methods method_one, method_two"
177
+ self .assertRaisesRegex (TypeError , msg , C )
178
+
162
179
def test_abstractmethod_integration (self ):
163
180
for abstractthing in [abc .abstractmethod , abc .abstractproperty ,
164
181
abc .abstractclassmethod ,
@@ -219,6 +236,7 @@ def bar(self):
219
236
bar .__isabstractmethod__ = NotBool ()
220
237
foo = property (bar )
221
238
239
+
222
240
def test_customdescriptors_with_abstractmethod (self ):
223
241
class Descriptor :
224
242
def __init__ (self , fget , fset = None ):
@@ -318,7 +336,7 @@ class B:
318
336
token_old = abc_get_cache_token ()
319
337
A .register (B )
320
338
token_new = abc_get_cache_token ()
321
- self .assertNotEqual ( token_old , token_new )
339
+ self .assertGreater ( token_new , token_old )
322
340
self .assertTrue (isinstance (b , A ))
323
341
self .assertTrue (isinstance (b , (A ,)))
324
342
@@ -451,6 +469,24 @@ class S(metaclass=abc_ABCMeta):
451
469
with self .assertRaisesRegex (Exception , exc_msg ):
452
470
issubclass (int , S )
453
471
472
+ def test_subclasshook (self ):
473
+ class A (metaclass = abc .ABCMeta ):
474
+ @classmethod
475
+ def __subclasshook__ (cls , C ):
476
+ if cls is A :
477
+ return 'foo' in C .__dict__
478
+ return NotImplemented
479
+ self .assertFalse (issubclass (A , A ))
480
+ self .assertFalse (issubclass (A , (A ,)))
481
+ class B :
482
+ foo = 42
483
+ self .assertTrue (issubclass (B , A ))
484
+ self .assertTrue (issubclass (B , (A ,)))
485
+ class C :
486
+ spam = 42
487
+ self .assertFalse (issubclass (C , A ))
488
+ self .assertFalse (issubclass (C , (A ,)))
489
+
454
490
def test_all_new_methods_are_called (self ):
455
491
class A (metaclass = abc_ABCMeta ):
456
492
pass
@@ -480,6 +516,155 @@ class C(with_metaclass(abc_ABCMeta, A, B)):
480
516
pass
481
517
self .assertEqual (C .__class__ , abc_ABCMeta )
482
518
519
+ def test_update_del (self ):
520
+ class A (metaclass = abc_ABCMeta ):
521
+ @abc .abstractmethod
522
+ def foo (self ):
523
+ pass
524
+
525
+ del A .foo
526
+ self .assertEqual (A .__abstractmethods__ , {'foo' })
527
+ self .assertFalse (hasattr (A , 'foo' ))
528
+
529
+ abc .update_abstractmethods (A )
530
+
531
+ self .assertEqual (A .__abstractmethods__ , set ())
532
+ A ()
533
+
534
+
535
+ def test_update_new_abstractmethods (self ):
536
+ class A (metaclass = abc_ABCMeta ):
537
+ @abc .abstractmethod
538
+ def bar (self ):
539
+ pass
540
+
541
+ @abc .abstractmethod
542
+ def updated_foo (self ):
543
+ pass
544
+
545
+ A .foo = updated_foo
546
+ abc .update_abstractmethods (A )
547
+ self .assertEqual (A .__abstractmethods__ , {'foo' , 'bar' })
548
+ msg = "class A with abstract methods bar, foo"
549
+ self .assertRaisesRegex (TypeError , msg , A )
550
+
551
+ def test_update_implementation (self ):
552
+ class A (metaclass = abc_ABCMeta ):
553
+ @abc .abstractmethod
554
+ def foo (self ):
555
+ pass
556
+
557
+ class B (A ):
558
+ pass
559
+
560
+ msg = "class B with abstract method foo"
561
+ self .assertRaisesRegex (TypeError , msg , B )
562
+ self .assertEqual (B .__abstractmethods__ , {'foo' })
563
+
564
+ B .foo = lambda self : None
565
+
566
+ abc .update_abstractmethods (B )
567
+
568
+ B ()
569
+ self .assertEqual (B .__abstractmethods__ , set ())
570
+
571
+ def test_update_as_decorator (self ):
572
+ class A (metaclass = abc_ABCMeta ):
573
+ @abc .abstractmethod
574
+ def foo (self ):
575
+ pass
576
+
577
+ def class_decorator (cls ):
578
+ cls .foo = lambda self : None
579
+ return cls
580
+
581
+ @abc .update_abstractmethods
582
+ @class_decorator
583
+ class B (A ):
584
+ pass
585
+
586
+ B ()
587
+ self .assertEqual (B .__abstractmethods__ , set ())
588
+
589
+ def test_update_non_abc (self ):
590
+ class A :
591
+ pass
592
+
593
+ @abc .abstractmethod
594
+ def updated_foo (self ):
595
+ pass
596
+
597
+ A .foo = updated_foo
598
+ abc .update_abstractmethods (A )
599
+ A ()
600
+ self .assertFalse (hasattr (A , '__abstractmethods__' ))
601
+
602
+ def test_update_del_implementation (self ):
603
+ class A (metaclass = abc_ABCMeta ):
604
+ @abc .abstractmethod
605
+ def foo (self ):
606
+ pass
607
+
608
+ class B (A ):
609
+ def foo (self ):
610
+ pass
611
+
612
+ B ()
613
+
614
+ del B .foo
615
+
616
+ abc .update_abstractmethods (B )
617
+
618
+ msg = "class B with abstract method foo"
619
+ self .assertRaisesRegex (TypeError , msg , B )
620
+
621
+ def test_update_layered_implementation (self ):
622
+ class A (metaclass = abc_ABCMeta ):
623
+ @abc .abstractmethod
624
+ def foo (self ):
625
+ pass
626
+
627
+ class B (A ):
628
+ pass
629
+
630
+ class C (B ):
631
+ def foo (self ):
632
+ pass
633
+
634
+ C ()
635
+
636
+ del C .foo
637
+
638
+ abc .update_abstractmethods (C )
639
+
640
+ msg = "class C with abstract method foo"
641
+ self .assertRaisesRegex (TypeError , msg , C )
642
+
643
+ def test_update_multi_inheritance (self ):
644
+ class A (metaclass = abc_ABCMeta ):
645
+ @abc .abstractmethod
646
+ def foo (self ):
647
+ pass
648
+
649
+ class B (metaclass = abc_ABCMeta ):
650
+ def foo (self ):
651
+ pass
652
+
653
+ class C (B , A ):
654
+ @abc .abstractmethod
655
+ def foo (self ):
656
+ pass
657
+
658
+ self .assertEqual (C .__abstractmethods__ , {'foo' })
659
+
660
+ del C .foo
661
+
662
+ abc .update_abstractmethods (C )
663
+
664
+ self .assertEqual (C .__abstractmethods__ , set ())
665
+
666
+ C ()
667
+
483
668
484
669
class TestABCWithInitSubclass (unittest .TestCase ):
485
670
def test_works_with_init_subclass (self ):
0 commit comments