|
1 ''' |
|
2 Tests for fileinput module. |
|
3 Nick Mathewson |
|
4 ''' |
|
5 |
|
6 from test.test_support import verify, verbose, TESTFN, TestFailed |
|
7 import sys, os, re |
|
8 from StringIO import StringIO |
|
9 from fileinput import FileInput, hook_encoded |
|
10 |
|
11 # The fileinput module has 2 interfaces: the FileInput class which does |
|
12 # all the work, and a few functions (input, etc.) that use a global _state |
|
13 # variable. We only test the FileInput class, since the other functions |
|
14 # only provide a thin facade over FileInput. |
|
15 |
|
16 # Write lines (a list of lines) to temp file number i, and return the |
|
17 # temp file's name. |
|
18 def writeTmp(i, lines, mode='w'): # opening in text mode is the default |
|
19 name = TESTFN + str(i) |
|
20 f = open(name, mode) |
|
21 f.writelines(lines) |
|
22 f.close() |
|
23 return name |
|
24 |
|
25 pat = re.compile(r'LINE (\d+) OF FILE (\d+)') |
|
26 |
|
27 def remove_tempfiles(*names): |
|
28 for name in names: |
|
29 try: |
|
30 os.unlink(name) |
|
31 except: |
|
32 pass |
|
33 |
|
34 def runTests(t1, t2, t3, t4, bs=0, round=0): |
|
35 start = 1 + round*6 |
|
36 if verbose: |
|
37 print '%s. Simple iteration (bs=%s)' % (start+0, bs) |
|
38 fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) |
|
39 lines = list(fi) |
|
40 fi.close() |
|
41 verify(len(lines) == 31) |
|
42 verify(lines[4] == 'Line 5 of file 1\n') |
|
43 verify(lines[30] == 'Line 1 of file 4\n') |
|
44 verify(fi.lineno() == 31) |
|
45 verify(fi.filename() == t4) |
|
46 |
|
47 if verbose: |
|
48 print '%s. Status variables (bs=%s)' % (start+1, bs) |
|
49 fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) |
|
50 s = "x" |
|
51 while s and s != 'Line 6 of file 2\n': |
|
52 s = fi.readline() |
|
53 verify(fi.filename() == t2) |
|
54 verify(fi.lineno() == 21) |
|
55 verify(fi.filelineno() == 6) |
|
56 verify(not fi.isfirstline()) |
|
57 verify(not fi.isstdin()) |
|
58 |
|
59 if verbose: |
|
60 print '%s. Nextfile (bs=%s)' % (start+2, bs) |
|
61 fi.nextfile() |
|
62 verify(fi.readline() == 'Line 1 of file 3\n') |
|
63 verify(fi.lineno() == 22) |
|
64 fi.close() |
|
65 |
|
66 if verbose: |
|
67 print '%s. Stdin (bs=%s)' % (start+3, bs) |
|
68 fi = FileInput(files=(t1, t2, t3, t4, '-'), bufsize=bs) |
|
69 savestdin = sys.stdin |
|
70 try: |
|
71 sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n") |
|
72 lines = list(fi) |
|
73 verify(len(lines) == 33) |
|
74 verify(lines[32] == 'Line 2 of stdin\n') |
|
75 verify(fi.filename() == '<stdin>') |
|
76 fi.nextfile() |
|
77 finally: |
|
78 sys.stdin = savestdin |
|
79 |
|
80 if verbose: |
|
81 print '%s. Boundary conditions (bs=%s)' % (start+4, bs) |
|
82 fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) |
|
83 verify(fi.lineno() == 0) |
|
84 verify(fi.filename() == None) |
|
85 fi.nextfile() |
|
86 verify(fi.lineno() == 0) |
|
87 verify(fi.filename() == None) |
|
88 |
|
89 if verbose: |
|
90 print '%s. Inplace (bs=%s)' % (start+5, bs) |
|
91 savestdout = sys.stdout |
|
92 try: |
|
93 fi = FileInput(files=(t1, t2, t3, t4), inplace=1, bufsize=bs) |
|
94 for line in fi: |
|
95 line = line[:-1].upper() |
|
96 print line |
|
97 fi.close() |
|
98 finally: |
|
99 sys.stdout = savestdout |
|
100 |
|
101 fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs) |
|
102 for line in fi: |
|
103 verify(line[-1] == '\n') |
|
104 m = pat.match(line[:-1]) |
|
105 verify(m != None) |
|
106 verify(int(m.group(1)) == fi.filelineno()) |
|
107 fi.close() |
|
108 |
|
109 |
|
110 def writeFiles(): |
|
111 global t1, t2, t3, t4 |
|
112 t1 = writeTmp(1, ["Line %s of file 1\n" % (i+1) for i in range(15)]) |
|
113 t2 = writeTmp(2, ["Line %s of file 2\n" % (i+1) for i in range(10)]) |
|
114 t3 = writeTmp(3, ["Line %s of file 3\n" % (i+1) for i in range(5)]) |
|
115 t4 = writeTmp(4, ["Line %s of file 4\n" % (i+1) for i in range(1)]) |
|
116 |
|
117 # First, run the tests with default and teeny buffer size. |
|
118 for round, bs in (0, 0), (1, 30): |
|
119 try: |
|
120 writeFiles() |
|
121 runTests(t1, t2, t3, t4, bs, round) |
|
122 finally: |
|
123 remove_tempfiles(t1, t2, t3, t4) |
|
124 |
|
125 # Next, check for proper behavior with 0-byte files. |
|
126 if verbose: |
|
127 print "13. 0-byte files" |
|
128 try: |
|
129 t1 = writeTmp(1, [""]) |
|
130 t2 = writeTmp(2, [""]) |
|
131 t3 = writeTmp(3, ["The only line there is.\n"]) |
|
132 t4 = writeTmp(4, [""]) |
|
133 fi = FileInput(files=(t1, t2, t3, t4)) |
|
134 line = fi.readline() |
|
135 verify(line == 'The only line there is.\n') |
|
136 verify(fi.lineno() == 1) |
|
137 verify(fi.filelineno() == 1) |
|
138 verify(fi.filename() == t3) |
|
139 line = fi.readline() |
|
140 verify(not line) |
|
141 verify(fi.lineno() == 1) |
|
142 verify(fi.filelineno() == 0) |
|
143 verify(fi.filename() == t4) |
|
144 fi.close() |
|
145 finally: |
|
146 remove_tempfiles(t1, t2, t3, t4) |
|
147 |
|
148 if verbose: |
|
149 print "14. Files that don't end with newline" |
|
150 try: |
|
151 t1 = writeTmp(1, ["A\nB\nC"]) |
|
152 t2 = writeTmp(2, ["D\nE\nF"]) |
|
153 fi = FileInput(files=(t1, t2)) |
|
154 lines = list(fi) |
|
155 verify(lines == ["A\n", "B\n", "C", "D\n", "E\n", "F"]) |
|
156 verify(fi.filelineno() == 3) |
|
157 verify(fi.lineno() == 6) |
|
158 finally: |
|
159 remove_tempfiles(t1, t2) |
|
160 |
|
161 if verbose: |
|
162 print "15. Unicode filenames" |
|
163 try: |
|
164 t1 = writeTmp(1, ["A\nB"]) |
|
165 encoding = sys.getfilesystemencoding() |
|
166 if encoding is None: |
|
167 encoding = 'ascii' |
|
168 fi = FileInput(files=unicode(t1, encoding)) |
|
169 lines = list(fi) |
|
170 verify(lines == ["A\n", "B"]) |
|
171 finally: |
|
172 remove_tempfiles(t1) |
|
173 |
|
174 if verbose: |
|
175 print "16. fileno()" |
|
176 try: |
|
177 t1 = writeTmp(1, ["A\nB"]) |
|
178 t2 = writeTmp(2, ["C\nD"]) |
|
179 fi = FileInput(files=(t1, t2)) |
|
180 verify(fi.fileno() == -1) |
|
181 line = fi.next() |
|
182 verify(fi.fileno() != -1) |
|
183 fi.nextfile() |
|
184 verify(fi.fileno() == -1) |
|
185 line = list(fi) |
|
186 verify(fi.fileno() == -1) |
|
187 finally: |
|
188 remove_tempfiles(t1, t2) |
|
189 |
|
190 if verbose: |
|
191 print "17. Specify opening mode" |
|
192 try: |
|
193 # invalid mode, should raise ValueError |
|
194 fi = FileInput(mode="w") |
|
195 raise TestFailed("FileInput should reject invalid mode argument") |
|
196 except ValueError: |
|
197 pass |
|
198 try: |
|
199 # try opening in universal newline mode |
|
200 t1 = writeTmp(1, ["A\nB\r\nC\rD"], mode="wb") |
|
201 fi = FileInput(files=t1, mode="U") |
|
202 lines = list(fi) |
|
203 verify(lines == ["A\n", "B\n", "C\n", "D"]) |
|
204 finally: |
|
205 remove_tempfiles(t1) |
|
206 |
|
207 if verbose: |
|
208 print "18. Test file opening hook" |
|
209 try: |
|
210 # cannot use openhook and inplace mode |
|
211 fi = FileInput(inplace=1, openhook=lambda f,m: None) |
|
212 raise TestFailed("FileInput should raise if both inplace " |
|
213 "and openhook arguments are given") |
|
214 except ValueError: |
|
215 pass |
|
216 try: |
|
217 fi = FileInput(openhook=1) |
|
218 raise TestFailed("FileInput should check openhook for being callable") |
|
219 except ValueError: |
|
220 pass |
|
221 try: |
|
222 t1 = writeTmp(1, ["A\nB"], mode="wb") |
|
223 fi = FileInput(files=t1, openhook=hook_encoded("rot13")) |
|
224 lines = list(fi) |
|
225 verify(lines == ["N\n", "O"]) |
|
226 finally: |
|
227 remove_tempfiles(t1) |