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 import textwrap
13
14 from test.support import verbose
15 from test.support.os_helper import create_empty_file
16 from reprlib import repr as r # Don't shadow builtin repr
17 from reprlib import Repr
18 from reprlib import recursive_repr
19
20
21 def nestedTuple(nesting):
22 t = ()
23 for i in range(nesting):
24 t = (t,)
25 return t
26
27 class ESC[4;38;5;81mReprTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
28
29 def test_init_kwargs(self):
30 example_kwargs = {
31 "maxlevel": 101,
32 "maxtuple": 102,
33 "maxlist": 103,
34 "maxarray": 104,
35 "maxdict": 105,
36 "maxset": 106,
37 "maxfrozenset": 107,
38 "maxdeque": 108,
39 "maxstring": 109,
40 "maxlong": 110,
41 "maxother": 111,
42 "fillvalue": "x" * 112,
43 "indent": "x" * 113,
44 }
45 r1 = Repr()
46 for attr, val in example_kwargs.items():
47 setattr(r1, attr, val)
48 r2 = Repr(**example_kwargs)
49 for attr in example_kwargs:
50 self.assertEqual(getattr(r1, attr), getattr(r2, attr), msg=attr)
51
52 def test_string(self):
53 eq = self.assertEqual
54 eq(r("abc"), "'abc'")
55 eq(r("abcdefghijklmnop"),"'abcdefghijklmnop'")
56
57 s = "a"*30+"b"*30
58 expected = repr(s)[:13] + "..." + repr(s)[-14:]
59 eq(r(s), expected)
60
61 eq(r("\"'"), repr("\"'"))
62 s = "\""*30+"'"*100
63 expected = repr(s)[:13] + "..." + repr(s)[-14:]
64 eq(r(s), expected)
65
66 def test_tuple(self):
67 eq = self.assertEqual
68 eq(r((1,)), "(1,)")
69
70 t3 = (1, 2, 3)
71 eq(r(t3), "(1, 2, 3)")
72
73 r2 = Repr()
74 r2.maxtuple = 2
75 expected = repr(t3)[:-2] + "...)"
76 eq(r2.repr(t3), expected)
77
78 # modified fillvalue:
79 r3 = Repr()
80 r3.fillvalue = '+++'
81 r3.maxtuple = 2
82 expected = repr(t3)[:-2] + "+++)"
83 eq(r3.repr(t3), expected)
84
85 def test_container(self):
86 from array import array
87 from collections import deque
88
89 eq = self.assertEqual
90 # Tuples give up after 6 elements
91 eq(r(()), "()")
92 eq(r((1,)), "(1,)")
93 eq(r((1, 2, 3)), "(1, 2, 3)")
94 eq(r((1, 2, 3, 4, 5, 6)), "(1, 2, 3, 4, 5, 6)")
95 eq(r((1, 2, 3, 4, 5, 6, 7)), "(1, 2, 3, 4, 5, 6, ...)")
96
97 # Lists give up after 6 as well
98 eq(r([]), "[]")
99 eq(r([1]), "[1]")
100 eq(r([1, 2, 3]), "[1, 2, 3]")
101 eq(r([1, 2, 3, 4, 5, 6]), "[1, 2, 3, 4, 5, 6]")
102 eq(r([1, 2, 3, 4, 5, 6, 7]), "[1, 2, 3, 4, 5, 6, ...]")
103
104 # Sets give up after 6 as well
105 eq(r(set([])), "set()")
106 eq(r(set([1])), "{1}")
107 eq(r(set([1, 2, 3])), "{1, 2, 3}")
108 eq(r(set([1, 2, 3, 4, 5, 6])), "{1, 2, 3, 4, 5, 6}")
109 eq(r(set([1, 2, 3, 4, 5, 6, 7])), "{1, 2, 3, 4, 5, 6, ...}")
110
111 # Frozensets give up after 6 as well
112 eq(r(frozenset([])), "frozenset()")
113 eq(r(frozenset([1])), "frozenset({1})")
114 eq(r(frozenset([1, 2, 3])), "frozenset({1, 2, 3})")
115 eq(r(frozenset([1, 2, 3, 4, 5, 6])), "frozenset({1, 2, 3, 4, 5, 6})")
116 eq(r(frozenset([1, 2, 3, 4, 5, 6, 7])), "frozenset({1, 2, 3, 4, 5, 6, ...})")
117
118 # collections.deque after 6
119 eq(r(deque([1, 2, 3, 4, 5, 6, 7])), "deque([1, 2, 3, 4, 5, 6, ...])")
120
121 # Dictionaries give up after 4.
122 eq(r({}), "{}")
123 d = {'alice': 1, 'bob': 2, 'charles': 3, 'dave': 4}
124 eq(r(d), "{'alice': 1, 'bob': 2, 'charles': 3, 'dave': 4}")
125 d['arthur'] = 1
126 eq(r(d), "{'alice': 1, 'arthur': 1, 'bob': 2, 'charles': 3, ...}")
127
128 # array.array after 5.
129 eq(r(array('i')), "array('i')")
130 eq(r(array('i', [1])), "array('i', [1])")
131 eq(r(array('i', [1, 2])), "array('i', [1, 2])")
132 eq(r(array('i', [1, 2, 3])), "array('i', [1, 2, 3])")
133 eq(r(array('i', [1, 2, 3, 4])), "array('i', [1, 2, 3, 4])")
134 eq(r(array('i', [1, 2, 3, 4, 5])), "array('i', [1, 2, 3, 4, 5])")
135 eq(r(array('i', [1, 2, 3, 4, 5, 6])),
136 "array('i', [1, 2, 3, 4, 5, ...])")
137
138 def test_set_literal(self):
139 eq = self.assertEqual
140 eq(r({1}), "{1}")
141 eq(r({1, 2, 3}), "{1, 2, 3}")
142 eq(r({1, 2, 3, 4, 5, 6}), "{1, 2, 3, 4, 5, 6}")
143 eq(r({1, 2, 3, 4, 5, 6, 7}), "{1, 2, 3, 4, 5, 6, ...}")
144
145 def test_frozenset(self):
146 eq = self.assertEqual
147 eq(r(frozenset({1})), "frozenset({1})")
148 eq(r(frozenset({1, 2, 3})), "frozenset({1, 2, 3})")
149 eq(r(frozenset({1, 2, 3, 4, 5, 6})), "frozenset({1, 2, 3, 4, 5, 6})")
150 eq(r(frozenset({1, 2, 3, 4, 5, 6, 7})), "frozenset({1, 2, 3, 4, 5, 6, ...})")
151
152 def test_numbers(self):
153 eq = self.assertEqual
154 eq(r(123), repr(123))
155 eq(r(123), repr(123))
156 eq(r(1.0/3), repr(1.0/3))
157
158 n = 10**100
159 expected = repr(n)[:18] + "..." + repr(n)[-19:]
160 eq(r(n), expected)
161
162 def test_instance(self):
163 eq = self.assertEqual
164 i1 = ClassWithRepr("a")
165 eq(r(i1), repr(i1))
166
167 i2 = ClassWithRepr("x"*1000)
168 expected = repr(i2)[:13] + "..." + repr(i2)[-14:]
169 eq(r(i2), expected)
170
171 i3 = ClassWithFailingRepr()
172 eq(r(i3), ("<ClassWithFailingRepr instance at %#x>"%id(i3)))
173
174 s = r(ClassWithFailingRepr)
175 self.assertTrue(s.startswith("<class "))
176 self.assertTrue(s.endswith(">"))
177 self.assertIn(s.find("..."), [12, 13])
178
179 def test_lambda(self):
180 r = repr(lambda x: x)
181 self.assertTrue(r.startswith("<function ReprTests.test_lambda.<locals>.<lambda"), r)
182 # XXX anonymous functions? see func_repr
183
184 def test_builtin_function(self):
185 eq = self.assertEqual
186 # Functions
187 eq(repr(hash), '<built-in function hash>')
188 # Methods
189 self.assertTrue(repr(''.split).startswith(
190 '<built-in method split of str object at 0x'))
191
192 def test_range(self):
193 eq = self.assertEqual
194 eq(repr(range(1)), 'range(0, 1)')
195 eq(repr(range(1, 2)), 'range(1, 2)')
196 eq(repr(range(1, 4, 3)), 'range(1, 4, 3)')
197
198 def test_nesting(self):
199 eq = self.assertEqual
200 # everything is meant to give up after 6 levels.
201 eq(r([[[[[[[]]]]]]]), "[[[[[[[]]]]]]]")
202 eq(r([[[[[[[[]]]]]]]]), "[[[[[[[...]]]]]]]")
203
204 eq(r(nestedTuple(6)), "(((((((),),),),),),)")
205 eq(r(nestedTuple(7)), "(((((((...),),),),),),)")
206
207 eq(r({ nestedTuple(5) : nestedTuple(5) }),
208 "{((((((),),),),),): ((((((),),),),),)}")
209 eq(r({ nestedTuple(6) : nestedTuple(6) }),
210 "{((((((...),),),),),): ((((((...),),),),),)}")
211
212 eq(r([[[[[[{}]]]]]]), "[[[[[[{}]]]]]]")
213 eq(r([[[[[[[{}]]]]]]]), "[[[[[[[...]]]]]]]")
214
215 def test_cell(self):
216 def get_cell():
217 x = 42
218 def inner():
219 return x
220 return inner
221 x = get_cell().__closure__[0]
222 self.assertRegex(repr(x), r'<cell at 0x[0-9A-Fa-f]+: '
223 r'int object at 0x[0-9A-Fa-f]+>')
224 self.assertRegex(r(x), r'<cell at 0x.*\.\.\..*>')
225
226 def test_descriptors(self):
227 eq = self.assertEqual
228 # method descriptors
229 eq(repr(dict.items), "<method 'items' of 'dict' objects>")
230 # XXX member descriptors
231 # XXX attribute descriptors
232 # XXX slot descriptors
233 # static and class methods
234 class ESC[4;38;5;81mC:
235 def foo(cls): pass
236 x = staticmethod(C.foo)
237 self.assertEqual(repr(x), f'<staticmethod({C.foo!r})>')
238 x = classmethod(C.foo)
239 self.assertEqual(repr(x), f'<classmethod({C.foo!r})>')
240
241 def test_unsortable(self):
242 # Repr.repr() used to call sorted() on sets, frozensets and dicts
243 # without taking into account that not all objects are comparable
244 x = set([1j, 2j, 3j])
245 y = frozenset(x)
246 z = {1j: 1, 2j: 2}
247 r(x)
248 r(y)
249 r(z)
250
251 def test_valid_indent(self):
252 test_cases = [
253 {
254 'object': (),
255 'tests': (
256 (dict(indent=None), '()'),
257 (dict(indent=False), '()'),
258 (dict(indent=True), '()'),
259 (dict(indent=0), '()'),
260 (dict(indent=1), '()'),
261 (dict(indent=4), '()'),
262 (dict(indent=4, maxlevel=2), '()'),
263 (dict(indent=''), '()'),
264 (dict(indent='-->'), '()'),
265 (dict(indent='....'), '()'),
266 ),
267 },
268 {
269 'object': '',
270 'tests': (
271 (dict(indent=None), "''"),
272 (dict(indent=False), "''"),
273 (dict(indent=True), "''"),
274 (dict(indent=0), "''"),
275 (dict(indent=1), "''"),
276 (dict(indent=4), "''"),
277 (dict(indent=4, maxlevel=2), "''"),
278 (dict(indent=''), "''"),
279 (dict(indent='-->'), "''"),
280 (dict(indent='....'), "''"),
281 ),
282 },
283 {
284 'object': [1, 'spam', {'eggs': True, 'ham': []}],
285 'tests': (
286 (dict(indent=None), '''\
287 [1, 'spam', {'eggs': True, 'ham': []}]'''),
288 (dict(indent=False), '''\
289 [
290 1,
291 'spam',
292 {
293 'eggs': True,
294 'ham': [],
295 },
296 ]'''),
297 (dict(indent=True), '''\
298 [
299 1,
300 'spam',
301 {
302 'eggs': True,
303 'ham': [],
304 },
305 ]'''),
306 (dict(indent=0), '''\
307 [
308 1,
309 'spam',
310 {
311 'eggs': True,
312 'ham': [],
313 },
314 ]'''),
315 (dict(indent=1), '''\
316 [
317 1,
318 'spam',
319 {
320 'eggs': True,
321 'ham': [],
322 },
323 ]'''),
324 (dict(indent=4), '''\
325 [
326 1,
327 'spam',
328 {
329 'eggs': True,
330 'ham': [],
331 },
332 ]'''),
333 (dict(indent=4, maxlevel=2), '''\
334 [
335 1,
336 'spam',
337 {
338 'eggs': True,
339 'ham': [],
340 },
341 ]'''),
342 (dict(indent=''), '''\
343 [
344 1,
345 'spam',
346 {
347 'eggs': True,
348 'ham': [],
349 },
350 ]'''),
351 (dict(indent='-->'), '''\
352 [
353 -->1,
354 -->'spam',
355 -->{
356 -->-->'eggs': True,
357 -->-->'ham': [],
358 -->},
359 ]'''),
360 (dict(indent='....'), '''\
361 [
362 ....1,
363 ....'spam',
364 ....{
365 ........'eggs': True,
366 ........'ham': [],
367 ....},
368 ]'''),
369 ),
370 },
371 {
372 'object': {
373 1: 'two',
374 b'three': [
375 (4.5, 6.7),
376 [set((8, 9)), frozenset((10, 11))],
377 ],
378 },
379 'tests': (
380 (dict(indent=None), '''\
381 {1: 'two', b'three': [(4.5, 6.7), [{8, 9}, frozenset({10, 11})]]}'''),
382 (dict(indent=False), '''\
383 {
384 1: 'two',
385 b'three': [
386 (
387 4.5,
388 6.7,
389 ),
390 [
391 {
392 8,
393 9,
394 },
395 frozenset({
396 10,
397 11,
398 }),
399 ],
400 ],
401 }'''),
402 (dict(indent=True), '''\
403 {
404 1: 'two',
405 b'three': [
406 (
407 4.5,
408 6.7,
409 ),
410 [
411 {
412 8,
413 9,
414 },
415 frozenset({
416 10,
417 11,
418 }),
419 ],
420 ],
421 }'''),
422 (dict(indent=0), '''\
423 {
424 1: 'two',
425 b'three': [
426 (
427 4.5,
428 6.7,
429 ),
430 [
431 {
432 8,
433 9,
434 },
435 frozenset({
436 10,
437 11,
438 }),
439 ],
440 ],
441 }'''),
442 (dict(indent=1), '''\
443 {
444 1: 'two',
445 b'three': [
446 (
447 4.5,
448 6.7,
449 ),
450 [
451 {
452 8,
453 9,
454 },
455 frozenset({
456 10,
457 11,
458 }),
459 ],
460 ],
461 }'''),
462 (dict(indent=4), '''\
463 {
464 1: 'two',
465 b'three': [
466 (
467 4.5,
468 6.7,
469 ),
470 [
471 {
472 8,
473 9,
474 },
475 frozenset({
476 10,
477 11,
478 }),
479 ],
480 ],
481 }'''),
482 (dict(indent=4, maxlevel=2), '''\
483 {
484 1: 'two',
485 b'three': [
486 (...),
487 [...],
488 ],
489 }'''),
490 (dict(indent=''), '''\
491 {
492 1: 'two',
493 b'three': [
494 (
495 4.5,
496 6.7,
497 ),
498 [
499 {
500 8,
501 9,
502 },
503 frozenset({
504 10,
505 11,
506 }),
507 ],
508 ],
509 }'''),
510 (dict(indent='-->'), '''\
511 {
512 -->1: 'two',
513 -->b'three': [
514 -->-->(
515 -->-->-->4.5,
516 -->-->-->6.7,
517 -->-->),
518 -->-->[
519 -->-->-->{
520 -->-->-->-->8,
521 -->-->-->-->9,
522 -->-->-->},
523 -->-->-->frozenset({
524 -->-->-->-->10,
525 -->-->-->-->11,
526 -->-->-->}),
527 -->-->],
528 -->],
529 }'''),
530 (dict(indent='....'), '''\
531 {
532 ....1: 'two',
533 ....b'three': [
534 ........(
535 ............4.5,
536 ............6.7,
537 ........),
538 ........[
539 ............{
540 ................8,
541 ................9,
542 ............},
543 ............frozenset({
544 ................10,
545 ................11,
546 ............}),
547 ........],
548 ....],
549 }'''),
550 ),
551 },
552 ]
553 for test_case in test_cases:
554 with self.subTest(test_object=test_case['object']):
555 for repr_settings, expected_repr in test_case['tests']:
556 with self.subTest(repr_settings=repr_settings):
557 r = Repr()
558 for attribute, value in repr_settings.items():
559 setattr(r, attribute, value)
560 resulting_repr = r.repr(test_case['object'])
561 expected_repr = textwrap.dedent(expected_repr)
562 self.assertEqual(resulting_repr, expected_repr)
563
564 def test_invalid_indent(self):
565 test_object = [1, 'spam', {'eggs': True, 'ham': []}]
566 test_cases = [
567 (-1, (ValueError, '[Nn]egative|[Pp]ositive')),
568 (-4, (ValueError, '[Nn]egative|[Pp]ositive')),
569 ((), (TypeError, None)),
570 ([], (TypeError, None)),
571 ((4,), (TypeError, None)),
572 ([4,], (TypeError, None)),
573 (object(), (TypeError, None)),
574 ]
575 for indent, (expected_error, expected_msg) in test_cases:
576 with self.subTest(indent=indent):
577 r = Repr()
578 r.indent = indent
579 expected_msg = expected_msg or f'{type(indent)}'
580 with self.assertRaisesRegex(expected_error, expected_msg):
581 r.repr(test_object)
582
583 def write_file(path, text):
584 with open(path, 'w', encoding='ASCII') as fp:
585 fp.write(text)
586
587 class ESC[4;38;5;81mLongReprTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
588 longname = 'areallylongpackageandmodulenametotestreprtruncation'
589
590 def setUp(self):
591 self.pkgname = os.path.join(self.longname)
592 self.subpkgname = os.path.join(self.longname, self.longname)
593 # Make the package and subpackage
594 shutil.rmtree(self.pkgname, ignore_errors=True)
595 os.mkdir(self.pkgname)
596 create_empty_file(os.path.join(self.pkgname, '__init__.py'))
597 shutil.rmtree(self.subpkgname, ignore_errors=True)
598 os.mkdir(self.subpkgname)
599 create_empty_file(os.path.join(self.subpkgname, '__init__.py'))
600 # Remember where we are
601 self.here = os.getcwd()
602 sys.path.insert(0, self.here)
603 # When regrtest is run with its -j option, this command alone is not
604 # enough.
605 importlib.invalidate_caches()
606
607 def tearDown(self):
608 actions = []
609 for dirpath, dirnames, filenames in os.walk(self.pkgname):
610 for name in dirnames + filenames:
611 actions.append(os.path.join(dirpath, name))
612 actions.append(self.pkgname)
613 actions.sort()
614 actions.reverse()
615 for p in actions:
616 if os.path.isdir(p):
617 os.rmdir(p)
618 else:
619 os.remove(p)
620 del sys.path[0]
621
622 def _check_path_limitations(self, module_name):
623 # base directory
624 source_path_len = len(self.here)
625 # a path separator + `longname` (twice)
626 source_path_len += 2 * (len(self.longname) + 1)
627 # a path separator + `module_name` + ".py"
628 source_path_len += len(module_name) + 1 + len(".py")
629 cached_path_len = (source_path_len +
630 len(importlib.util.cache_from_source("x.py")) - len("x.py"))
631 if os.name == 'nt' and cached_path_len >= 258:
632 # Under Windows, the max path len is 260 including C's terminating
633 # NUL character.
634 # (see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#maxpath)
635 self.skipTest("test paths too long (%d characters) for Windows' 260 character limit"
636 % cached_path_len)
637 elif os.name == 'nt' and verbose:
638 print("cached_path_len =", cached_path_len)
639
640 def test_module(self):
641 self.maxDiff = None
642 self._check_path_limitations(self.pkgname)
643 create_empty_file(os.path.join(self.subpkgname, self.pkgname + '.py'))
644 importlib.invalidate_caches()
645 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import areallylongpackageandmodulenametotestreprtruncation
646 module = areallylongpackageandmodulenametotestreprtruncation
647 self.assertEqual(repr(module), "<module %r from %r>" % (module.__name__, module.__file__))
648 self.assertEqual(repr(sys), "<module 'sys' (built-in)>")
649
650 def test_type(self):
651 self._check_path_limitations('foo')
652 eq = self.assertEqual
653 write_file(os.path.join(self.subpkgname, 'foo.py'), '''\
654 class foo(object):
655 pass
656 ''')
657 importlib.invalidate_caches()
658 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import foo
659 eq(repr(foo.foo),
660 "<class '%s.foo'>" % foo.__name__)
661
662 @unittest.skip('need a suitable object')
663 def test_object(self):
664 # XXX Test the repr of a type with a really long tp_name but with no
665 # tp_repr. WIBNI we had ::Inline? :)
666 pass
667
668 def test_class(self):
669 self._check_path_limitations('bar')
670 write_file(os.path.join(self.subpkgname, 'bar.py'), '''\
671 class bar:
672 pass
673 ''')
674 importlib.invalidate_caches()
675 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import bar
676 # Module name may be prefixed with "test.", depending on how run.
677 self.assertEqual(repr(bar.bar), "<class '%s.bar'>" % bar.__name__)
678
679 def test_instance(self):
680 self._check_path_limitations('baz')
681 write_file(os.path.join(self.subpkgname, 'baz.py'), '''\
682 class baz:
683 pass
684 ''')
685 importlib.invalidate_caches()
686 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import baz
687 ibaz = baz.baz()
688 self.assertTrue(repr(ibaz).startswith(
689 "<%s.baz object at 0x" % baz.__name__))
690
691 def test_method(self):
692 self._check_path_limitations('qux')
693 eq = self.assertEqual
694 write_file(os.path.join(self.subpkgname, 'qux.py'), '''\
695 class aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
696 def amethod(self): pass
697 ''')
698 importlib.invalidate_caches()
699 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux
700 # Unbound methods first
701 r = repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod)
702 self.assertTrue(r.startswith('<function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod'), r)
703 # Bound method next
704 iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
705 r = repr(iqux.amethod)
706 self.assertTrue(r.startswith(
707 '<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa object at 0x' \
708 % (qux.__name__,) ), r)
709
710 @unittest.skip('needs a built-in function with a really long name')
711 def test_builtin_function(self):
712 # XXX test built-in functions and methods with really long names
713 pass
714
715 class ESC[4;38;5;81mClassWithRepr:
716 def __init__(self, s):
717 self.s = s
718 def __repr__(self):
719 return "ClassWithRepr(%r)" % self.s
720
721
722 class ESC[4;38;5;81mClassWithFailingRepr:
723 def __repr__(self):
724 raise Exception("This should be caught by Repr.repr_instance")
725
726 class ESC[4;38;5;81mMyContainer:
727 'Helper class for TestRecursiveRepr'
728 def __init__(self, values):
729 self.values = list(values)
730 def append(self, value):
731 self.values.append(value)
732 @recursive_repr()
733 def __repr__(self):
734 return '<' + ', '.join(map(str, self.values)) + '>'
735
736 class ESC[4;38;5;81mMyContainer2(ESC[4;38;5;149mMyContainer):
737 @recursive_repr('+++')
738 def __repr__(self):
739 return '<' + ', '.join(map(str, self.values)) + '>'
740
741 class ESC[4;38;5;81mMyContainer3:
742 def __repr__(self):
743 'Test document content'
744 pass
745 wrapped = __repr__
746 wrapper = recursive_repr()(wrapped)
747
748 class ESC[4;38;5;81mTestRecursiveRepr(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
749 def test_recursive_repr(self):
750 m = MyContainer(list('abcde'))
751 m.append(m)
752 m.append('x')
753 m.append(m)
754 self.assertEqual(repr(m), '<a, b, c, d, e, ..., x, ...>')
755 m = MyContainer2(list('abcde'))
756 m.append(m)
757 m.append('x')
758 m.append(m)
759 self.assertEqual(repr(m), '<a, b, c, d, e, +++, x, +++>')
760
761 def test_assigned_attributes(self):
762 from functools import WRAPPER_ASSIGNMENTS as assigned
763 wrapped = MyContainer3.wrapped
764 wrapper = MyContainer3.wrapper
765 for name in assigned:
766 self.assertIs(getattr(wrapper, name), getattr(wrapped, name))
767
768 if __name__ == "__main__":
769 unittest.main()