From 03d633f2e763ee062dfad0cc4ecc1feed1bddd74 Mon Sep 17 00:00:00 2001 From: Ed Swartz Date: Tue, 11 Aug 2015 11:11:05 -0500 Subject: [PATCH] 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. --- direct/src/stdpy/file.py | 74 ++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/direct/src/stdpy/file.py b/direct/src/stdpy/file.py index 91cf209b04..25f5b6e1a1 100644 --- a/direct/src/stdpy/file.py +++ b/direct/src/stdpy/file.py @@ -11,6 +11,7 @@ __all__ = [ ] from panda3d import core +import sys import types _vfs = core.VirtualFileSystem.getGlobalPtr() @@ -65,12 +66,27 @@ class file: self.filename = filename 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 + if 'b' in mode and 't' in mode: + raise IOError("can't have text and binary mode at once") + if 'b' in mode: # Strip 'b'. This means a binary file. i = mode.index('b') mode = mode[:i] + mode[i + 1:] 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: # Strip 'U'. We don't use it; universal-newline support @@ -83,61 +99,69 @@ class file: mode = 'r' # Per Python docs, we insist this is true. - assert mode[0] in 'rwa' + modeType = mode[0] + assert modeType in 'rwa' if binary: filename.setBinary() else: filename.setText() - - # Actually open the streams. - if mode == '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 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+': + + # Actually open the streams, taking care to + # ignore unknown chars in the mode string. + # We already asserted that it starts with a mode + # char above, so locate the '+' + if modeType == 'w' and '+' in mode: self.__stream = _vfs.openReadWriteFile(filename, True) if not self.__stream: message = 'Could not open %s for writing' % (filename) - raise IOError, message + raise IOError(message) readMode = True writeMode = True - elif mode == 'a+': + elif modeType == 'a' and '+' in mode: self.__stream = _vfs.openReadAppendFile(filename) if not self.__stream: message = 'Could not open %s for writing' % (filename) - raise IOError, message + raise IOError(message) readMode = True writeMode = True - elif mode == 'r+': + elif modeType == 'r' and '+' in mode: self.__stream = _vfs.openReadWriteFile(filename, False) if not self.__stream: message = 'Could not open %s for writing' % (filename) - raise IOError, message + raise IOError(message) readMode = True writeMode = True + + 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 mode == 'r': + 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) if not self.__stream: if not _vfs.exists(filename): message = 'No such file: %s' % (filename) else: message = 'Could not open %s for reading' % (filename) - raise IOError, message + raise IOError(message) readMode = True + + else: + # should not get here unless there's a bug above + raise IOError("Unhandled mode flags: " + mode) self.__needsVfsClose = True