Browse Source

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.
Ed Swartz 10 years ago
parent
commit
03d633f2e7
1 changed files with 47 additions and 23 deletions
  1. 47 23
      direct/src/stdpy/file.py

+ 47 - 23
direct/src/stdpy/file.py

@@ -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,61 +99,69 @@ 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.
-            if mode == 'w':
-                self.__stream = _vfs.openWriteFile(filename, autoUnwrap, True)
+            
+            # 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:
                 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
                 writeMode = True
                 writeMode = True
 
 
-            elif mode == 'a':
-                self.__stream = _vfs.openAppendFile(filename)
+            elif modeType == 'a' and '+' in mode:
+                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
                 writeMode = True
                 writeMode = True
 
 
-            elif mode == 'w+':
-                self.__stream = _vfs.openReadWriteFile(filename, True)
+            elif modeType == 'r' and '+' in mode:
+                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 == 'a+':
-                self.__stream = _vfs.openReadAppendFile(filename)
+                
+            elif modeType == 'w':
+                self.__stream = _vfs.openWriteFile(filename, autoUnwrap, 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
-                readMode = True
+                    raise IOError(message)
                 writeMode = True
                 writeMode = True
 
 
-            elif mode == 'r+':
-                self.__stream = _vfs.openReadWriteFile(filename, False)
+            elif modeType == 'a':
+                self.__stream = _vfs.openAppendFile(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
-                readMode = True
+                    raise IOError(message)
                 writeMode = True
                 writeMode = True
 
 
-            elif mode == 'r':
+            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