blob: 17ca944d71049f1203e777b36fdb44a55305d962 [file] [log] [blame]
Tim Peters3230d5c2001-07-11 22:21:17 +00001'''
2Tests for fileinput module.
3Nick Mathewson
4'''
5
Georg Brandlc029f872006-02-19 14:12:34 +00006from test.test_support import verify, verbose, TESTFN, TestFailed
Tim Peters3230d5c2001-07-11 22:21:17 +00007import sys, os, re
8from StringIO import StringIO
Georg Brandlc98eeed2006-02-19 14:57:47 +00009from fileinput import FileInput, hook_encoded
Tim Peters3230d5c2001-07-11 22:21:17 +000010
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.
Tim Peters4d7cad12006-02-19 21:22:10 +000018def writeTmp(i, lines, mode='w'): # opening in text mode is the default
Tim Peters3230d5c2001-07-11 22:21:17 +000019 name = TESTFN + str(i)
Tim Peters4d7cad12006-02-19 21:22:10 +000020 f = open(name, mode)
Guido van Rossumdc0b1a12007-04-12 22:55:07 +000021 for line in lines:
22 f.write(line)
Tim Peters3230d5c2001-07-11 22:21:17 +000023 f.close()
24 return name
25
26pat = re.compile(r'LINE (\d+) OF FILE (\d+)')
27
28def remove_tempfiles(*names):
29 for name in names:
30 try:
31 os.unlink(name)
32 except:
33 pass
34
35def runTests(t1, t2, t3, t4, bs=0, round=0):
36 start = 1 + round*6
37 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000038 print('%s. Simple iteration (bs=%s)' % (start+0, bs))
Tim Peters3230d5c2001-07-11 22:21:17 +000039 fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
40 lines = list(fi)
41 fi.close()
42 verify(len(lines) == 31)
43 verify(lines[4] == 'Line 5 of file 1\n')
44 verify(lines[30] == 'Line 1 of file 4\n')
45 verify(fi.lineno() == 31)
46 verify(fi.filename() == t4)
47
48 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000049 print('%s. Status variables (bs=%s)' % (start+1, bs))
Tim Peters3230d5c2001-07-11 22:21:17 +000050 fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
51 s = "x"
52 while s and s != 'Line 6 of file 2\n':
53 s = fi.readline()
54 verify(fi.filename() == t2)
55 verify(fi.lineno() == 21)
56 verify(fi.filelineno() == 6)
57 verify(not fi.isfirstline())
58 verify(not fi.isstdin())
59
60 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000061 print('%s. Nextfile (bs=%s)' % (start+2, bs))
Tim Peters3230d5c2001-07-11 22:21:17 +000062 fi.nextfile()
63 verify(fi.readline() == 'Line 1 of file 3\n')
64 verify(fi.lineno() == 22)
65 fi.close()
66
67 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000068 print('%s. Stdin (bs=%s)' % (start+3, bs))
Tim Peters3230d5c2001-07-11 22:21:17 +000069 fi = FileInput(files=(t1, t2, t3, t4, '-'), bufsize=bs)
70 savestdin = sys.stdin
71 try:
72 sys.stdin = StringIO("Line 1 of stdin\nLine 2 of stdin\n")
73 lines = list(fi)
74 verify(len(lines) == 33)
75 verify(lines[32] == 'Line 2 of stdin\n')
76 verify(fi.filename() == '<stdin>')
77 fi.nextfile()
78 finally:
79 sys.stdin = savestdin
80
81 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000082 print('%s. Boundary conditions (bs=%s)' % (start+4, bs))
Tim Peters3230d5c2001-07-11 22:21:17 +000083 fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
84 verify(fi.lineno() == 0)
85 verify(fi.filename() == None)
86 fi.nextfile()
87 verify(fi.lineno() == 0)
88 verify(fi.filename() == None)
89
90 if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +000091 print('%s. Inplace (bs=%s)' % (start+5, bs))
Tim Peters3230d5c2001-07-11 22:21:17 +000092 savestdout = sys.stdout
93 try:
94 fi = FileInput(files=(t1, t2, t3, t4), inplace=1, bufsize=bs)
95 for line in fi:
96 line = line[:-1].upper()
Guido van Rossumbe19ed72007-02-09 05:37:30 +000097 print(line)
Tim Peters3230d5c2001-07-11 22:21:17 +000098 fi.close()
99 finally:
100 sys.stdout = savestdout
101
102 fi = FileInput(files=(t1, t2, t3, t4), bufsize=bs)
103 for line in fi:
104 verify(line[-1] == '\n')
105 m = pat.match(line[:-1])
106 verify(m != None)
107 verify(int(m.group(1)) == fi.filelineno())
108 fi.close()
109
110
111def writeFiles():
112 global t1, t2, t3, t4
113 t1 = writeTmp(1, ["Line %s of file 1\n" % (i+1) for i in range(15)])
114 t2 = writeTmp(2, ["Line %s of file 2\n" % (i+1) for i in range(10)])
115 t3 = writeTmp(3, ["Line %s of file 3\n" % (i+1) for i in range(5)])
116 t4 = writeTmp(4, ["Line %s of file 4\n" % (i+1) for i in range(1)])
117
118# First, run the tests with default and teeny buffer size.
119for round, bs in (0, 0), (1, 30):
120 try:
121 writeFiles()
122 runTests(t1, t2, t3, t4, bs, round)
123 finally:
124 remove_tempfiles(t1, t2, t3, t4)
125
126# Next, check for proper behavior with 0-byte files.
127if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000128 print("13. 0-byte files")
Tim Peters3230d5c2001-07-11 22:21:17 +0000129try:
130 t1 = writeTmp(1, [""])
131 t2 = writeTmp(2, [""])
132 t3 = writeTmp(3, ["The only line there is.\n"])
133 t4 = writeTmp(4, [""])
134 fi = FileInput(files=(t1, t2, t3, t4))
135 line = fi.readline()
136 verify(line == 'The only line there is.\n')
137 verify(fi.lineno() == 1)
138 verify(fi.filelineno() == 1)
139 verify(fi.filename() == t3)
140 line = fi.readline()
141 verify(not line)
142 verify(fi.lineno() == 1)
143 verify(fi.filelineno() == 0)
144 verify(fi.filename() == t4)
145 fi.close()
146finally:
147 remove_tempfiles(t1, t2, t3, t4)
148
149if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000150 print("14. Files that don't end with newline")
Tim Peters3230d5c2001-07-11 22:21:17 +0000151try:
152 t1 = writeTmp(1, ["A\nB\nC"])
153 t2 = writeTmp(2, ["D\nE\nF"])
154 fi = FileInput(files=(t1, t2))
155 lines = list(fi)
156 verify(lines == ["A\n", "B\n", "C", "D\n", "E\n", "F"])
157 verify(fi.filelineno() == 3)
158 verify(fi.lineno() == 6)
159finally:
160 remove_tempfiles(t1, t2)
Georg Brandle4662172006-02-19 09:51:27 +0000161
162if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000163 print("15. Unicode filenames")
Georg Brandle4662172006-02-19 09:51:27 +0000164try:
165 t1 = writeTmp(1, ["A\nB"])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000166 encoding = sys.getfilesystemencoding()
167 if encoding is None:
168 encoding = 'ascii'
169 fi = FileInput(files=unicode(t1, encoding))
Georg Brandle4662172006-02-19 09:51:27 +0000170 lines = list(fi)
171 verify(lines == ["A\n", "B"])
172finally:
173 remove_tempfiles(t1)
Georg Brandl67e9fb92006-02-19 13:56:17 +0000174
175if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000176 print("16. fileno()")
Georg Brandl67e9fb92006-02-19 13:56:17 +0000177try:
178 t1 = writeTmp(1, ["A\nB"])
179 t2 = writeTmp(2, ["C\nD"])
180 fi = FileInput(files=(t1, t2))
181 verify(fi.fileno() == -1)
Georg Brandla18af4e2007-04-21 15:47:16 +0000182 line = next(fi)
Georg Brandl67e9fb92006-02-19 13:56:17 +0000183 verify(fi.fileno() != -1)
184 fi.nextfile()
185 verify(fi.fileno() == -1)
186 line = list(fi)
187 verify(fi.fileno() == -1)
188finally:
189 remove_tempfiles(t1, t2)
Georg Brandlc029f872006-02-19 14:12:34 +0000190
191if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000192 print("17. Specify opening mode")
Georg Brandlc029f872006-02-19 14:12:34 +0000193try:
194 # invalid mode, should raise ValueError
195 fi = FileInput(mode="w")
196 raise TestFailed("FileInput should reject invalid mode argument")
197except ValueError:
198 pass
199try:
200 # try opening in universal newline mode
Tim Peters4d7cad12006-02-19 21:22:10 +0000201 t1 = writeTmp(1, ["A\nB\r\nC\rD"], mode="wb")
Georg Brandlc029f872006-02-19 14:12:34 +0000202 fi = FileInput(files=t1, mode="U")
203 lines = list(fi)
204 verify(lines == ["A\n", "B\n", "C\n", "D"])
205finally:
206 remove_tempfiles(t1)
Georg Brandlc98eeed2006-02-19 14:57:47 +0000207
208if verbose:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000209 print("18. Test file opening hook")
Georg Brandlc98eeed2006-02-19 14:57:47 +0000210try:
211 # cannot use openhook and inplace mode
212 fi = FileInput(inplace=1, openhook=lambda f,m: None)
213 raise TestFailed("FileInput should raise if both inplace "
214 "and openhook arguments are given")
215except ValueError:
216 pass
217try:
218 fi = FileInput(openhook=1)
219 raise TestFailed("FileInput should check openhook for being callable")
220except ValueError:
221 pass
222try:
Tim Peters4d7cad12006-02-19 21:22:10 +0000223 t1 = writeTmp(1, ["A\nB"], mode="wb")
Georg Brandlc98eeed2006-02-19 14:57:47 +0000224 fi = FileInput(files=t1, openhook=hook_encoded("rot13"))
225 lines = list(fi)
226 verify(lines == ["N\n", "O"])
227finally:
228 remove_tempfiles(t1)