blob: e21e47f9e8853f256c02d2752d53bdc769e76a45 [file] [log] [blame]
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +00001# Adapted from test_file.py by Daniel Stutzbach
Antoine Pitrou19690592009-06-12 20:14:08 +00002
3from __future__ import unicode_literals
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +00004
5import sys
6import os
Antoine Pitrou19690592009-06-12 20:14:08 +00007import errno
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +00008import unittest
9from array import array
10from weakref import proxy
Antoine Pitrou19690592009-06-12 20:14:08 +000011from functools import wraps
Antoine Pitrou78e761e2012-10-16 22:57:11 +020012from UserList import UserList
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000013
Georg Brandla4f46e12010-02-07 17:03:15 +000014from test.test_support import TESTFN, check_warnings, run_unittest, make_bad_fd
Serhiy Storchaka76249ea2014-02-07 10:06:05 +020015from test.test_support import py3k_bytes as bytes, cpython_only
Antoine Pitrou7c587bf2010-04-19 18:52:43 +000016from test.script_helper import run_python
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000017
Antoine Pitrou19690592009-06-12 20:14:08 +000018from _io import FileIO as _FileIO
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000019
20class AutoFileTests(unittest.TestCase):
21 # file tests for which a test file is automatically set up
22
23 def setUp(self):
Antoine Pitrou19690592009-06-12 20:14:08 +000024 self.f = _FileIO(TESTFN, 'w')
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000025
26 def tearDown(self):
27 if self.f:
28 self.f.close()
29 os.remove(TESTFN)
30
31 def testWeakRefs(self):
32 # verify weak references
33 p = proxy(self.f)
34 p.write(bytes(range(10)))
Ezio Melotti2623a372010-11-21 13:34:58 +000035 self.assertEqual(self.f.tell(), p.tell())
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000036 self.f.close()
37 self.f = None
38 self.assertRaises(ReferenceError, getattr, p, 'tell')
39
40 def testSeekTell(self):
Antoine Pitrou19690592009-06-12 20:14:08 +000041 self.f.write(bytes(range(20)))
Ezio Melotti2623a372010-11-21 13:34:58 +000042 self.assertEqual(self.f.tell(), 20)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000043 self.f.seek(0)
Ezio Melotti2623a372010-11-21 13:34:58 +000044 self.assertEqual(self.f.tell(), 0)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000045 self.f.seek(10)
Ezio Melotti2623a372010-11-21 13:34:58 +000046 self.assertEqual(self.f.tell(), 10)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000047 self.f.seek(5, 1)
Ezio Melotti2623a372010-11-21 13:34:58 +000048 self.assertEqual(self.f.tell(), 15)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000049 self.f.seek(-5, 1)
Ezio Melotti2623a372010-11-21 13:34:58 +000050 self.assertEqual(self.f.tell(), 10)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000051 self.f.seek(-5, 2)
Ezio Melotti2623a372010-11-21 13:34:58 +000052 self.assertEqual(self.f.tell(), 15)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000053
54 def testAttributes(self):
55 # verify expected attributes exist
56 f = self.f
57
Ezio Melotti2623a372010-11-21 13:34:58 +000058 self.assertEqual(f.mode, "wb")
59 self.assertEqual(f.closed, False)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000060
61 # verify the attributes are readonly
62 for attr in 'mode', 'closed':
63 self.assertRaises((AttributeError, TypeError),
64 setattr, f, attr, 'oops')
65
66 def testReadinto(self):
67 # verify readinto
Antoine Pitrou19690592009-06-12 20:14:08 +000068 self.f.write(b"\x01\x02")
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000069 self.f.close()
Antoine Pitrou19690592009-06-12 20:14:08 +000070 a = array(b'b', b'x'*10)
71 self.f = _FileIO(TESTFN, 'r')
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000072 n = self.f.readinto(a)
Ezio Melotti2623a372010-11-21 13:34:58 +000073 self.assertEqual(array(b'b', [1, 2]), a[:n])
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +000074
Antoine Pitrou78e761e2012-10-16 22:57:11 +020075 def testWritelinesList(self):
76 l = [b'123', b'456']
77 self.f.writelines(l)
78 self.f.close()
79 self.f = _FileIO(TESTFN, 'rb')
80 buf = self.f.read()
81 self.assertEqual(buf, b'123456')
82
83 def testWritelinesUserList(self):
84 l = UserList([b'123', b'456'])
85 self.f.writelines(l)
86 self.f.close()
87 self.f = _FileIO(TESTFN, 'rb')
88 buf = self.f.read()
89 self.assertEqual(buf, b'123456')
90
91 def testWritelinesError(self):
92 self.assertRaises(TypeError, self.f.writelines, [1, 2, 3])
93 self.assertRaises(TypeError, self.f.writelines, None)
94
Benjamin Petersonddd392c2009-12-13 19:19:07 +000095 def test_none_args(self):
96 self.f.write(b"hi\nbye\nabc")
97 self.f.close()
98 self.f = _FileIO(TESTFN, 'r')
99 self.assertEqual(self.f.read(None), b"hi\nbye\nabc")
100 self.f.seek(0)
101 self.assertEqual(self.f.readline(None), b"hi\n")
102 self.assertEqual(self.f.readlines(None), [b"bye\n", b"abc"])
103
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000104 def testRepr(self):
Ezio Melotti2623a372010-11-21 13:34:58 +0000105 self.assertEqual(repr(self.f), "<_io.FileIO name=%r mode='%s'>"
106 % (self.f.name, self.f.mode))
Antoine Pitrou19690592009-06-12 20:14:08 +0000107 del self.f.name
Ezio Melotti2623a372010-11-21 13:34:58 +0000108 self.assertEqual(repr(self.f), "<_io.FileIO fd=%r mode='%s'>"
109 % (self.f.fileno(), self.f.mode))
Antoine Pitrou19690592009-06-12 20:14:08 +0000110 self.f.close()
Ezio Melotti2623a372010-11-21 13:34:58 +0000111 self.assertEqual(repr(self.f), "<_io.FileIO [closed]>")
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000112
113 def testErrors(self):
114 f = self.f
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000115 self.assertTrue(not f.isatty())
116 self.assertTrue(not f.closed)
Ezio Melotti2623a372010-11-21 13:34:58 +0000117 #self.assertEqual(f.name, TESTFN)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000118 self.assertRaises(ValueError, f.read, 10) # Open for reading
119 f.close()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000120 self.assertTrue(f.closed)
Antoine Pitrou19690592009-06-12 20:14:08 +0000121 f = _FileIO(TESTFN, 'r')
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000122 self.assertRaises(TypeError, f.readinto, "")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000123 self.assertTrue(not f.closed)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000124 f.close()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000125 self.assertTrue(f.closed)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000126
127 def testMethods(self):
Serhiy Storchakaabb7e652015-04-16 11:56:35 +0300128 methods = ['fileno', 'isatty', 'seekable', 'readable', 'writable',
129 'read', 'readall', 'readline', 'readlines',
130 'tell', 'truncate', 'flush']
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000131 if sys.platform.startswith('atheos'):
132 methods.remove('truncate')
133
134 self.f.close()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000135 self.assertTrue(self.f.closed)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000136
137 for methodname in methods:
138 method = getattr(self.f, methodname)
139 # should raise on closed file
140 self.assertRaises(ValueError, method)
141
Serhiy Storchakaabb7e652015-04-16 11:56:35 +0300142 self.assertRaises(ValueError, self.f.readinto) # XXX should be TypeError?
143 self.assertRaises(ValueError, self.f.readinto, bytearray(1))
144 self.assertRaises(ValueError, self.f.seek)
145 self.assertRaises(ValueError, self.f.seek, 0)
146 self.assertRaises(ValueError, self.f.write)
147 self.assertRaises(ValueError, self.f.write, b'')
148 self.assertRaises(TypeError, self.f.writelines)
149 self.assertRaises(ValueError, self.f.writelines, b'')
150
Benjamin Petersonf22c26e2008-09-01 14:13:43 +0000151 def testOpendir(self):
152 # Issue 3703: opening a directory should fill the errno
153 # Windows always returns "[Errno 13]: Permission denied
154 # Unix calls dircheck() and returns "[Errno 21]: Is a directory"
155 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000156 _FileIO('.', 'r')
Benjamin Petersonf22c26e2008-09-01 14:13:43 +0000157 except IOError as e:
158 self.assertNotEqual(e.errno, 0)
Benjamin Peterson7af65562008-12-29 17:56:58 +0000159 self.assertEqual(e.filename, ".")
Benjamin Petersonf22c26e2008-09-01 14:13:43 +0000160 else:
161 self.fail("Should have raised IOError")
162
Antoine Pitrouc2ec9922012-07-06 18:48:24 +0200163 @unittest.skipIf(os.name == 'nt', "test only works on a POSIX-like system")
164 def testOpenDirFD(self):
165 fd = os.open('.', os.O_RDONLY)
166 with self.assertRaises(IOError) as cm:
167 _FileIO(fd, 'r')
168 os.close(fd)
169 self.assertEqual(cm.exception.errno, errno.EISDIR)
170
Antoine Pitrou19690592009-06-12 20:14:08 +0000171 #A set of functions testing that we get expected behaviour if someone has
172 #manually closed the internal file descriptor. First, a decorator:
173 def ClosedFD(func):
174 @wraps(func)
175 def wrapper(self):
176 #forcibly close the fd before invoking the problem function
177 f = self.f
178 os.close(f.fileno())
179 try:
180 func(self, f)
181 finally:
182 try:
183 self.f.close()
184 except IOError:
185 pass
186 return wrapper
187
188 def ClosedFDRaises(func):
189 @wraps(func)
190 def wrapper(self):
191 #forcibly close the fd before invoking the problem function
192 f = self.f
193 os.close(f.fileno())
194 try:
195 func(self, f)
196 except IOError as e:
197 self.assertEqual(e.errno, errno.EBADF)
198 else:
199 self.fail("Should have raised IOError")
200 finally:
201 try:
202 self.f.close()
203 except IOError:
204 pass
205 return wrapper
206
207 @ClosedFDRaises
208 def testErrnoOnClose(self, f):
209 f.close()
210
211 @ClosedFDRaises
212 def testErrnoOnClosedWrite(self, f):
213 f.write('a')
214
215 @ClosedFDRaises
216 def testErrnoOnClosedSeek(self, f):
217 f.seek(0)
218
219 @ClosedFDRaises
220 def testErrnoOnClosedTell(self, f):
221 f.tell()
222
223 @ClosedFDRaises
224 def testErrnoOnClosedTruncate(self, f):
225 f.truncate(0)
226
227 @ClosedFD
228 def testErrnoOnClosedSeekable(self, f):
229 f.seekable()
230
231 @ClosedFD
232 def testErrnoOnClosedReadable(self, f):
233 f.readable()
234
235 @ClosedFD
236 def testErrnoOnClosedWritable(self, f):
237 f.writable()
238
239 @ClosedFD
240 def testErrnoOnClosedFileno(self, f):
241 f.fileno()
242
243 @ClosedFD
244 def testErrnoOnClosedIsatty(self, f):
245 self.assertEqual(f.isatty(), False)
246
247 def ReopenForRead(self):
248 try:
249 self.f.close()
250 except IOError:
251 pass
252 self.f = _FileIO(TESTFN, 'r')
253 os.close(self.f.fileno())
254 return self.f
255
256 @ClosedFDRaises
257 def testErrnoOnClosedRead(self, f):
258 f = self.ReopenForRead()
259 f.read(1)
260
261 @ClosedFDRaises
262 def testErrnoOnClosedReadall(self, f):
263 f = self.ReopenForRead()
264 f.readall()
265
266 @ClosedFDRaises
267 def testErrnoOnClosedReadinto(self, f):
268 f = self.ReopenForRead()
269 a = array(b'b', b'x'*10)
270 f.readinto(a)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000271
272class OtherFileTests(unittest.TestCase):
273
274 def testAbles(self):
275 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000276 f = _FileIO(TESTFN, "w")
Ezio Melotti2623a372010-11-21 13:34:58 +0000277 self.assertEqual(f.readable(), False)
278 self.assertEqual(f.writable(), True)
279 self.assertEqual(f.seekable(), True)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000280 f.close()
281
Antoine Pitrou19690592009-06-12 20:14:08 +0000282 f = _FileIO(TESTFN, "r")
Ezio Melotti2623a372010-11-21 13:34:58 +0000283 self.assertEqual(f.readable(), True)
284 self.assertEqual(f.writable(), False)
285 self.assertEqual(f.seekable(), True)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000286 f.close()
287
Antoine Pitrou19690592009-06-12 20:14:08 +0000288 f = _FileIO(TESTFN, "a+")
Ezio Melotti2623a372010-11-21 13:34:58 +0000289 self.assertEqual(f.readable(), True)
290 self.assertEqual(f.writable(), True)
291 self.assertEqual(f.seekable(), True)
292 self.assertEqual(f.isatty(), False)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000293 f.close()
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000294 finally:
295 os.unlink(TESTFN)
296
Zachary Ware1f702212013-12-10 14:09:20 -0600297 @unittest.skipIf(sys.platform == 'win32', 'no ttys on Windows')
298 def testAblesOnTTY(self):
299 try:
300 f = _FileIO("/dev/tty", "a")
301 except EnvironmentError:
302 # When run in a cron job there just aren't any
303 # ttys, so skip the test. This also handles other
304 # OS'es that don't support /dev/tty.
305 self.skipTest('need /dev/tty')
306 else:
307 self.assertEqual(f.readable(), False)
308 self.assertEqual(f.writable(), True)
309 if sys.platform != "darwin" and \
310 'bsd' not in sys.platform and \
311 not sys.platform.startswith('sunos'):
312 # Somehow /dev/tty appears seekable on some BSDs
313 self.assertEqual(f.seekable(), False)
314 self.assertEqual(f.isatty(), True)
315 f.close()
316
Antoine Pitrou213fec42013-09-04 20:46:33 +0200317 def testInvalidModeStrings(self):
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000318 # check invalid mode strings
Benjamin Petersonbfc51562008-11-22 01:59:15 +0000319 for mode in ("", "aU", "wU+", "rw", "rt"):
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000320 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000321 f = _FileIO(TESTFN, mode)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000322 except ValueError:
323 pass
324 else:
325 f.close()
326 self.fail('%r is an invalid file mode' % mode)
327
Antoine Pitrou213fec42013-09-04 20:46:33 +0200328 def testModeStrings(self):
329 # test that the mode attribute is correct for various mode strings
330 # given as init args
331 try:
332 for modes in [('w', 'wb'), ('wb', 'wb'), ('wb+', 'rb+'),
333 ('w+b', 'rb+'), ('a', 'ab'), ('ab', 'ab'),
334 ('ab+', 'ab+'), ('a+b', 'ab+'), ('r', 'rb'),
335 ('rb', 'rb'), ('rb+', 'rb+'), ('r+b', 'rb+')]:
336 # read modes are last so that TESTFN will exist first
337 with _FileIO(TESTFN, modes[0]) as f:
338 self.assertEqual(f.mode, modes[1])
339 finally:
340 if os.path.exists(TESTFN):
341 os.unlink(TESTFN)
342
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000343 def testUnicodeOpen(self):
344 # verify repr works for unicode too
Antoine Pitrou19690592009-06-12 20:14:08 +0000345 f = _FileIO(str(TESTFN), "w")
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000346 f.close()
347 os.unlink(TESTFN)
348
Antoine Pitrou19690592009-06-12 20:14:08 +0000349 def testBytesOpen(self):
350 # Opening a bytes filename
351 try:
352 fn = TESTFN.encode("ascii")
353 except UnicodeEncodeError:
Zachary Ware1f702212013-12-10 14:09:20 -0600354 self.skipTest('could not encode %r to ascii' % TESTFN)
Antoine Pitrou19690592009-06-12 20:14:08 +0000355 f = _FileIO(fn, "w")
356 try:
357 f.write(b"abc")
358 f.close()
359 with open(TESTFN, "rb") as f:
Ezio Melotti2623a372010-11-21 13:34:58 +0000360 self.assertEqual(f.read(), b"abc")
Antoine Pitrou19690592009-06-12 20:14:08 +0000361 finally:
362 os.unlink(TESTFN)
363
Benjamin Peterson5848d1f2009-01-19 00:08:08 +0000364 def testInvalidFd(self):
Antoine Pitrou19690592009-06-12 20:14:08 +0000365 self.assertRaises(ValueError, _FileIO, -10)
366 self.assertRaises(OSError, _FileIO, make_bad_fd())
Antoine Pitroue6ebcda2010-09-04 21:24:42 +0000367 if sys.platform == 'win32':
368 import msvcrt
369 self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd())
Serhiy Storchaka76249ea2014-02-07 10:06:05 +0200370
371 @cpython_only
372 def testInvalidFd_overflow(self):
Serhiy Storchaka74f49ab2013-01-19 12:55:39 +0200373 # Issue 15989
Serhiy Storchaka76249ea2014-02-07 10:06:05 +0200374 import _testcapi
Serhiy Storchaka74f49ab2013-01-19 12:55:39 +0200375 self.assertRaises(TypeError, _FileIO, _testcapi.INT_MAX + 1)
376 self.assertRaises(TypeError, _FileIO, _testcapi.INT_MIN - 1)
Benjamin Peterson5848d1f2009-01-19 00:08:08 +0000377
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000378 def testBadModeArgument(self):
379 # verify that we get a sensible error message for bad mode argument
380 bad_mode = "qwerty"
381 try:
Antoine Pitrou19690592009-06-12 20:14:08 +0000382 f = _FileIO(TESTFN, bad_mode)
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000383 except ValueError as msg:
384 if msg.args[0] != 0:
385 s = str(msg)
Ezio Melotti187f93d2010-03-17 14:22:34 +0000386 if TESTFN in s or bad_mode not in s:
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000387 self.fail("bad error message for invalid mode: %s" % s)
388 # if msg.args[0] == 0, we're probably on Windows where there may be
389 # no obvious way to discover why open() failed.
390 else:
391 f.close()
392 self.fail("no error for invalid mode: %s" % bad_mode)
393
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000394 def testTruncate(self):
395 f = _FileIO(TESTFN, 'w')
396 f.write(bytes(bytearray(range(10))))
397 self.assertEqual(f.tell(), 10)
398 f.truncate(5)
399 self.assertEqual(f.tell(), 10)
400 self.assertEqual(f.seek(0, os.SEEK_END), 5)
401 f.truncate(15)
402 self.assertEqual(f.tell(), 5)
403 self.assertEqual(f.seek(0, os.SEEK_END), 15)
Antoine Pitrou594a0462010-10-31 13:05:48 +0000404 f.close()
Antoine Pitrouf3fa0742010-01-31 22:26:04 +0000405
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000406 def testTruncateOnWindows(self):
407 def bug801631():
408 # SF bug <http://www.python.org/sf/801631>
409 # "file.truncate fault on windows"
Antoine Pitrou19690592009-06-12 20:14:08 +0000410 f = _FileIO(TESTFN, 'w')
411 f.write(bytes(range(11)))
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000412 f.close()
413
Antoine Pitrou19690592009-06-12 20:14:08 +0000414 f = _FileIO(TESTFN,'r+')
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000415 data = f.read(5)
Antoine Pitrou19690592009-06-12 20:14:08 +0000416 if data != bytes(range(5)):
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000417 self.fail("Read on file opened for update failed %r" % data)
418 if f.tell() != 5:
419 self.fail("File pos after read wrong %d" % f.tell())
420
421 f.truncate()
422 if f.tell() != 5:
423 self.fail("File pos after ftruncate wrong %d" % f.tell())
424
425 f.close()
426 size = os.path.getsize(TESTFN)
427 if size != 5:
428 self.fail("File size after ftruncate wrong %d" % size)
429
430 try:
431 bug801631()
432 finally:
433 os.unlink(TESTFN)
434
435 def testAppend(self):
436 try:
437 f = open(TESTFN, 'wb')
438 f.write(b'spam')
439 f.close()
440 f = open(TESTFN, 'ab')
441 f.write(b'eggs')
442 f.close()
443 f = open(TESTFN, 'rb')
444 d = f.read()
445 f.close()
446 self.assertEqual(d, b'spameggs')
447 finally:
448 try:
449 os.unlink(TESTFN)
450 except:
451 pass
452
Neal Norwitz901e4712008-08-24 22:03:05 +0000453 def testInvalidInit(self):
Antoine Pitrou19690592009-06-12 20:14:08 +0000454 self.assertRaises(TypeError, _FileIO, "1", 0, 0)
Neal Norwitz901e4712008-08-24 22:03:05 +0000455
Benjamin Peterson81e92e52008-11-03 22:34:57 +0000456 def testWarnings(self):
Florent Xicluna6de9e932010-03-07 12:18:33 +0000457 with check_warnings(quiet=True) as w:
Benjamin Peterson81e92e52008-11-03 22:34:57 +0000458 self.assertEqual(w.warnings, [])
Antoine Pitrou19690592009-06-12 20:14:08 +0000459 self.assertRaises(TypeError, _FileIO, [])
Benjamin Peterson81e92e52008-11-03 22:34:57 +0000460 self.assertEqual(w.warnings, [])
Antoine Pitrou19690592009-06-12 20:14:08 +0000461 self.assertRaises(ValueError, _FileIO, "/some/invalid/name", "rt")
Benjamin Peterson81e92e52008-11-03 22:34:57 +0000462 self.assertEqual(w.warnings, [])
463
Antoine Pitrou7c587bf2010-04-19 18:52:43 +0000464 def test_surrogates(self):
465 # Issue #8438: try to open a filename containing surrogates.
466 # It should either fail because the file doesn't exist or the filename
467 # can't be represented using the filesystem encoding, but not because
468 # of a LookupError for the error handler "surrogateescape".
469 filename = u'\udc80.txt'
470 try:
471 with _FileIO(filename):
472 pass
473 except (UnicodeEncodeError, IOError):
474 pass
475 # Spawn a separate Python process with a different "file system
476 # default encoding", to exercise this further.
477 env = dict(os.environ)
478 env[b'LC_CTYPE'] = b'C'
479 _, out = run_python('-c', 'import _io; _io.FileIO(%r)' % filename, env=env)
Ned Deilyaa1e1a22013-02-11 22:10:59 -0800480 if ('UnicodeEncodeError' not in out and not
481 ( ('IOError: [Errno 2] No such file or directory' in out) or
482 ('IOError: [Errno 22] Invalid argument' in out) ) ):
Antoine Pitrou7c587bf2010-04-19 18:52:43 +0000483 self.fail('Bad output: %r' % out)
Neal Norwitz901e4712008-08-24 22:03:05 +0000484
Hynek Schlawack9bd4bf22012-06-21 19:45:19 +0200485 def testUnclosedFDOnException(self):
486 class MyException(Exception): pass
487 class MyFileIO(_FileIO):
488 def __setattr__(self, name, value):
489 if name == "name":
490 raise MyException("blocked setting name")
491 return super(MyFileIO, self).__setattr__(name, value)
492 fd = os.open(__file__, os.O_RDONLY)
493 self.assertRaises(MyException, MyFileIO, fd)
494 os.close(fd) # should not raise OSError(EBADF)
495
Benjamin Peterson0e3a6cf2008-07-18 14:14:41 +0000496def test_main():
497 # Historically, these tests have been sloppy about removing TESTFN.
498 # So get rid of it no matter what.
499 try:
500 run_unittest(AutoFileTests, OtherFileTests)
501 finally:
502 if os.path.exists(TESTFN):
503 os.unlink(TESTFN)
504
505if __name__ == '__main__':
506 test_main()