Home | History | Annotate | Download | only in test
      1 """
      2   Test cases for the repr module
      3   Nick Mathewson
      4 """
      5 
      6 import sys
      7 import os
      8 import shutil
      9 import unittest
     10 
     11 from test.test_support import run_unittest, check_py3k_warnings
     12 from repr import repr as r # Don't shadow builtin repr
     13 from repr import Repr
     14 
     15 
     16 def nestedTuple(nesting):
     17     t = ()
     18     for i in range(nesting):
     19         t = (t,)
     20     return t
     21 
     22 class ReprTests(unittest.TestCase):
     23 
     24     def test_string(self):
     25         eq = self.assertEqual
     26         eq(r("abc"), "'abc'")
     27         eq(r("abcdefghijklmnop"),"'abcdefghijklmnop'")
     28 
     29         s = "a"*30+"b"*30
     30         expected = repr(s)[:13] + "..." + repr(s)[-14:]
     31         eq(r(s), expected)
     32 
     33         eq(r("\"'"), repr("\"'"))
     34         s = "\""*30+"'"*100
     35         expected = repr(s)[:13] + "..." + repr(s)[-14:]
     36         eq(r(s), expected)
     37 
     38     def test_tuple(self):
     39         eq = self.assertEqual
     40         eq(r((1,)), "(1,)")
     41 
     42         t3 = (1, 2, 3)
     43         eq(r(t3), "(1, 2, 3)")
     44 
     45         r2 = Repr()
     46         r2.maxtuple = 2
     47         expected = repr(t3)[:-2] + "...)"
     48         eq(r2.repr(t3), expected)
     49 
     50     def test_container(self):
     51         from array import array
     52         from collections import deque
     53 
     54         eq = self.assertEqual
     55         # Tuples give up after 6 elements
     56         eq(r(()), "()")
     57         eq(r((1,)), "(1,)")
     58         eq(r((1, 2, 3)), "(1, 2, 3)")
     59         eq(r((1, 2, 3, 4, 5, 6)), "(1, 2, 3, 4, 5, 6)")
     60         eq(r((1, 2, 3, 4, 5, 6, 7)), "(1, 2, 3, 4, 5, 6, ...)")
     61 
     62         # Lists give up after 6 as well
     63         eq(r([]), "[]")
     64         eq(r([1]), "[1]")
     65         eq(r([1, 2, 3]), "[1, 2, 3]")
     66         eq(r([1, 2, 3, 4, 5, 6]), "[1, 2, 3, 4, 5, 6]")
     67         eq(r([1, 2, 3, 4, 5, 6, 7]), "[1, 2, 3, 4, 5, 6, ...]")
     68 
     69         # Sets give up after 6 as well
     70         eq(r(set([])), "set([])")
     71         eq(r(set([1])), "set([1])")
     72         eq(r(set([1, 2, 3])), "set([1, 2, 3])")
     73         eq(r(set([1, 2, 3, 4, 5, 6])), "set([1, 2, 3, 4, 5, 6])")
     74         eq(r(set([1, 2, 3, 4, 5, 6, 7])), "set([1, 2, 3, 4, 5, 6, ...])")
     75 
     76         # Frozensets give up after 6 as well
     77         eq(r(frozenset([])), "frozenset([])")
     78         eq(r(frozenset([1])), "frozenset([1])")
     79         eq(r(frozenset([1, 2, 3])), "frozenset([1, 2, 3])")
     80         eq(r(frozenset([1, 2, 3, 4, 5, 6])), "frozenset([1, 2, 3, 4, 5, 6])")
     81         eq(r(frozenset([1, 2, 3, 4, 5, 6, 7])), "frozenset([1, 2, 3, 4, 5, 6, ...])")
     82 
     83         # collections.deque after 6
     84         eq(r(deque([1, 2, 3, 4, 5, 6, 7])), "deque([1, 2, 3, 4, 5, 6, ...])")
     85 
     86         # Dictionaries give up after 4.
     87         eq(r({}), "{}")
     88         d = {'alice': 1, 'bob': 2, 'charles': 3, 'dave': 4}
     89         eq(r(d), "{'alice': 1, 'bob': 2, 'charles': 3, 'dave': 4}")
     90         d['arthur'] = 1
     91         eq(r(d), "{'alice': 1, 'arthur': 1, 'bob': 2, 'charles': 3, ...}")
     92 
     93         # array.array after 5.
     94         eq(r(array('i')), "array('i', [])")
     95         eq(r(array('i', [1])), "array('i', [1])")
     96         eq(r(array('i', [1, 2])), "array('i', [1, 2])")
     97         eq(r(array('i', [1, 2, 3])), "array('i', [1, 2, 3])")
     98         eq(r(array('i', [1, 2, 3, 4])), "array('i', [1, 2, 3, 4])")
     99         eq(r(array('i', [1, 2, 3, 4, 5])), "array('i', [1, 2, 3, 4, 5])")
    100         eq(r(array('i', [1, 2, 3, 4, 5, 6])),
    101                    "array('i', [1, 2, 3, 4, 5, ...])")
    102 
    103     def test_numbers(self):
    104         eq = self.assertEqual
    105         eq(r(123), repr(123))
    106         eq(r(123L), repr(123L))
    107         eq(r(1.0/3), repr(1.0/3))
    108 
    109         n = 10L**100
    110         expected = repr(n)[:18] + "..." + repr(n)[-19:]
    111         eq(r(n), expected)
    112 
    113     def test_instance(self):
    114         eq = self.assertEqual
    115         i1 = ClassWithRepr("a")
    116         eq(r(i1), repr(i1))
    117 
    118         i2 = ClassWithRepr("x"*1000)
    119         expected = repr(i2)[:13] + "..." + repr(i2)[-14:]
    120         eq(r(i2), expected)
    121 
    122         i3 = ClassWithFailingRepr()
    123         eq(r(i3), ("<ClassWithFailingRepr instance at %x>"%id(i3)))
    124 
    125         s = r(ClassWithFailingRepr)
    126         self.assertTrue(s.startswith("<class "))
    127         self.assertTrue(s.endswith(">"))
    128         self.assertTrue(s.find("...") == 8)
    129 
    130     def test_file(self):
    131         fp = open(unittest.__file__)
    132         self.assertTrue(repr(fp).startswith(
    133             "<open file %r, mode 'r' at 0x" % unittest.__file__))
    134         fp.close()
    135         self.assertTrue(repr(fp).startswith(
    136             "<closed file %r, mode 'r' at 0x" % unittest.__file__))
    137 
    138     def test_lambda(self):
    139         self.assertTrue(repr(lambda x: x).startswith(
    140             "<function <lambda"))
    141         # XXX anonymous functions?  see func_repr
    142 
    143     def test_builtin_function(self):
    144         eq = self.assertEqual
    145         # Functions
    146         eq(repr(hash), '<built-in function hash>')
    147         # Methods
    148         self.assertTrue(repr(''.split).startswith(
    149             '<built-in method split of str object at 0x'))
    150 
    151     def test_xrange(self):
    152         eq = self.assertEqual
    153         eq(repr(xrange(1)), 'xrange(1)')
    154         eq(repr(xrange(1, 2)), 'xrange(1, 2)')
    155         eq(repr(xrange(1, 2, 3)), 'xrange(1, 4, 3)')
    156 
    157     def test_nesting(self):
    158         eq = self.assertEqual
    159         # everything is meant to give up after 6 levels.
    160         eq(r([[[[[[[]]]]]]]), "[[[[[[[]]]]]]]")
    161         eq(r([[[[[[[[]]]]]]]]), "[[[[[[[...]]]]]]]")
    162 
    163         eq(r(nestedTuple(6)), "(((((((),),),),),),)")
    164         eq(r(nestedTuple(7)), "(((((((...),),),),),),)")
    165 
    166         eq(r({ nestedTuple(5) : nestedTuple(5) }),
    167            "{((((((),),),),),): ((((((),),),),),)}")
    168         eq(r({ nestedTuple(6) : nestedTuple(6) }),
    169            "{((((((...),),),),),): ((((((...),),),),),)}")
    170 
    171         eq(r([[[[[[{}]]]]]]), "[[[[[[{}]]]]]]")
    172         eq(r([[[[[[[{}]]]]]]]), "[[[[[[[...]]]]]]]")
    173 
    174     def test_buffer(self):
    175         # XXX doesn't test buffers with no b_base or read-write buffers (see
    176         # bufferobject.c).  The test is fairly incomplete too.  Sigh.
    177         with check_py3k_warnings():
    178             x = buffer('foo')
    179         self.assertTrue(repr(x).startswith('<read-only buffer for 0x'))
    180 
    181     def test_cell(self):
    182         def get_cell():
    183             x = 42
    184             def inner():
    185                 return x
    186             return inner
    187         x = get_cell().__closure__[0]
    188         self.assertRegexpMatches(repr(x), r'<cell at 0x[0-9A-Fa-f]+: '
    189                                           r'int object at 0x[0-9A-Fa-f]+>')
    190         self.assertRegexpMatches(r(x), r'<cell at.*\.\.\..*>')
    191 
    192     def test_descriptors(self):
    193         eq = self.assertEqual
    194         # method descriptors
    195         eq(repr(dict.items), "<method 'items' of 'dict' objects>")
    196         # XXX member descriptors
    197         # XXX attribute descriptors
    198         # XXX slot descriptors
    199         # static and class methods
    200         class C:
    201             def foo(cls): pass
    202         x = staticmethod(C.foo)
    203         self.assertTrue(repr(x).startswith('<staticmethod object at 0x'))
    204         x = classmethod(C.foo)
    205         self.assertTrue(repr(x).startswith('<classmethod object at 0x'))
    206 
    207     def test_unsortable(self):
    208         # Repr.repr() used to call sorted() on sets, frozensets and dicts
    209         # without taking into account that not all objects are comparable
    210         x = set([1j, 2j, 3j])
    211         y = frozenset(x)
    212         z = {1j: 1, 2j: 2}
    213         r(x)
    214         r(y)
    215         r(z)
    216 
    217 def touch(path, text=''):
    218     fp = open(path, 'w')
    219     fp.write(text)
    220     fp.close()
    221 
    222 class LongReprTest(unittest.TestCase):
    223     def setUp(self):
    224         longname = 'areallylongpackageandmodulenametotestreprtruncation'
    225         self.pkgname = os.path.join(longname)
    226         self.subpkgname = os.path.join(longname, longname)
    227         # Make the package and subpackage
    228         shutil.rmtree(self.pkgname, ignore_errors=True)
    229         os.mkdir(self.pkgname)
    230         touch(os.path.join(self.pkgname, '__init__'+os.extsep+'py'))
    231         shutil.rmtree(self.subpkgname, ignore_errors=True)
    232         os.mkdir(self.subpkgname)
    233         touch(os.path.join(self.subpkgname, '__init__'+os.extsep+'py'))
    234         # Remember where we are
    235         self.here = os.getcwd()
    236         sys.path.insert(0, self.here)
    237 
    238     def tearDown(self):
    239         actions = []
    240         for dirpath, dirnames, filenames in os.walk(self.pkgname):
    241             for name in dirnames + filenames:
    242                 actions.append(os.path.join(dirpath, name))
    243         actions.append(self.pkgname)
    244         actions.sort()
    245         actions.reverse()
    246         for p in actions:
    247             if os.path.isdir(p):
    248                 os.rmdir(p)
    249             else:
    250                 os.remove(p)
    251         del sys.path[0]
    252 
    253     def test_module(self):
    254         eq = self.assertEqual
    255         touch(os.path.join(self.subpkgname, self.pkgname + os.extsep + 'py'))
    256         from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import areallylongpackageandmodulenametotestreprtruncation
    257         eq(repr(areallylongpackageandmodulenametotestreprtruncation),
    258            "<module '%s' from '%s'>" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__))
    259         eq(repr(sys), "<module 'sys' (built-in)>")
    260 
    261     def test_type(self):
    262         eq = self.assertEqual
    263         touch(os.path.join(self.subpkgname, 'foo'+os.extsep+'py'), '''\
    264 class foo(object):
    265     pass
    266 ''')
    267         from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import foo
    268         eq(repr(foo.foo),
    269                "<class '%s.foo'>" % foo.__name__)
    270 
    271     @unittest.skip('need a suitable object')
    272     def test_object(self):
    273         # XXX Test the repr of a type with a really long tp_name but with no
    274         # tp_repr.  WIBNI we had ::Inline? :)
    275         pass
    276 
    277     def test_class(self):
    278         touch(os.path.join(self.subpkgname, 'bar'+os.extsep+'py'), '''\
    279 class bar:
    280     pass
    281 ''')
    282         from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import bar
    283         # Module name may be prefixed with "test.", depending on how run.
    284         self.assertTrue(repr(bar.bar).startswith(
    285             "<class %s.bar at 0x" % bar.__name__))
    286 
    287     def test_instance(self):
    288         touch(os.path.join(self.subpkgname, 'baz'+os.extsep+'py'), '''\
    289 class baz:
    290     pass
    291 ''')
    292         from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import baz
    293         ibaz = baz.baz()
    294         self.assertTrue(repr(ibaz).startswith(
    295             "<%s.baz instance at 0x" % baz.__name__))
    296 
    297     def test_method(self):
    298         eq = self.assertEqual
    299         touch(os.path.join(self.subpkgname, 'qux'+os.extsep+'py'), '''\
    300 class aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
    301     def amethod(self): pass
    302 ''')
    303         from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux
    304         # Unbound methods first
    305         eq(repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod),
    306         '<unbound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod>')
    307         # Bound method next
    308         iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
    309         self.assertTrue(repr(iqux.amethod).startswith(
    310             '<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa instance at 0x' \
    311             % (qux.__name__,) ))
    312 
    313     @unittest.skip('needs a built-in function with a really long name')
    314     def test_builtin_function(self):
    315         # XXX test built-in functions and methods with really long names
    316         pass
    317 
    318 class ClassWithRepr:
    319     def __init__(self, s):
    320         self.s = s
    321     def __repr__(self):
    322         return "ClassWithLongRepr(%r)" % self.s
    323 
    324 
    325 class ClassWithFailingRepr:
    326     def __repr__(self):
    327         raise Exception("This should be caught by Repr.repr_instance")
    328 
    329 
    330 def test_main():
    331     run_unittest(ReprTests)
    332     run_unittest(LongReprTest)
    333 
    334 
    335 if __name__ == "__main__":
    336     test_main()
    337