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