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