Completed
Push — master ( 49a9b0...0da5e6 )
by Max
05:47
created

test_abstractmethod_integration()   F

Complexity

Conditions 13

Size

Total Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 1 Features 0
Metric Value
dl 0
loc 49
c 6
b 1
f 0
rs 2.5507
cc 13

4 Methods

Rating   Name   Duplication   Size   Complexity  
A EClass.footer() 0 2 1
A DClass.barter() 0 2 1
A CClass.barter() 0 2 1
A FClass.barter() 0 3 1

How to fix   Complexity   

Complexity

Complex classes like test_abstractmethod_integration() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
from abc import abstractmethod
2
import abc as abc_main
3
from inspect import isabstract
4
import sys
5
6
import pytest
7
8
9
def test_import_compat(compat):
10
    """Test the module is importable. See conftest.py for the actual import."""
11
    assert compat
12
13
14
def test_import_abc(abc):
15
    """Test the module is importable. See conftest.py for the actual import."""
16
    assert abc
17
18
19
def test_has_class(abc):
20
    """Test the convenience class exists."""
21
    assert abc.NamespaceableABC
22
23
24
def test_abc_helper(abc):
25
    """Test the convenience class works as expected."""
26
    # create an ABC using the helper class and perform basic checks
27
    class CClass(abc.NamespaceableABC):
28
        """A throwaway test class."""
29
        @classmethod
30
        @abstractmethod
31
        def footer(cls):
32
            return cls.__name__
33
    assert isinstance(CClass, abc.NamespaceableABCMeta)
34
    with pytest.raises(TypeError):
35
        print(CClass())
36
37
    class DClass(CClass):
38
        """A throwaway test class."""
39
        @classmethod
40
        def footer(cls):
41
            return super().footer()
42
    assert DClass.footer() == 'DClass'
43
44
45
def test_abstractmethod_basics():
46
    """Test abstractmethod works as expected.
47
48
    Adapted from Python's test suite.
49
    """
50
    @abstractmethod
51
    def footer(self):
52
        """Return self. Abstract."""
53
        return self
54
    assert footer.__isabstractmethod__
55
56
    def barter(self):
57
        """Return self. Concrete."""
58
        return self
59
    assert not hasattr(barter, "__isabstractmethod__")
60
61
62
# IT IS TOO USED.
63
def test_abstractproperty_basics(abc):
64
    """Test abstract property works as expected.
65
66
    Adapted from Python's test suite.
67
    """
68
    @property
69
    @abstractmethod
70
    def footer(self):
71
        """Return nothing. Abstract."""
72
    assert footer.__isabstractmethod__
73
74
    def barter(self):
75
        """Return nothing. Concrete."""
76
    assert not getattr(barter, "__isabstractmethod__", False)
77
78
    class CClass(metaclass=abc.NamespaceableABCMeta):
79
        """A throwaway test class."""
80
        @property
81
        @abstractmethod
82
        def footer(self):
83
            """Return 3. Abstract."""
84
            return 3
85
    with pytest.raises(TypeError):
86
        print(CClass())
87
88
    class DClass(CClass):
89
        """A throwaway test class."""
90
        @CClass.footer.getter
91
        def footer(self):
92
            """Return 3. Concrete."""
93
            return super().footer
94
    assert DClass().footer == 3
95
96
97
def test_abstractproperty_namespaced(abc, namespace):
98
    """Test interaction between namespaces and abstract properties."""
99
    class CClass(metaclass=abc.NamespaceableABCMeta):
100
        """A throwaway test class."""
101
        with namespace() as ns:
102
            @property
103
            @abstractmethod
104
            def footer(self):
105
                """Return 3. Abstract."""
106
                return 3
107
    with pytest.raises(TypeError):
108
        print(CClass())
109
110
    class DClass(CClass):
111
        """A throwaway test class."""
112
        with namespace() as ns:
113
            @CClass.ns.footer.getter
114
            def footer(self):
115
                """Return 3. Concrete."""
116
                return super().ns.footer
117
    assert DClass().ns.footer == 3
118
119
120 View Code Duplication
def test_abstractclassmethod_basics(abc):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
121
    """Test abstract classmethod works as expected.
122
123
    Adapted from Python's test suite.
124
    """
125
    @classmethod
126
    @abstractmethod
127
    def footer(cls):
128
        pass
129
    assert footer.__isabstractmethod__
130
131
    @classmethod
132
    def barter(cls):
133
        pass
134
    assert not getattr(barter, "__isabstractmethod__", False)
