Completed
Push — master ( dd9775...803fb0 )
by Max
17:53 queued 13:56
created

test_abstractclassmethod_namespaced()   B

Complexity

Conditions 4

Size

Total Lines 22

Duplication

Lines 22
Ratio 100 %

Importance

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