blob: 53f99530715308b75466541ad67f34eeebaa4ace [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 Norwitz9cdfa4c2006-04-03 05:27:05 +0000103# This causes the interpreter to exit on OSF1 v5.1.
104if sys.platform != 'osf1V5':
105 try:
106 sys.stdin.seek(-1)
107 except IOError:
108 pass
109 else:
110 print "should not be able to seek on sys.stdin"
Neal Norwitzfcf44352005-11-27 20:37:43 +0000111else:
Neal Norwitz9cdfa4c2006-04-03 05:27:05 +0000112 print >>sys.__stdout__, (
113 ' Skipping sys.stdin.seek(-1), it may crash the interpreter.'
114 ' Test manually.')
Neal Norwitzfcf44352005-11-27 20:37:43 +0000115
116try:
Neal Norwitzfcf44352005-11-27 20:37:43 +0000117 sys.stdin.truncate()
118except IOError:
119 pass
120else:
121 print "should not be able to truncate on sys.stdin"
122
123# verify repr works
124f = open(TESTFN)
125if not repr(f).startswith("<open file '" + TESTFN):
126 print "repr(file) failed"
127f.close()
128
129# verify repr works for unicode too
130f = open(unicode(TESTFN))
131if not repr(f).startswith("<open file u'" + TESTFN):
132 print "repr(file with unicode name) failed"
133f.close()
134
Jeremy Hylton734c7fb2001-11-09 19:34:43 +0000135# verify that we get a sensible error message for bad mode argument
Jeremy Hylton41c83212001-11-09 16:17:24 +0000136bad_mode = "qwerty"
137try:
138 open(TESTFN, bad_mode)
Georg Brandl7b90e162006-05-18 07:01:27 +0000139except ValueError, msg:
Jeremy Hylton734c7fb2001-11-09 19:34:43 +0000140 if msg[0] != 0:
141 s = str(msg)
142 if s.find(TESTFN) != -1 or s.find(bad_mode) == -1:
143 print "bad error message for invalid mode: %s" % s
144 # if msg[0] == 0, we're probably on Windows where there may be
145 # no obvious way to discover why open() failed.
Jeremy Hylton41c83212001-11-09 16:17:24 +0000146else:
147 print "no error for invalid mode: %s" % bad_mode
148
Neal Norwitz653d85f2002-01-01 19:11:13 +0000149f = open(TESTFN)
150if f.name != TESTFN:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000151 raise TestFailed, 'file.name should be "%s"' % TESTFN
Neal Norwitz653d85f2002-01-01 19:11:13 +0000152if f.isatty():
Neal Norwitzb1295da2002-04-01 18:59:20 +0000153 raise TestFailed, 'file.isatty() should be false'
Neal Norwitz653d85f2002-01-01 19:11:13 +0000154
155if f.closed:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000156 raise TestFailed, 'file.closed should be false'
Neal Norwitz653d85f2002-01-01 19:11:13 +0000157
Neal Norwitz62f5a9d2002-04-01 00:09:00 +0000158try:
159 f.readinto("")
160except TypeError:
161 pass
162else:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000163 raise TestFailed, 'file.readinto("") should raise a TypeError'
Neal Norwitz62f5a9d2002-04-01 00:09:00 +0000164
Neal Norwitz653d85f2002-01-01 19:11:13 +0000165f.close()
166if not f.closed:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000167 raise TestFailed, 'file.closed should be true'
Neal Norwitz653d85f2002-01-01 19:11:13 +0000168
Andrew MacIntyre4e10ed32004-04-04 07:01:35 +0000169# make sure that explicitly setting the buffer size doesn't cause
170# misbehaviour especially with repeated close() calls
171for s in (-1, 0, 1, 512):
172 try:
173 f = open(TESTFN, 'w', s)
174 f.write(str(s))
175 f.close()
176 f.close()
177 f = open(TESTFN, 'r', s)
178 d = int(f.read())
179 f.close()
180 f.close()
181 except IOError, msg:
182 raise TestFailed, 'error setting buffer size %d: %s' % (s, str(msg))
183 if d != s:
184 raise TestFailed, 'readback failure using buffer size %d'
185
Guido van Rossum3c668c12002-08-06 15:58:24 +0000186methods = ['fileno', 'flush', 'isatty', 'next', 'read', 'readinto',
187 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write',
188 'xreadlines', '__iter__']
Martin v. Löwisf90ae202002-06-11 06:22:31 +0000189if sys.platform.startswith('atheos'):
190 methods.remove('truncate')
191
192for methodname in methods:
Neal Norwitz653d85f2002-01-01 19:11:13 +0000193 method = getattr(f, methodname)
194 try:
195 method()
196 except ValueError:
197 pass
198 else:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000199 raise TestFailed, 'file.%s() on a closed file should raise a ValueError' % methodname
Neal Norwitz653d85f2002-01-01 19:11:13 +0000200
201try:
202 f.writelines([])
203except ValueError:
204 pass
205else:
Neal Norwitzb1295da2002-04-01 18:59:20 +0000206 raise TestFailed, 'file.writelines([]) on a closed file should raise a ValueError'
Neal Norwitz653d85f2002-01-01 19:11:13 +0000207
Fred Drake2ec80fa2000-10-23 16:59:35 +0000208os.unlink(TESTFN)
Tim Petersf1827cf2003-09-07 03:30:18 +0000209
210def bug801631():
211 # SF bug <http://www.python.org/sf/801631>
212 # "file.truncate fault on windows"
213 f = file(TESTFN, 'wb')
214 f.write('12345678901') # 11 bytes
215 f.close()
216
217 f = file(TESTFN,'rb+')
218 data = f.read(5)
219 if data != '12345':
220 raise TestFailed("Read on file opened for update failed %r" % data)
221 if f.tell() != 5:
222 raise TestFailed("File pos after read wrong %d" % f.tell())
223
224 f.truncate()
225 if f.tell() != 5:
226 raise TestFailed("File pos after ftruncate wrong %d" % f.tell())
227
228 f.close()
229 size = os.path.getsize(TESTFN)
230 if size != 5:
231 raise TestFailed("File size after ftruncate wrong %d" % size)
232
233try:
234 bug801631()
235finally:
236 os.unlink(TESTFN)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000237
238# Test the complex interaction when mixing file-iteration and the various
239# read* methods. Ostensibly, the mixture could just be tested to work
240# when it should work according to the Python language, instead of fail
241# when it should fail according to the current CPython implementation.
242# People don't always program Python the way they should, though, and the
243# implemenation might change in subtle ways, so we explicitly test for
244# errors, too; the test will just have to be updated when the
245# implementation changes.
246dataoffset = 16384
247filler = "ham\n"
248assert not dataoffset % len(filler), \
249 "dataoffset must be multiple of len(filler)"
250nchunks = dataoffset // len(filler)
251testlines = [
252 "spam, spam and eggs\n",
253 "eggs, spam, ham and spam\n",
254 "saussages, spam, spam and eggs\n",
255 "spam, ham, spam and eggs\n",
256 "spam, spam, spam, spam, spam, ham, spam\n",
257 "wonderful spaaaaaam.\n"
258]
259methods = [("readline", ()), ("read", ()), ("readlines", ()),
260 ("readinto", (array("c", " "*100),))]
261
262try:
263 # Prepare the testfile
264 bag = open(TESTFN, "w")
265 bag.write(filler * nchunks)
266 bag.writelines(testlines)
267 bag.close()
268 # Test for appropriate errors mixing read* and iteration
269 for methodname, args in methods:
270 f = open(TESTFN)
271 if f.next() != filler:
272 raise TestFailed, "Broken testfile"
273 meth = getattr(f, methodname)
274 try:
275 meth(*args)
276 except ValueError:
277 pass
278 else:
279 raise TestFailed("%s%r after next() didn't raise ValueError" %
280 (methodname, args))
281 f.close()
282
283 # Test to see if harmless (by accident) mixing of read* and iteration
284 # still works. This depends on the size of the internal iteration
285 # buffer (currently 8192,) but we can test it in a flexible manner.
286 # Each line in the bag o' ham is 4 bytes ("h", "a", "m", "\n"), so
287 # 4096 lines of that should get us exactly on the buffer boundary for
288 # any power-of-2 buffersize between 4 and 16384 (inclusive).
289 f = open(TESTFN)
290 for i in range(nchunks):
291 f.next()
292 testline = testlines.pop(0)
293 try:
294 line = f.readline()
295 except ValueError:
296 raise TestFailed("readline() after next() with supposedly empty "
297 "iteration-buffer failed anyway")
298 if line != testline:
299 raise TestFailed("readline() after next() with empty buffer "
300 "failed. Got %r, expected %r" % (line, testline))
301 testline = testlines.pop(0)
302 buf = array("c", "\x00" * len(testline))
303 try:
304 f.readinto(buf)
305 except ValueError:
306 raise TestFailed("readinto() after next() with supposedly empty "
307 "iteration-buffer failed anyway")
308 line = buf.tostring()
309 if line != testline:
310 raise TestFailed("readinto() after next() with empty buffer "
311 "failed. Got %r, expected %r" % (line, testline))
312
313 testline = testlines.pop(0)
314 try:
315 line = f.read(len(testline))
316 except ValueError:
317 raise TestFailed("read() after next() with supposedly empty "
318 "iteration-buffer failed anyway")
319 if line != testline:
320 raise TestFailed("read() after next() with empty buffer "
321 "failed. Got %r, expected %r" % (line, testline))
322 try:
323 lines = f.readlines()
324 except ValueError:
325 raise TestFailed("readlines() after next() with supposedly empty "
326 "iteration-buffer failed anyway")
327 if lines != testlines:
328 raise TestFailed("readlines() after next() with empty buffer "
329 "failed. Got %r, expected %r" % (line, testline))
330 # Reading after iteration hit EOF shouldn't hurt either
331 f = open(TESTFN)
Thomas Woutersc45251a2006-02-12 11:53:32 +0000332 try:
Tim Peterscffcfed2006-02-14 17:41:18 +0000333 for line in f:
334 pass
335 try:
336 f.readline()
337 f.readinto(buf)
338 f.read()
339 f.readlines()
340 except ValueError:
341 raise TestFailed("read* failed after next() consumed file")
342 finally:
343 f.close()
Thomas Woutersc45251a2006-02-12 11:53:32 +0000344finally:
Tim Peterscffcfed2006-02-14 17:41:18 +0000345 os.unlink(TESTFN)