135
136
    class CClass(metaclass=abc.NamespaceableABCMeta):
137
        """A throwaway test class."""
138
        @classmethod
139
        @abstractmethod
140
        def footer(cls):
141
            return cls.__name__
142
    with pytest.raises(TypeError):
143
        print(CClass())
144
145
    class DClass(CClass):
146
        """A throwaway test class."""
147
        @classmethod
148
        def footer(cls):
149
            return super().footer()
150
    assert DClass.footer() == 'DClass'
151
    assert DClass().footer() == 'DClass'
152
153
154 View Code Duplication
def test_abstractclassmethod_namespaced(abc, namespace):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
155
    """Test interaction between namespaces and abstract classmethods."""
156
    class CClass(metaclass=abc.NamespaceableABCMeta):
157
        """A throwaway test class."""
158
        with namespace() as ns:
159
            @classmethod
160
            @abstractmethod
161
            def footer(cls):
162
                return cls.__name__
163
    with pytest.raises(TypeError):
164
        print(CClass())
165
166
    class DClass(CClass):
167
        """A throwaway test class."""
168
        with namespace() as ns:
169
            @classmethod
170
            def footer(cls):
171
                return super().ns.footer()
172
    assert DClass.ns.footer() == 'DClass'
173
    assert DClass().ns.footer() == 'DClass'
174
175
176 View Code Duplication
def test_abstractstaticmethod_basics(abc):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
177
    """Test abstract staticmethod works as expected.
178
179
    Adapted from Python's test suite.
180
    """
181
    @staticmethod
182
    @abstractmethod
183
    def footer():
184
        pass
185
    assert footer.__isabstractmethod__
186
187
    @staticmethod
188
    def barter():
189
        pass
190
    assert not (getattr(barter, "__isabstractmethod__", False))
191
192
    class CClass(metaclass=abc.NamespaceableABCMeta):
193
        """A throwaway test class."""
194
        @staticmethod
195
        @abstractmethod
196
        def footer():
197
            return 3
198
    with pytest.raises(TypeError):
199
        print(CClass())
200
201
    class DClass(CClass):
202
        """A throwaway test class."""
203
        @staticmethod
204
        def footer():
205
            return 4
206
    assert DClass.footer() == 4
207
    assert DClass().footer() == 4
208
209
210 View Code Duplication
def test_abstractstaticmethod_namespaced(abc, namespace):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
211
    """Test interaction between namespaces and abstract staticmethods."""
212
    class CClass(metaclass=abc.NamespaceableABCMeta):
213
        """A throwaway test class."""
214
        with namespace() as ns:
215
            @staticmethod
216
            @abstractmethod
217
            def footer():
218
                return 3
219
    with pytest.raises(TypeError):
220
        print(CClass())
221
222
    class DClass(CClass):
223
        """A throwaway test class."""
224
        with namespace() as ns:
225
            @staticmethod
226
            def footer():
227
                return 4
228
    assert DClass.ns.footer() == 4
229
    assert DClass().ns.footer() == 4
230
231
232
def test_abstractmethod_integration(abc):
233
    """Test abstract shortcut decorators work as expected.
234
235
    Adapted from Python's test suite.
236
    """
237
    for abstractthing in [abstractmethod, abc_main.abstractproperty,
238
                          abc_main.abstractclassmethod,
239
                          abc_main.abstractstaticmethod]:
240
        class CClass(metaclass=abc.NamespaceableABCMeta):
241
            """A throwaway test class."""
242
            @abstractthing
243
            def footer(self):
244
                pass  # abstract
245
246
            def barter(self):
247
                pass  # concrete
248
        assert CClass.__abstractmethods__ == {"footer"}
249
        with pytest.raises(TypeError):
250
            print(CClass())  # because footer is abstract
251
        assert isabstract(CClass)
252
253
        class DClass(CClass):
254
            """A throwaway test class."""
255
256
            def barter(self):
257
                pass  # concrete override of concrete
258
        assert DClass.__abstractmethods__ == {"footer"}
259
        with pytest.raises(TypeError):
260
            print(DClass())  # because footer is still abstract
261
        assert isabstract(DClass)
262
263
        class EClass(DClass):
264
            """A throwaway test class."""
265
266
            def footer(self):
267
                pass
268
        assert EClass.__abstractmethods__ == set()
269
        EClass()  # now footer is concrete, too
270
        assert not isabstract(EClass)
271
272
        class FClass(EClass):
273
            """A throwaway test class."""
274
            @abstractthing
275
            def barter(self):
276
                pass  # abstract override of concrete
277
        assert FClass.__abstractmethods__ == {"barter"}
278
        with pytest.raises(TypeError):
279
            print(FClass())  # because barter is abstract now
280
        assert isabstract(FClass)
281
282
283
def test_abstractmethod_integration_namespaced(abc, namespace):
284
    """Test abstract shortcut decorators work as expected, under a namespace.
285
286
    Adapted from Python's test suite.
287
    """
288
    for abstractthing in [abstractmethod, abc_main.abstractproperty,
289
                          abc_main.abstractclassmethod,
290
                          abc_main.abstractstaticmethod]:
291
        class CClass(metaclass=abc.NamespaceableABCMeta):
292
            """A throwaway test class."""
293
            with namespace() as ns:
294
                @abstractthing
295
                def footer(self):
296
                    pass  # abstract
297
298
                def barter(self):
299
                    pass  # concrete
300
        assert CClass.__abstractmethods__ == {"ns.footer"}
301
        with pytest.raises(TypeError):
302
            print(CClass())  # because footer is abstract
303
        assert isabstract(CClass)
304
305
        class DClass(CClass):
306
            """A throwaway test class."""
307
            with namespace() as ns:
308
                def barter(self):
309
                    pass  # concrete override of concrete
310
        assert DClass.__abstractmethods__ == {"ns.footer"}
311
        with pytest.raises(TypeError):
312
            print(DClass())  # because footer is still abstract
313
        assert isabstract(DClass)
314
315
        class EClass(DClass):
316
            """A throwaway test class."""
317
            with namespace() as ns:
318
                def footer(self):
319
                    pass
320
        assert EClass.__abstractmethods__ == set()
321
        EClass()  # now footer is concrete, too
322
        assert not isabstract(EClass)
323
324
        class FClass(EClass):
325
            """A throwaway test class."""
326
            with namespace() as ns:
327
                @abstractthing
328
                def barter(self):
329
                    pass  # abstract override of concrete
330
        assert FClass.__abstractmethods__ == {"ns.barter"}
331
        with pytest.raises(TypeError):
332
            print(FClass())  # because barter is abstract now
333
        assert isabstract(FClass)
334
335
336
def test_descriptors_with_abstractmethod(abc):
337
    """Test abstract property methods work as expected.
338
339
    Adapted from Python's test suite.
340
    """
341
    class CClass(metaclass=abc.NamespaceableABCMeta):
342
        """A throwaway test class."""
343
        @property
344
        @abstractmethod
345
        def footer(self):
346
            return 3
347
348
        @footer.setter
349
        @abstractmethod
350
        def footer(self, val):
351
            pass
352
    with pytest.raises(TypeError):
353
        print(CClass())
354
355
    class DClass(CClass):
356
        """A throwaway test class."""
357
        @CClass.footer.getter
358
        def footer(self):
359
            return super().footer
360
    with pytest.raises(TypeError):
361
        print(DClass())
362
363
    class EClass(DClass):
364
        """A throwaway test class."""
365
        @DClass.footer.setter
366
        def footer(self, val):
367
            pass
368
    assert EClass().footer == 3
369
    # check that the property's __isabstractmethod__ descriptor does the
370
    # right thing when presented with a value that fails truth testing:
371
372
    class NotBool(object):
373
        """A pathological class for test purposes."""
374
375
        def __bool__(self):
376
            raise ValueError()
377
        __len__ = __bool__
378
    with pytest.raises(ValueError):
379
        class FClass(CClass):
380
            """A throwaway test class."""
381
382
            def barter(self):
383
                pass
384
            barter.__isabstractmethod__ = NotBool()
385
            footer = property(barter)
386
387
388
def test_descriptors_with_abstractmethod_namespaced(abc, namespace):
389
    """Test abstract property methods work as expected under a namespace.
390
391
    Adapted from Python's test suite.
392
    """
393
    class CClass(metaclass=abc.NamespaceableABCMeta):
394
        """A throwaway test class."""
395
        with namespace() as ns:
396
            @property
397
            @abstractmethod
398
            def footer(self):
399
                return 3
400
401
            @footer.setter
402
            @abstractmethod
403
            def footer(self, val):
404
                pass
405
    with pytest.raises(TypeError):
406
        print(CClass())
407
408
    class DClass(CClass):
409
        """A throwaway test class."""
410
        with namespace() as ns:
411
            @CClass.ns.footer.getter
412
            def footer(self):
413
                return super().ns.footer
414
    with pytest.raises(TypeError):
415
        print(DClass())
416
417
    class EClass(DClass):
418
        """A throwaway test class."""
419
        with namespace() as ns:
420
            @DClass.ns.footer.setter
421
            def footer(self, val):
422
                pass
423
    assert EClass().ns.footer == 3
424
    # check that the property's __isabstractmethod__ descriptor does the
425
    # right thing when presented with a value that fails truth testing:
426
427
    class NotBool(object):
428
        """A pathological class for test purposes."""
429
430
        def __bool__(self):
431
            raise ValueError()
432
        __len__ = __bool__
433
    with pytest.raises(ValueError):
434
        class FClass(CClass):
435
            """A throwaway test class."""
436
            with namespace() as ns:
437
                def barter(self):
438
                    pass
439
                barter.__isabstractmethod__ = NotBool()
440
                footer = property(barter)
441
442
443
def test_customdescriptors_with_abstractmethod(abc):
444
    """Test abstract custom descriptors work as expected.
445
446
    Adapted from Python's test suite.
447
    """
448
    class Descriptor:
449
        """A descriptor class integrated some with the ABC protocol."""
450
451
        def __init__(self, fget, fset=None):
452
            self._fget = fget
453
            self._fset = fset
454
455
        def getter(self, callable):
456
            return Descriptor(callable, self._fget)
457
458
        def setter(self, callable):
459
            return Descriptor(self._fget, callable)
460
461
        @property
462
        def __isabstractmethod__(self):
463
            return (getattr(self._fget, '__isabstractmethod__', False) or
464
                    getattr(self._fset, '__isabstractmethod__', False))
465
466
    class CClass(metaclass=abc.NamespaceableABCMeta):
467
        """A throwaway test class."""
468
        @Descriptor
469
        @abstractmethod
470
        def footer(self):
471
            return 3
472
473
        @footer.setter
474
        @abstractmethod
475
        def footer(self, val):
476
            pass
477
    with pytest.raises(TypeError):
478
        print(CClass())
479
480
    class DClass(CClass):
481
        """A throwaway test class."""
482
        @CClass.footer.getter
483
        def footer(self):
484
            return super().footer
485
    with pytest.raises(TypeError):
486
        print(DClass())
487
488
    class EClass(DClass):
489
        """A throwaway test class."""
490
        @DClass.footer.setter
491
        def footer(self, val):
492
            pass
493
    assert not (EClass.footer.__isabstractmethod__)
494
495
496
def test_customdescriptors_with_abstractmethod_namespaced(abc, namespace):
497
    """Test abstract custom descriptors work as expected under a namespace.
498
499
    Adapted from Python's test suite.
500
    """
501
    class Descriptor:
502
        """A descriptor class integrated some with the ABC protocol."""
503
504
        def __init__(self, fget, fset=None):
505
            self._fget = fget
506
            self._fset = fset
507
508
        def getter(self, callable):
509
            return Descriptor(callable, self._fget)
510
511
        def setter(self, callable):
512
            return Descriptor(self._fget, callable)
513
514
        @property
515
        def __isabstractmethod__(self):
516
            return (getattr(self._fget, '__isabstractmethod__', False) or
517
                    getattr(self._fset, '__isabstractmethod__', False))
518
519
    class CClass(metaclass=abc.NamespaceableABCMeta):
520
        """A throwaway test class."""
521
        with namespace() as ns:
522
            @Descriptor
523
            @abstractmethod
524
            def footer(self):
525
                return 3
526
527
            @footer.setter
528
            @abstractmethod
529
            def footer(self, val):
530
                pass
531
    with pytest.raises(TypeError):
532
        print(CClass())
533
534
    class DClass(CClass):
535
        """A throwaway test class."""
536
        with namespace() as ns:
537
            @CClass.ns.footer.getter
538
            def footer(self):
539
                return super().ns.footer
540
    with pytest.raises(TypeError):
541
        print(DClass())
542
543
    class EClass(DClass):
544
        """A throwaway test class."""
545
        with namespace() as ns:
546
            @DClass.ns.footer.setter
547
            def footer(self, val):
548
                pass
549
    assert not (EClass.ns.footer.__isabstractmethod__)
550
551
552
def test_metaclass_abc(abc):
553
    """Test abstract metaclasses work as expected.
554
555
    Adapted from Python's test suite.
556
    """
557
    # Metaclasses can be ABCs, too.
558
    class AClass(metaclass=abc.NamespaceableABCMeta):
