From: <pj...@us...> - 2009-10-24 07:19:11
|
Revision: 6899 http://jython.svn.sourceforge.net/jython/?rev=6899&view=rev Author: pjenvey Date: 2009-10-24 07:19:01 +0000 (Sat, 24 Oct 2009) Log Message: ----------- migrate more over to PosixModule and more lazy imports in posix.py Modified Paths: -------------- trunk/jython/Lib/posix.py trunk/jython/src/org/python/core/Py.java trunk/jython/src/org/python/core/io/FileDescriptors.java trunk/jython/src/org/python/modules/posix/PosixModule.java Modified: trunk/jython/Lib/posix.py =================================================================== --- trunk/jython/Lib/posix.py 2009-10-24 05:46:34 UTC (rev 6898) +++ trunk/jython/Lib/posix.py 2009-10-24 07:19:01 UTC (rev 6899) @@ -11,19 +11,12 @@ import _nt as _posix from _nt import * import errno -import jarray -import stat as _stat import sys -from java.io import File -from org.python.core.io import FileDescriptors, IOBase -from org.python.core.Py import newString as asPyString __all__ = [name for name in _posix.__all__ if not name.startswith('__doc__')] -__all__.extend(['access', 'chdir', 'chmod', 'close', 'fdopen', 'fsync', - 'ftruncate', 'getcwd', 'getcwdu', 'getenv', 'getpid', 'isatty', - 'lseek', 'mkdir', 'popen', 'putenv', 'read', 'remove', - 'rename', 'rmdir', 'system', 'umask', 'unlink', 'unsetenv', - 'urandom', 'utime', 'write']) +__all__.extend(['chmod', 'fsync', 'getenv', 'getpid', 'isatty', 'mkdir', + 'popen', 'putenv', 'remove', 'rename', 'rmdir', 'system', + 'umask', 'unlink', 'unsetenv', 'urandom', 'utime']) _name = _posix.__name__[1:] @@ -33,36 +26,6 @@ # For urandom urandom_source = None -# Lazily loaded path module -_path = None - -def getcwd(): - """getcwd() -> path - - Return a string representing the current working directory. - """ - return asPyString(sys.getCurrentWorkingDir()) - -def getcwdu(): - """getcwd() -> path - - Return a unicode string representing the current working directory. - """ - return sys.getCurrentWorkingDir() - -def chdir(path): - """chdir(path) - - Change the current working directory to the specified path. - """ - global _path - if not _stat.S_ISDIR(stat(path).st_mode): - raise OSError(errno.ENOTDIR, strerror(errno.ENOTDIR), path) - if _path is None: - import os - _path = os.path - sys.setCurrentWorkingDir(_path.realpath(path)) - def chmod(path, mode): """chmod(path, mode) @@ -70,6 +33,7 @@ """ # XXX no error handling for chmod in jna-posix # catch not found errors explicitly here, for now + from java.io import File abs_path = sys.getPath(path) if not File(abs_path).exists(): raise OSError(errno.ENOENT, strerror(errno.ENOENT), path) @@ -83,6 +47,7 @@ The optional parameter is currently ignored. """ # XXX: use _posix_impl.mkdir when we can get the real errno upon failure + from java.io import File fp = File(sys.getPath(path)) if not fp.mkdir(): if fp.isDirectory() or fp.isFile(): @@ -97,6 +62,7 @@ Remove a file (same as unlink(path)). """ + from java.io import File if not File(sys.getPath(path)).delete(): raise OSError(0, "couldn't delete file", path) @@ -107,6 +73,7 @@ Rename a file or directory. """ + from java.io import File if not File(sys.getPath(path)).renameTo(File(sys.getPath(newpath))): raise OSError(0, "couldn't rename file", path) @@ -114,6 +81,7 @@ """rmdir(path) Remove a directory.""" + from java.io import File f = File(sys.getPath(path)) if not f.exists(): raise OSError(errno.ENOENT, strerror(errno.ENOENT), path) @@ -122,34 +90,6 @@ elif not f.delete(): raise OSError(0, "couldn't delete directory", path) -def access(path, mode): - """access(path, mode) -> True if granted, False otherwise - - Use the real uid/gid to test for access to a path. Note that most - operations will use the effective uid/gid, therefore this routine can - be used in a suid/sgid environment to test if the invoking user has the - specified access to the path. The mode argument can be F_OK to test - existence, or the inclusive-OR of R_OK, W_OK, and X_OK. - """ - if not isinstance(mode, (int, long)): - raise TypeError('an integer is required') - - f = File(sys.getPath(path)) - result = True - if not f.exists(): - result = False - if mode & R_OK and not f.canRead(): - result = False - if mode & W_OK and not f.canWrite(): - result = False - if mode & X_OK: - # NOTE: always False without jna-posix stat - try: - result = (stat(path).st_mode & _stat.S_IEXEC) != 0 - except OSError: - result = False - return result - def utime(path, times): """utime(path, (atime, mtime)) utime(path, None) @@ -201,78 +141,6 @@ usec = 0 return floor, usec -def close(fd): - """close(fd) - - Close a file descriptor (for low level IO). - """ - rawio = FileDescriptors.get(fd) - _handle_oserror(rawio.close) - -def fdopen(fd, mode='r', bufsize=-1): - """fdopen(fd [, mode='r' [, bufsize]]) -> file_object - - Return an open file object connected to a file descriptor. - """ - rawio = FileDescriptors.get(fd) - if (len(mode) and mode[0] or '') not in 'rwa': - raise ValueError("invalid file mode '%s'" % mode) - if rawio.closed(): - raise OSError(errno.EBADF, strerror(errno.EBADF)) - - try: - fp = FileDescriptors.wrap(rawio, mode, bufsize) - except IOError: - raise OSError(errno.EINVAL, strerror(errno.EINVAL)) - return fp - -def ftruncate(fd, length): - """ftruncate(fd, length) - - Truncate a file to a specified length. - """ - rawio = FileDescriptors.get(fd) - try: - rawio.truncate(length) - except Exception, e: - raise IOError(errno.EBADF, strerror(errno.EBADF)) - -def lseek(fd, pos, how): - """lseek(fd, pos, how) -> newpos - - Set the current position of a file descriptor. - """ - rawio = FileDescriptors.get(fd) - return _handle_oserror(rawio.seek, pos, how) - -def read(fd, buffersize): - """read(fd, buffersize) -> string - - Read a file descriptor. - """ - from org.python.core.util import StringUtil - rawio = FileDescriptors.get(fd) - buf = _handle_oserror(rawio.read, buffersize) - return asPyString(StringUtil.fromBytes(buf)) - -def write(fd, string): - """write(fd, string) -> byteswritten - - Write a string to a file descriptor. - """ - from java.nio import ByteBuffer - from org.python.core.util import StringUtil - rawio = FileDescriptors.get(fd) - return _handle_oserror(rawio.write, - ByteBuffer.wrap(StringUtil.toBytes(string))) - -def _handle_oserror(func, *args, **kwargs): - """Translate exceptions into OSErrors""" - try: - return func(*args, **kwargs) - except: - raise OSError(errno.EBADF, strerror(errno.EBADF)) - def system(command): """system(command) -> exit_status @@ -442,7 +310,7 @@ """wait() -> (pid, status) Wait for completion of a child process.""" - + import jarray status = jarray.zeros(1, 'i') res_pid = _posix_impl.wait(status) if res_pid == -1: @@ -453,6 +321,7 @@ """waitpid(pid, options) -> (pid, status) Wait for completion of a given child process.""" + import jarray status = jarray.zeros(1, 'i') res_pid = _posix_impl.waitpid(pid, status, options) if res_pid == -1: @@ -481,6 +350,7 @@ def _fsync(fd, metadata): """Internal fsync impl""" + from org.python.core.io import FileDescriptors rawio = FileDescriptors.get(fd) rawio.checkClosed() @@ -524,6 +394,7 @@ if isinstance(fileno, FileDescriptor): return _posix_impl.isatty(fileno) + from org.python.core.io import IOBase if not isinstance(fileno, IOBase): raise TypeError('a file descriptor is required') @@ -540,6 +411,7 @@ if urandom_source is None: from java.security import SecureRandom urandom_source = SecureRandom() + import jarray buffer = jarray.zeros(n, 'b') urandom_source.nextBytes(buffer) return buffer.tostring() Modified: trunk/jython/src/org/python/core/Py.java =================================================================== --- trunk/jython/src/org/python/core/Py.java 2009-10-24 05:46:34 UTC (rev 6898) +++ trunk/jython/src/org/python/core/Py.java 2009-10-24 07:19:01 UTC (rev 6899) @@ -108,6 +108,12 @@ return fromIOException(ioe, Py.OSError); } + public static PyException OSError(Constant errno) { + int value = errno.value(); + PyObject args = new PyTuple(Py.newInteger(value), PosixModule.strerror(value)); + return new PyException(Py.OSError, args); + } + public static PyException OSError(Constant errno, String filename) { int value = errno.value(); // Pass to strerror because constantine currently lacks Errno descriptions on Modified: trunk/jython/src/org/python/core/io/FileDescriptors.java =================================================================== --- trunk/jython/src/org/python/core/io/FileDescriptors.java 2009-10-24 05:46:34 UTC (rev 6898) +++ trunk/jython/src/org/python/core/io/FileDescriptors.java 2009-10-24 07:19:01 UTC (rev 6899) @@ -2,7 +2,6 @@ package org.python.core.io; import org.python.core.Py; -import org.python.core.PyFile; import org.python.core.PyObject; /** @@ -14,10 +13,6 @@ */ public class FileDescriptors { - public static PyFile wrap(RawIOBase raw, String mode, int bufsize) { - return new PyFile(raw, "<fdopen>", mode, bufsize); - } - /** * Return the RawIOBase associated with the specified file descriptor. * Modified: trunk/jython/src/org/python/modules/posix/PosixModule.java =================================================================== --- trunk/jython/src/org/python/modules/posix/PosixModule.java 2009-10-24 05:46:34 UTC (rev 6898) +++ trunk/jython/src/org/python/modules/posix/PosixModule.java 2009-10-24 07:19:01 UTC (rev 6899) @@ -8,6 +8,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; +import java.nio.ByteBuffer; import java.util.Map; import org.jruby.ext.posix.JavaPOSIX; @@ -17,12 +18,18 @@ import org.python.core.ClassDictInit; import org.python.core.Py; import org.python.core.PyDictionary; +import org.python.core.PyException; +import org.python.core.PyFile; import org.python.core.PyList; import org.python.core.PyObject; import org.python.core.PyString; import org.python.core.PyTuple; +import org.python.core.imp; +import org.python.core.io.FileDescriptors; import org.python.core.io.FileIO; +import org.python.core.io.RawIOBase; import org.python.core.util.RelativeFile; +import org.python.core.util.StringUtil; /** * The underlying _posix or _nt module, named depending on the platform. @@ -57,6 +64,15 @@ private static int O_TRUNC = 0x400; private static int O_EXCL = 0x800; + /** os.access constants. */ + private static int F_OK = 0; + private static int X_OK = 1 << 0; + private static int W_OK = 1 << 1; + private static int R_OK = 1 << 2; + + /** os.path.realpath function for use by chdir. Lazily loaded. */ + private static PyObject realpath; + public static void classDictInit(PyObject dict) { // only expose the open flags we support dict.__setitem__("O_RDONLY", Py.newInteger(O_RDONLY)); @@ -68,11 +84,10 @@ dict.__setitem__("O_TRUNC", Py.newInteger(O_TRUNC)); dict.__setitem__("O_EXCL", Py.newInteger(O_EXCL)); - // os.access constants - dict.__setitem__("F_OK", Py.Zero); - dict.__setitem__("X_OK", Py.newInteger(1 << 0)); - dict.__setitem__("W_OK", Py.newInteger(1 << 1)); - dict.__setitem__("R_OK", Py.newInteger(1 << 2)); + dict.__setitem__("F_OK", Py.newInteger(F_OK)); + dict.__setitem__("X_OK", Py.newInteger(X_OK)); + dict.__setitem__("W_OK", Py.newInteger(W_OK)); + dict.__setitem__("R_OK", Py.newInteger(R_OK)); // Successful termination dict.__setitem__("EX_OK", Py.Zero); @@ -86,6 +101,7 @@ dict.__setitem__("classDictInit", null); dict.__setitem__("getPOSIX", null); dict.__setitem__("getOSName", null); + dict.__setitem__("badFD", null); dict.__setitem__("__all__", dict.invoke("keys")); @@ -104,6 +120,129 @@ System.exit(status); } + public static PyString __doc__access = new PyString( + "access(path, mode) -> True if granted, False otherwise\n\n" + + "Use the real uid/gid to test for access to a path. Note that most\n" + + "operations will use the effective uid/gid, therefore this routine can\n" + + "be used in a suid/sgid environment to test if the invoking user has the\n" + + "specified access to the path. The mode argument can be F_OK to test\n" + + "existence, or the inclusive-OR of R_OK, W_OK, and X_OK."); + public static boolean access(String path, int mode) { + boolean result = true; + File file = new RelativeFile(path); + + if (!file.exists()) { + result = false; + } + if ((mode & R_OK) != 0 && !file.canRead()) { + result = false; + } + if ((mode & W_OK) != 0 && !file.canWrite()) { + result = false; + } + if ((mode & X_OK) != 0) { + // NOTE: always true without native jna-posix stat + try { + result = posix.stat(file.getPath()).isExecutable(); + } catch (PyException pye) { + if (!pye.match(Py.OSError)) { + throw pye; + } + // ENOENT + result = false; + } + } + return result; + } + + public static PyString __doc__chdir = new PyString( + "chdir(path)\n\n" + + "Change the current working directory to the specified path."); + public static void chdir(PyObject pathObj) { + if (!(pathObj instanceof PyString)) { + throw Py.TypeError(String.format("coercing to Unicode: need string, '%s' type found", + pathObj.getType().fastGetName())); + } + + String path = pathObj.toString(); + // stat raises ENOENT for us if path doesn't exist + if (!posix.stat(new RelativeFile(path).getPath()).isDirectory()) { + throw Py.OSError(Errno.ENOTDIR, path); + } + + if (realpath == null) { + realpath = imp.load("os.path").__getattr__("realpath"); + } + Py.getSystemState().setCurrentWorkingDir(realpath.__call__(pathObj).toString()); + } + + public static PyString __doc__close = new PyString( + "close(fd)\n\n" + + "Close a file descriptor (for low level IO)."); + public static void close(PyObject fd) { + try { + FileDescriptors.get(fd).close(); + } catch (PyException pye) { + badFD(); + } + } + + public static PyString __doc__fdopen = new PyString( + "fdopen(fd [, mode='r' [, bufsize]]) -> file_object\n\n" + + "Return an open file object connected to a file descriptor."); + public static PyObject fdopen(PyObject fd) { + return fdopen(fd, "r"); + + } + + public static PyObject fdopen(PyObject fd, String mode) { + return fdopen(fd, mode, -1); + + } + public static PyObject fdopen(PyObject fd, String mode, int bufsize) { + if (mode.length() == 0 || !"rwa".contains("" + mode.charAt(0))) { + throw Py.ValueError(String.format("invalid file mode '%s'", mode)); + } + RawIOBase rawIO = FileDescriptors.get(fd); + if (rawIO.closed()) { + badFD(); + } + + try { + return new PyFile(rawIO, "<fdopen>", mode, bufsize); + } catch (PyException pye) { + if (!pye.match(Py.IOError)) { + throw pye; + } + throw Py.OSError(Errno.EINVAL); + } + } + + public static PyString __doc__ftruncate = new PyString( + "ftruncate(fd, length)\n\n" + + "Truncate a file to a specified length."); + public static void ftruncate(PyObject fd, long length) { + try { + FileDescriptors.get(fd).truncate(length); + } catch (PyException pye) { + throw Py.IOError(Errno.EBADF); + } + } + + public static PyString __doc___getcwd = new PyString( + "getcwd() -> path\n\n" + + "Return a string representing the current working directory."); + public static PyObject getcwd() { + return Py.newString(Py.getSystemState().getCurrentWorkingDir()); + } + + public static PyString __doc___getcwdu = new PyString( + "getcwd() -> path\n\n" + + "Return a unicode string representing the current working directory."); + public static PyObject getcwdu() { + return Py.newUnicode(Py.getSystemState().getCurrentWorkingDir()); + } + public static PyString __doc__listdir = new PyString( "listdir(path) -> list_of_strings\n\n" + "Return a list containing the names of the entries in the directory.\n\n" + @@ -123,6 +262,18 @@ return list; } + public static PyString __doc__lseek = new PyString( + "lseek(fd, pos, how) -> newpos\n\n" + + "Set the current position of a file descriptor."); + public static long lseek(PyObject fd, long pos, int how) { + try { + return FileDescriptors.get(fd).seek(pos, how); + } catch (PyException pye) { + badFD(); + return -1; + } + } + public static PyString __doc__lstat = new PyString( "lstat(path) -> stat result\n\n" + "Like stat(path), but do not follow symbolic links."); @@ -134,11 +285,11 @@ "open(filename, flag [, mode=0777]) -> fd\n\n" + "Open a file (for low level IO).\n\n" + "Note that the mode argument is not currently supported on Jython."); - public static PyObject open(String path, int flag) { + public static FileIO open(String path, int flag) { return open(path, flag, 0777); } - public static PyObject open(String path, int flag, int mode) { + public static FileIO open(String path, int flag, int mode) { boolean reading = (flag & O_RDONLY) != 0; boolean writing = (flag & O_WRONLY) != 0; boolean updating = (flag & O_RDWR) != 0; @@ -181,18 +332,26 @@ String fileIOMode = (reading ? "r" : "") + (!appending && writing ? "w" : "") + (appending && (writing || updating) ? "a" : "") + (updating ? "+" : ""); - FileIO fileIO; if (sync && (writing || updating)) { try { - fileIO = new FileIO(new RandomAccessFile(file, "rws").getChannel(), fileIOMode); + return new FileIO(new RandomAccessFile(file, "rws").getChannel(), fileIOMode); } catch (FileNotFoundException fnfe) { throw Py.OSError(file.isDirectory() ? Errno.EISDIR : Errno.ENOENT, path); } - } else { - fileIO = new FileIO(path, fileIOMode); } + return new FileIO(path, fileIOMode); + } - return Py.java2py(fileIO); + public static PyString __doc__read = new PyString( + "read(fd, buffersize) -> string\n\n" + + "Read a file descriptor."); + public static String read(PyObject fd, int buffersize) { + try { + return StringUtil.fromBytes(FileDescriptors.get(fd).read(buffersize)); + } catch (PyException pye) { + badFD(); + return null; + } } public static PyString __doc__stat = new PyString( @@ -221,6 +380,18 @@ return new PyString(errno.toString()); } + public static PyString __doc__write = new PyString( + "write(fd, string) -> byteswritten\n\n" + + "Write a string to a file descriptor."); + public static int write(PyObject fd, String string) { + try { + return FileDescriptors.get(fd).write(ByteBuffer.wrap(StringUtil.toBytes(string))); + } catch (PyException pye) { + badFD(); + return -1; + } + } + /** * Helper function for the subprocess module, returns the potential shell commands for * this OS. @@ -259,6 +430,10 @@ return environ; } + private static void badFD() { + throw Py.OSError(Errno.EBADF); + } + public static POSIX getPOSIX() { return posix; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |