From: <pj...@us...> - 2009-10-28 02:28:46
|
Revision: 6921 http://jython.svn.sourceforge.net/jython/?rev=6921&view=rev Author: pjenvey Date: 2009-10-28 02:28:34 +0000 (Wed, 28 Oct 2009) Log Message: ----------- o more over to PosixModule, so we don't need the builtin-in function class var workaround for tempfile refs #1396 o bring back the PosixModule method hider with hiding per OS and whether the posix impl is native Modified Paths: -------------- trunk/jython/CPythonLib.includes trunk/jython/Lib/posix.py trunk/jython/Lib/test/test_tempfile.py trunk/jython/src/org/python/modules/posix/PosixModule.java Added Paths: ----------- trunk/jython/src/org/python/modules/posix/Hider.java Removed Paths: ------------- trunk/jython/Lib/tempfile.py Modified: trunk/jython/CPythonLib.includes =================================================================== --- trunk/jython/CPythonLib.includes 2009-10-27 23:54:38 UTC (rev 6920) +++ trunk/jython/CPythonLib.includes 2009-10-28 02:28:34 UTC (rev 6921) @@ -134,6 +134,7 @@ tabnanny.py this.py textwrap.py +tempfile.py token.py tokenize.py trace.py Modified: trunk/jython/Lib/posix.py =================================================================== --- trunk/jython/Lib/posix.py 2009-10-27 23:54:38 UTC (rev 6920) +++ trunk/jython/Lib/posix.py 2009-10-28 02:28:34 UTC (rev 6921) @@ -14,8 +14,8 @@ import sys __all__ = [name for name in _posix.__all__ if not name.startswith('__doc__')] -__all__.extend(['fsync', 'getenv', 'getpid', 'isatty', 'popen', 'putenv', - 'remove', 'rename', 'rmdir', 'system', 'umask', 'unlink', +__all__.extend(['fsync', 'getenv', 'isatty', 'popen', 'putenv', + 'rename', 'rmdir', 'system', 'unsetenv', 'urandom', 'utime']) _name = _posix.__name__[1:] @@ -26,17 +26,6 @@ # For urandom urandom_source = None -def remove(path): - """remove(path) - - 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) - -unlink = remove - def rename(path, newpath): """rename(old, new) @@ -181,13 +170,6 @@ return os.environ.get(key, default) if _name == 'posix': - def link(src, dst): - """link(src, dst) - - Create a hard link to a file. - """ - _posix_impl.link(sys.getPath(src), sys.getPath(dst)) - def symlink(src, dst): """symlink(src, dst) @@ -305,7 +287,7 @@ """ _fsync(fd, False) - __all__.extend(['link', 'symlink', 'readlink', 'getegid', 'geteuid', + __all__.extend(['symlink', 'readlink', 'getegid', 'geteuid', 'getgid', 'getlogin', 'getpgrp', 'getppid', 'getuid', 'setpgrp', 'setsid', 'kill', 'wait', 'waitpid', 'fdatasync']) @@ -334,14 +316,6 @@ except IOException, ioe: raise OSError(ioe) -def getpid(): - """getpid() -> pid - - Return the current process id.""" - # XXX: getpid and umask should really be hidden from __all__ when - # not _native_posix - return _posix_impl.getpid() - def isatty(fileno): """isatty(fd) -> bool @@ -371,12 +345,6 @@ return fileno.isatty() -def umask(new_mask): - """umask(new_mask) -> old_mask - - Set the current numeric umask and return the previous umask.""" - return _posix_impl.umask(int(new_mask)) - def urandom(n): global urandom_source if urandom_source is None: Deleted: trunk/jython/Lib/tempfile.py =================================================================== --- trunk/jython/Lib/tempfile.py 2009-10-27 23:54:38 UTC (rev 6920) +++ trunk/jython/Lib/tempfile.py 2009-10-28 02:28:34 UTC (rev 6921) @@ -1,494 +0,0 @@ -"""Temporary files. - -This module provides generic, low- and high-level interfaces for -creating temporary files and directories. The interfaces listed -as "safe" just below can be used without fear of race conditions. -Those listed as "unsafe" cannot, and are provided for backward -compatibility only. - -This module also provides some data items to the user: - - TMP_MAX - maximum number of names that will be tried before - giving up. - template - the default prefix for all temporary names. - You may change this to control the default prefix. - tempdir - If this is set to a string before the first use of - any routine from this module, it will be considered as - another candidate location to store temporary files. -""" - -__all__ = [ - "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces - "mkstemp", "mkdtemp", # low level safe interfaces - "mktemp", # deprecated unsafe interface - "TMP_MAX", "gettempprefix", # constants - "tempdir", "gettempdir" - ] - - -# Imports. - -import os as _os -import errno as _errno -from random import Random as _Random - -if _os.name == 'mac': - import Carbon.Folder as _Folder - import Carbon.Folders as _Folders - -try: - import fcntl as _fcntl -except ImportError: - def _set_cloexec(fd): - pass -else: - def _set_cloexec(fd): - try: - flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0) - except IOError: - pass - else: - # flags read successfully, modify - flags |= _fcntl.FD_CLOEXEC - _fcntl.fcntl(fd, _fcntl.F_SETFD, flags) - - -try: - import thread as _thread -except ImportError: - import dummy_thread as _thread -_allocate_lock = _thread.allocate_lock - -_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL -if hasattr(_os, 'O_NOINHERIT'): - _text_openflags |= _os.O_NOINHERIT -if hasattr(_os, 'O_NOFOLLOW'): - _text_openflags |= _os.O_NOFOLLOW - -_bin_openflags = _text_openflags -if hasattr(_os, 'O_BINARY'): - _bin_openflags |= _os.O_BINARY - -if hasattr(_os, 'TMP_MAX'): - TMP_MAX = _os.TMP_MAX -else: - TMP_MAX = 10000 - -template = "tmp" - -tempdir = None - -# Internal routines. - -_once_lock = _allocate_lock() - -if hasattr(_os, "lstat"): - _stat = _os.lstat -elif hasattr(_os, "stat"): - _stat = _os.stat -else: - # Fallback. All we need is something that raises os.error if the - # file doesn't exist. - def _stat(fn): - try: - f = open(fn) - except IOError: - raise _os.error - f.close() - -def _exists(fn): - try: - _stat(fn) - except _os.error: - return False - else: - return True - -class _RandomNameSequence: - """An instance of _RandomNameSequence generates an endless - sequence of unpredictable strings which can safely be incorporated - into file names. Each string is six characters long. Multiple - threads can safely use the same instance at the same time. - - _RandomNameSequence is an iterator.""" - - characters = ("abcdefghijklmnopqrstuvwxyz" + - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + - "0123456789-_") - - def __init__(self): - self.mutex = _allocate_lock() - self.rng = _Random() - self.normcase = _os.path.normcase - - def __iter__(self): - return self - - def next(self): - m = self.mutex - c = self.characters - choose = self.rng.choice - - m.acquire() - try: - letters = [choose(c) for dummy in "123456"] - finally: - m.release() - - return self.normcase(''.join(letters)) - -def _candidate_tempdir_list(): - """Generate a list of candidate temporary directories which - _get_default_tempdir will try.""" - - dirlist = [] - - # First, try the environment. - for envname in 'TMPDIR', 'TEMP', 'TMP': - dirname = _os.getenv(envname) - if dirname: dirlist.append(dirname) - - # Failing that, try OS-specific locations. - if _os.name == 'mac': - try: - fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk, - _Folders.kTemporaryFolderType, 1) - dirname = fsr.as_pathname() - dirlist.append(dirname) - except _Folder.error: - pass - elif _os.name == 'riscos': - dirname = _os.getenv('Wimp$ScrapDir') - if dirname: dirlist.append(dirname) - elif _os.name == 'nt': - dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) - else: - dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) - - # As a last resort, the current directory. - try: - dirlist.append(_os.getcwd()) - except (AttributeError, _os.error): - dirlist.append(_os.curdir) - - return dirlist - -def _get_default_tempdir(): - """Calculate the default directory to use for temporary files. - This routine should be called exactly once. - - We determine whether or not a candidate temp dir is usable by - trying to create and write to a file in that directory. If this - is successful, the test file is deleted. To prevent denial of - service, the name of the test file must be randomized.""" - - namer = _RandomNameSequence() - dirlist = _candidate_tempdir_list() - flags = _text_openflags - - for dir in dirlist: - if dir != _os.curdir: - dir = _os.path.normcase(_os.path.abspath(dir)) - # Try only a few names per directory. - for seq in xrange(100): - name = namer.next() - filename = _os.path.join(dir, name) - try: - fd = _os.open(filename, flags, 0600) - fp = _os.fdopen(fd, 'w') - fp.write('blat') - fp.close() - _os.unlink(filename) - del fp, fd - return dir - except (OSError, IOError), e: - if e[0] != _errno.EEXIST: - break # no point trying more names in this directory - pass - raise IOError, (_errno.ENOENT, - ("No usable temporary directory found in %s" % dirlist)) - -_name_sequence = None - -def _get_candidate_names(): - """Common setup sequence for all user-callable interfaces.""" - - global _name_sequence - if _name_sequence is None: - _once_lock.acquire() - try: - if _name_sequence is None: - _name_sequence = _RandomNameSequence() - finally: - _once_lock.release() - return _name_sequence - - -def _mkstemp_inner(dir, pre, suf, flags): - """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile.""" - - names = _get_candidate_names() - - for seq in xrange(TMP_MAX): - name = names.next() - file = _os.path.join(dir, pre + name + suf) - try: - fd = _os.open(file, flags, 0600) - _set_cloexec(fd) - return (fd, _os.path.abspath(file)) - except OSError, e: - if e.errno == _errno.EEXIST: - continue # try again - raise - - raise IOError, (_errno.EEXIST, "No usable temporary file name found") - - -# User visible interfaces. - -def gettempprefix(): - """Accessor for tempdir.template.""" - return template - -tempdir = None - -def gettempdir(): - """Accessor for tempdir.tempdir.""" - global tempdir - if tempdir is None: - _once_lock.acquire() - try: - if tempdir is None: - tempdir = _get_default_tempdir() - finally: - _once_lock.release() - return tempdir - -def mkstemp(suffix="", prefix=template, dir=None, text=False): - """mkstemp([suffix, [prefix, [dir, [text]]]]) - User-callable function to create and return a unique temporary - file. The return value is a pair (fd, name) where fd is the - file descriptor returned by os.open, and name is the filename. - - If 'suffix' is specified, the file name will end with that suffix, - otherwise there will be no suffix. - - If 'prefix' is specified, the file name will begin with that prefix, - otherwise a default prefix is used. - - If 'dir' is specified, the file will be created in that directory, - otherwise a default directory is used. - - If 'text' is specified and true, the file is opened in text - mode. Else (the default) the file is opened in binary mode. On - some operating systems, this makes no difference. - - The file is readable and writable only by the creating user ID. - If the operating system uses permission bits to indicate whether a - file is executable, the file is executable by no one. The file - descriptor is not inherited by children of this process. - - Caller is responsible for deleting the file when done with it. - """ - - if dir is None: - dir = gettempdir() - - if text: - flags = _text_openflags - else: - flags = _bin_openflags - - return _mkstemp_inner(dir, prefix, suffix, flags) - - -def mkdtemp(suffix="", prefix=template, dir=None): - """mkdtemp([suffix, [prefix, [dir]]]) - User-callable function to create and return a unique temporary - directory. The return value is the pathname of the directory. - - Arguments are as for mkstemp, except that the 'text' argument is - not accepted. - - The directory is readable, writable, and searchable only by the - creating user. - - Caller is responsible for deleting the directory when done with it. - """ - - if dir is None: - dir = gettempdir() - - names = _get_candidate_names() - - for seq in xrange(TMP_MAX): - name = names.next() - file = _os.path.join(dir, prefix + name + suffix) - try: - _os.mkdir(file, 0700) - return file - except OSError, e: - if e.errno == _errno.EEXIST: - continue # try again - raise - - raise IOError, (_errno.EEXIST, "No usable temporary directory name found") - -def mktemp(suffix="", prefix=template, dir=None): - """mktemp([suffix, [prefix, [dir]]]) - User-callable function to return a unique temporary file name. The - file is not created. - - Arguments are as for mkstemp, except that the 'text' argument is - not accepted. - - This function is unsafe and should not be used. The file name - refers to a file that did not exist at some point, but by the time - you get around to creating it, someone else may have beaten you to - the punch. - """ - -## from warnings import warn as _warn -## _warn("mktemp is a potential security risk to your program", -## RuntimeWarning, stacklevel=2) - - if dir is None: - dir = gettempdir() - - names = _get_candidate_names() - for seq in xrange(TMP_MAX): - name = names.next() - file = _os.path.join(dir, prefix + name + suffix) - if not _exists(file): - return file - - raise IOError, (_errno.EEXIST, "No usable temporary filename found") - -class _TemporaryFileWrapper: - """Temporary file wrapper - - This class provides a wrapper around files opened for - temporary use. In particular, it seeks to automatically - remove the file when it is no longer needed. - """ - - def __init__(self, file, name): - self.file = file - self.name = name - self.close_called = False - - # XXX: CPython assigns unlink as a class var but this would - # rebind Jython's os.unlink (to be a classmethod) because it's - # not a built-in function (unfortunately built-in functions act - # differently when binding: - # http://mail.python.org/pipermail/python-dev/2003-April/034749.html) - - # Cache the unlinker so we don't get spurious errors at - # shutdown when the module-level "os" is None'd out. Note - # that this must be referenced as self.unlink, because the - # name TemporaryFileWrapper may also get None'd out before - # __del__ is called. - self.unlink = _os.unlink - - def __getattr__(self, name): - # Attribute lookups are delegated to the underlying file - # and cached for non-numeric results - # (i.e. methods are cached, closed and friends are not) - file = self.__dict__['file'] - a = getattr(file, name) - if type(a) != type(0): - setattr(self, name, a) - return a - - # The underlying __enter__ method returns the wrong object - # (self.file) so override it to return the wrapper - def __enter__(self): - self.file.__enter__() - return self - - # NT provides delete-on-close as a primitive, so we don't need - # the wrapper to do anything special. We still use it so that - # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile. - if _os.name != 'nt': - def close(self): - if not self.close_called: - self.close_called = True - self.file.close() - self.unlink(self.name) - - def __del__(self): - self.close() - - # Need to trap __exit__ as well to ensure the file gets - # deleted when used in a with statement - def __exit__(self, exc, value, tb): - result = self.file.__exit__(exc, value, tb) - self.close() - return result - - -def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="", - prefix=template, dir=None): - """Create and return a temporary file. - Arguments: - 'prefix', 'suffix', 'dir' -- as for mkstemp. - 'mode' -- the mode argument to os.fdopen (default "w+b"). - 'bufsize' -- the buffer size argument to os.fdopen (default -1). - The file is created as mkstemp() would do it. - - Returns an object with a file-like interface; the name of the file - is accessible as file.name. The file will be automatically deleted - when it is closed. - """ - - if dir is None: - dir = gettempdir() - - if 'b' in mode: - flags = _bin_openflags - else: - flags = _text_openflags - - # Setting O_TEMPORARY in the flags causes the OS to delete - # the file when it is closed. This is only supported by Windows. - if _os.name == 'nt': - flags |= _os.O_TEMPORARY - - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) - file = _os.fdopen(fd, mode, bufsize) - return _TemporaryFileWrapper(file, name) - -if _os.name != 'posix' or _os.sys.platform == 'cygwin': - # On non-POSIX and Cygwin systems, assume that we cannot unlink a file - # while it is open. - TemporaryFile = NamedTemporaryFile - -else: - def TemporaryFile(mode='w+b', bufsize=-1, suffix="", - prefix=template, dir=None): - """Create and return a temporary file. - Arguments: - 'prefix', 'suffix', 'dir' -- as for mkstemp. - 'mode' -- the mode argument to os.fdopen (default "w+b"). - 'bufsize' -- the buffer size argument to os.fdopen (default -1). - The file is created as mkstemp() would do it. - - Returns an object with a file-like interface. The file has no - name, and will cease to exist when it is closed. - """ - - if dir is None: - dir = gettempdir() - - if 'b' in mode: - flags = _bin_openflags - else: - flags = _text_openflags - - (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags) - try: - _os.unlink(name) - return _os.fdopen(fd, mode, bufsize) - except: - _os.close(fd) - raise Modified: trunk/jython/Lib/test/test_tempfile.py =================================================================== --- trunk/jython/Lib/test/test_tempfile.py 2009-10-27 23:54:38 UTC (rev 6920) +++ trunk/jython/Lib/test/test_tempfile.py 2009-10-28 02:28:34 UTC (rev 6921) @@ -208,18 +208,13 @@ class mkstemped: _bflags = tempfile._bin_openflags _tflags = tempfile._text_openflags + _close = os.close + _unlink = os.unlink def __init__(self, dir, pre, suf, bin): if bin: flags = self._bflags else: flags = self._tflags - # XXX: CPython assigns _close/_unlink as class vars but this - # would rebind Jython's close/unlink (to be classmethods) - # because they're not built-in functions (unfortunately - # built-in functions act differently when binding: - # http://mail.python.org/pipermail/python-dev/2003-April/034749.html) - self._close = os.close - self._unlink = os.unlink (self.fd, self.name) = tempfile._mkstemp_inner(dir, pre, suf, flags) def write(self, str): @@ -494,7 +489,7 @@ # mkdtemp creates directories with the proper mode if not has_stat: return # ugh, can't use TestSkipped. - if os.name == 'java': + if sys.platform.startswith('java') and not os._native_posix: # Java doesn't support stating files for permissions return @@ -529,13 +524,10 @@ self.dir = None class mktemped: + _unlink = os.unlink _bflags = tempfile._bin_openflags def __init__(self, dir, pre, suf): - # XXX: Assign _unlink here, instead of as a class var. See - # mkstemped.__init__ for an explanation - self._unlink = os.unlink - self.name = tempfile.mktemp(dir=dir, prefix=pre, suffix=suf) # Create the file. This will raise an exception if it's # mysteriously appeared in the meanwhile. @@ -704,5 +696,5 @@ test_main() # XXX: Nudge Java's GC in an attempt to trigger any temp file's # __del__ (cause them to be deleted) that hasn't been called - from java.lang import System - System.gc() + import gc + gc.collect() Added: trunk/jython/src/org/python/modules/posix/Hider.java =================================================================== --- trunk/jython/src/org/python/modules/posix/Hider.java (rev 0) +++ trunk/jython/src/org/python/modules/posix/Hider.java 2009-10-28 02:28:34 UTC (rev 6921) @@ -0,0 +1,75 @@ +/* Copyright (c) Jython Developers */ +package org.python.modules.posix; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; + +import org.python.core.PyObject; + +/** + * Utility class for hiding PosixModule methods depending on the platform, or whether the + * underlying posix implementation is native. + */ +class Hider { + + /** + * Hide module level functions defined in the PosixModule dict not applicable to this + * OS, identified by the PosixModule.Hide annotation. + * + * @param cls the PosixModule class + * @param dict the PosixModule module dict + * @param os the underlying OS + * @param native whether the underlying posix is native + */ + public static void hideFunctions(Class<?> cls, PyObject dict, OS os, boolean isNative) { + for (Method method: cls.getDeclaredMethods()) { + if (isHidden(method, os, isNative ? PosixImpl.NATIVE : PosixImpl.JAVA)) { + dict.__setitem__(method.getName(), null); + } + } + } + + /** + * Determine if method should be hidden for this OS/PosixImpl. + */ + private static boolean isHidden(Method method, OS os, PosixImpl posixImpl) { + if (method.isAnnotationPresent(Hide.class)) { + Hide hide = method.getAnnotation(Hide.class); + if (hide.posixImpl() != PosixImpl.NOT_APPLICABLE && hide.posixImpl() == posixImpl) { + return true; + } + for (OS hideOS : hide.value()) { + if (os == hideOS) { + return true; + } + } + } + return false; + } +} + +/** + * Tags PosixModule methods as hidden on the specified OS or PosixImpl. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@interface Hide { + + /** Hide method on these OSes. */ + OS[] value() default {}; + + /** + * @Hide(posixImpl = PosixImpl.JAVA) hides the method from Python when the POSIX + * library isn't native. The default NOT_APPLICABLE means the POSIX implementation + * doesn't matter. + */ + PosixImpl posixImpl() default PosixImpl.NOT_APPLICABLE; +} + +/** + * The type of underlying POSIX library implementation (native or not). + */ +enum PosixImpl {NOT_APPLICABLE, NATIVE, JAVA}; Modified: trunk/jython/src/org/python/modules/posix/PosixModule.java =================================================================== --- trunk/jython/src/org/python/modules/posix/PosixModule.java 2009-10-27 23:54:38 UTC (rev 6920) +++ trunk/jython/src/org/python/modules/posix/PosixModule.java 2009-10-28 02:28:34 UTC (rev 6921) @@ -92,13 +92,15 @@ // Successful termination dict.__setitem__("EX_OK", Py.Zero); + boolean nativePosix = !(posix instanceof JavaPOSIX); + dict.__setitem__("_native_posix", Py.newBoolean(nativePosix)); + dict.__setitem__("_posix_impl", Py.java2py(posix)); dict.__setitem__("environ", getEnviron()); dict.__setitem__("error", Py.OSError); dict.__setitem__("stat_result", PyStatResult.TYPE); - dict.__setitem__("_posix_impl", Py.java2py(posix)); - dict.__setitem__("_native_posix", Py.newBoolean(!(posix instanceof JavaPOSIX))); // Hide from Python + Hider.hideFunctions(PosixModule.class, dict, os, nativePosix); dict.__setitem__("classDictInit", null); dict.__setitem__("getPOSIX", null); dict.__setitem__("getOSName", null); @@ -190,6 +192,7 @@ public static PyString __doc__chown = new PyString( "chown(path, uid, gid)\n\n" + "Change the owner and group id of path to the numeric uid and gid."); + @Hide(OS.POSIX) public static void chown(String path, int uid, int gid) { if (posix.chown(absolutePath(path), uid, gid) < 0) { throw errorFromErrno(path); @@ -263,6 +266,22 @@ return Py.newUnicode(Py.getSystemState().getCurrentWorkingDir()); } + public static PyString __doc___getpid = new PyString( + "getpid() -> pid\n\n" + + "Return the current process id"); + @Hide(posixImpl = PosixImpl.JAVA) + public static int getpid() { + return posix.getpid(); + } + + public static PyString __doc__link = new PyString( + "link(src, dst)\n\n" + + "Create a hard link to a file."); + @Hide(OS.NT) + public static void link(String src, String dst) { + posix.link(absolutePath(src), absolutePath(dst)); + } + 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" + @@ -286,7 +305,6 @@ if (!file.canRead()) { throw Py.OSError(Errno.EACCES, path); } - // throw Py.OSError("listdir(): an unknown error occured: " + path); } for (String name : names) { @@ -399,6 +417,13 @@ } } + public static PyString __doc__remove = new PyString( + "remove(path)\n\n" + + "Remove a file (same as unlink(path))."); + public static void remove(String path) { + unlink(path); + } + public static PyString __doc__stat = new PyString( "stat(path) -> stat result\n\n" + "Perform a stat system call on the given path.\n\n" + @@ -425,6 +450,34 @@ return new PyString(errno.toString()); } + public static PyString __doc__umask = new PyString( + "umask(new_mask) -> old_mask\n\n" + + "Set the current numeric umask and return the previous umask."); + @Hide(posixImpl = PosixImpl.JAVA) + public static int umask(int mask) { + return posix.umask(mask); + } + + public static PyString __doc__unlink = new PyString( + "unlink(path)\n\n" + + "Remove a file (same as remove(path))."); + public static void unlink(String path) { + ensurePath(path); + File file = new RelativeFile(path); + if (!file.delete()) { + // Something went wrong, does stat raise an error? + posix.stat(absolutePath(path)); + // It exists, is it a directory, or do we not have permissions? + if (file.isDirectory()) { + throw Py.OSError(Errno.EISDIR, path); + } + if (!file.canWrite()) { + throw Py.OSError(Errno.EPERM, path); + } + throw Py.OSError("unlink(): an unknown error occured: " + path); + } + } + public static PyString __doc__write = new PyString( "write(fd, string) -> byteswritten\n\n" + "Write a string to a file descriptor."); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |