blob: 69501dfe089e39e42f16839592e03e1cbd0be87c [file] [log] [blame]
Martin v. Löwisf90ae202002-06-11 06:22:31 +00001import sys
Fred Drake2ec80fa2000-10-23 16:59:35 +00002import os
Neal Norwitz62f5a9d2002-04-01 00:09:00 +00003from array import array
Raymond Hettingercb87bc82004-05-31 00:35:52 +00004from weakref import proxy
Fred Drake2ec80fa2000-10-23 16:59:35 +00005
Thomas Woutersc45251a2006-02-12 11:53:32 +00006from test.test_support import verify, TESTFN, TestFailed, findfile
Marc-André Lemburgfa44d792000-08-25 22:37:31 +00007from UserList import UserList
8
Raymond Hettingercb87bc82004-05-31 00:35:52 +00009# verify weak references
10f = file(TESTFN, 'w')
11p = proxy(f)
12p.write('teststring')
13verify(f.tell(), p.tell())
14f.close()
15f = None
16try:
17 p.tell()
18except ReferenceError:
19 pass
20else:
21 raise TestFailed('file proxy still exists when the file is gone')
22
Tim Peters015dd822003-05-04 04:16:52 +000023# verify expected attributes exist
24f = file(TESTFN, 'w')
25softspace = f.softspace
26f.name # merely shouldn't blow up
27f.mode # ditto
28f.closed # ditto
29
30# verify softspace is writable
31f.softspace = softspace # merely shouldn't blow up
32
33# verify the others aren't
34for attr in 'name', 'mode', 'closed':
35 try:
36 setattr(f, attr, 'oops')
Barry Warsawb180c062005-04-20 19:41:36 +000037 except (AttributeError, TypeError):
Tim Peters015dd822003-05-04 04:16:52 +000038 pass
39 else:
Barry Warsawb180c062005-04-20 19:41:36 +000040 raise TestFailed('expected exception setting file attr %r' % attr)
Tim Peters015dd822003-05-04 04:16:52 +000041f.close()
42
Skip Montanarobbf12ba2005-05-20 03:07:06 +000043# check invalid mode strings
44for mode in ("", "aU", "wU+"):
45 try:
46 f = file(TESTFN, mode)
47 except ValueError:
48 pass
49 else:
50 f.close()
51 raise TestFailed('%r is an invalid file mode' % mode)
52
Marc-André Lemburgfa44d792000-08-25 22:37:31 +000053# verify writelines with instance sequence
54l = UserList(['1', '2'])
55f = open(TESTFN, 'wb')
56f.writelines(l)
57f.close()
58f = open(TESTFN, 'rb')
59buf = f.read()
60f.close()
Marc-André Lemburg36619082001-01-17 19:11:13 +000061verify(buf == '12')
Marc-André Lemburgfa44d792000-08-25 22:37:31 +000062
Neal Norwitz62f5a9d2002-04-01 00:09:00 +000063# verify readinto
64a = array('c', 'x'*10)
65f = open(TESTFN, 'rb')
66n = f.readinto(a)
67f.close()
68verify(buf == a.tostring()[:n])
69
Marc-André Lemburgfa44d792000-08-25 22:37:31 +000070# verify writelines with integers
71f = open(TESTFN, 'wb')
72try:
73 f.writelines([1, 2, 3])
74except TypeError:
75 pass
76else:
77 print "writelines accepted sequence of integers"
78f.close()
79
80# verify writelines with integers in UserList
81f = open(TESTFN, 'wb')
82l = UserList([1,2,3])
83try:
84 f.writelines(l)
85except TypeError:
86 pass
87else:
88 print "writelines accepted sequence of integers"
89f.close()
90
91# verify writelines with non-string object
92class NonString: pass
93
94f = open(TESTFN, 'wb')
95try:
96 f.writelines([NonString(), NonString()])
97except TypeError:
98 pass
99else:
100 print "writelines accepted sequence of non-string objects"
101f.close()
Fred Drake2ec80fa2000-10-23 16:59:35 +0000102
Neal Norwitzfcf44352005-11-27 20:37:43 +0000103try:
Neal Norwitza6fc3972005-12-05 01:17:03 +0000104 sys.stdin.seek(-1)
Neal Norwitzfcf44352005-11-27 20:37:43 +0000105except IOError:
106 pass
107else:
108 print "should not be able to seek on sys.stdin"
109
110try:
Neal Norwitzfcf44352005-11-27 20:37:43 +0000111 sys.stdin.truncate()
112except IOError:
113 pass
114else:
115 print "should not be able to truncate on sys.stdin"
116
117# verify repr works
118f = open(TESTFN)
119if not repr(f).startswith("<open file '" + TESTFN):
120 print "repr(file) failed"
121f.close()
122
123# verify repr works for unicode too
124f = open(unicode(TESTFN))
125if not repr(f).startswith("<open file u'" + TESTFN):
126 print "repr(file with unicode name) failed"
127f.close()
128
Jeremy Hylton734c7fb2001-11-09 19:34:43 +0000129# verify that we get a sensible error message for bad mode argument
Jeremy Hylton41c83212001-11-09 16:17:24 +0000130bad_mode = "qwerty"
131try:
132 open(TESTFN, bad_mode)
133except IOError, msg:
Jeremy Hylton734c7fb2001-11-09 19:34:43 +0000134 if msg[0] != 0:
135 s = str(msg)
136 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
137 print "bad error message for invalid mode: %s" % s
138 # if msg[0] == 0, we're probably on Windows where there may be
139 # no obvious way to discover why open() failed.
Jeremy Hylton41c83212001-11-09 16:17:24 +0000140else:
141 print "no error for invalid mode: %s" % bad_mode
142
Neal Norwitz653d85f2002-01-01 19:11:13 +0000143f = open(TESTFN)
144if f.name != TESTFN:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000145 raise TestFailed, 'file.name should be "%s"' % TESTFN
Neal Norwitz653d85f2002-01-01 19:11:13 +0000146if f.isatty():
Neal Norwitzb1295da2002-04-01 18:59:20 +0000147 raise TestFailed, 'file.isatty() should be false'
Neal Norwitz653d85f2002-01-01 19:11:13 +0000148
149if f.closed:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000150 raise TestFailed, 'file.closed should be false'
Neal Norwitz653d85f2002-01-01 19:11:13 +0000151
Neal Norwitz62f5a9d2002-04-01 00:09:00 +0000152try:
153 f.readinto("")
154except TypeError:
155 pass
156else:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000157 raise TestFailed, 'file.readinto("") should raise a TypeError'
Neal Norwitz62f5a9d2002-04-01 00:09:00 +0000158
Neal Norwitz653d85f2002-01-01 19:11:13 +0000159f.close()
160if not f.closed:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000161 raise TestFailed, 'file.closed should be true'
Neal Norwitz653d85f2002-01-01 19:11:13 +0000162
Andrew MacIntyre4e10ed32004-04-04 07:01:35 +0000163# make sure that explicitly setting the buffer size doesn't cause
164# misbehaviour especially with repeated close() calls
165for s in (-1, 0, 1, 512):
166 try:
167 f = open(TESTFN, 'w', s)
168 f.write(str(s))
169 f.close()
170 f.close()
171 f = open(TESTFN, 'r', s)
172 d = int(f.read())
173 f.close()
174 f.close()
175 except IOError, msg:
176 raise TestFailed, 'error setting buffer size %d: %s' % (s, str(msg))
177 if d != s:
178 raise TestFailed, 'readback failure using buffer size %d'
179
Guido van Rossum3c668c12002-08-06 15:58:24 +0000180methods = ['fileno', 'flush', 'isatty', 'next', 'read', 'readinto',
181 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write',
182 'xreadlines', '__iter__']
Martin v. Löwisf90ae202002-06-11 06:22:31 +0000183if sys.platform.startswith('atheos'):
184 methods.remove('truncate')
185
186for methodname in methods:
Neal Norwitz653d85f2002-01-01 19:11:13 +0000187 method = getattr(f, methodname)
188 try:
189 method()
190 except ValueError:
191 pass
192 else:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000193 raise TestFailed, 'file.%s() on a closed file should raise a ValueError' % methodname
Neal Norwitz653d85f2002-01-01 19:11:13 +0000194
195try:
196 f.writelines([])
197except ValueError:
198 pass
199else:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000200 raise TestFailed, 'file.writelines([]) on a closed file should raise a ValueError'
Neal Norwitz653d85f2002-01-01 19:11:13 +0000201
Fred Drake2ec80fa2000-10-23 16:59:35 +0000202os.unlink(TESTFN)
Tim Petersf1827cf2003-09-07 03:30:18 +0000203
204def bug801631():
205 # SF bug <http://www.python.org/sf/801631>
206 # "file.truncate fault on windows"
207 f = file(TESTFN, 'wb')
208 f.write('12345678901') # 11 bytes
209 f.close()
210
211 f = file(TESTFN,'rb+')
212 data = f.read(5)
213 if data != '12345':
214 raise TestFailed("Read on file opened for update failed %r" % data)
215 if f.tell() != 5:
216 raise TestFailed("File pos after read wrong %d" % f.tell())
217
218 f.truncate()
219 if f.tell() != 5:
220 raise TestFailed("File pos after ftruncate wrong %d" % f.tell())
221
222 f.close()
223 size = os.path.getsize(TESTFN)
224 if size != 5:
225 raise TestFailed("File size after ftruncate wrong %d" % size)
226
227try:
228 bug801631()
229finally:
230 os.unlink(TESTFN)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000231
232# Test the complex interaction when mixing file-iteration and the various
233# read* methods. Ostensibly, the mixture could just be tested to work
234# when it should work according to the Python language, instead of fail
235# when it should fail according to the current CPython implementation.
236# People don't always program Python the way they should, though, and the
237# implemenation might change in subtle ways, so we explicitly test for
238# errors, too; the test will just have to be updated when the
239# implementation changes.
240dataoffset = 16384
241filler = "ham\n"
242assert not dataoffset % len(filler), \
243 "dataoffset must be multiple of len(filler)"
244nchunks = dataoffset // len(filler)
245testlines = [
246 "spam, spam and eggs\n",
247 "eggs, spam, ham and spam\n",
248 "saussages, spam, spam and eggs\n",
249 "spam, ham, spam and eggs\n",
250 "spam, spam, spam, spam, spam, ham, spam\n",
251 "wonderful spaaaaaam.\n"
252]
253methods = [("readline", ()), ("read", ()), ("readlines", ()),
254 ("readinto", (array("c", " "*100),))]
255
256try:
257 # Prepare the testfile
258 bag = open(TESTFN, "w")
259 bag.write(filler * nchunks)
260 bag.writelines(testlines)
261 bag.close()
262 # Test for appropriate errors mixing read* and iteration
263 for methodname, args in methods:
264 f = open(TESTFN)
265 if f.next() != filler:
266 raise TestFailed, "Broken testfile"
267 meth = getattr(f, methodname)
268 try:
269 meth(*args)
270 except ValueError:
271 pass
272 else:
273 raise TestFailed("%s%r after next() didn't raise ValueError" %
274 (methodname, args))
275 f.close()
276
277 # Test to see if harmless (by accident) mixing of read* and iteration
278 # still works. This depends on the size of the internal iteration
279 # buffer (currently 8192,) but we can test it in a flexible manner.
280 # Each line in the bag o' ham is 4 bytes ("h", "a", "m", "\n"), so
281 # 4096 lines of that should get us exactly on the buffer boundary for
282 # any power-of-2 buffersize between 4 and 16384 (inclusive).
283 f = open(TESTFN)
284 for i in range(nchunks):
285 f.next()
286 testline = testlines.pop(0)
287 try:
288 line = f.readline()
289 except ValueError:
290 raise TestFailed("readline() after next() with supposedly empty "
291 "iteration-buffer failed anyway")
292 if line != testline:
293 raise TestFailed("readline() after next() with empty buffer "
294 "failed. Got %r, expected %r" % (line, testline))
295 testline = testlines.pop(0)
296 buf = array("c", "\x00" * len(testline))
297 try:
298 f.readinto(buf)
299 except ValueError:
300 raise TestFailed("readinto() after next() with supposedly empty "
301 "iteration-buffer failed anyway")
302 line = buf.tostring()
303 if line != testline:
304 raise TestFailed("readinto() after next() with empty buffer "
305 "failed. Got %r, expected %r" % (line, testline))
306
307 testline = testlines.pop(0)
308 try:
309 line = f.read(len(testline))
310 except ValueError:
311 raise TestFailed("read() after next() with supposedly empty "
312 "iteration-buffer failed anyway")
313 if line != testline:
314 raise TestFailed("read() after next() with empty buffer "
315 "failed. Got %r, expected %r" % (line, testline))
316 try:
317 lines = f.readlines()
318 except ValueError:
319 raise TestFailed("readlines() after next() with supposedly empty "
320 "iteration-buffer failed anyway")
321 if lines != testlines:
322 raise TestFailed("readlines() after next() with empty buffer "
323 "failed. Got %r, expected %r" % (line, testline))
324 # Reading after iteration hit EOF shouldn't hurt either
325 f = open(TESTFN)
326 for line in f:
327 pass
328 try:
329 f.readline()
330 f.readinto(buf)
331 f.read()
332 f.readlines()
333 except ValueError:
334 raise TestFailed("read* failed after next() consumed file")
335finally:
336 # Bare 'except' so as not to mask errors in the test
337 try:
338 os.unlink(TESTFN)
339 except:
340 pass