2
Test cases for the repr module
13
from test.support import run_unittest, create_empty_file, verbose
14
from reprlib import repr as r # Don't shadow builtin repr
15
from reprlib import Repr
16
from reprlib import recursive_repr
19
def nestedTuple(nesting):
21
for i in range(nesting):
25
class ReprTests(unittest.TestCase):
27
def test_string(self):
30
eq(r("abcdefghijklmnop"),"'abcdefghijklmnop'")
33
expected = repr(s)[:13] + "..." + repr(s)[-14:]
36
eq(r("\"'"), repr("\"'"))
38
expected = repr(s)[:13] + "..." + repr(s)[-14:]
46
eq(r(t3), "(1, 2, 3)")
50
expected = repr(t3)[:-2] + "...)"
51
eq(r2.repr(t3), expected)
53
def test_container(self):
54
from array import array
55
from collections import deque
58
# Tuples give up after 6 elements
61
eq(r((1, 2, 3)), "(1, 2, 3)")
62
eq(r((1, 2, 3, 4, 5, 6)), "(1, 2, 3, 4, 5, 6)")
63
eq(r((1, 2, 3, 4, 5, 6, 7)), "(1, 2, 3, 4, 5, 6, ...)")
65
# Lists give up after 6 as well
68
eq(r([1, 2, 3]), "[1, 2, 3]")
69
eq(r([1, 2, 3, 4, 5, 6]), "[1, 2, 3, 4, 5, 6]")
70
eq(r([1, 2, 3, 4, 5, 6, 7]), "[1, 2, 3, 4, 5, 6, ...]")
72
# Sets give up after 6 as well
73
eq(r(set([])), "set([])")
74
eq(r(set([1])), "set([1])")
75
eq(r(set([1, 2, 3])), "set([1, 2, 3])")
76
eq(r(set([1, 2, 3, 4, 5, 6])), "set([1, 2, 3, 4, 5, 6])")
77
eq(r(set([1, 2, 3, 4, 5, 6, 7])), "set([1, 2, 3, 4, 5, 6, ...])")
79
# Frozensets give up after 6 as well
80
eq(r(frozenset([])), "frozenset([])")
81
eq(r(frozenset([1])), "frozenset([1])")
82
eq(r(frozenset([1, 2, 3])), "frozenset([1, 2, 3])")
83
eq(r(frozenset([1, 2, 3, 4, 5, 6])), "frozenset([1, 2, 3, 4, 5, 6])")
84
eq(r(frozenset([1, 2, 3, 4, 5, 6, 7])), "frozenset([1, 2, 3, 4, 5, 6, ...])")
86
# collections.deque after 6
87
eq(r(deque([1, 2, 3, 4, 5, 6, 7])), "deque([1, 2, 3, 4, 5, 6, ...])")
89
# Dictionaries give up after 4.
91
d = {'alice': 1, 'bob': 2, 'charles': 3, 'dave': 4}
92
eq(r(d), "{'alice': 1, 'bob': 2, 'charles': 3, 'dave': 4}")
94
eq(r(d), "{'alice': 1, 'arthur': 1, 'bob': 2, 'charles': 3, ...}")
96
# array.array after 5.
97
eq(r(array('i')), "array('i', [])")
98
eq(r(array('i', [1])), "array('i', [1])")
99
eq(r(array('i', [1, 2])), "array('i', [1, 2])")
100
eq(r(array('i', [1, 2, 3])), "array('i', [1, 2, 3])")
101
eq(r(array('i', [1, 2, 3, 4])), "array('i', [1, 2, 3, 4])")
102
eq(r(array('i', [1, 2, 3, 4, 5])), "array('i', [1, 2, 3, 4, 5])")
103
eq(r(array('i', [1, 2, 3, 4, 5, 6])),
104
"array('i', [1, 2, 3, 4, 5, ...])")
106
def test_numbers(self):
107
eq = self.assertEqual
108
eq(r(123), repr(123))
109
eq(r(123), repr(123))
110
eq(r(1.0/3), repr(1.0/3))
113
expected = repr(n)[:18] + "..." + repr(n)[-19:]
116
def test_instance(self):
117
eq = self.assertEqual
118
i1 = ClassWithRepr("a")
121
i2 = ClassWithRepr("x"*1000)
122
expected = repr(i2)[:13] + "..." + repr(i2)[-14:]
125
i3 = ClassWithFailingRepr()
126
eq(r(i3), ("<ClassWithFailingRepr instance at %x>"%id(i3)))
128
s = r(ClassWithFailingRepr)
129
self.assertTrue(s.startswith("<class "))
130
self.assertTrue(s.endswith(">"))
131
self.assertIn(s.find("..."), [12, 13])
133
def test_lambda(self):
134
r = repr(lambda x: x)
135
self.assertTrue(r.startswith("<function ReprTests.test_lambda.<locals>.<lambda"), r)
136
# XXX anonymous functions? see func_repr
138
def test_builtin_function(self):
139
eq = self.assertEqual
141
eq(repr(hash), '<built-in function hash>')
143
self.assertTrue(repr(''.split).startswith(
144
'<built-in method split of str object at 0x'))
146
def test_range(self):
147
eq = self.assertEqual
148
eq(repr(range(1)), 'range(0, 1)')
149
eq(repr(range(1, 2)), 'range(1, 2)')
150
eq(repr(range(1, 4, 3)), 'range(1, 4, 3)')
152
def test_nesting(self):
153
eq = self.assertEqual
154
# everything is meant to give up after 6 levels.
155
eq(r([[[[[[[]]]]]]]), "[[[[[[[]]]]]]]")
156
eq(r([[[[[[[[]]]]]]]]), "[[[[[[[...]]]]]]]")
158
eq(r(nestedTuple(6)), "(((((((),),),),),),)")
159
eq(r(nestedTuple(7)), "(((((((...),),),),),),)")
161
eq(r({ nestedTuple(5) : nestedTuple(5) }),
162
"{((((((),),),),),): ((((((),),),),),)}")
163
eq(r({ nestedTuple(6) : nestedTuple(6) }),
164
"{((((((...),),),),),): ((((((...),),),),),)}")
166
eq(r([[[[[[{}]]]]]]), "[[[[[[{}]]]]]]")
167
eq(r([[[[[[[{}]]]]]]]), "[[[[[[[...]]]]]]]")
170
# XXX Hmm? How to get at a cell object?
173
def test_descriptors(self):
174
eq = self.assertEqual
176
eq(repr(dict.items), "<method 'items' of 'dict' objects>")
177
# XXX member descriptors
178
# XXX attribute descriptors
179
# XXX slot descriptors
180
# static and class methods
183
x = staticmethod(C.foo)
184
self.assertTrue(repr(x).startswith('<staticmethod object at 0x'))
185
x = classmethod(C.foo)
186
self.assertTrue(repr(x).startswith('<classmethod object at 0x'))
188
def test_unsortable(self):
189
# Repr.repr() used to call sorted() on sets, frozensets and dicts
190
# without taking into account that not all objects are comparable
191
x = set([1j, 2j, 3j])
198
def write_file(path, text):
199
with open(path, 'w', encoding='ASCII') as fp:
202
class LongReprTest(unittest.TestCase):
203
longname = 'areallylongpackageandmodulenametotestreprtruncation'
206
self.pkgname = os.path.join(self.longname)
207
self.subpkgname = os.path.join(self.longname, self.longname)
208
# Make the package and subpackage
209
shutil.rmtree(self.pkgname, ignore_errors=True)
210
os.mkdir(self.pkgname)
211
create_empty_file(os.path.join(self.pkgname, '__init__.py'))
212
shutil.rmtree(self.subpkgname, ignore_errors=True)
213
os.mkdir(self.subpkgname)
214
create_empty_file(os.path.join(self.subpkgname, '__init__.py'))
215
# Remember where we are
216
self.here = os.getcwd()
217
sys.path.insert(0, self.here)
218
# When regrtest is run with its -j option, this command alone is not
220
importlib.invalidate_caches()
224
for dirpath, dirnames, filenames in os.walk(self.pkgname):
225
for name in dirnames + filenames:
226
actions.append(os.path.join(dirpath, name))
227
actions.append(self.pkgname)
237
def _check_path_limitations(self, module_name):
239
source_path_len = len(self.here)
240
# a path separator + `longname` (twice)
241
source_path_len += 2 * (len(self.longname) + 1)
242
# a path separator + `module_name` + ".py"
243
source_path_len += len(module_name) + 1 + len(".py")
244
cached_path_len = (source_path_len +
245
len(importlib.util.cache_from_source("x.py")) - len("x.py"))
246
if os.name == 'nt' and cached_path_len >= 258:
247
# Under Windows, the max path len is 260 including C's terminating
249
# (see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#maxpath)
250
self.skipTest("test paths too long (%d characters) for Windows' 260 character limit"
252
elif os.name == 'nt' and verbose:
253
print("cached_path_len =", cached_path_len)
255
def test_module(self):
257
self._check_path_limitations(self.pkgname)
258
create_empty_file(os.path.join(self.subpkgname, self.pkgname + '.py'))
259
importlib.invalidate_caches()
260
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import areallylongpackageandmodulenametotestreprtruncation
261
module = areallylongpackageandmodulenametotestreprtruncation
262
self.assertEqual(repr(module), "<module %r from %r>" % (module.__name__, module.__file__))
263
self.assertEqual(repr(sys), "<module 'sys' (built-in)>")
266
self._check_path_limitations('foo')
267
eq = self.assertEqual
268
write_file(os.path.join(self.subpkgname, 'foo.py'), '''\
272
importlib.invalidate_caches()
273
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import foo
275
"<class '%s.foo'>" % foo.__name__)
277
def test_object(self):
278
# XXX Test the repr of a type with a really long tp_name but with no
279
# tp_repr. WIBNI we had ::Inline? :)
282
def test_class(self):
283
self._check_path_limitations('bar')
284
write_file(os.path.join(self.subpkgname, 'bar.py'), '''\
288
importlib.invalidate_caches()
289
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import bar
290
# Module name may be prefixed with "test.", depending on how run.
291
self.assertEqual(repr(bar.bar), "<class '%s.bar'>" % bar.__name__)
293
def test_instance(self):
294
self._check_path_limitations('baz')
295
write_file(os.path.join(self.subpkgname, 'baz.py'), '''\
299
importlib.invalidate_caches()
300
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import baz
302
self.assertTrue(repr(ibaz).startswith(
303
"<%s.baz object at 0x" % baz.__name__))
305
def test_method(self):
306
self._check_path_limitations('qux')
307
eq = self.assertEqual
308
write_file(os.path.join(self.subpkgname, 'qux.py'), '''\
309
class aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
310
def amethod(self): pass
312
importlib.invalidate_caches()
313
from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux
314
# Unbound methods first
315
r = repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod)
316
self.assertTrue(r.startswith('<function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod'), r)
318
iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
319
r = repr(iqux.amethod)
320
self.assertTrue(r.startswith(
321
'<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa object at 0x' \
322
% (qux.__name__,) ), r)
324
def test_builtin_function(self):
325
# XXX test built-in functions and methods with really long names
329
def __init__(self, s):
332
return "ClassWithRepr(%r)" % self.s
335
class ClassWithFailingRepr:
337
raise Exception("This should be caught by Repr.repr_instance")
340
'Helper class for TestRecursiveRepr'
341
def __init__(self, values):
342
self.values = list(values)
343
def append(self, value):
344
self.values.append(value)
347
return '<' + ', '.join(map(str, self.values)) + '>'
349
class MyContainer2(MyContainer):
350
@recursive_repr('+++')
352
return '<' + ', '.join(map(str, self.values)) + '>'
354
class TestRecursiveRepr(unittest.TestCase):
355
def test_recursive_repr(self):
356
m = MyContainer(list('abcde'))
360
self.assertEqual(repr(m), '<a, b, c, d, e, ..., x, ...>')
361
m = MyContainer2(list('abcde'))
365
self.assertEqual(repr(m), '<a, b, c, d, e, +++, x, +++>')
368
run_unittest(ReprTests)
369
run_unittest(LongReprTest)
370
run_unittest(TestRecursiveRepr)
373
if __name__ == "__main__":