| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. | |
| 2 # See LICENSE for details. | |
| 3 | |
| 4 | |
| 5 """ | |
| 6 Test cases for twisted.reflect module. | |
| 7 """ | |
| 8 | |
| 9 import weakref, os | |
| 10 from ihooks import ModuleImporter | |
| 11 | |
| 12 try: | |
| 13 from collections import deque | |
| 14 except ImportError: | |
| 15 deque = None | |
| 16 | |
| 17 # Twisted Imports | |
| 18 from twisted.trial import unittest | |
| 19 from twisted.python import reflect | |
| 20 | |
| 21 | |
| 22 | |
| 23 class SettableTest(unittest.TestCase): | |
| 24 def setUp(self): | |
| 25 self.setter = reflect.Settable() | |
| 26 | |
| 27 def tearDown(self): | |
| 28 del self.setter | |
| 29 | |
| 30 def testSet(self): | |
| 31 self.setter(a=1, b=2) | |
| 32 self.failUnlessEqual(self.setter.a, 1) | |
| 33 self.failUnlessEqual(self.setter.b, 2) | |
| 34 | |
| 35 | |
| 36 class AccessorTester(reflect.Accessor): | |
| 37 def set_x(self, x): | |
| 38 self.y = x | |
| 39 self.reallySet('x',x) | |
| 40 | |
| 41 def get_z(self): | |
| 42 self.q = 1 | |
| 43 return 1 | |
| 44 | |
| 45 def del_z(self): | |
| 46 self.reallyDel("q") | |
| 47 | |
| 48 | |
| 49 class AccessorTest(unittest.TestCase): | |
| 50 def setUp(self): | |
| 51 self.tester = AccessorTester() | |
| 52 | |
| 53 def testSet(self): | |
| 54 self.tester.x = 1 | |
| 55 self.failUnlessEqual(self.tester.x, 1) | |
| 56 self.failUnlessEqual(self.tester.y, 1) | |
| 57 | |
| 58 def testGet(self): | |
| 59 self.failUnlessEqual(self.tester.z, 1) | |
| 60 self.failUnlessEqual(self.tester.q, 1) | |
| 61 | |
| 62 def testDel(self): | |
| 63 self.tester.z | |
| 64 self.failUnlessEqual(self.tester.q, 1) | |
| 65 del self.tester.z | |
| 66 self.failUnlessEqual(hasattr(self.tester, "q"), 0) | |
| 67 self.tester.x = 1 | |
| 68 del self.tester.x | |
| 69 self.failUnlessEqual(hasattr(self.tester, "x"), 0) | |
| 70 | |
| 71 | |
| 72 class LookupsTestCase(unittest.TestCase): | |
| 73 """ | |
| 74 Tests for L{namedClass}, L{namedModule}, and L{namedAny}. | |
| 75 """ | |
| 76 | |
| 77 def test_namedClassLookup(self): | |
| 78 """ | |
| 79 L{namedClass} should return the class object for the name it is passed. | |
| 80 """ | |
| 81 self.assertIdentical( | |
| 82 reflect.namedClass("twisted.python.reflect.Summer"), | |
| 83 reflect.Summer) | |
| 84 | |
| 85 | |
| 86 def test_namedModuleLookup(self): | |
| 87 """ | |
| 88 L{namedModule} should return the module object for the name it is | |
| 89 passed. | |
| 90 """ | |
| 91 self.assertIdentical( | |
| 92 reflect.namedModule("twisted.python.reflect"), reflect) | |
| 93 | |
| 94 | |
| 95 def test_namedAnyPackageLookup(self): | |
| 96 """ | |
| 97 L{namedAny} should return the package object for the name it is passed. | |
| 98 """ | |
| 99 import twisted.python | |
| 100 self.assertIdentical( | |
| 101 reflect.namedAny("twisted.python"), twisted.python) | |
| 102 | |
| 103 def test_namedAnyModuleLookup(self): | |
| 104 """ | |
| 105 L{namedAny} should return the module object for the name it is passed. | |
| 106 """ | |
| 107 self.assertIdentical( | |
| 108 reflect.namedAny("twisted.python.reflect"), reflect) | |
| 109 | |
| 110 | |
| 111 def test_namedAnyClassLookup(self): | |
| 112 """ | |
| 113 L{namedAny} should return the class object for the name it is passed. | |
| 114 """ | |
| 115 self.assertIdentical( | |
| 116 reflect.namedAny("twisted.python.reflect.Summer"), reflect.Summer) | |
| 117 | |
| 118 | |
| 119 def test_namedAnyAttributeLookup(self): | |
| 120 """ | |
| 121 L{namedAny} should return the object an attribute of a non-module, | |
| 122 non-package object is bound to for the name it is passed. | |
| 123 """ | |
| 124 # Note - not assertEqual because unbound method lookup creates a new | |
| 125 # object every time. This is a foolishness of Python's object | |
| 126 # implementation, not a bug in Twisted. | |
| 127 self.assertEqual( | |
| 128 reflect.namedAny("twisted.python.reflect.Summer.reallySet"), | |
| 129 reflect.Summer.reallySet) | |
| 130 | |
| 131 | |
| 132 def test_namedAnySecondAttributeLookup(self): | |
| 133 """ | |
| 134 L{namedAny} should return the object an attribute of an object which | |
| 135 itself was an attribute of a non-module, non-package object is bound to | |
| 136 for the name it is passed. | |
| 137 """ | |
| 138 self.assertIdentical( | |
| 139 reflect.namedAny( | |
| 140 "twisted.python.reflect.Summer.reallySet.__doc__"), | |
| 141 reflect.Summer.reallySet.__doc__) | |
| 142 | |
| 143 | |
| 144 def test_importExceptions(self): | |
| 145 """ | |
| 146 Exceptions raised by modules which L{namedAny} causes to be imported | |
| 147 should pass through L{namedAny} to the caller. | |
| 148 """ | |
| 149 self.assertRaises( | |
| 150 ZeroDivisionError, | |
| 151 reflect.namedAny, "twisted.test.reflect_helper_ZDE") | |
| 152 # Make sure that this behavior is *consistent* for 2.3, where there is | |
| 153 # no post-failed-import cleanup | |
| 154 self.assertRaises( | |
| 155 ZeroDivisionError, | |
| 156 reflect.namedAny, "twisted.test.reflect_helper_ZDE") | |
| 157 self.assertRaises( | |
| 158 ValueError, | |
| 159 reflect.namedAny, "twisted.test.reflect_helper_VE") | |
| 160 # Modules which themselves raise ImportError when imported should result
in an ImportError | |
| 161 self.assertRaises( | |
| 162 ImportError, | |
| 163 reflect.namedAny, "twisted.test.reflect_helper_IE") | |
| 164 | |
| 165 | |
| 166 def test_attributeExceptions(self): | |
| 167 """ | |
| 168 If segments on the end of a fully-qualified Python name represents | |
| 169 attributes which aren't actually present on the object represented by | |
| 170 the earlier segments, L{namedAny} should raise an L{AttributeError}. | |
| 171 """ | |
| 172 self.assertRaises( | |
| 173 AttributeError, | |
| 174 reflect.namedAny, "twisted.nosuchmoduleintheworld") | |
| 175 # ImportError behaves somewhat differently between "import | |
| 176 # extant.nonextant" and "import extant.nonextant.nonextant", so test | |
| 177 # the latter as well. | |
| 178 self.assertRaises( | |
| 179 AttributeError, | |
| 180 reflect.namedAny, "twisted.nosuch.modulein.theworld") | |
| 181 self.assertRaises( | |
| 182 AttributeError, | |
| 183 reflect.namedAny, "twisted.python.reflect.Summer.nosuchattributeinth
eworld") | |
| 184 | |
| 185 | |
| 186 def test_invalidNames(self): | |
| 187 """ | |
| 188 Passing a name which isn't a fully-qualified Python name to L{namedAny} | |
| 189 should result in a L{ValueError}. | |
| 190 """ | |
| 191 # Finally, invalid module names should raise a ValueError | |
| 192 self.assertRaises( | |
| 193 ValueError, | |
| 194 reflect.namedAny, "") | |
| 195 self.assertRaises( | |
| 196 ValueError, | |
| 197 reflect.namedAny, "12345") | |
| 198 self.assertRaises( | |
| 199 ValueError, | |
| 200 reflect.namedAny, "@#$@(#.!@(#!@#") | |
| 201 # This case is kind of stupid and is mostly a historical accident. | |
| 202 self.assertRaises( | |
| 203 ValueError, | |
| 204 reflect.namedAny, "tcelfer.nohtyp.detsiwt") | |
| 205 | |
| 206 | |
| 207 | |
| 208 class ImportHooksLookupTests(LookupsTestCase): | |
| 209 """ | |
| 210 Tests for lookup methods in the presence of L{ihooks}-style import hooks. | |
| 211 Runs all of the tests from L{LookupsTestCase} after installing a custom | |
| 212 import hook. | |
| 213 """ | |
| 214 def setUp(self): | |
| 215 """ | |
| 216 Perturb the normal import behavior subtly by installing an import | |
| 217 hook. No custom behavior is provided, but this adds some extra | |
| 218 frames to the call stack, which L{namedAny} must be able to account | |
| 219 for. | |
| 220 """ | |
| 221 self.importer = ModuleImporter() | |
| 222 self.importer.install() | |
| 223 | |
| 224 | |
| 225 def tearDown(self): | |
| 226 """ | |
| 227 Uninstall the custom import hook. | |
| 228 """ | |
| 229 self.importer.uninstall() | |
| 230 | |
| 231 | |
| 232 | |
| 233 class ObjectGrep(unittest.TestCase): | |
| 234 def test_dictionary(self): | |
| 235 """ | |
| 236 Test references search through a dictionnary, as a key or as a value. | |
| 237 """ | |
| 238 o = object() | |
| 239 d1 = {None: o} | |
| 240 d2 = {o: None} | |
| 241 | |
| 242 self.assertIn("[None]", reflect.objgrep(d1, o, reflect.isSame)) | |
| 243 self.assertIn("{None}", reflect.objgrep(d2, o, reflect.isSame)) | |
| 244 | |
| 245 def test_list(self): | |
| 246 """ | |
| 247 Test references search through a list. | |
| 248 """ | |
| 249 o = object() | |
| 250 L = [None, o] | |
| 251 | |
| 252 self.assertIn("[1]", reflect.objgrep(L, o, reflect.isSame)) | |
| 253 | |
| 254 def test_tuple(self): | |
| 255 """ | |
| 256 Test references search through a tuple. | |
| 257 """ | |
| 258 o = object() | |
| 259 T = (o, None) | |
| 260 | |
| 261 self.assertIn("[0]", reflect.objgrep(T, o, reflect.isSame)) | |
| 262 | |
| 263 def test_instance(self): | |
| 264 """ | |
| 265 Test references search through an object attribute. | |
| 266 """ | |
| 267 class Dummy: | |
| 268 pass | |
| 269 o = object() | |
| 270 d = Dummy() | |
| 271 d.o = o | |
| 272 | |
| 273 self.assertIn(".o", reflect.objgrep(d, o, reflect.isSame)) | |
| 274 | |
| 275 def test_weakref(self): | |
| 276 """ | |
| 277 Test references search through a weakref object. | |
| 278 """ | |
| 279 class Dummy: | |
| 280 pass | |
| 281 o = Dummy() | |
| 282 w1 = weakref.ref(o) | |
| 283 | |
| 284 self.assertIn("()", reflect.objgrep(w1, o, reflect.isSame)) | |
| 285 | |
| 286 def test_boundMethod(self): | |
| 287 """ | |
| 288 Test references search through method special attributes. | |
| 289 """ | |
| 290 class Dummy: | |
| 291 def dummy(self): | |
| 292 pass | |
| 293 o = Dummy() | |
| 294 m = o.dummy | |
| 295 | |
| 296 self.assertIn(".im_self", reflect.objgrep(m, m.im_self, reflect.isSame)) | |
| 297 self.assertIn(".im_class", reflect.objgrep(m, m.im_class, reflect.isSame
)) | |
| 298 self.assertIn(".im_func", reflect.objgrep(m, m.im_func, reflect.isSame)) | |
| 299 | |
| 300 def test_everything(self): | |
| 301 """ | |
| 302 Test references search using complex set of objects. | |
| 303 """ | |
| 304 class Dummy: | |
| 305 def method(self): | |
| 306 pass | |
| 307 | |
| 308 o = Dummy() | |
| 309 D1 = {(): "baz", None: "Quux", o: "Foosh"} | |
| 310 L = [None, (), D1, 3] | |
| 311 T = (L, {}, Dummy()) | |
| 312 D2 = {0: "foo", 1: "bar", 2: T} | |
| 313 i = Dummy() | |
| 314 i.attr = D2 | |
| 315 m = i.method | |
| 316 w = weakref.ref(m) | |
| 317 | |
| 318 self.assertIn("().im_self.attr[2][0][2]{'Foosh'}", reflect.objgrep(w, o,
reflect.isSame)) | |
| 319 | |
| 320 def test_depthLimit(self): | |
| 321 """ | |
| 322 Test the depth of references search. | |
| 323 """ | |
| 324 a = [] | |
| 325 b = [a] | |
| 326 c = [a, b] | |
| 327 d = [a, c] | |
| 328 | |
| 329 self.assertEquals(['[0]'], reflect.objgrep(d, a, reflect.isSame, maxDept
h=1)) | |
| 330 self.assertEquals(['[0]', '[1][0]'], reflect.objgrep(d, a, reflect.isSam
e, maxDepth=2)) | |
| 331 self.assertEquals(['[0]', '[1][0]', '[1][1][0]'], reflect.objgrep(d, a,
reflect.isSame, maxDepth=3)) | |
| 332 | |
| 333 def test_deque(self): | |
| 334 """ | |
| 335 Test references search through a deque object. Only for Python > 2.3. | |
| 336 """ | |
| 337 o = object() | |
| 338 D = deque() | |
| 339 D.append(None) | |
| 340 D.append(o) | |
| 341 | |
| 342 self.assertIn("[1]", reflect.objgrep(D, o, reflect.isSame)) | |
| 343 | |
| 344 if deque is None: | |
| 345 test_deque.skip = "Deque not available" | |
| 346 | |
| 347 | |
| 348 class GetClass(unittest.TestCase): | |
| 349 def testOld(self): | |
| 350 class OldClass: | |
| 351 pass | |
| 352 old = OldClass() | |
| 353 self.assertIn(reflect.getClass(OldClass).__name__, ('class', 'classobj')
) | |
| 354 self.assertEquals(reflect.getClass(old).__name__, 'OldClass') | |
| 355 | |
| 356 def testNew(self): | |
| 357 class NewClass(object): | |
| 358 pass | |
| 359 new = NewClass() | |
| 360 self.assertEquals(reflect.getClass(NewClass).__name__, 'type') | |
| 361 self.assertEquals(reflect.getClass(new).__name__, 'NewClass') | |
| 362 | |
| 363 class Breakable(object): | |
| 364 | |
| 365 breakRepr = False | |
| 366 breakStr = False | |
| 367 | |
| 368 def __str__(self): | |
| 369 if self.breakStr: | |
| 370 raise self | |
| 371 else: | |
| 372 return '<Breakable>' | |
| 373 | |
| 374 def __repr__(self): | |
| 375 if self.breakRepr: | |
| 376 raise self | |
| 377 else: | |
| 378 return 'Breakable()' | |
| 379 | |
| 380 class BrokenType(Breakable, type): | |
| 381 breakName = False | |
| 382 def get___name__(self): | |
| 383 if self.breakName: | |
| 384 raise RuntimeError("no name") | |
| 385 return 'BrokenType' | |
| 386 __name__ = property(get___name__) | |
| 387 | |
| 388 class BTBase(Breakable): | |
| 389 __metaclass__ = BrokenType | |
| 390 breakRepr = True | |
| 391 breakStr = True | |
| 392 | |
| 393 | |
| 394 class NoClassAttr(object): | |
| 395 __class__ = property(lambda x: x.not_class) | |
| 396 | |
| 397 class SafeRepr(unittest.TestCase): | |
| 398 | |
| 399 def testWorkingRepr(self): | |
| 400 x = [1,2,3] | |
| 401 self.assertEquals(reflect.safe_repr(x), repr(x)) | |
| 402 | |
| 403 def testBrokenRepr(self): | |
| 404 b = Breakable() | |
| 405 b.breakRepr = True | |
| 406 reflect.safe_repr(b) | |
| 407 | |
| 408 def testBrokenStr(self): | |
| 409 b = Breakable() | |
| 410 b.breakStr = True | |
| 411 reflect.safe_repr(b) | |
| 412 | |
| 413 def testBrokenClassRepr(self): | |
| 414 class X(BTBase): | |
| 415 breakRepr = True | |
| 416 reflect.safe_repr(X) | |
| 417 reflect.safe_repr(X()) | |
| 418 | |
| 419 def testBrokenClassStr(self): | |
| 420 class X(BTBase): | |
| 421 breakStr = True | |
| 422 reflect.safe_repr(X) | |
| 423 reflect.safe_repr(X()) | |
| 424 | |
| 425 def testBroken__Class__Attr(self): | |
| 426 reflect.safe_repr(NoClassAttr()) | |
| 427 | |
| 428 def testBroken__Class__Name__Attr(self): | |
| 429 class X(BTBase): | |
| 430 breakName = True | |
| 431 reflect.safe_repr(X()) | |
| 432 | |
| 433 | |
| 434 class SafeStr(unittest.TestCase): | |
| 435 def testWorkingStr(self): | |
| 436 x = [1,2,3] | |
| 437 self.assertEquals(reflect.safe_str(x), str(x)) | |
| 438 | |
| 439 def testBrokenStr(self): | |
| 440 b = Breakable() | |
| 441 b.breakStr = True | |
| 442 reflect.safe_str(b) | |
| 443 | |
| 444 def testBrokenRepr(self): | |
| 445 b = Breakable() | |
| 446 b.breakRepr = True | |
| 447 reflect.safe_str(b) | |
| 448 | |
| 449 def testBrokenClassStr(self): | |
| 450 class X(BTBase): | |
| 451 breakStr = True | |
| 452 reflect.safe_str(X) | |
| 453 reflect.safe_str(X()) | |
| 454 | |
| 455 def testBrokenClassRepr(self): | |
| 456 class X(BTBase): | |
| 457 breakRepr = True | |
| 458 reflect.safe_str(X) | |
| 459 reflect.safe_str(X()) | |
| 460 | |
| 461 def testBroken__Class__Attr(self): | |
| 462 reflect.safe_str(NoClassAttr()) | |
| 463 | |
| 464 def testBroken__Class__Name__Attr(self): | |
| 465 class X(BTBase): | |
| 466 breakName = True | |
| 467 reflect.safe_str(X()) | |
| 468 | |
| 469 | |
| 470 class FilenameToModule(unittest.TestCase): | |
| 471 """ | |
| 472 Test L{reflect.filenameToModuleName} detection. | |
| 473 """ | |
| 474 def test_directory(self): | |
| 475 """ | |
| 476 Tests it finds good name for directories/packages. | |
| 477 """ | |
| 478 module = reflect.filenameToModuleName(os.path.join('twisted', 'test')) | |
| 479 self.assertEquals(module, 'test') | |
| 480 module = reflect.filenameToModuleName(os.path.join('twisted', 'test') | |
| 481 + os.path.sep) | |
| 482 self.assertEquals(module, 'test') | |
| 483 | |
| 484 def test_file(self): | |
| 485 """ | |
| 486 Test it finds good name for files. | |
| 487 """ | |
| 488 module = reflect.filenameToModuleName( | |
| 489 os.path.join('twisted', 'test', 'test_reflect.py')) | |
| 490 self.assertEquals(module, 'test_reflect') | |
| 491 | |
| OLD | NEW |