|
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 |
|
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.assertEquals |
|
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.assertEquals |
|
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.assertEquals |
|
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.assertEquals |
|
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.assertEquals |
|
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.failUnless(s.startswith("<class ")) |
|
127 self.failUnless(s.endswith(">")) |
|
128 self.failUnless(s.find("...") == 8) |
|
129 |
|
130 def test_file(self): |
|
131 fp = open(unittest.__file__) |
|
132 self.failUnless(repr(fp).startswith( |
|
133 "<open file '%s', mode 'r' at 0x" % unittest.__file__)) |
|
134 fp.close() |
|
135 self.failUnless(repr(fp).startswith( |
|
136 "<closed file '%s', mode 'r' at 0x" % unittest.__file__)) |
|
137 |
|
138 def test_lambda(self): |
|
139 self.failUnless(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.assertEquals |
|
145 # Functions |
|
146 eq(repr(hash), '<built-in function hash>') |
|
147 # Methods |
|
148 self.failUnless(repr(''.split).startswith( |
|
149 '<built-in method split of str object at 0x')) |
|
150 |
|
151 def test_xrange(self): |
|
152 eq = self.assertEquals |
|
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.assertEquals |
|
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 x = buffer('foo') |
|
178 self.failUnless(repr(x).startswith('<read-only buffer for 0x')) |
|
179 |
|
180 def test_cell(self): |
|
181 # XXX Hmm? How to get at a cell object? |
|
182 pass |
|
183 |
|
184 def test_descriptors(self): |
|
185 eq = self.assertEquals |
|
186 # method descriptors |
|
187 eq(repr(dict.items), "<method 'items' of 'dict' objects>") |
|
188 # XXX member descriptors |
|
189 # XXX attribute descriptors |
|
190 # XXX slot descriptors |
|
191 # static and class methods |
|
192 class C: |
|
193 def foo(cls): pass |
|
194 x = staticmethod(C.foo) |
|
195 self.failUnless(repr(x).startswith('<staticmethod object at 0x')) |
|
196 x = classmethod(C.foo) |
|
197 self.failUnless(repr(x).startswith('<classmethod object at 0x')) |
|
198 |
|
199 def test_unsortable(self): |
|
200 # Repr.repr() used to call sorted() on sets, frozensets and dicts |
|
201 # without taking into account that not all objects are comparable |
|
202 x = set([1j, 2j, 3j]) |
|
203 y = frozenset(x) |
|
204 z = {1j: 1, 2j: 2} |
|
205 r(x) |
|
206 r(y) |
|
207 r(z) |
|
208 |
|
209 def touch(path, text=''): |
|
210 fp = open(path, 'w') |
|
211 fp.write(text) |
|
212 fp.close() |
|
213 |
|
214 class LongReprTest(unittest.TestCase): |
|
215 def setUp(self): |
|
216 longname = 'areallylongpackageandmodulenametotestreprtruncation' |
|
217 self.pkgname = os.path.join(longname) |
|
218 self.subpkgname = os.path.join(longname, longname) |
|
219 # Make the package and subpackage |
|
220 shutil.rmtree(self.pkgname, ignore_errors=True) |
|
221 os.mkdir(self.pkgname) |
|
222 touch(os.path.join(self.pkgname, '__init__'+os.extsep+'py')) |
|
223 shutil.rmtree(self.subpkgname, ignore_errors=True) |
|
224 os.mkdir(self.subpkgname) |
|
225 touch(os.path.join(self.subpkgname, '__init__'+os.extsep+'py')) |
|
226 # Remember where we are |
|
227 self.here = os.getcwd() |
|
228 sys.path.insert(0, self.here) |
|
229 |
|
230 def tearDown(self): |
|
231 actions = [] |
|
232 for dirpath, dirnames, filenames in os.walk(self.pkgname): |
|
233 for name in dirnames + filenames: |
|
234 actions.append(os.path.join(dirpath, name)) |
|
235 actions.append(self.pkgname) |
|
236 actions.sort() |
|
237 actions.reverse() |
|
238 for p in actions: |
|
239 if os.path.isdir(p): |
|
240 os.rmdir(p) |
|
241 else: |
|
242 os.remove(p) |
|
243 del sys.path[0] |
|
244 |
|
245 def test_module(self): |
|
246 eq = self.assertEquals |
|
247 touch(os.path.join(self.subpkgname, self.pkgname + os.extsep + 'py')) |
|
248 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import areallylongpackageandmodulenametotestreprtruncation |
|
249 eq(repr(areallylongpackageandmodulenametotestreprtruncation), |
|
250 "<module '%s' from '%s'>" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__)) |
|
251 eq(repr(sys), "<module 'sys' (built-in)>") |
|
252 |
|
253 def test_type(self): |
|
254 eq = self.assertEquals |
|
255 touch(os.path.join(self.subpkgname, 'foo'+os.extsep+'py'), '''\ |
|
256 class foo(object): |
|
257 pass |
|
258 ''') |
|
259 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import foo |
|
260 eq(repr(foo.foo), |
|
261 "<class '%s.foo'>" % foo.__name__) |
|
262 |
|
263 def test_object(self): |
|
264 # XXX Test the repr of a type with a really long tp_name but with no |
|
265 # tp_repr. WIBNI we had ::Inline? :) |
|
266 pass |
|
267 |
|
268 def test_class(self): |
|
269 touch(os.path.join(self.subpkgname, 'bar'+os.extsep+'py'), '''\ |
|
270 class bar: |
|
271 pass |
|
272 ''') |
|
273 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import bar |
|
274 # Module name may be prefixed with "test.", depending on how run. |
|
275 self.failUnless(repr(bar.bar).startswith( |
|
276 "<class %s.bar at 0x" % bar.__name__)) |
|
277 |
|
278 def test_instance(self): |
|
279 touch(os.path.join(self.subpkgname, 'baz'+os.extsep+'py'), '''\ |
|
280 class baz: |
|
281 pass |
|
282 ''') |
|
283 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import baz |
|
284 ibaz = baz.baz() |
|
285 self.failUnless(repr(ibaz).startswith( |
|
286 "<%s.baz instance at 0x" % baz.__name__)) |
|
287 |
|
288 def test_method(self): |
|
289 eq = self.assertEquals |
|
290 touch(os.path.join(self.subpkgname, 'qux'+os.extsep+'py'), '''\ |
|
291 class aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: |
|
292 def amethod(self): pass |
|
293 ''') |
|
294 from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import qux |
|
295 # Unbound methods first |
|
296 eq(repr(qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod), |
|
297 '<unbound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod>') |
|
298 # Bound method next |
|
299 iqux = qux.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() |
|
300 self.failUnless(repr(iqux.amethod).startswith( |
|
301 '<bound method aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.amethod of <%s.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa instance at 0x' \ |
|
302 % (qux.__name__,) )) |
|
303 |
|
304 def test_builtin_function(self): |
|
305 # XXX test built-in functions and methods with really long names |
|
306 pass |
|
307 |
|
308 class ClassWithRepr: |
|
309 def __init__(self, s): |
|
310 self.s = s |
|
311 def __repr__(self): |
|
312 return "ClassWithLongRepr(%r)" % self.s |
|
313 |
|
314 |
|
315 class ClassWithFailingRepr: |
|
316 def __repr__(self): |
|
317 raise Exception("This should be caught by Repr.repr_instance") |
|
318 |
|
319 |
|
320 def test_main(): |
|
321 run_unittest(ReprTests) |
|
322 if os.name != 'mac': |
|
323 run_unittest(LongReprTest) |
|
324 |
|
325 |
|
326 if __name__ == "__main__": |
|
327 test_main() |