For stdpy.file wrapper, handle mode more consistently with Python.

For Python 2, ignore unknown characters in the mode rather than silently failing to open.
For Python 3, fail if unknown characters appear.
This commit is contained in:
Ed Swartz 2015-08-11 11:11:05 -05:00
parent 888efc18af
commit 03d633f2e7

View File

@ -11,6 +11,7 @@ __all__ = [
] ]
from panda3d import core from panda3d import core
import sys
import types import types
_vfs = core.VirtualFileSystem.getGlobalPtr() _vfs = core.VirtualFileSystem.getGlobalPtr()
@ -65,12 +66,27 @@ class file:
self.filename = filename self.filename = filename
self.name = filename.toOsSpecific() self.name = filename.toOsSpecific()
if sys.version_info >= (3, 0):
# Python 3 is much stricter than Python 2, which lets
# unknown flags fall through.
for ch in mode:
if not ch in 'rwxabt+U':
raise IOError("invalid mode: " + mode)
binary = False binary = False
if 'b' in mode and 't' in mode:
raise IOError("can't have text and binary mode at once")
if 'b' in mode: if 'b' in mode:
# Strip 'b'. This means a binary file. # Strip 'b'. This means a binary file.
i = mode.index('b') i = mode.index('b')
mode = mode[:i] + mode[i + 1:] mode = mode[:i] + mode[i + 1:]
binary = True binary = True
elif 't' in mode:
# Strip 't'. This means a text file (redundant, yes).
i = mode.index('t')
mode = mode[:i] + mode[i + 1:]
binary = False
if 'U' in mode: if 'U' in mode:
# Strip 'U'. We don't use it; universal-newline support # Strip 'U'. We don't use it; universal-newline support
@ -83,62 +99,70 @@ class file:
mode = 'r' mode = 'r'
# Per Python docs, we insist this is true. # Per Python docs, we insist this is true.
assert mode[0] in 'rwa' modeType = mode[0]
assert modeType in 'rwa'
if binary: if binary:
filename.setBinary() filename.setBinary()
else: else:
filename.setText() filename.setText()
# Actually open the streams. # Actually open the streams, taking care to
if mode == 'w': # ignore unknown chars in the mode string.
self.__stream = _vfs.openWriteFile(filename, autoUnwrap, True) # We already asserted that it starts with a mode
if not self.__stream: # char above, so locate the '+'
message = 'Could not open %s for writing' % (filename) if modeType == 'w' and '+' in mode:
raise IOError, message
writeMode = True
elif mode == 'a':
self.__stream = _vfs.openAppendFile(filename)
if not self.__stream:
message = 'Could not open %s for writing' % (filename)
raise IOError, message
writeMode = True
elif mode == 'w+':
self.__stream = _vfs.openReadWriteFile(filename, True) self.__stream = _vfs.openReadWriteFile(filename, True)
if not self.__stream: if not self.__stream:
message = 'Could not open %s for writing' % (filename) message = 'Could not open %s for writing' % (filename)
raise IOError, message raise IOError(message)
readMode = True readMode = True
writeMode = True writeMode = True
elif mode == 'a+': elif modeType == 'a' and '+' in mode:
self.__stream = _vfs.openReadAppendFile(filename) self.__stream = _vfs.openReadAppendFile(filename)
if not self.__stream: if not self.__stream:
message = 'Could not open %s for writing' % (filename) message = 'Could not open %s for writing' % (filename)
raise IOError, message raise IOError(message)
readMode = True readMode = True
writeMode = True writeMode = True
elif mode == 'r+': elif modeType == 'r' and '+' in mode:
self.__stream = _vfs.openReadWriteFile(filename, False) self.__stream = _vfs.openReadWriteFile(filename, False)
if not self.__stream: if not self.__stream:
message = 'Could not open %s for writing' % (filename) message = 'Could not open %s for writing' % (filename)
raise IOError, message raise IOError(message)
readMode = True readMode = True
writeMode = True writeMode = True
elif mode == 'r': elif modeType == 'w':
self.__stream = _vfs.openWriteFile(filename, autoUnwrap, True)
if not self.__stream:
message = 'Could not open %s for writing' % (filename)
raise IOError(message)
writeMode = True
elif modeType == 'a':
self.__stream = _vfs.openAppendFile(filename)
if not self.__stream:
message = 'Could not open %s for writing' % (filename)
raise IOError(message)
writeMode = True
elif modeType == 'r':
self.__stream = _vfs.openReadFile(filename, autoUnwrap) self.__stream = _vfs.openReadFile(filename, autoUnwrap)
if not self.__stream: if not self.__stream:
if not _vfs.exists(filename): if not _vfs.exists(filename):
message = 'No such file: %s' % (filename) message = 'No such file: %s' % (filename)
else: else:
message = 'Could not open %s for reading' % (filename) message = 'Could not open %s for reading' % (filename)
raise IOError, message raise IOError(message)
readMode = True readMode = True
else:
# should not get here unless there's a bug above
raise IOError("Unhandled mode flags: " + mode)
self.__needsVfsClose = True self.__needsVfsClose = True
if readMode: if readMode: