Completed
Push — master ( 6006b8...dd9775 )
by Max
24:40 queued 19:14
created

AClass

Complexity

Total Complexity 0

Size/Duplication

Total Lines 5
Duplicated Lines 0 %

Importance

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