python (3.11.7)

(root)/
lib/
python3.11/
test/
test_reprlib.py
       1  """
       2    Test cases for the repr module
       3    Nick Mathewson
       4  """
       5  
       6  import sys
       7  import os
       8  import shutil
       9  import importlib
      10  import importlib.util
      11  import unittest
      12  
      13  from test.support import verbose
      14  from test.support.os_helper import create_empty_file
      15  from reprlib import repr as r # Don't shadow builtin repr
      16  from reprlib import Repr
      17  from reprlib import recursive_repr
      18  
      19  
      20  def nestedTuple(nesting):
      21      t = ()
      22      for i in range(nesting):
      23          t = (t,)
      24      return t
      25  
      26  class ESC[4;38;5;81mReprTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      27  
      28      def test_string(self):
      29          eq = self.assertEqual
      30          eq(r("abc"), "'abc'")
      31          eq(r("abcdefghijklmnop"),"'abcdefghijklmnop'")
      32  
      33          s = "a"*30+"b"*30
      34          expected = repr(s)[:13] + "..." + repr(s)[-14:]
      35          eq(r(s), expected)
      36  
      37          eq(r("\"'"), repr("\"'"))
      38          s = "\""*30+"'"*100
      39          expected = repr(s)[:13] + "..." + repr(s)[-14:]
      40          eq(r(s), expected)
      41  
      42      def test_tuple(self):
      43          eq = self.assertEqual
      44          eq(r((1,)), "(1,)")
      45  
      46          t3 = (1, 2, 3)
      47          eq(r(t3), "(1, 2, 3)")
      48  
      49          r2 = Repr()
      50          r2.maxtuple = 2
      51          expected = repr(t3)[:-2] + "...)"
      52          eq(r2.repr(t3), expected)
      53  
      54          # modified fillvalue:
      55          r3 = Repr()
      56          r3.fillvalue = '+++'
      57          r3.maxtuple = 2
      58          expected = repr(t3)[:-2] + "+++)"
      59          eq(r3.repr(t3), expected)
      60  
      61      def test_container(self):
      62          from array import array
      63          from collections import deque
      64  
      65          eq = self.assertEqual
      66          # Tuples give up after 6 elements
      67          eq(r(()), "()")
      68          eq(r((1,)), "(1,)")
      69          eq(r((1, 2, 3)), "(1, 2, 3)")
      70          eq(r((1, 2, 3, 4, 5, 6)), "(1, 2, 3, 4, 5, 6)")
      71          eq(r((1, 2, 3, 4, 5, 6, 7)), "(1, 2, 3, 4, 5, 6, ...)")
      72  
      73          # Lists give up after 6 as well
      74          eq(r([]), "[]")
      75          eq(r([1]), "[1]")
      76          eq(r([1, 2, 3]), "[1, 2, 3]")
      77          eq(r([1, 2, 3, 4, 5, 6]), "[1, 2, 3, 4, 5, 6]")
      78          eq(r([1, 2, 3, 4, 5, 6, 7]), "[1, 2, 3, 4, 5, 6, ...]")
      79  
      80          # Sets give up after 6 as well
      81          eq(r(set([])), "set()")
      82          eq(r(set([1])), "{1}")
      83          eq(r(set([1, 2, 3])), "{1, 2, 3}")
      84          eq(r(set([1, 2, 3, 4, 5, 6])), "{1, 2, 3, 4, 5, 6}")
      85          eq(r(set([1, 2, 3, 4, 5, 6, 7])), "{1, 2, 3, 4, 5, 6, ...}")
      86  
      87          # Frozensets give up after 6 as well
      88          eq(r(frozenset([])), "frozenset()")
      89          eq(r(frozenset([1])), "frozenset({1})")
      90          eq(r(frozenset([1, 2, 3])), "frozenset({1, 2, 3})")
      91          eq(r(frozenset([1, 2, 3, 4, 5, 6])), "frozenset({1, 2, 3, 4, 5, 6})")
      92          eq(r(frozenset([1, 2, 3, 4, 5, 6, 7])), "frozenset({1, 2, 3, 4, 5, 6, ...})")
      93  
      94          # collections.deque after 6
      95          eq(r(deque([1, 2, 3, 4, 5, 6, 7])), "deque([1, 2, 3, 4, 5, 6, ...])")
      96  
      97          # Dictionaries give up after 4.
      98          eq(r({}), "{}")
      99          d = {'alice': 1, 'bob': 2, 'charles': 3, 'dave': 4}
     100          eq(r(d), "{'alice': 1, 'bob': 2, 'charles': 3, 'dave': 4}")
     101          d['arthur'] = 1
     102          eq(r(d), "{'alice': 1, 'arthur': 1, 'bob': 2, 'charles': 3, ...}")
     103  
     104          # array.array after 5.
     105          eq(r(array('i')), "array('i')")
     106          eq(r(array('i', [1])), "array('i', [1])")
     107          eq(r(array('i', [1, 2])), "array('i', [1, 2])")
     108          eq(r(array('i', [1, 2, 3])), "array('i', [1, 2, 3])")
     109          eq(r(array('i', [1, 2, 3, 4])), "array('i', [1, 2, 3, 4])")
     110          eq(r(array('i', [1, 2, 3, 4, 5])), "array('i', [1, 2, 3, 4, 5])")
     111          eq(r(array('i', [1, 2, 3, 4, 5, 6])),
     112                     "array('i', [1, 2, 3, 4, 5, ...])")
     113  
     114      def test_set_literal(self):
     115          eq = self.assertEqual
     116          eq(r({1}), "{1}")
     117          eq(r({1, 2, 3}), "{1, 2, 3}")
     118          eq(r({1, 2, 3, 4, 5, 6}), "{1, 2, 3, 4, 5, 6}")
     119          eq(r({1, 2, 3, 4, 5, 6, 7}), "{1, 2, 3, 4, 5, 6, ...}")
     120  
     121      def test_frozenset(self):
     122          eq = self.assertEqual
     123          eq(r(frozenset({1})), "frozenset({1})")
     124          eq(r(frozenset({1, 2, 3})), "frozenset({1, 2, 3})")
     125          eq(r(frozenset({1, 2, 3, 4, 5, 6})), "frozenset({1, 2, 3, 4, 5, 6})")
     126          eq(r(frozenset({1, 2, 3, 4, 5, 6, 7})), "frozenset({1, 2, 3, 4, 5, 6, ...})")
     127  
     128      def test_numbers(self):
     129          eq = self.assertEqual
     130          eq(r(123), repr(123))
     131          eq(r(123), repr(123))
     132          eq(r(1.0/3), repr(1.0/3))
     133  
     134          n = 10**100
     135          expected = repr(n)[:18] + "..." + repr(n)[-19:]
     136          eq(r(n), expected)
     137  
     138      def test_instance(self):
     139          eq = self.assertEqual
     140          i1 = ClassWithRepr("a")
     141          eq(r(i1), repr(i1))
     142  
     143          i2 = ClassWithRepr("x"*1000)
     144          expected = repr(i2)[:13] + "..." + repr(i2)[-14:]
     145          eq(r(i2), expected)
     146  
     147          i3 = ClassWithFailingRepr()
     148          eq(r(i3), ("<ClassWithFailingRepr instance at %#x>"%id(i3)))
     149  
     150          s = r(ClassWithFailingRepr)
     151          self.assertTrue(s.startswith("<class "))
     152          self.assertTrue(s.endswith(">"))
     153          self.assertIn(s.find("..."), [12, 13])
     154  
     155      def test_lambda(self):
     156          r = repr(lambda x: x)
     157          self.assertTrue(r.startswith("<function ReprTests.test_lambda.<locals>.<lambda"), r)
     158          # XXX anonymous functions?  see func_repr
     159  
     160      def test_builtin_function(self):
     161          eq = self.assertEqual
     162          # Functions
     163          eq(repr(hash), '<built-in function hash>')
     164          # Methods
     165          self.assertTrue(repr(''.split).startswith(
     166              '<built-in method split of str object at 0x'))
     167  
     168      def test_range(self):
     169          eq = self.assertEqual
     170          eq(repr(range(1)), 'range(0, 1)')
     171          eq(repr(range(1, 2)), 'range(1, 2)')
     172          eq(repr(range(1, 4, 3)), 'range(1, 4, 3)')
     173  
     174      def test_nesting(self):
     175          eq = self.assertEqual
     176          # everything is meant to give up after 6 levels.
     177          eq(r([[[[[[[]]]]]]]), "[[[[[[[]]]]]]]")
     178          eq(r([[[[[[[[]]]]]]]]), "[[[[[[[...]]]]]]]")
     179  
     180          eq(r(nestedTuple(6)), "(((((((),),),),),),)")
     181          eq(r(nestedTuple(7)), "(((((((...),),),),),),)")
     182  
     183          eq(r({ nestedTuple(5) : nestedTuple(5) }),
     184             "{((((((),),),),),): ((((((),),),),),)}")
     185          eq(r({ nestedTuple(6) : nestedTuple(6) }),
     186             "{((((((...),),),),),): ((((((...),),),),),)}")
     187  
     188          eq(r([[[[[[{}]]]]]]), "[[[[[[{}]]]]]]")
     189          eq(r([[[[[[[{}]]]]]]]), "[[[[[[[...]]]]]]]")
     190  
     191      def test_cell(self):
     192          def get_cell():
     193              x = 42
     194              def inner():
     195                  return x
     196              return inner
     197          x = get_cell().__closure__[0]
     198          self.assertRegex(repr(x), r'<cell at 0x[0-9A-Fa-f]+: '
     199                                    r'int object at 0x[0-9A-Fa-f]+>')
     200          self.assertRegex(r(x), r'<cell at 0x.*\.\.\..*>')
     201  
     202      def test_descriptors(self):
     203          eq = self.assertEqual
     204          # method descriptors
     205          eq(repr(dict.items), "<method 'items' of 'dict' objects>")
     206          # XXX member descriptors
     207          # XXX attribute descriptors
     208          # XXX slot descriptors
     209          # static and class methods
     210          class ESC[4;38;5;81mC:
     211              def foo(cls): pass
     212          x = staticmethod(C.foo)
     213          self.assertEqual(repr(x), f'<staticmethod({C.foo!r})>')
     214          x = classmethod(C.foo)
     215          self.assertEqual(repr(x), f'<classmethod({C.foo!r})>')
     216  
     217      def test_unsortable(self):
     218          # Repr.repr() used to call sorted() on sets, frozensets and dicts
     219          # without taking into account that not all objects are comparable
     220          x = set([1j, 2j, 3j])
     221          y = frozenset(x)
     222          z = {1j: 1, 2j: 2}
     223          r(x)
     224          r(y)
     225          r(z)
     226  
     227  def write_file(path, text):
     228      with open(path, 'w', encoding='ASCII') as fp:
     229          fp.write(text)
     230  
     231  class ESC[4;38;5;81mLongReprTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     232      longname = 'areallylongpackageandmodulenametotestreprtruncation'
     233  
     234      def setUp(self):
     235          self.pkgname = os.path.join(self.longname)
     236          self.subpkgname = os.path.join(self.longname, self.longname)
     237          # Make the package and subpackage
     238          shutil.rmtree(self.pkgname, ignore_errors=True)
     239          os.mkdir(self.pkgname)
     240          create_empty_file(os.path.join(self.pkgname, '__init__.py'))
     241          shutil.rmtree(self.subpkgname, ignore_errors=True)
     242          os.mkdir(self.subpkgname)
     243          create_empty_file(os.path.join(self.subpkgname, '__init__.py'))
     244          # Remember where we are
     245          self.here = os.getcwd()
     246          sys.path.insert(0, self.here)
     247          # When regrtest is run with its -j option, this command alone is not
     248          # enough.
     249          importlib.invalidate_caches()
     250  
     251      def tearDown(self):
     252          actions = []
     253          for dirpath, dirnames, filenames in os.walk(self.pkgname):
     254              for name in dirnames + filenames:
     255                  actions.append(os.path.join(dirpath, name))
     256          actions.append(self.pkgname)
     257          actions.sort()
     258          actions.reverse()
     259          for p in actions:
     260              if os.path.isdir(p):
     261                  os.rmdir(p)
     262              else:
     263                  os.remove(p)
     264          del sys.path[0]
     265  
     266      def _check_path_limitations(self, module_name):
     267          # base directory
     268          source_path_len = len(self.here)
     269          # a path separator + `longname` (twice)
     270          source_path_len += 2 * (len(self.longname) + 1)
     271          # a path separator + `module_name` + ".py"
     272          source_path_len += len(module_name) + 1 + len(".py")
     273          cached_path_len = (source_path_len +
     274              len(importlib.util.cache_from_source("x.py")) - len("x.py"))
     275          if os.name == 'nt' and cached_path_len >= 258:
     276              # Under Windows, the max path len is 260 including C's terminating
     277              # NUL character.
     278              # (see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#maxpath)
     279              self.skipTest("test paths too long (%d characters) for Windows' 260 character limit"
     280                            % cached_path_len)
     281          elif os.name == 'nt' and verbose:
     282              print("cached_path_len =", cached_path_len)
     283  
     284      def test_module(self):
     285          self.maxDiff = None
     286          self._check_path_limitations(self.pkgname)
     287          create_empty_file(os.path.join(self.subpkgname, self.pkgname + '.py'))
     288          importlib.invalidate_caches()
     289          from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import areallylongpackageandmodulenametotestreprtruncation
     290          module = areallylongpackageandmodulenametotestreprtruncation
     291          self.assertEqual(repr(module), "<module %r from %r>" % (module.__name__, module.__file__))
     292          self.assertEqual(repr(sys), "<module 'sys' (built-in)>")
     293  
     294      def test_type(self):
     295          self._check_path_limitations('foo')
     296          eq = self.assertEqual
     297          write_file(os.path.join(self.subpkgname, 'foo.py'), '''\
     298  class foo(object):
     299      pass
     300  ''')
     301          importlib.invalidate_caches()
     302          from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import foo
     303          eq(repr(foo.foo),
     304                 "<class '%s.foo'>" % foo.__name__)
     305  
     306      @unittest.skip('need a suitable object')
     307      def test_object(self):
     308          # XXX Test the repr of a type with a really long tp_name but with no
     309          # tp_repr.  WIBNI we had ::Inline? :)
     310          pass
     311  
     312      def test_class(self):
     313          self._check_path_limitations('bar')
     314          write_file(os.path.join(self.subpkgname, 'bar.py'), '''\
     315  class bar:
     316      pass
     317  ''')
     318          importlib.invalidate_caches()
     319          from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import bar
     320          # Module name may be prefixed with "test.", depending on how run.
     321          self.assertEqual(repr(bar.bar), "<class '%s.bar'>" % bar.__name__)
     322  
     323      def test_instance(self):
     324          self._check_path_limitations('baz')
     325          write_file(os.path.join(self.subpkgname, 'baz.py'), '''\
     326  class baz:
     327      pass
     328  ''')
     329          importlib.invalidate_caches()
     330          from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import baz
     331          ibaz = baz.baz()
     332          self.assertTrue(repr(ibaz).startswith(
     333              "<%s.baz object at 0x" % baz.__name__))
     334  
     335      def test_method(self):
     336          self._check_path_limitations('qux')
     337          eq = self.assertEqual
     338          write_file(os.path.join(self.subpkgname, 'qux.py'), '''\
     339  class aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
     340      def amethod(self): pass
     341  ''')
     342          importlib.invalidate_caches()
     343          from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux
     344          # Unbound methods first
     345          r = repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod)
     346          self.assertTrue(r.startswith('<function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod'), r)
     347          # Bound method next
     348          iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
     349          r = repr(iqux.amethod)
     350          self.assertTrue(r.startswith(
     351              '<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa object at 0x' \
     352              % (qux.__name__,) ), r)
     353  
     354      @unittest.skip('needs a built-in function with a really long name')
     355      def test_builtin_function(self):
     356          # XXX test built-in functions and methods with really long names
     357          pass
     358  
     359  class ESC[4;38;5;81mClassWithRepr:
     360      def __init__(self, s):
     361          self.s = s
     362      def __repr__(self):
     363          return "ClassWithRepr(%r)" % self.s
     364  
     365  
     366  class ESC[4;38;5;81mClassWithFailingRepr:
     367      def __repr__(self):
     368          raise Exception("This should be caught by Repr.repr_instance")
     369  
     370  class ESC[4;38;5;81mMyContainer:
     371      'Helper class for TestRecursiveRepr'
     372      def __init__(self, values):
     373          self.values = list(values)
     374      def append(self, value):
     375          self.values.append(value)
     376      @recursive_repr()
     377      def __repr__(self):
     378          return '<' + ', '.join(map(str, self.values)) + '>'
     379  
     380  class ESC[4;38;5;81mMyContainer2(ESC[4;38;5;149mMyContainer):
     381      @recursive_repr('+++')
     382      def __repr__(self):
     383          return '<' + ', '.join(map(str, self.values)) + '>'
     384  
     385  class ESC[4;38;5;81mMyContainer3:
     386      def __repr__(self):
     387          'Test document content'
     388          pass
     389      wrapped = __repr__
     390      wrapper = recursive_repr()(wrapped)
     391  
     392  class ESC[4;38;5;81mTestRecursiveRepr(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
     393      def test_recursive_repr(self):
     394          m = MyContainer(list('abcde'))
     395          m.append(m)
     396          m.append('x')
     397          m.append(m)
     398          self.assertEqual(repr(m), '<a, b, c, d, e, ..., x, ...>')
     399          m = MyContainer2(list('abcde'))
     400          m.append(m)
     401          m.append('x')
     402          m.append(m)
     403          self.assertEqual(repr(m), '<a, b, c, d, e, +++, x, +++>')
     404  
     405      def test_assigned_attributes(self):
     406          from functools import WRAPPER_ASSIGNMENTS as assigned
     407          wrapped = MyContainer3.wrapped
     408          wrapper = MyContainer3.wrapper
     409          for name in assigned:
     410              self.assertIs(getattr(wrapper, name), getattr(wrapped, name))
     411  
     412  if __name__ == "__main__":
     413      unittest.main()