1 # Adapted from test_file.py by Daniel Stutzbach
3 from __future__
import unicode_literals
9 from array
import array
10 from weakref
import proxy
11 from functools
import wraps
13 from test
.test_support
import TESTFN
, check_warnings
, run_unittest
, make_bad_fd
14 from test
.test_support
import py3k_bytes
as bytes
15 from test
.script_helper
import run_python
17 from _io
import FileIO
as _FileIO
19 class AutoFileTests(unittest
.TestCase
):
20 # file tests for which a test file is automatically set up
23 self
.f
= _FileIO(TESTFN
, 'w')
30 def testWeakRefs(self
):
31 # verify weak references
33 p
.write(bytes(range(10)))
34 self
.assertEquals(self
.f
.tell(), p
.tell())
37 self
.assertRaises(ReferenceError, getattr, p
, 'tell')
39 def testSeekTell(self
):
40 self
.f
.write(bytes(range(20)))
41 self
.assertEquals(self
.f
.tell(), 20)
43 self
.assertEquals(self
.f
.tell(), 0)
45 self
.assertEquals(self
.f
.tell(), 10)
47 self
.assertEquals(self
.f
.tell(), 15)
49 self
.assertEquals(self
.f
.tell(), 10)
51 self
.assertEquals(self
.f
.tell(), 15)
53 def testAttributes(self
):
54 # verify expected attributes exist
57 self
.assertEquals(f
.mode
, "wb")
58 self
.assertEquals(f
.closed
, False)
60 # verify the attributes are readonly
61 for attr
in 'mode', 'closed':
62 self
.assertRaises((AttributeError, TypeError),
63 setattr, f
, attr
, 'oops')
65 def testReadinto(self
):
67 self
.f
.write(b
"\x01\x02")
69 a
= array(b
'b', b
'x'*10)
70 self
.f
= _FileIO(TESTFN
, 'r')
71 n
= self
.f
.readinto(a
)
72 self
.assertEquals(array(b
'b', [1, 2]), a
[:n
])
74 def test_none_args(self
):
75 self
.f
.write(b
"hi\nbye\nabc")
77 self
.f
= _FileIO(TESTFN
, 'r')
78 self
.assertEqual(self
.f
.read(None), b
"hi\nbye\nabc")
80 self
.assertEqual(self
.f
.readline(None), b
"hi\n")
81 self
.assertEqual(self
.f
.readlines(None), [b
"bye\n", b
"abc"])
84 self
.assertEquals(repr(self
.f
), "<_io.FileIO name=%r mode='%s'>"
85 % (self
.f
.name
, self
.f
.mode
))
87 self
.assertEquals(repr(self
.f
), "<_io.FileIO fd=%r mode='%s'>"
88 % (self
.f
.fileno(), self
.f
.mode
))
90 self
.assertEquals(repr(self
.f
), "<_io.FileIO [closed]>")
94 self
.assertTrue(not f
.isatty())
95 self
.assertTrue(not f
.closed
)
96 #self.assertEquals(f.name, TESTFN)
97 self
.assertRaises(ValueError, f
.read
, 10) # Open for reading
99 self
.assertTrue(f
.closed
)
100 f
= _FileIO(TESTFN
, 'r')
101 self
.assertRaises(TypeError, f
.readinto
, "")
102 self
.assertTrue(not f
.closed
)
104 self
.assertTrue(f
.closed
)
106 def testMethods(self
):
107 methods
= ['fileno', 'isatty', 'read', 'readinto',
108 'seek', 'tell', 'truncate', 'write', 'seekable',
109 'readable', 'writable']
110 if sys
.platform
.startswith('atheos'):
111 methods
.remove('truncate')
114 self
.assertTrue(self
.f
.closed
)
116 for methodname
in methods
:
117 method
= getattr(self
.f
, methodname
)
118 # should raise on closed file
119 self
.assertRaises(ValueError, method
)
121 def testOpendir(self
):
122 # Issue 3703: opening a directory should fill the errno
123 # Windows always returns "[Errno 13]: Permission denied
124 # Unix calls dircheck() and returns "[Errno 21]: Is a directory"
128 self
.assertNotEqual(e
.errno
, 0)
129 self
.assertEqual(e
.filename
, ".")
131 self
.fail("Should have raised IOError")
133 #A set of functions testing that we get expected behaviour if someone has
134 #manually closed the internal file descriptor. First, a decorator:
138 #forcibly close the fd before invoking the problem function
150 def ClosedFDRaises(func
):
153 #forcibly close the fd before invoking the problem function
159 self
.assertEqual(e
.errno
, errno
.EBADF
)
161 self
.fail("Should have raised IOError")
170 def testErrnoOnClose(self
, f
):
174 def testErrnoOnClosedWrite(self
, f
):
178 def testErrnoOnClosedSeek(self
, f
):
182 def testErrnoOnClosedTell(self
, f
):
186 def testErrnoOnClosedTruncate(self
, f
):
190 def testErrnoOnClosedSeekable(self
, f
):
194 def testErrnoOnClosedReadable(self
, f
):
198 def testErrnoOnClosedWritable(self
, f
):
202 def testErrnoOnClosedFileno(self
, f
):
206 def testErrnoOnClosedIsatty(self
, f
):
207 self
.assertEqual(f
.isatty(), False)
209 def ReopenForRead(self
):
214 self
.f
= _FileIO(TESTFN
, 'r')
215 os
.close(self
.f
.fileno())
219 def testErrnoOnClosedRead(self
, f
):
220 f
= self
.ReopenForRead()
224 def testErrnoOnClosedReadall(self
, f
):
225 f
= self
.ReopenForRead()
229 def testErrnoOnClosedReadinto(self
, f
):
230 f
= self
.ReopenForRead()
231 a
= array(b
'b', b
'x'*10)
234 class OtherFileTests(unittest
.TestCase
):
238 f
= _FileIO(TESTFN
, "w")
239 self
.assertEquals(f
.readable(), False)
240 self
.assertEquals(f
.writable(), True)
241 self
.assertEquals(f
.seekable(), True)
244 f
= _FileIO(TESTFN
, "r")
245 self
.assertEquals(f
.readable(), True)
246 self
.assertEquals(f
.writable(), False)
247 self
.assertEquals(f
.seekable(), True)
250 f
= _FileIO(TESTFN
, "a+")
251 self
.assertEquals(f
.readable(), True)
252 self
.assertEquals(f
.writable(), True)
253 self
.assertEquals(f
.seekable(), True)
254 self
.assertEquals(f
.isatty(), False)
257 if sys
.platform
!= "win32":
259 f
= _FileIO("/dev/tty", "a")
260 except EnvironmentError:
261 # When run in a cron job there just aren't any
262 # ttys, so skip the test. This also handles other
263 # OS'es that don't support /dev/tty.
266 f
= _FileIO("/dev/tty", "a")
267 self
.assertEquals(f
.readable(), False)
268 self
.assertEquals(f
.writable(), True)
269 if sys
.platform
!= "darwin" and \
270 'bsd' not in sys
.platform
and \
271 not sys
.platform
.startswith('sunos'):
272 # Somehow /dev/tty appears seekable on some BSDs
273 self
.assertEquals(f
.seekable(), False)
274 self
.assertEquals(f
.isatty(), True)
279 def testModeStrings(self
):
280 # check invalid mode strings
281 for mode
in ("", "aU", "wU+", "rw", "rt"):
283 f
= _FileIO(TESTFN
, mode
)
288 self
.fail('%r is an invalid file mode' % mode
)
290 def testUnicodeOpen(self
):
291 # verify repr works for unicode too
292 f
= _FileIO(str(TESTFN
), "w")
296 def testBytesOpen(self
):
297 # Opening a bytes filename
299 fn
= TESTFN
.encode("ascii")
300 except UnicodeEncodeError:
307 with
open(TESTFN
, "rb") as f
:
308 self
.assertEquals(f
.read(), b
"abc")
312 def testInvalidFd(self
):
313 self
.assertRaises(ValueError, _FileIO
, -10)
314 self
.assertRaises(OSError, _FileIO
, make_bad_fd())
316 def testBadModeArgument(self
):
317 # verify that we get a sensible error message for bad mode argument
320 f
= _FileIO(TESTFN
, bad_mode
)
321 except ValueError as msg
:
324 if TESTFN
in s
or bad_mode
not in s
:
325 self
.fail("bad error message for invalid mode: %s" % s
)
326 # if msg.args[0] == 0, we're probably on Windows where there may be
327 # no obvious way to discover why open() failed.
330 self
.fail("no error for invalid mode: %s" % bad_mode
)
332 def testTruncate(self
):
333 f
= _FileIO(TESTFN
, 'w')
334 f
.write(bytes(bytearray(range(10))))
335 self
.assertEqual(f
.tell(), 10)
337 self
.assertEqual(f
.tell(), 10)
338 self
.assertEqual(f
.seek(0, os
.SEEK_END
), 5)
340 self
.assertEqual(f
.tell(), 5)
341 self
.assertEqual(f
.seek(0, os
.SEEK_END
), 15)
343 def testTruncateOnWindows(self
):
345 # SF bug <http://www.python.org/sf/801631>
346 # "file.truncate fault on windows"
347 f
= _FileIO(TESTFN
, 'w')
348 f
.write(bytes(range(11)))
351 f
= _FileIO(TESTFN
,'r+')
353 if data
!= bytes(range(5)):
354 self
.fail("Read on file opened for update failed %r" % data
)
356 self
.fail("File pos after read wrong %d" % f
.tell())
360 self
.fail("File pos after ftruncate wrong %d" % f
.tell())
363 size
= os
.path
.getsize(TESTFN
)
365 self
.fail("File size after ftruncate wrong %d" % size
)
372 def testAppend(self
):
374 f
= open(TESTFN
, 'wb')
377 f
= open(TESTFN
, 'ab')
380 f
= open(TESTFN
, 'rb')
383 self
.assertEqual(d
, b
'spameggs')
390 def testInvalidInit(self
):
391 self
.assertRaises(TypeError, _FileIO
, "1", 0, 0)
393 def testWarnings(self
):
394 with
check_warnings(quiet
=True) as w
:
395 self
.assertEqual(w
.warnings
, [])
396 self
.assertRaises(TypeError, _FileIO
, [])
397 self
.assertEqual(w
.warnings
, [])
398 self
.assertRaises(ValueError, _FileIO
, "/some/invalid/name", "rt")
399 self
.assertEqual(w
.warnings
, [])
401 def test_surrogates(self
):
402 # Issue #8438: try to open a filename containing surrogates.
403 # It should either fail because the file doesn't exist or the filename
404 # can't be represented using the filesystem encoding, but not because
405 # of a LookupError for the error handler "surrogateescape".
406 filename
= u
'\udc80.txt'
408 with
_FileIO(filename
):
410 except (UnicodeEncodeError, IOError):
412 # Spawn a separate Python process with a different "file system
413 # default encoding", to exercise this further.
414 env
= dict(os
.environ
)
415 env
[b
'LC_CTYPE'] = b
'C'
416 _
, out
= run_python('-c', 'import _io; _io.FileIO(%r)' % filename
, env
=env
)
417 if ('UnicodeEncodeError' not in out
and
418 'IOError: [Errno 2] No such file or directory' not in out
):
419 self
.fail('Bad output: %r' % out
)
422 # Historically, these tests have been sloppy about removing TESTFN.
423 # So get rid of it no matter what.
425 run_unittest(AutoFileTests
, OtherFileTests
)
427 if os
.path
.exists(TESTFN
):
430 if __name__
== '__main__':