1""" 2 Test cases for the repr module 3 Nick Mathewson 4""" 5 6import sys 7import os 8import shutil 9import unittest 10 11from test.test_support import run_unittest, check_py3k_warnings 12from repr import repr as r # Don't shadow builtin repr 13from repr import Repr 14 15 16def nestedTuple(nesting): 17 t = () 18 for i in range(nesting): 19 t = (t,) 20 return t 21 22class 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 217def touch(path, text=''): 218 fp = open(path, 'w') 219 fp.write(text) 220 fp.close() 221 222class 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'), '''\ 264class 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'), '''\ 279class 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'), '''\ 289class 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'), '''\ 300class 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 318class ClassWithRepr: 319 def __init__(self, s): 320 self.s = s 321 def __repr__(self): 322 return "ClassWithLongRepr(%r)" % self.s 323 324 325class ClassWithFailingRepr: 326 def __repr__(self): 327 raise Exception("This should be caught by Repr.repr_instance") 328 329 330def test_main(): 331 run_unittest(ReprTests) 332 run_unittest(LongReprTest) 333 334 335if __name__ == "__main__": 336 test_main() 337