1# Copyright (c) Twisted Matrix Laboratories.
2# See LICENSE for details.
3
4"""
5Test cases for the L{twisted.python.reflect} module.
6"""
7
8from __future__ import division, absolute_import
9
10import os
11import weakref
12from collections import deque
13
14from twisted.python.compat import _PY3
15from twisted.trial import unittest
16from twisted.trial.unittest import SynchronousTestCase as TestCase
17from twisted.python import reflect
18from twisted.python.reflect import (
19    accumulateMethods, prefixedMethods, prefixedMethodNames,
20    addMethodNamesToDict, fullyQualifiedName)
21from twisted.python.versions import Version
22
23
24class Base(object):
25    """
26    A no-op class which can be used to verify the behavior of
27    method-discovering APIs.
28    """
29
30    def method(self):
31        """
32        A no-op method which can be discovered.
33        """
34
35
36
37class Sub(Base):
38    """
39    A subclass of a class with a method which can be discovered.
40    """
41
42
43
44class Separate(object):
45    """
46    A no-op class with methods with differing prefixes.
47    """
48
49    def good_method(self):
50        """
51        A no-op method which a matching prefix to be discovered.
52        """
53
54
55    def bad_method(self):
56        """
57        A no-op method with a mismatched prefix to not be discovered.
58        """
59
60
61
62class AccumulateMethodsTests(TestCase):
63    """
64    Tests for L{accumulateMethods} which finds methods on a class hierarchy and
65    adds them to a dictionary.
66    """
67
68    def test_ownClass(self):
69        """
70        If x is and instance of Base and Base defines a method named method,
71        L{accumulateMethods} adds an item to the given dictionary with
72        C{"method"} as the key and a bound method object for Base.method value.
73        """
74        x = Base()
75        output = {}
76        accumulateMethods(x, output)
77        self.assertEqual({"method": x.method}, output)
78
79
80    def test_baseClass(self):
81        """
82        If x is an instance of Sub and Sub is a subclass of Base and Base
83        defines a method named method, L{accumulateMethods} adds an item to the
84        given dictionary with C{"method"} as the key and a bound method object
85        for Base.method as the value.
86        """
87        x = Sub()
88        output = {}
89        accumulateMethods(x, output)
90        self.assertEqual({"method": x.method}, output)
91
92
93    def test_prefix(self):
94        """
95        If a prefix is given, L{accumulateMethods} limits its results to
96        methods beginning with that prefix.  Keys in the resulting dictionary
97        also have the prefix removed from them.
98        """
99        x = Separate()
100        output = {}
101        accumulateMethods(x, output, 'good_')
102        self.assertEqual({'method': x.good_method}, output)
103
104
105
106class PrefixedMethodsTests(TestCase):
107    """
108    Tests for L{prefixedMethods} which finds methods on a class hierarchy and
109    adds them to a dictionary.
110    """
111
112    def test_onlyObject(self):
113        """
114        L{prefixedMethods} returns a list of the methods discovered on an
115        object.
116        """
117        x = Base()
118        output = prefixedMethods(x)
119        self.assertEqual([x.method], output)
120
121
122    def test_prefix(self):
123        """
124        If a prefix is given, L{prefixedMethods} returns only methods named
125        with that prefix.
126        """
127        x = Separate()
128        output = prefixedMethods(x, 'good_')
129        self.assertEqual([x.good_method], output)
130
131
132
133class PrefixedMethodNamesTests(TestCase):
134    """
135    Tests for L{prefixedMethodNames}.
136    """
137    def test_method(self):
138        """
139        L{prefixedMethodNames} returns a list including methods with the given
140        prefix defined on the class passed to it.
141        """
142        self.assertEqual(["method"], prefixedMethodNames(Separate, "good_"))
143
144
145    def test_inheritedMethod(self):
146        """
147        L{prefixedMethodNames} returns a list included methods with the given
148        prefix defined on base classes of the class passed to it.
149        """
150        class Child(Separate):
151            pass
152        self.assertEqual(["method"], prefixedMethodNames(Child, "good_"))
153
154
155
156class AddMethodNamesToDictTests(TestCase):
157    """
158    Tests for L{addMethodNamesToDict}.
159    """
160    def test_baseClass(self):
161        """
162        If C{baseClass} is passed to L{addMethodNamesToDict}, only methods which
163        are a subclass of C{baseClass} are added to the result dictionary.
164        """
165        class Alternate(object):
166            pass
167
168        class Child(Separate, Alternate):
169            def good_alternate(self):
170                pass
171
172        result = {}
173        addMethodNamesToDict(Child, result, 'good_', Alternate)
174        self.assertEqual({'alternate': 1}, result)
175
176
177
178class Summer(object):
179    """
180    A class we look up as part of the LookupsTestCase.
181    """
182
183    def reallySet(self):
184        """
185        Do something.
186        """
187
188
189
190class LookupsTestCase(TestCase):
191    """
192    Tests for L{namedClass}, L{namedModule}, and L{namedAny}.
193    """
194
195    def test_namedClassLookup(self):
196        """
197        L{namedClass} should return the class object for the name it is passed.
198        """
199        self.assertIdentical(
200            reflect.namedClass("twisted.test.test_reflect.Summer"),
201            Summer)
202
203
204    def test_namedModuleLookup(self):
205        """
206        L{namedModule} should return the module object for the name it is
207        passed.
208        """
209        from twisted.python import monkey
210        self.assertIdentical(
211            reflect.namedModule("twisted.python.monkey"), monkey)
212
213
214    def test_namedAnyPackageLookup(self):
215        """
216        L{namedAny} should return the package object for the name it is passed.
217        """
218        import twisted.python
219        self.assertIdentical(
220            reflect.namedAny("twisted.python"), twisted.python)
221
222
223    def test_namedAnyModuleLookup(self):
224        """
225        L{namedAny} should return the module object for the name it is passed.
226        """
227        from twisted.python import monkey
228        self.assertIdentical(
229            reflect.namedAny("twisted.python.monkey"), monkey)
230
231
232    def test_namedAnyClassLookup(self):
233        """
234        L{namedAny} should return the class object for the name it is passed.
235        """
236        self.assertIdentical(
237            reflect.namedAny("twisted.test.test_reflect.Summer"),
238            Summer)
239
240
241    def test_namedAnyAttributeLookup(self):
242        """
243        L{namedAny} should return the object an attribute of a non-module,
244        non-package object is bound to for the name it is passed.
245        """
246        # Note - not assertEqual because unbound method lookup creates a new
247        # object every time.  This is a foolishness of Python's object
248        # implementation, not a bug in Twisted.
249        self.assertEqual(
250            reflect.namedAny(
251                "twisted.test.test_reflect.Summer.reallySet"),
252            Summer.reallySet)
253
254
255    def test_namedAnySecondAttributeLookup(self):
256        """
257        L{namedAny} should return the object an attribute of an object which
258        itself was an attribute of a non-module, non-package object is bound to
259        for the name it is passed.
260        """
261        self.assertIdentical(
262            reflect.namedAny(
263                "twisted.test.test_reflect."
264                "Summer.reallySet.__doc__"),
265            Summer.reallySet.__doc__)
266
267
268    def test_importExceptions(self):
269        """
270        Exceptions raised by modules which L{namedAny} causes to be imported
271        should pass through L{namedAny} to the caller.
272        """
273        self.assertRaises(
274            ZeroDivisionError,
275            reflect.namedAny, "twisted.test.reflect_helper_ZDE")
276        # Make sure that there is post-failed-import cleanup
277        self.assertRaises(
278            ZeroDivisionError,
279            reflect.namedAny, "twisted.test.reflect_helper_ZDE")
280        self.assertRaises(
281            ValueError,
282            reflect.namedAny, "twisted.test.reflect_helper_VE")
283        # Modules which themselves raise ImportError when imported should
284        # result in an ImportError
285        self.assertRaises(
286            ImportError,
287            reflect.namedAny, "twisted.test.reflect_helper_IE")
288
289
290    def test_attributeExceptions(self):
291        """
292        If segments on the end of a fully-qualified Python name represents
293        attributes which aren't actually present on the object represented by
294        the earlier segments, L{namedAny} should raise an L{AttributeError}.
295        """
296        self.assertRaises(
297            AttributeError,
298            reflect.namedAny, "twisted.nosuchmoduleintheworld")
299        # ImportError behaves somewhat differently between "import
300        # extant.nonextant" and "import extant.nonextant.nonextant", so test
301        # the latter as well.
302        self.assertRaises(
303            AttributeError,
304            reflect.namedAny, "twisted.nosuch.modulein.theworld")
305        self.assertRaises(
306            AttributeError,
307            reflect.namedAny,
308            "twisted.test.test_reflect.Summer.nosuchattribute")
309
310
311    def test_invalidNames(self):
312        """
313        Passing a name which isn't a fully-qualified Python name to L{namedAny}
314        should result in one of the following exceptions:
315         - L{InvalidName}: the name is not a dot-separated list of Python
316           objects
317         - L{ObjectNotFound}: the object doesn't exist
318         - L{ModuleNotFound}: the object doesn't exist and there is only one
319           component in the name
320        """
321        err = self.assertRaises(reflect.ModuleNotFound, reflect.namedAny,
322                                'nosuchmoduleintheworld')
323        self.assertEqual(str(err), "No module named 'nosuchmoduleintheworld'")
324
325        # This is a dot-separated list, but it isn't valid!
326        err = self.assertRaises(reflect.ObjectNotFound, reflect.namedAny,
327                                "@#$@(#.!@(#!@#")
328        self.assertEqual(str(err), "'@#$@(#.!@(#!@#' does not name an object")
329
330        err = self.assertRaises(reflect.ObjectNotFound, reflect.namedAny,
331                                "tcelfer.nohtyp.detsiwt")
332        self.assertEqual(
333            str(err),
334            "'tcelfer.nohtyp.detsiwt' does not name an object")
335
336        err = self.assertRaises(reflect.InvalidName, reflect.namedAny, '')
337        self.assertEqual(str(err), 'Empty module name')
338
339        for invalidName in ['.twisted', 'twisted.', 'twisted..python']:
340            err = self.assertRaises(
341                reflect.InvalidName, reflect.namedAny, invalidName)
342            self.assertEqual(
343                str(err),
344                "name must be a string giving a '.'-separated list of Python "
345                "identifiers, not %r" % (invalidName,))
346
347
348    def test_requireModuleImportError(self):
349        """
350        When module import fails with ImportError it returns the specified
351        default value.
352        """
353        for name in ['nosuchmtopodule', 'no.such.module']:
354            default = object()
355
356            result = reflect.requireModule(name, default=default)
357
358            self.assertIs(result, default)
359
360
361    def test_requireModuleDefaultNone(self):
362        """
363        When module import fails it returns C{None} by default.
364        """
365        result = reflect.requireModule('no.such.module')
366
367        self.assertIs(None, result)
368
369
370    def test_requireModuleRequestedImport(self):
371        """
372        When module import succeed it returns the module and not the default
373        value.
374        """
375        from twisted.python import monkey
376        default = object()
377
378        self.assertIs(
379            reflect.requireModule('twisted.python.monkey', default=default),
380            monkey,
381            )
382
383
384
385class Breakable(object):
386
387    breakRepr = False
388    breakStr = False
389
390    def __str__(self):
391        if self.breakStr:
392            raise RuntimeError("str!")
393        else:
394            return '<Breakable>'
395
396
397    def __repr__(self):
398        if self.breakRepr:
399            raise RuntimeError("repr!")
400        else:
401            return 'Breakable()'
402
403
404
405class BrokenType(Breakable, type):
406    breakName = False
407
408    def get___name__(self):
409        if self.breakName:
410            raise RuntimeError("no name")
411        return 'BrokenType'
412    __name__ = property(get___name__)
413
414
415
416BTBase = BrokenType('BTBase', (Breakable,),
417                    {"breakRepr": True,
418                     "breakStr": True})
419
420
421
422class NoClassAttr(Breakable):
423    __class__ = property(lambda x: x.not_class)
424
425
426
427class SafeRepr(TestCase):
428    """
429    Tests for L{reflect.safe_repr} function.
430    """
431
432    def test_workingRepr(self):
433        """
434        L{reflect.safe_repr} produces the same output as C{repr} on a working
435        object.
436        """
437        x = [1, 2, 3]
438        self.assertEqual(reflect.safe_repr(x), repr(x))
439
440
441    def test_brokenRepr(self):
442        """
443        L{reflect.safe_repr} returns a string with class name, address, and
444        traceback when the repr call failed.
445        """
446        b = Breakable()
447        b.breakRepr = True
448        bRepr = reflect.safe_repr(b)
449        self.assertIn("Breakable instance at 0x", bRepr)
450        # Check that the file is in the repr, but without the extension as it
451        # can be .py/.pyc
452        self.assertIn(os.path.splitext(__file__)[0], bRepr)
453        self.assertIn("RuntimeError: repr!", bRepr)
454
455
456    def test_brokenStr(self):
457        """
458        L{reflect.safe_repr} isn't affected by a broken C{__str__} method.
459        """
460        b = Breakable()
461        b.breakStr = True
462        self.assertEqual(reflect.safe_repr(b), repr(b))
463
464
465    def test_brokenClassRepr(self):
466        class X(BTBase):
467            breakRepr = True
468        reflect.safe_repr(X)
469        reflect.safe_repr(X())
470
471
472    def test_brokenReprIncludesID(self):
473        """
474        C{id} is used to print the ID of the object in case of an error.
475
476        L{safe_repr} includes a traceback after a newline, so we only check
477        against the first line of the repr.
478        """
479        class X(BTBase):
480            breakRepr = True
481
482        xRepr = reflect.safe_repr(X)
483        xReprExpected = ('<BrokenType instance at 0x%x with repr error:'
484                         % (id(X),))
485        self.assertEqual(xReprExpected, xRepr.split('\n')[0])
486
487
488    def test_brokenClassStr(self):
489        class X(BTBase):
490            breakStr = True
491        reflect.safe_repr(X)
492        reflect.safe_repr(X())
493
494
495    def test_brokenClassAttribute(self):
496        """
497        If an object raises an exception when accessing its C{__class__}
498        attribute, L{reflect.safe_repr} uses C{type} to retrieve the class
499        object.
500        """
501        b = NoClassAttr()
502        b.breakRepr = True
503        bRepr = reflect.safe_repr(b)
504        self.assertIn("NoClassAttr instance at 0x", bRepr)
505        self.assertIn(os.path.splitext(__file__)[0], bRepr)
506        self.assertIn("RuntimeError: repr!", bRepr)
507
508
509    def test_brokenClassNameAttribute(self):
510        """
511        If a class raises an exception when accessing its C{__name__} attribute
512        B{and} when calling its C{__str__} implementation, L{reflect.safe_repr}
513        returns 'BROKEN CLASS' instead of the class name.
514        """
515        class X(BTBase):
516            breakName = True
517        xRepr = reflect.safe_repr(X())
518        self.assertIn("<BROKEN CLASS AT 0x", xRepr)
519        self.assertIn(os.path.splitext(__file__)[0], xRepr)
520        self.assertIn("RuntimeError: repr!", xRepr)
521
522
523
524class SafeStr(TestCase):
525    """
526    Tests for L{reflect.safe_str} function.
527    """
528
529    def test_workingStr(self):
530        x = [1, 2, 3]
531        self.assertEqual(reflect.safe_str(x), str(x))
532
533
534    def test_brokenStr(self):
535        b = Breakable()
536        b.breakStr = True
537        reflect.safe_str(b)
538
539
540    def test_brokenRepr(self):
541        b = Breakable()
542        b.breakRepr = True
543        reflect.safe_str(b)
544
545
546    def test_brokenClassStr(self):
547        class X(BTBase):
548            breakStr = True
549        reflect.safe_str(X)
550        reflect.safe_str(X())
551
552
553    def test_brokenClassRepr(self):
554        class X(BTBase):
555            breakRepr = True
556        reflect.safe_str(X)
557        reflect.safe_str(X())
558
559
560    def test_brokenClassAttribute(self):
561        """
562        If an object raises an exception when accessing its C{__class__}
563        attribute, L{reflect.safe_str} uses C{type} to retrieve the class
564        object.
565        """
566        b = NoClassAttr()
567        b.breakStr = True
568        bStr = reflect.safe_str(b)
569        self.assertIn("NoClassAttr instance at 0x", bStr)
570        self.assertIn(os.path.splitext(__file__)[0], bStr)
571        self.assertIn("RuntimeError: str!", bStr)
572
573
574    def test_brokenClassNameAttribute(self):
575        """
576        If a class raises an exception when accessing its C{__name__} attribute
577        B{and} when calling its C{__str__} implementation, L{reflect.safe_str}
578        returns 'BROKEN CLASS' instead of the class name.
579        """
580        class X(BTBase):
581            breakName = True
582        xStr = reflect.safe_str(X())
583        self.assertIn("<BROKEN CLASS AT 0x", xStr)
584        self.assertIn(os.path.splitext(__file__)[0], xStr)
585        self.assertIn("RuntimeError: str!", xStr)
586
587
588
589class FilenameToModule(TestCase):
590    """
591    Test L{filenameToModuleName} detection.
592    """
593
594    def setUp(self):
595        self.path = os.path.join(self.mktemp(), "fakepackage", "test")
596        os.makedirs(self.path)
597        with open(os.path.join(self.path, "__init__.py"), "w") as f:
598            f.write("")
599        with open(os.path.join(os.path.dirname(self.path), "__init__.py"),
600                  "w") as f:
601            f.write("")
602
603
604    def test_directory(self):
605        """
606        L{filenameToModuleName} returns the correct module (a package) given a
607        directory.
608        """
609        module = reflect.filenameToModuleName(self.path)
610        self.assertEqual(module, 'fakepackage.test')
611        module = reflect.filenameToModuleName(self.path + os.path.sep)
612        self.assertEqual(module, 'fakepackage.test')
613
614
615    def test_file(self):
616        """
617        L{filenameToModuleName} returns the correct module given the path to
618        its file.
619        """
620        module = reflect.filenameToModuleName(
621            os.path.join(self.path, 'test_reflect.py'))
622        self.assertEqual(module, 'fakepackage.test.test_reflect')
623
624
625    def test_bytes(self):
626        """
627        L{filenameToModuleName} returns the correct module given a C{bytes}
628        path to its file.
629        """
630        module = reflect.filenameToModuleName(
631            os.path.join(self.path.encode("utf-8"), b'test_reflect.py'))
632        # Module names are always native string:
633        self.assertEqual(module, 'fakepackage.test.test_reflect')
634
635
636
637class FullyQualifiedNameTests(TestCase):
638    """
639    Test for L{fullyQualifiedName}.
640    """
641
642    def _checkFullyQualifiedName(self, obj, expected):
643        """
644        Helper to check that fully qualified name of C{obj} results to
645        C{expected}.
646        """
647        self.assertEqual(fullyQualifiedName(obj), expected)
648
649
650    def test_package(self):
651        """
652        L{fullyQualifiedName} returns the full name of a package and a
653        subpackage.
654        """
655        import twisted
656        self._checkFullyQualifiedName(twisted, 'twisted')
657        import twisted.python
658        self._checkFullyQualifiedName(twisted.python, 'twisted.python')
659
660
661    def test_module(self):
662        """
663        L{fullyQualifiedName} returns the name of a module inside a a package.
664        """
665        import twisted.python.compat
666        self._checkFullyQualifiedName(
667            twisted.python.compat, 'twisted.python.compat')
668
669
670    def test_class(self):
671        """
672        L{fullyQualifiedName} returns the name of a class and its module.
673        """
674        self._checkFullyQualifiedName(
675            FullyQualifiedNameTests,
676            '%s.FullyQualifiedNameTests' % (__name__,))
677
678
679    def test_function(self):
680        """
681        L{fullyQualifiedName} returns the name of a function inside its module.
682        """
683        self._checkFullyQualifiedName(
684            fullyQualifiedName, "twisted.python.reflect.fullyQualifiedName")
685
686
687    def test_boundMethod(self):
688        """
689        L{fullyQualifiedName} returns the name of a bound method inside its
690        class and its module.
691        """
692        self._checkFullyQualifiedName(
693            self.test_boundMethod,
694            "%s.%s.test_boundMethod" % (__name__, self.__class__.__name__))
695
696
697    def test_unboundMethod(self):
698        """
699        L{fullyQualifiedName} returns the name of an unbound method inside its
700        class and its module.
701        """
702        self._checkFullyQualifiedName(
703            self.__class__.test_unboundMethod,
704            "%s.%s.test_unboundMethod" % (__name__, self.__class__.__name__))
705
706
707class ObjectGrep(unittest.TestCase):
708    if _PY3:
709        # This is to be removed when fixing #6986
710        skip = "twisted.python.reflect.objgrep hasn't been ported to Python 3"
711
712
713    def test_dictionary(self):
714        """
715        Test references search through a dictionnary, as a key or as a value.
716        """
717        o = object()
718        d1 = {None: o}
719        d2 = {o: None}
720
721        self.assertIn("[None]", reflect.objgrep(d1, o, reflect.isSame))
722        self.assertIn("{None}", reflect.objgrep(d2, o, reflect.isSame))
723
724    def test_list(self):
725        """
726        Test references search through a list.
727        """
728        o = object()
729        L = [None, o]
730
731        self.assertIn("[1]", reflect.objgrep(L, o, reflect.isSame))
732
733    def test_tuple(self):
734        """
735        Test references search through a tuple.
736        """
737        o = object()
738        T = (o, None)
739
740        self.assertIn("[0]", reflect.objgrep(T, o, reflect.isSame))
741
742    def test_instance(self):
743        """
744        Test references search through an object attribute.
745        """
746        class Dummy:
747            pass
748        o = object()
749        d = Dummy()
750        d.o = o
751
752        self.assertIn(".o", reflect.objgrep(d, o, reflect.isSame))
753
754    def test_weakref(self):
755        """
756        Test references search through a weakref object.
757        """
758        class Dummy:
759            pass
760        o = Dummy()
761        w1 = weakref.ref(o)
762
763        self.assertIn("()", reflect.objgrep(w1, o, reflect.isSame))
764
765    def test_boundMethod(self):
766        """
767        Test references search through method special attributes.
768        """
769        class Dummy:
770            def dummy(self):
771                pass
772        o = Dummy()
773        m = o.dummy
774
775        self.assertIn(".__self__",
776                      reflect.objgrep(m, m.__self__, reflect.isSame))
777        self.assertIn(".__self__.__class__",
778                      reflect.objgrep(m, m.__self__.__class__, reflect.isSame))
779        self.assertIn(".__func__",
780                      reflect.objgrep(m, m.__func__, reflect.isSame))
781
782    def test_everything(self):
783        """
784        Test references search using complex set of objects.
785        """
786        class Dummy:
787            def method(self):
788                pass
789
790        o = Dummy()
791        D1 = {(): "baz", None: "Quux", o: "Foosh"}
792        L = [None, (), D1, 3]
793        T = (L, {}, Dummy())
794        D2 = {0: "foo", 1: "bar", 2: T}
795        i = Dummy()
796        i.attr = D2
797        m = i.method
798        w = weakref.ref(m)
799
800        self.assertIn("().__self__.attr[2][0][2]{'Foosh'}",
801                      reflect.objgrep(w, o, reflect.isSame))
802
803    def test_depthLimit(self):
804        """
805        Test the depth of references search.
806        """
807        a = []
808        b = [a]
809        c = [a, b]
810        d = [a, c]
811
812        self.assertEqual(['[0]'], reflect.objgrep(d, a, reflect.isSame, maxDepth=1))
813        self.assertEqual(['[0]', '[1][0]'], reflect.objgrep(d, a, reflect.isSame, maxDepth=2))
814        self.assertEqual(['[0]', '[1][0]', '[1][1][0]'], reflect.objgrep(d, a, reflect.isSame, maxDepth=3))
815
816
817    def test_deque(self):
818        """
819        Test references search through a deque object.
820        """
821        o = object()
822        D = deque()
823        D.append(None)
824        D.append(o)
825
826        self.assertIn("[1]", reflect.objgrep(D, o, reflect.isSame))
827
828
829class GetClass(unittest.TestCase):
830    if _PY3:
831        oldClassNames = ['type']
832    else:
833        oldClassNames = ['class', 'classobj']
834
835    def testOld(self):
836        class OldClass:
837            pass
838        old = OldClass()
839        self.assertIn(reflect.getClass(OldClass).__name__, self.oldClassNames)
840        self.assertEqual(reflect.getClass(old).__name__, 'OldClass')
841
842    def testNew(self):
843        class NewClass(object):
844            pass
845        new = NewClass()
846        self.assertEqual(reflect.getClass(NewClass).__name__, 'type')
847        self.assertEqual(reflect.getClass(new).__name__, 'NewClass')
848
849
850if not _PY3:
851    # The functions tested below are deprecated but still used by external
852    # projects like Nevow 0.10. They are not going to be ported to Python 3
853    # (hence the condition above) and will be removed as soon as no project used
854    # by Twisted will depend on these functions. Also, have a look at the
855    # comments related to those functions in twisted.python.reflect.
856    class DeprecationTestCase(unittest.TestCase):
857        """
858        Test deprecations in twisted.python.reflect
859        """
860
861        def test_allYourBase(self):
862            """
863            Test deprecation of L{reflect.allYourBase}. See #5481 for removal.
864            """
865            self.callDeprecated(
866                (Version("Twisted", 11, 0, 0), "inspect.getmro"),
867                reflect.allYourBase, DeprecationTestCase)
868
869
870        def test_accumulateBases(self):
871            """
872            Test deprecation of L{reflect.accumulateBases}. See #5481 for removal.
873            """
874            l = []
875            self.callDeprecated(
876                (Version("Twisted", 11, 0, 0), "inspect.getmro"),
877                reflect.accumulateBases, DeprecationTestCase, l, None)
878
879
880        def test_getcurrent(self):
881            """
882            Test deprecation of L{reflect.getcurrent}.
883            """
884
885            class C:
886                pass
887
888            self.callDeprecated(
889                Version("Twisted", 14, 0, 0),
890                reflect.getcurrent, C)
891
892
893        def test_isinst(self):
894            """
895            Test deprecation of L{reflect.isinst}.
896            """
897
898            self.callDeprecated(
899                (Version("Twisted", 14, 0, 0), "isinstance"),
900                reflect.isinst, object(), object)
901