blob: d6cfb65d3329874d4ac4b71602b61e61a9c4c04f [file] [log] [blame]
Brett Cannonb8d37352008-03-13 20:33:10 +00001doctests = """
2Tests for the tokenize module.
Jeremy Hylton29bef0b2006-08-23 18:37:43 +00003
Brett Cannonb8d37352008-03-13 20:33:10 +00004 >>> import glob, random, sys
Jeremy Hylton29bef0b2006-08-23 18:37:43 +00005
Brett Cannonb8d37352008-03-13 20:33:10 +00006The tests can be really simple. Given a small fragment of source
7code, print out a table with thokens. The ENDMARK is omitted for
Jeremy Hylton29bef0b2006-08-23 18:37:43 +00008brevity.
9
Brett Cannonb8d37352008-03-13 20:33:10 +000010 >>> dump_tokens("1 + 1")
11 NUMBER '1' (1, 0) (1, 1)
12 OP '+' (1, 2) (1, 3)
13 NUMBER '1' (1, 4) (1, 5)
Jeremy Hylton76467ba2006-08-23 21:14:03 +000014
Brett Cannonb8d37352008-03-13 20:33:10 +000015 >>> dump_tokens("if False:\\n"
16 ... " # NL\\n"
17 ... " True = False # NEWLINE\\n")
18 NAME 'if' (1, 0) (1, 2)
19 NAME 'False' (1, 3) (1, 8)
20 OP ':' (1, 8) (1, 9)
21 NEWLINE '\\n' (1, 9) (1, 10)
22 COMMENT '# NL' (2, 4) (2, 8)
23 NL '\\n' (2, 8) (2, 9)
24 INDENT ' ' (3, 0) (3, 4)
25 NAME 'True' (3, 4) (3, 8)
26 OP '=' (3, 9) (3, 10)
27 NAME 'False' (3, 11) (3, 16)
28 COMMENT '# NEWLINE' (3, 17) (3, 26)
29 NEWLINE '\\n' (3, 26) (3, 27)
30 DEDENT '' (4, 0) (4, 0)
Jeremy Hylton76467ba2006-08-23 21:14:03 +000031
Brett Cannonb8d37352008-03-13 20:33:10 +000032 >>> indent_error_file = \"""
33 ... def k(x):
34 ... x += 2
35 ... x += 5
36 ... \"""
Tim Peters147f9ae2006-08-25 22:05:39 +000037
Brett Cannonb8d37352008-03-13 20:33:10 +000038 >>> for tok in generate_tokens(StringIO(indent_error_file).readline): pass
39 Traceback (most recent call last):
40 ...
41 IndentationError: unindent does not match any outer indentation level
Jeremy Hylton29bef0b2006-08-23 18:37:43 +000042
Brett Cannonb8d37352008-03-13 20:33:10 +000043Test roundtrip for `untokenize`. `f` is an open file or a string. The source
44code in f is tokenized, converted back to source code via tokenize.untokenize(),
45and tokenized again from the latter. The test fails if the second tokenization
46doesn't match the first.
Jeremy Hylton29bef0b2006-08-23 18:37:43 +000047
Brett Cannonb8d37352008-03-13 20:33:10 +000048 >>> def roundtrip(f):
49 ... if isinstance(f, str): f = StringIO(f)
50 ... token_list = list(generate_tokens(f.readline))
51 ... f.close()
52 ... tokens1 = [tok[:2] for tok in token_list]
53 ... new_text = untokenize(tokens1)
54 ... readline = iter(new_text.splitlines(1)).next
55 ... tokens2 = [tok[:2] for tok in generate_tokens(readline)]
56 ... return tokens1 == tokens2
57 ...
Jeremy Hylton76467ba2006-08-23 21:14:03 +000058
Brett Cannonb8d37352008-03-13 20:33:10 +000059There are some standard formattig practises that are easy to get right.
Jeremy Hylton29bef0b2006-08-23 18:37:43 +000060
Brett Cannonb8d37352008-03-13 20:33:10 +000061 >>> roundtrip("if x == 1:\\n"
62 ... " print x\\n")
63 True
64
65 >>> roundtrip("# This is a comment\\n# This also")
66 True
Jeremy Hylton76467ba2006-08-23 21:14:03 +000067
68Some people use different formatting conventions, which makes
Brett Cannonb8d37352008-03-13 20:33:10 +000069untokenize a little trickier. Note that this test involves trailing
70whitespace after the colon. Note that we use hex escapes to make the
71two trailing blanks apperant in the expected output.
Jeremy Hylton76467ba2006-08-23 21:14:03 +000072
Brett Cannonb8d37352008-03-13 20:33:10 +000073 >>> roundtrip("if x == 1 : \\n"
74 ... " print x\\n")
75 True
Jeremy Hylton76467ba2006-08-23 21:14:03 +000076
Brett Cannonb8d37352008-03-13 20:33:10 +000077 >>> f = test_support.findfile("tokenize_tests" + os.extsep + "txt")
78 >>> roundtrip(open(f))
79 True
Jeremy Hylton76467ba2006-08-23 21:14:03 +000080
Brett Cannonb8d37352008-03-13 20:33:10 +000081 >>> roundtrip("if x == 1:\\n"
82 ... " # A comment by itself.\\n"
83 ... " print x # Comment here, too.\\n"
84 ... " # Another comment.\\n"
85 ... "after_if = True\\n")
86 True
Jeremy Hylton76467ba2006-08-23 21:14:03 +000087
Brett Cannonb8d37352008-03-13 20:33:10 +000088 >>> roundtrip("if (x # The comments need to go in the right place\\n"
89 ... " == 1):\\n"
90 ... " print 'x==1'\\n")
91 True
Jeremy Hylton76467ba2006-08-23 21:14:03 +000092
Brett Cannonb8d37352008-03-13 20:33:10 +000093 >>> roundtrip("class Test: # A comment here\\n"
94 ... " # A comment with weird indent\\n"
95 ... " after_com = 5\\n"
96 ... " def x(m): return m*5 # a one liner\\n"
97 ... " def y(m): # A whitespace after the colon\\n"
98 ... " return y*4 # 3-space indent\\n")
99 True
100
101Some error-handling code
102
103 >>> roundtrip("try: import somemodule\\n"
104 ... "except ImportError: # comment\\n"
105 ... " print 'Can not import' # comment2\\n"
106 ... "else: print 'Loaded'\\n")
107 True
108
109Balancing contunuation
110
111 >>> roundtrip("a = (3,4, \\n"
112 ... "5,6)\\n"
113 ... "y = [3, 4,\\n"
114 ... "5]\\n"
115 ... "z = {'a': 5,\\n"
116 ... "'b':15, 'c':True}\\n"
117 ... "x = len(y) + 5 - a[\\n"
118 ... "3] - a[2]\\n"
119 ... "+ len(z) - z[\\n"
120 ... "'b']\\n")
121 True
122
123Ordinary integers and binary operators
124
125 >>> dump_tokens("0xff <= 255")
126 NUMBER '0xff' (1, 0) (1, 4)
127 OP '<=' (1, 5) (1, 7)
128 NUMBER '255' (1, 8) (1, 11)
129 >>> dump_tokens("01234567 > ~0x15")
130 NUMBER '01234567' (1, 0) (1, 8)
131 OP '>' (1, 9) (1, 10)
132 OP '~' (1, 11) (1, 12)
133 NUMBER '0x15' (1, 12) (1, 16)
134 >>> dump_tokens("2134568 != 01231515")
135 NUMBER '2134568' (1, 0) (1, 7)
136 OP '!=' (1, 8) (1, 10)
137 NUMBER '01231515' (1, 11) (1, 19)
138 >>> dump_tokens("(-124561-1) & 0200000000")
139 OP '(' (1, 0) (1, 1)
140 OP '-' (1, 1) (1, 2)
141 NUMBER '124561' (1, 2) (1, 8)
142 OP '-' (1, 8) (1, 9)
143 NUMBER '1' (1, 9) (1, 10)
144 OP ')' (1, 10) (1, 11)
145 OP '&' (1, 12) (1, 13)
146 NUMBER '0200000000' (1, 14) (1, 24)
147 >>> dump_tokens("0xdeadbeef != -1")
148 NUMBER '0xdeadbeef' (1, 0) (1, 10)
149 OP '!=' (1, 11) (1, 13)
150 OP '-' (1, 14) (1, 15)
151 NUMBER '1' (1, 15) (1, 16)
152 >>> dump_tokens("0xdeadc0de & 012345")
153 NUMBER '0xdeadc0de' (1, 0) (1, 10)
154 OP '&' (1, 11) (1, 12)
155 NUMBER '012345' (1, 13) (1, 19)
156 >>> dump_tokens("0xFF & 0x15 | 1234")
157 NUMBER '0xFF' (1, 0) (1, 4)
158 OP '&' (1, 5) (1, 6)
159 NUMBER '0x15' (1, 7) (1, 11)
160 OP '|' (1, 12) (1, 13)
161 NUMBER '1234' (1, 14) (1, 18)
162
163Long integers
164
165 >>> dump_tokens("x = 0L")
166 NAME 'x' (1, 0) (1, 1)
167 OP '=' (1, 2) (1, 3)
168 NUMBER '0L' (1, 4) (1, 6)
169 >>> dump_tokens("x = 0xfffffffffff")
170 NAME 'x' (1, 0) (1, 1)
171 OP '=' (1, 2) (1, 3)
172 NUMBER '0xffffffffff (1, 4) (1, 17)
173 >>> dump_tokens("x = 123141242151251616110l")
174 NAME 'x' (1, 0) (1, 1)
175 OP '=' (1, 2) (1, 3)
176 NUMBER '123141242151 (1, 4) (1, 26)
177 >>> dump_tokens("x = -15921590215012591L")
178 NAME 'x' (1, 0) (1, 1)
179 OP '=' (1, 2) (1, 3)
180 OP '-' (1, 4) (1, 5)
181 NUMBER '159215902150 (1, 5) (1, 23)
182
183Floating point numbers
184
185 >>> dump_tokens("x = 3.14159")
186 NAME 'x' (1, 0) (1, 1)
187 OP '=' (1, 2) (1, 3)
188 NUMBER '3.14159' (1, 4) (1, 11)
189 >>> dump_tokens("x = 314159.")
190 NAME 'x' (1, 0) (1, 1)
191 OP '=' (1, 2) (1, 3)
192 NUMBER '314159.' (1, 4) (1, 11)
193 >>> dump_tokens("x = .314159")
194 NAME 'x' (1, 0) (1, 1)
195 OP '=' (1, 2) (1, 3)
196 NUMBER '.314159' (1, 4) (1, 11)
197 >>> dump_tokens("x = 3e14159")
198 NAME 'x' (1, 0) (1, 1)
199 OP '=' (1, 2) (1, 3)
200 NUMBER '3e14159' (1, 4) (1, 11)
201 >>> dump_tokens("x = 3E123")
202 NAME 'x' (1, 0) (1, 1)
203 OP '=' (1, 2) (1, 3)
204 NUMBER '3E123' (1, 4) (1, 9)
205 >>> dump_tokens("x+y = 3e-1230")
206 NAME 'x' (1, 0) (1, 1)
207 OP '+' (1, 1) (1, 2)
208 NAME 'y' (1, 2) (1, 3)
209 OP '=' (1, 4) (1, 5)
210 NUMBER '3e-1230' (1, 6) (1, 13)
211 >>> dump_tokens("x = 3.14e159")
212 NAME 'x' (1, 0) (1, 1)
213 OP '=' (1, 2) (1, 3)
214 NUMBER '3.14e159' (1, 4) (1, 12)
215
216String literals
217
218 >>> dump_tokens("x = ''; y = \\\"\\\"")
219 NAME 'x' (1, 0) (1, 1)
220 OP '=' (1, 2) (1, 3)
221 STRING "''" (1, 4) (1, 6)
222 OP ';' (1, 6) (1, 7)
223 NAME 'y' (1, 8) (1, 9)
224 OP '=' (1, 10) (1, 11)
225 STRING '""' (1, 12) (1, 14)
226 >>> dump_tokens("x = '\\\"'; y = \\\"'\\\"")
227 NAME 'x' (1, 0) (1, 1)
228 OP '=' (1, 2) (1, 3)
229 STRING '\\'"\\'' (1, 4) (1, 7)
230 OP ';' (1, 7) (1, 8)
231 NAME 'y' (1, 9) (1, 10)
232 OP '=' (1, 11) (1, 12)
233 STRING '"\\'"' (1, 13) (1, 16)
234 >>> dump_tokens("x = \\\"doesn't \\\"shrink\\\", does it\\\"")
235 NAME 'x' (1, 0) (1, 1)
236 OP '=' (1, 2) (1, 3)
237 STRING '"doesn\\'t "' (1, 4) (1, 14)
238 NAME 'shrink' (1, 14) (1, 20)
239 STRING '", does it"' (1, 20) (1, 31)
240 >>> dump_tokens("x = u'abc' + U'ABC'")
241 NAME 'x' (1, 0) (1, 1)
242 OP '=' (1, 2) (1, 3)
243 STRING "u'abc'" (1, 4) (1, 10)
244 OP '+' (1, 11) (1, 12)
245 STRING "U'ABC'" (1, 13) (1, 19)
246 >>> dump_tokens('y = u"ABC" + U"ABC"')
247 NAME 'y' (1, 0) (1, 1)
248 OP '=' (1, 2) (1, 3)
249 STRING 'u"ABC"' (1, 4) (1, 10)
250 OP '+' (1, 11) (1, 12)
251 STRING 'U"ABC"' (1, 13) (1, 19)
252 >>> dump_tokens("x = ur'abc' + Ur'ABC' + uR'ABC' + UR'ABC'")
253 NAME 'x' (1, 0) (1, 1)
254 OP '=' (1, 2) (1, 3)
255 STRING "ur'abc'" (1, 4) (1, 11)
256 OP '+' (1, 12) (1, 13)
257 STRING "Ur'ABC'" (1, 14) (1, 21)
258 OP '+' (1, 22) (1, 23)
259 STRING "uR'ABC'" (1, 24) (1, 31)
260 OP '+' (1, 32) (1, 33)
261 STRING "UR'ABC'" (1, 34) (1, 41)
262 >>> dump_tokens('y = ur"abc" + Ur"ABC" + uR"ABC" + UR"ABC"')
263 NAME 'y' (1, 0) (1, 1)
264 OP '=' (1, 2) (1, 3)
265 STRING 'ur"abc"' (1, 4) (1, 11)
266 OP '+' (1, 12) (1, 13)
267 STRING 'Ur"ABC"' (1, 14) (1, 21)
268 OP '+' (1, 22) (1, 23)
269 STRING 'uR"ABC"' (1, 24) (1, 31)
270 OP '+' (1, 32) (1, 33)
271 STRING 'UR"ABC"' (1, 34) (1, 41)
272
273Operators
274
275 >>> dump_tokens("def d22(a, b, c=2, d=2, *k): pass")
276 NAME 'def' (1, 0) (1, 3)
277 NAME 'd22' (1, 4) (1, 7)
278 OP '(' (1, 7) (1, 8)
279 NAME 'a' (1, 8) (1, 9)
280 OP ',' (1, 9) (1, 10)
281 NAME 'b' (1, 11) (1, 12)
282 OP ',' (1, 12) (1, 13)
283 NAME 'c' (1, 14) (1, 15)
284 OP '=' (1, 15) (1, 16)
285 NUMBER '2' (1, 16) (1, 17)
286 OP ',' (1, 17) (1, 18)
287 NAME 'd' (1, 19) (1, 20)
288 OP '=' (1, 20) (1, 21)
289 NUMBER '2' (1, 21) (1, 22)
290 OP ',' (1, 22) (1, 23)
291 OP '*' (1, 24) (1, 25)
292 NAME 'k' (1, 25) (1, 26)
293 OP ')' (1, 26) (1, 27)
294 OP ':' (1, 27) (1, 28)
295 NAME 'pass' (1, 29) (1, 33)
296 >>> dump_tokens("def d01v_(a=1, *k, **w): pass")
297 NAME 'def' (1, 0) (1, 3)
298 NAME 'd01v_' (1, 4) (1, 9)
299 OP '(' (1, 9) (1, 10)
300 NAME 'a' (1, 10) (1, 11)
301 OP '=' (1, 11) (1, 12)
302 NUMBER '1' (1, 12) (1, 13)
303 OP ',' (1, 13) (1, 14)
304 OP '*' (1, 15) (1, 16)
305 NAME 'k' (1, 16) (1, 17)
306 OP ',' (1, 17) (1, 18)
307 OP '**' (1, 19) (1, 21)
308 NAME 'w' (1, 21) (1, 22)
309 OP ')' (1, 22) (1, 23)
310 OP ':' (1, 23) (1, 24)
311 NAME 'pass' (1, 25) (1, 29)
312
313Comparison
314
315 >>> dump_tokens("if 1 < 1 > 1 == 1 >= 5 <= 0x15 <= 0x12 != " +
316 ... "1 and 5 in 1 not in 1 is 1 or 5 is not 1: pass")
317 NAME 'if' (1, 0) (1, 2)
318 NUMBER '1' (1, 3) (1, 4)
319 OP '<' (1, 5) (1, 6)
320 NUMBER '1' (1, 7) (1, 8)
321 OP '>' (1, 9) (1, 10)
322 NUMBER '1' (1, 11) (1, 12)
323 OP '==' (1, 13) (1, 15)
324 NUMBER '1' (1, 16) (1, 17)
325 OP '>=' (1, 18) (1, 20)
326 NUMBER '5' (1, 21) (1, 22)
327 OP '<=' (1, 23) (1, 25)
328 NUMBER '0x15' (1, 26) (1, 30)
329 OP '<=' (1, 31) (1, 33)
330 NUMBER '0x12' (1, 34) (1, 38)
331 OP '!=' (1, 39) (1, 41)
332 NUMBER '1' (1, 42) (1, 43)
333 NAME 'and' (1, 44) (1, 47)
334 NUMBER '5' (1, 48) (1, 49)
335 NAME 'in' (1, 50) (1, 52)
336 NUMBER '1' (1, 53) (1, 54)
337 NAME 'not' (1, 55) (1, 58)
338 NAME 'in' (1, 59) (1, 61)
339 NUMBER '1' (1, 62) (1, 63)
340 NAME 'is' (1, 64) (1, 66)
341 NUMBER '1' (1, 67) (1, 68)
342 NAME 'or' (1, 69) (1, 71)
343 NUMBER '5' (1, 72) (1, 73)
344 NAME 'is' (1, 74) (1, 76)
345 NAME 'not' (1, 77) (1, 80)
346 NUMBER '1' (1, 81) (1, 82)
347 OP ':' (1, 82) (1, 83)
348 NAME 'pass' (1, 84) (1, 88)
349
350Shift
351
352 >>> dump_tokens("x = 1 << 1 >> 5")
353 NAME 'x' (1, 0) (1, 1)
354 OP '=' (1, 2) (1, 3)
355 NUMBER '1' (1, 4) (1, 5)
356 OP '<<' (1, 6) (1, 8)
357 NUMBER '1' (1, 9) (1, 10)
358 OP '>>' (1, 11) (1, 13)
359 NUMBER '5' (1, 14) (1, 15)
360
361Additive
362
363 >>> dump_tokens("x = 1 - y + 15 - 01 + 0x124 + z + a[5]")
364 NAME 'x' (1, 0) (1, 1)
365 OP '=' (1, 2) (1, 3)
366 NUMBER '1' (1, 4) (1, 5)
367 OP '-' (1, 6) (1, 7)
368 NAME 'y' (1, 8) (1, 9)
369 OP '+' (1, 10) (1, 11)
370 NUMBER '15' (1, 12) (1, 14)
371 OP '-' (1, 15) (1, 16)
372 NUMBER '01' (1, 17) (1, 19)
373 OP '+' (1, 20) (1, 21)
374 NUMBER '0x124' (1, 22) (1, 27)
375 OP '+' (1, 28) (1, 29)
376 NAME 'z' (1, 30) (1, 31)
377 OP '+' (1, 32) (1, 33)
378 NAME 'a' (1, 34) (1, 35)
379 OP '[' (1, 35) (1, 36)
380 NUMBER '5' (1, 36) (1, 37)
381 OP ']' (1, 37) (1, 38)
382
383Multiplicative
384
385 >>> dump_tokens("x = 1//1*1/5*12%0x12")
386 NAME 'x' (1, 0) (1, 1)
387 OP '=' (1, 2) (1, 3)
388 NUMBER '1' (1, 4) (1, 5)
389 OP '//' (1, 5) (1, 7)
390 NUMBER '1' (1, 7) (1, 8)
391 OP '*' (1, 8) (1, 9)
392 NUMBER '1' (1, 9) (1, 10)
393 OP '/' (1, 10) (1, 11)
394 NUMBER '5' (1, 11) (1, 12)
395 OP '*' (1, 12) (1, 13)
396 NUMBER '12' (1, 13) (1, 15)
397 OP '%' (1, 15) (1, 16)
398 NUMBER '0x12' (1, 16) (1, 20)
399
400Unary
401
402 >>> dump_tokens("~1 ^ 1 & 1 |1 ^ -1")
403 OP '~' (1, 0) (1, 1)
404 NUMBER '1' (1, 1) (1, 2)
405 OP '^' (1, 3) (1, 4)
406 NUMBER '1' (1, 5) (1, 6)
407 OP '&' (1, 7) (1, 8)
408 NUMBER '1' (1, 9) (1, 10)
409 OP '|' (1, 11) (1, 12)
410 NUMBER '1' (1, 12) (1, 13)
411 OP '^' (1, 14) (1, 15)
412 OP '-' (1, 16) (1, 17)
413 NUMBER '1' (1, 17) (1, 18)
414 >>> dump_tokens("-1*1/1+1*1//1 - ---1**1")
415 OP '-' (1, 0) (1, 1)
416 NUMBER '1' (1, 1) (1, 2)
417 OP '*' (1, 2) (1, 3)
418 NUMBER '1' (1, 3) (1, 4)
419 OP '/' (1, 4) (1, 5)
420 NUMBER '1' (1, 5) (1, 6)
421 OP '+' (1, 6) (1, 7)
422 NUMBER '1' (1, 7) (1, 8)
423 OP '*' (1, 8) (1, 9)
424 NUMBER '1' (1, 9) (1, 10)
425 OP '//' (1, 10) (1, 12)
426 NUMBER '1' (1, 12) (1, 13)
427 OP '-' (1, 14) (1, 15)
428 OP '-' (1, 16) (1, 17)
429 OP '-' (1, 17) (1, 18)
430 OP '-' (1, 18) (1, 19)
431 NUMBER '1' (1, 19) (1, 20)
432 OP '**' (1, 20) (1, 22)
433 NUMBER '1' (1, 22) (1, 23)
434
435Selector
436
437 >>> dump_tokens("import sys, time\\nx = sys.modules['time'].time()")
438 NAME 'import' (1, 0) (1, 6)
439 NAME 'sys' (1, 7) (1, 10)
440 OP ',' (1, 10) (1, 11)
441 NAME 'time' (1, 12) (1, 16)
442 NEWLINE '\\n' (1, 16) (1, 17)
443 NAME 'x' (2, 0) (2, 1)
444 OP '=' (2, 2) (2, 3)
445 NAME 'sys' (2, 4) (2, 7)
446 OP '.' (2, 7) (2, 8)
447 NAME 'modules' (2, 8) (2, 15)
448 OP '[' (2, 15) (2, 16)
449 STRING "'time'" (2, 16) (2, 22)
450 OP ']' (2, 22) (2, 23)
451 OP '.' (2, 23) (2, 24)
452 NAME 'time' (2, 24) (2, 28)
453 OP '(' (2, 28) (2, 29)
454 OP ')' (2, 29) (2, 30)
455
456Methods
457
458 >>> dump_tokens("@staticmethod\\ndef foo(x,y): pass")
459 OP '@' (1, 0) (1, 1)
460 NAME 'staticmethod (1, 1) (1, 13)
461 NEWLINE '\\n' (1, 13) (1, 14)
462 NAME 'def' (2, 0) (2, 3)
463 NAME 'foo' (2, 4) (2, 7)
464 OP '(' (2, 7) (2, 8)
465 NAME 'x' (2, 8) (2, 9)
466 OP ',' (2, 9) (2, 10)
467 NAME 'y' (2, 10) (2, 11)
468 OP ')' (2, 11) (2, 12)
469 OP ':' (2, 12) (2, 13)
470 NAME 'pass' (2, 14) (2, 18)
471
472Backslash means line continuation, except for comments
473
474 >>> roundtrip("x=1+\\\\n"
475 ... "1\\n"
476 ... "# This is a comment\\\\n"
477 ... "# This also\\n")
478 True
479 >>> roundtrip("# Comment \\\\nx = 0")
480 True
481
482 >>>
483 >>> tempdir = os.path.dirname(f) or os.curdir
484 >>> testfiles = glob.glob(os.path.join(tempdir, "test*.py"))
485 >>> if not test_support.is_resource_enabled("compiler"):
486 ... testfiles = random.sample(testfiles, 10)
487 ...
488 >>> for testfile in testfiles:
489 ... if not roundtrip(open(testfile)): break
490 ... else: True
491 True
Jeremy Hylton29bef0b2006-08-23 18:37:43 +0000492"""
493
Guido van Rossum0874f7f1997-10-27 22:15:06 +0000494
Brett Cannonb8d37352008-03-13 20:33:10 +0000495from test import test_support
496from tokenize import (tokenize, untokenize, generate_tokens, NUMBER, NAME, OP,
497 STRING, ENDMARKER, tok_name)
498from StringIO import StringIO
499import os
Raymond Hettinger68c04532005-06-10 11:05:19 +0000500
Jeremy Hylton29bef0b2006-08-23 18:37:43 +0000501def dump_tokens(s):
502 """Print out the tokens in s in a table format.
503
504 The ENDMARKER is omitted.
505 """
506 f = StringIO(s)
507 for type, token, start, end, line in generate_tokens(f.readline):
508 if type == ENDMARKER:
509 break
510 type = tok_name[type]
Brett Cannonb8d37352008-03-13 20:33:10 +0000511 print("%(type)-10.10s %(token)-13.13r %(start)s %(end)s" % locals())
Jeremy Hylton29bef0b2006-08-23 18:37:43 +0000512
Tim Petersef575672006-03-31 03:17:30 +0000513# This is an example from the docs, set up as a doctest.
Raymond Hettinger68c04532005-06-10 11:05:19 +0000514def decistmt(s):
515 """Substitute Decimals for floats in a string of statements.
516
517 >>> from decimal import Decimal
518 >>> s = 'print +21.3e-5*-.1234/81.7'
519 >>> decistmt(s)
520 "print +Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7')"
521
Tim Petersef575672006-03-31 03:17:30 +0000522 The format of the exponent is inherited from the platform C library.
523 Known cases are "e-007" (Windows) and "e-07" (not Windows). Since
524 we're only showing 12 digits, and the 13th isn't close to 5, the
525 rest of the output should be platform-independent.
526
527 >>> exec(s) #doctest: +ELLIPSIS
528 -3.21716034272e-0...7
529
530 Output from calculations with Decimal should be identical across all
531 platforms.
532
Raymond Hettinger68c04532005-06-10 11:05:19 +0000533 >>> exec(decistmt(s))
534 -3.217160342717258261933904529E-7
Raymond Hettinger68c04532005-06-10 11:05:19 +0000535 """
Tim Petersef575672006-03-31 03:17:30 +0000536
Raymond Hettinger68c04532005-06-10 11:05:19 +0000537 result = []
538 g = generate_tokens(StringIO(s).readline) # tokenize the string
539 for toknum, tokval, _, _, _ in g:
540 if toknum == NUMBER and '.' in tokval: # replace NUMBER tokens
541 result.extend([
542 (NAME, 'Decimal'),
543 (OP, '('),
544 (STRING, repr(tokval)),
545 (OP, ')')
546 ])
547 else:
548 result.append((toknum, tokval))
549 return untokenize(result)
550
Brett Cannonb8d37352008-03-13 20:33:10 +0000551
552__test__ = {"doctests" : doctests, 'decistmt': decistmt}
553
554
Tim Petersef575672006-03-31 03:17:30 +0000555def test_main():
Brett Cannonb8d37352008-03-13 20:33:10 +0000556 from test import test_tokenize
557 test_support.run_doctest(test_tokenize, True)
Tim Petersef575672006-03-31 03:17:30 +0000558
559if __name__ == "__main__":
560 test_main()