559
        """A throwaway test class."""
560
        @abstractmethod
561
        def x(self):
562
            pass
563
    assert AClass.__abstractmethods__ == {"x"}
564
565
    class meta(type, AClass):
566
        """A throwaway test metaclass."""
567
568
        def x(self):
569
            return 1
570
571
    class CClass(metaclass=meta):
572
        """A throwaway test class."""
573
574
575
def test_metaclass_abc_namespaced(abc, namespace):
576
    """Test abstract metaclasses work as expected, with namespaces.
577
578
    Adapted from Python's test suite.
579
    """
580
    # Metaclasses can be ABCs, too.
581
    class AClass(metaclass=abc.NamespaceableABCMeta):
582
        """A throwaway test class."""
583
        with namespace() as ns:
584
            @abstractmethod
585
            def x(self):
586
                pass
587
    assert AClass.__abstractmethods__ == {"ns.x"}
588
589
    class meta(type, AClass):
590
        """A throwaway test metaclass."""
591
        with namespace() as ns:
592
            def x(self):
593
                return 1
594
595
    class CClass(metaclass=meta):
596
        """A throwaway test class."""
597
598
599
def test_registration_basics(abc):
600
    """Test ABC registration.
601
602
    Adapted from Python's test suite.
603
    """
604
    class AClass(metaclass=abc.NamespaceableABCMeta):
605
        """A throwaway test class."""
606
607
    class BClass(object):
608
        """A throwaway test class."""
609
    b = BClass()
610
    assert not (issubclass(BClass, AClass))
611
    assert not (issubclass(BClass, (AClass,)))
612
    assert not isinstance(b, AClass)
613
    assert not isinstance(b, (AClass,))
614
    BClass1 = AClass.register(BClass)
615
    assert issubclass(BClass, AClass)
616
    assert issubclass(BClass, (AClass,))
617
    assert isinstance(b, AClass)
618
    assert isinstance(b, (AClass,))
619
    assert BClass1 is BClass
620
621
    class CClass(BClass):
622
        """A throwaway test class."""
623
    c = CClass()
624
    assert issubclass(CClass, AClass)
625
    assert issubclass(CClass, (AClass,))
626
    assert isinstance(c, AClass)
627
    assert isinstance(c, (AClass,))
628
629
630
def test_register_as_class_deco(abc):
631
    """Test ABC registration decorator.
632
633
    Adapted from Python's test suite.
634
    """
635
    class AClass(metaclass=abc.NamespaceableABCMeta):
636
        """A throwaway test class."""
637
638
    @AClass.register
639
    class BClass(object):
640
        """A throwaway test class."""
641
    b = BClass()
642
    assert issubclass(BClass, AClass)
643
    assert issubclass(BClass, (AClass,))
644
    assert isinstance(b, AClass)
645
    assert isinstance(b, (AClass,))
646
647
    @AClass.register
648
    class CClass(BClass):
649
        """A throwaway test class."""
650
    c = CClass()
651
    assert issubclass(CClass, AClass)
652
    assert issubclass(CClass, (AClass,))
653
    assert isinstance(c, AClass)
654
    assert isinstance(c, (AClass,))
655
    assert CClass is AClass.register(CClass)
656
657
658
@pytest.mark.xfail(sys.version_info < (3, 4),
659
                   reason="python3.4 api changes?", strict=True)
660
def test_isinstance_invalidation(abc):
661
    """Test after-the-fact registration behavior.
662
663
    Adapted from Python's test suite.
664
    """
665
    class AClass(metaclass=abc.NamespaceableABCMeta):
666
        """A throwaway test class."""
667
668
    class BClass:
669
        """A throwaway test class."""
670
    b = BClass()
671
    assert not (isinstance(b, AClass))
672
    assert not (isinstance(b, (AClass,)))
673
    token_old = abc_main.get_cache_token()
674
    AClass.register(BClass)
675
    token_new = abc_main.get_cache_token()
676
    assert token_old != token_new
677
    assert isinstance(b, AClass)
678
    assert isinstance(b, (AClass,))
679
680
681
def test_registration_builtins(abc):
682
    """Test making builtin classes into registered subclasses.
683
684
    Adapted from Python's test suite.
685
    """
686
    class AClass(metaclass=abc.NamespaceableABCMeta):
687
        """A throwaway test class."""
688
    AClass.register(int)
689
    assert isinstance(42, AClass)
690
    assert isinstance(42, (AClass,))
691
    assert issubclass(int, AClass)
