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