1import textwrap 2import types 3import unittest 4 5 6def global_function(): 7 def inner_function(): 8 class LocalClass: 9 pass 10 global inner_global_function 11 def inner_global_function(): 12 def inner_function2(): 13 pass 14 return inner_function2 15 return LocalClass 16 return lambda: inner_function 17 18 19class FuncAttrsTest(unittest.TestCase): 20 def setUp(self): 21 class F: 22 def a(self): 23 pass 24 def b(): 25 return 3 26 self.fi = F() 27 self.F = F 28 self.b = b 29 30 def cannot_set_attr(self, obj, name, value, exceptions): 31 try: 32 setattr(obj, name, value) 33 except exceptions: 34 pass 35 else: 36 self.fail("shouldn't be able to set %s to %r" % (name, value)) 37 try: 38 delattr(obj, name) 39 except exceptions: 40 pass 41 else: 42 self.fail("shouldn't be able to del %s" % name) 43 44 45class FunctionPropertiesTest(FuncAttrsTest): 46 # Include the external setUp method that is common to all tests 47 def test_module(self): 48 self.assertEqual(self.b.__module__, __name__) 49 50 def test_dir_includes_correct_attrs(self): 51 self.b.known_attr = 7 52 self.assertIn('known_attr', dir(self.b), 53 "set attributes not in dir listing of method") 54 # Test on underlying function object of method 55 self.F.a.known_attr = 7 56 self.assertIn('known_attr', dir(self.fi.a), "set attribute on function " 57 "implementations, should show up in next dir") 58 59 def test_duplicate_function_equality(self): 60 # Body of `duplicate' is the exact same as self.b 61 def duplicate(): 62 'my docstring' 63 return 3 64 self.assertNotEqual(self.b, duplicate) 65 66 def test_copying___code__(self): 67 def test(): pass 68 self.assertEqual(test(), None) 69 test.__code__ = self.b.__code__ 70 self.assertEqual(test(), 3) # self.b always returns 3, arbitrarily 71 72 def test___globals__(self): 73 self.assertIs(self.b.__globals__, globals()) 74 self.cannot_set_attr(self.b, '__globals__', 2, 75 (AttributeError, TypeError)) 76 77 def test___builtins__(self): 78 self.assertIs(self.b.__builtins__, __builtins__) 79 self.cannot_set_attr(self.b, '__builtins__', 2, 80 (AttributeError, TypeError)) 81 82 # bpo-42990: If globals is specified and has no "__builtins__" key, 83 # a function inherits the current builtins namespace. 84 def func(s): return len(s) 85 ns = {} 86 func2 = type(func)(func.__code__, ns) 87 self.assertIs(func2.__globals__, ns) 88 self.assertIs(func2.__builtins__, __builtins__) 89 90 # Make sure that the function actually works. 91 self.assertEqual(func2("abc"), 3) 92 self.assertEqual(ns, {}) 93 94 # Define functions using exec() with different builtins, 95 # and test inheritance when globals has no "__builtins__" key 96 code = textwrap.dedent(""" 97 def func3(s): pass 98 func4 = type(func3)(func3.__code__, {}) 99 """) 100 safe_builtins = {'None': None} 101 ns = {'type': type, '__builtins__': safe_builtins} 102 exec(code, ns) 103 self.assertIs(ns['func3'].__builtins__, safe_builtins) 104 self.assertIs(ns['func4'].__builtins__, safe_builtins) 105 self.assertIs(ns['func3'].__globals__['__builtins__'], safe_builtins) 106 self.assertNotIn('__builtins__', ns['func4'].__globals__) 107 108 def test___closure__(self): 109 a = 12 110 def f(): print(a) 111 c = f.__closure__ 112 self.assertIsInstance(c, tuple) 113 self.assertEqual(len(c), 1) 114 # don't have a type object handy 115 self.assertEqual(c[0].__class__.__name__, "cell") 116 self.cannot_set_attr(f, "__closure__", c, AttributeError) 117 118 def test_cell_new(self): 119 cell_obj = types.CellType(1) 120 self.assertEqual(cell_obj.cell_contents, 1) 121 122 cell_obj = types.CellType() 123 msg = "shouldn't be able to read an empty cell" 124 with self.assertRaises(ValueError, msg=msg): 125 cell_obj.cell_contents 126 127 def test_empty_cell(self): 128 def f(): print(a) 129 try: 130 f.__closure__[0].cell_contents 131 except ValueError: 132 pass 133 else: 134 self.fail("shouldn't be able to read an empty cell") 135 a = 12 136 137 def test_set_cell(self): 138 a = 12 139 def f(): return a 140 c = f.__closure__ 141 c[0].cell_contents = 9 142 self.assertEqual(c[0].cell_contents, 9) 143 self.assertEqual(f(), 9) 144 self.assertEqual(a, 9) 145 del c[0].cell_contents 146 try: 147 c[0].cell_contents 148 except ValueError: 149 pass 150 else: 151 self.fail("shouldn't be able to read an empty cell") 152 with self.assertRaises(NameError): 153 f() 154 with self.assertRaises(UnboundLocalError): 155 print(a) 156 157 def test___name__(self): 158 self.assertEqual(self.b.__name__, 'b') 159 self.b.__name__ = 'c' 160 self.assertEqual(self.b.__name__, 'c') 161 self.b.__name__ = 'd' 162 self.assertEqual(self.b.__name__, 'd') 163 # __name__ and __name__ must be a string 164 self.cannot_set_attr(self.b, '__name__', 7, TypeError) 165 # __name__ must be available when in restricted mode. Exec will raise 166 # AttributeError if __name__ is not available on f. 167 s = """def f(): pass\nf.__name__""" 168 exec(s, {'__builtins__': {}}) 169 # Test on methods, too 170 self.assertEqual(self.fi.a.__name__, 'a') 171 self.cannot_set_attr(self.fi.a, "__name__", 'a', AttributeError) 172 173 def test___qualname__(self): 174 # PEP 3155 175 self.assertEqual(self.b.__qualname__, 'FuncAttrsTest.setUp.<locals>.b') 176 self.assertEqual(FuncAttrsTest.setUp.__qualname__, 'FuncAttrsTest.setUp') 177 self.assertEqual(global_function.__qualname__, 'global_function') 178 self.assertEqual(global_function().__qualname__, 179 'global_function.<locals>.<lambda>') 180 self.assertEqual(global_function()().__qualname__, 181 'global_function.<locals>.inner_function') 182 self.assertEqual(global_function()()().__qualname__, 183 'global_function.<locals>.inner_function.<locals>.LocalClass') 184 self.assertEqual(inner_global_function.__qualname__, 'inner_global_function') 185 self.assertEqual(inner_global_function().__qualname__, 'inner_global_function.<locals>.inner_function2') 186 self.b.__qualname__ = 'c' 187 self.assertEqual(self.b.__qualname__, 'c') 188 self.b.__qualname__ = 'd' 189 self.assertEqual(self.b.__qualname__, 'd') 190 # __qualname__ must be a string 191 self.cannot_set_attr(self.b, '__qualname__', 7, TypeError) 192 193 def test___code__(self): 194 num_one, num_two = 7, 8 195 def a(): pass 196 def b(): return 12 197 def c(): return num_one 198 def d(): return num_two 199 def e(): return num_one, num_two 200 for func in [a, b, c, d, e]: 201 self.assertEqual(type(func.__code__), types.CodeType) 202 self.assertEqual(c(), 7) 203 self.assertEqual(d(), 8) 204 d.__code__ = c.__code__ 205 self.assertEqual(c.__code__, d.__code__) 206 self.assertEqual(c(), 7) 207 # self.assertEqual(d(), 7) 208 try: 209 b.__code__ = c.__code__ 210 except ValueError: 211 pass 212 else: 213 self.fail("__code__ with different numbers of free vars should " 214 "not be possible") 215 try: 216 e.__code__ = d.__code__ 217 except ValueError: 218 pass 219 else: 220 self.fail("__code__ with different numbers of free vars should " 221 "not be possible") 222 223 def test_blank_func_defaults(self): 224 self.assertEqual(self.b.__defaults__, None) 225 del self.b.__defaults__ 226 self.assertEqual(self.b.__defaults__, None) 227 228 def test_func_default_args(self): 229 def first_func(a, b): 230 return a+b 231 def second_func(a=1, b=2): 232 return a+b 233 self.assertEqual(first_func.__defaults__, None) 234 self.assertEqual(second_func.__defaults__, (1, 2)) 235 first_func.__defaults__ = (1, 2) 236 self.assertEqual(first_func.__defaults__, (1, 2)) 237 self.assertEqual(first_func(), 3) 238 self.assertEqual(first_func(3), 5) 239 self.assertEqual(first_func(3, 5), 8) 240 del second_func.__defaults__ 241 self.assertEqual(second_func.__defaults__, None) 242 try: 243 second_func() 244 except TypeError: 245 pass 246 else: 247 self.fail("__defaults__ does not update; deleting it does not " 248 "remove requirement") 249 250 251class InstancemethodAttrTest(FuncAttrsTest): 252 253 def test___class__(self): 254 self.assertEqual(self.fi.a.__self__.__class__, self.F) 255 self.cannot_set_attr(self.fi.a, "__class__", self.F, TypeError) 256 257 def test___func__(self): 258 self.assertEqual(self.fi.a.__func__, self.F.a) 259 self.cannot_set_attr(self.fi.a, "__func__", self.F.a, AttributeError) 260 261 def test___self__(self): 262 self.assertEqual(self.fi.a.__self__, self.fi) 263 self.cannot_set_attr(self.fi.a, "__self__", self.fi, AttributeError) 264 265 def test___func___non_method(self): 266 # Behavior should be the same when a method is added via an attr 267 # assignment 268 self.fi.id = types.MethodType(id, self.fi) 269 self.assertEqual(self.fi.id(), id(self.fi)) 270 # Test usage 271 try: 272 self.fi.id.unknown_attr 273 except AttributeError: 274 pass 275 else: 276 self.fail("using unknown attributes should raise AttributeError") 277 # Test assignment and deletion 278 self.cannot_set_attr(self.fi.id, 'unknown_attr', 2, AttributeError) 279 280 281class ArbitraryFunctionAttrTest(FuncAttrsTest): 282 def test_set_attr(self): 283 self.b.known_attr = 7 284 self.assertEqual(self.b.known_attr, 7) 285 try: 286 self.fi.a.known_attr = 7 287 except AttributeError: 288 pass 289 else: 290 self.fail("setting attributes on methods should raise error") 291 292 def test_delete_unknown_attr(self): 293 try: 294 del self.b.unknown_attr 295 except AttributeError: 296 pass 297 else: 298 self.fail("deleting unknown attribute should raise TypeError") 299 300 def test_unset_attr(self): 301 for func in [self.b, self.fi.a]: 302 try: 303 func.non_existent_attr 304 except AttributeError: 305 pass 306 else: 307 self.fail("using unknown attributes should raise " 308 "AttributeError") 309 310 311class FunctionDictsTest(FuncAttrsTest): 312 def test_setting_dict_to_invalid(self): 313 self.cannot_set_attr(self.b, '__dict__', None, TypeError) 314 from collections import UserDict 315 d = UserDict({'known_attr': 7}) 316 self.cannot_set_attr(self.fi.a.__func__, '__dict__', d, TypeError) 317 318 def test_setting_dict_to_valid(self): 319 d = {'known_attr': 7} 320 self.b.__dict__ = d 321 # Test assignment 322 self.assertIs(d, self.b.__dict__) 323 # ... and on all the different ways of referencing the method's func 324 self.F.a.__dict__ = d 325 self.assertIs(d, self.fi.a.__func__.__dict__) 326 self.assertIs(d, self.fi.a.__dict__) 327 # Test value 328 self.assertEqual(self.b.known_attr, 7) 329 self.assertEqual(self.b.__dict__['known_attr'], 7) 330 # ... and again, on all the different method's names 331 self.assertEqual(self.fi.a.__func__.known_attr, 7) 332 self.assertEqual(self.fi.a.known_attr, 7) 333 334 def test_delete___dict__(self): 335 try: 336 del self.b.__dict__ 337 except TypeError: 338 pass 339 else: 340 self.fail("deleting function dictionary should raise TypeError") 341 342 def test_unassigned_dict(self): 343 self.assertEqual(self.b.__dict__, {}) 344 345 def test_func_as_dict_key(self): 346 value = "Some string" 347 d = {} 348 d[self.b] = value 349 self.assertEqual(d[self.b], value) 350 351 352class FunctionDocstringTest(FuncAttrsTest): 353 def test_set_docstring_attr(self): 354 self.assertEqual(self.b.__doc__, None) 355 docstr = "A test method that does nothing" 356 self.b.__doc__ = docstr 357 self.F.a.__doc__ = docstr 358 self.assertEqual(self.b.__doc__, docstr) 359 self.assertEqual(self.fi.a.__doc__, docstr) 360 self.cannot_set_attr(self.fi.a, "__doc__", docstr, AttributeError) 361 362 def test_delete_docstring(self): 363 self.b.__doc__ = "The docstring" 364 del self.b.__doc__ 365 self.assertEqual(self.b.__doc__, None) 366 367 368def cell(value): 369 """Create a cell containing the given value.""" 370 def f(): 371 print(a) 372 a = value 373 return f.__closure__[0] 374 375def empty_cell(empty=True): 376 """Create an empty cell.""" 377 def f(): 378 print(a) 379 # the intent of the following line is simply "if False:"; it's 380 # spelt this way to avoid the danger that a future optimization 381 # might simply remove an "if False:" code block. 382 if not empty: 383 a = 1729 384 return f.__closure__[0] 385 386 387class CellTest(unittest.TestCase): 388 def test_comparison(self): 389 # These tests are here simply to exercise the comparison code; 390 # their presence should not be interpreted as providing any 391 # guarantees about the semantics (or even existence) of cell 392 # comparisons in future versions of CPython. 393 self.assertTrue(cell(2) < cell(3)) 394 self.assertTrue(empty_cell() < cell('saturday')) 395 self.assertTrue(empty_cell() == empty_cell()) 396 self.assertTrue(cell(-36) == cell(-36.0)) 397 self.assertTrue(cell(True) > empty_cell()) 398 399 400class StaticMethodAttrsTest(unittest.TestCase): 401 def test_func_attribute(self): 402 def f(): 403 pass 404 405 c = classmethod(f) 406 self.assertTrue(c.__func__ is f) 407 408 s = staticmethod(f) 409 self.assertTrue(s.__func__ is f) 410 411 412class BuiltinFunctionPropertiesTest(unittest.TestCase): 413 # XXX Not sure where this should really go since I can't find a 414 # test module specifically for builtin_function_or_method. 415 416 def test_builtin__qualname__(self): 417 import time 418 419 # builtin function: 420 self.assertEqual(len.__qualname__, 'len') 421 self.assertEqual(time.time.__qualname__, 'time') 422 423 # builtin classmethod: 424 self.assertEqual(dict.fromkeys.__qualname__, 'dict.fromkeys') 425 self.assertEqual(float.__getformat__.__qualname__, 426 'float.__getformat__') 427 428 # builtin staticmethod: 429 self.assertEqual(str.maketrans.__qualname__, 'str.maketrans') 430 self.assertEqual(bytes.maketrans.__qualname__, 'bytes.maketrans') 431 432 # builtin bound instance method: 433 self.assertEqual([1, 2, 3].append.__qualname__, 'list.append') 434 self.assertEqual({'foo': 'bar'}.pop.__qualname__, 'dict.pop') 435 436 437if __name__ == "__main__": 438 unittest.main() 439