692
    assert issubclass(int, (AClass,))
693
694
    class BClass(AClass):
695
        """A throwaway test class."""
696
    BClass.register(str)
697
698
    class CClass(str):
699
        """A throwaway test class."""
700
    assert isinstance("", AClass)
701
    assert isinstance("", (AClass,))
702
    assert issubclass(str, AClass)
703
    assert issubclass(str, (AClass,))
704
    assert issubclass(CClass, AClass)
705
    assert issubclass(CClass, (AClass,))
706
707
708
def test_registration_edge_cases(abc):
709
    """Test edge cases in registration: reflexive, cyclic, repeated...
710
711
    Adapted from Python's test suite.
712
    """
713
    class AClass(metaclass=abc.NamespaceableABCMeta):
714
        """A throwaway test class."""
715
    AClass.register(AClass)  # should pass silently
716
717
    class AClass1(AClass):
718
        """A throwaway test class."""
719
    with pytest.raises(RuntimeError):
720
        AClass1.register(AClass)  # cycles not allowed
721
722
    class BClass(object):
723
        """A throwaway test class."""
724
    AClass1.register(BClass)  # ok
725
    AClass1.register(BClass)  # should pass silently
726
727
    class CClass(AClass):
728
        """A throwaway test class."""
729
    AClass.register(CClass)  # should pass silently
730
    with pytest.raises(RuntimeError):
731
        CClass.register(AClass)  # cycles not allowed
732
    CClass.register(BClass)  # ok
733
734
735
def test_register_non_class(abc):
736
    """Test that non-classes cannot be registered.
737
738
    Adapted from Python's test suite.
739
    """
740
    class AClass(metaclass=abc.NamespaceableABCMeta):
741
        """A throwaway test class."""
742
    with pytest.raises(TypeError, message="Can only register classes"):
743
        print(AClass.register(4))
744
745
746
def test_registration_transitiveness(abc):
747
    """Test that chains of registration hold.
748
749
    Adapted from Python's test suite.
750
    """
751
    class AClass(metaclass=abc.NamespaceableABCMeta):
752
        """A throwaway test class."""
753
    assert issubclass(AClass, AClass)
754
    assert issubclass(AClass, (AClass,))
755
756
    class BClass(metaclass=abc.NamespaceableABCMeta):
757
        """A throwaway test class."""
758
    assert not (issubclass(AClass, BClass))
759
    assert not (issubclass(AClass, (BClass,)))
760
    assert not (issubclass(BClass, AClass))
761
    assert not (issubclass(BClass, (AClass,)))
762
763
    class CClass(metaclass=abc.NamespaceableABCMeta):
764
        """A throwaway test class."""
765
    AClass.register(BClass)
766
767
    class BClass1(BClass):
768
        """A throwaway test class."""
769
    assert issubclass(BClass1, AClass)
770
    assert issubclass(BClass1, (AClass,))
771
772
    class CClass1(CClass):
773
        """A throwaway test class."""
774
    BClass1.register(CClass1)
775
    assert not issubclass(CClass, BClass)
776
    assert not issubclass(CClass, (BClass,))
777
    assert not issubclass(CClass, BClass1)
778
    assert not issubclass(CClass, (BClass1,))
779
    assert issubclass(CClass1, AClass)
780
    assert issubclass(CClass1, (AClass,))
781
    assert issubclass(CClass1, BClass)
782
    assert issubclass(CClass1, (BClass,))
783
    assert issubclass(CClass1, BClass1)
784
    assert issubclass(CClass1, (BClass1,))
785
    CClass1.register(int)
786
787
    class MyInt(int):
788
        """A throwaway test class."""
789
    assert issubclass(MyInt, AClass)
790
    assert issubclass(MyInt, (AClass,))
791
    assert isinstance(42, AClass)
792
    assert isinstance(42, (AClass,))
793
794
795
def test_all_new_methods_are_called(abc):
796
    """Test that super delegation still works using abstract classes.
797
798
    Adapted from Python's test suite.
799
    """
800
    class AClass(metaclass=abc.NamespaceableABCMeta):
801
        """A throwaway test class."""
802
803
    class BClass(object):
804
        """A throwaway test class."""
805
        counter = 0
806
807
        def __new__(cls):
808
            BClass.counter += 1
809
            return super().__new__(cls)
810
811
    class CClass(AClass, BClass):
812
        """A throwaway test class."""
813
    assert BClass.counter == 0
814
    CClass()
815
    assert BClass.counter == 1
816