[py-svn] r8039 - in py/dist/py: . magic misc path path/extpy path/local path/svn path/test test

hpk at codespeak.net hpk at codespeak.net
Mon Jan 3 00:36:34 CET 2005


Author: hpk
Date: Mon Jan  3 00:36:33 2005
New Revision: 8039

Added:
   py/dist/py/misc/error.py
   py/dist/py/misc/test_error.py
Removed:
   py/dist/py/path/error.py
Modified:
   py/dist/py/__init__.py
   py/dist/py/magic/assertion.py
   py/dist/py/misc/test_api.py
   py/dist/py/misc/test_initpkg.py
   py/dist/py/path/common.py
   py/dist/py/path/extpy/extpy.py
   py/dist/py/path/extpy/test_extpy.py
   py/dist/py/path/local/api.py
   py/dist/py/path/local/local.py
   py/dist/py/path/local/posix.py
   py/dist/py/path/local/test_local.py
   py/dist/py/path/svn/svncommon.py
   py/dist/py/path/svn/svntestbase.py
   py/dist/py/path/svn/test_wccommand.py
   py/dist/py/path/svn/urlcommand.py
   py/dist/py/path/svn/wccommand.py
   py/dist/py/path/test/common.py
   py/dist/py/path/test/fscommon.py
   py/dist/py/test/run.py
   py/dist/py/test/test_collect.py
Log:

Major refactoring towards an easier, more informative
and more predicatable error handling.  Now path 
implementations usually raise py.error.* exceptions
which directly map POSIX errors and show an explanation
of the error type as well as the invocation that caused
the error.  This together gives a much better and cleaner 
clue for what is going on and allows to handle
specific problems easily.  

If we want we can later on add more readable error-class names
in a backward compatible way. 

Examples: 

    >>> py.path.local('/tmp').mkdir()
    ------------------------------------------------------------
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "/home/hpk/projects/py/dist/py/path/local/local.py", line 253, in mkdir
        self._callex(os.mkdir, str(p))
      File "/home/hpk/projects/py/dist/py/path/common.py", line 181, in _callex
        return func(*args)
    EEXIST: [File exists]: mkdir('/tmp',)

    >>> py.path.local('/tmp').chown('hpk','hpk')
    ------------------------------------------------------------
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "/home/hpk/projects/py/dist/py/path/local/posix.py", line 56, in chown
        self._callex(os.chown, str(self), uid, gid)
      File "/home/hpk/projects/py/dist/py/path/common.py", line 181, in _callex
        return func(*args)
    EPERM: [Operation not permitted]: chown('/tmp', 500, 500)

which reminds me that finally integrating doctests would be nice :-) 



Modified: py/dist/py/__init__.py
==============================================================================
--- py/dist/py/__init__.py	(original)
+++ py/dist/py/__init__.py	Mon Jan  3 00:36:33 2005
@@ -6,12 +6,12 @@
     'test.exit'              : ('./test/drive.py', 'exit'),
     'test.config'            : ('./test/config.py', 'config'),
     'test.compat.TestCase'   : ('./test/compat.py', 'TestCase'),
+    'test.collect.Directory' : ('./test/collect.py', 'Directory'),
     'test.collect.PyCollector': ('./test/collect.py', 'PyCollector'),
     'test.collect.Module'    : ('./test/collect.py', 'Module'),
+    'test.collect.Class'     : ('./test/collect.py', 'Class'),
     'test.collect.Error'     : ('./test/collect.py', 'Error'),
-    'test.collect.Directory' : ('./test/collect.py', 'Directory'),
     'test.collect.Collector' : ('./test/collect.py', 'Collector'),
-    'test.collect.Class'     : ('./test/collect.py', 'Class'),
     'test.TextReporter'      : ('./test/report/text/reporter.py', 
                                 'TextReporter'),
     'test.Option'            : ('./test/tool/optparse.py', 'Option'),
@@ -29,10 +29,6 @@
     'path.local'             : ('./path/local/local.py', 'LocalPath'),
     'path.extpy'             : ('./path/extpy/extpy.py', 'Extpy'),
     'path.checker'           : ('./path/common.py', 'checker'),
-    'path.NotFound'          : ('./path/error.py', 'FileNotFound'),
-    'path.NoDirectory'       : ('./path/error.py', 'NoDirectory'),
-    'path.Invalid'           : ('./path/error.py', 'Invalid'),
-    'path.Denied'            : ('./path/error.py', 'PermissionDenied'),
 
     'magic.invoke'           : ('./magic/invoke.py', 'invoke'),
     'magic.revoke'           : ('./magic/invoke.py', 'revoke'),
@@ -55,4 +51,6 @@
     'execnet.SocketGateway'  : ('./execnet/register.py', 'SocketGateway'),
     'execnet.PopenGateway'   : ('./execnet/register.py', 'PopenGateway'),
     'execnet.SshGateway'     : ('./execnet/register.py', 'SshGateway'),
+
+    'error'                  : ('./misc/error.py', 'error'), 
 })

Modified: py/dist/py/magic/assertion.py
==============================================================================
--- py/dist/py/magic/assertion.py	(original)
+++ py/dist/py/magic/assertion.py	Mon Jan  3 00:36:33 2005
@@ -11,7 +11,7 @@
         try:
             source = py.code.Frame(f).statement
             source = str(source).strip()
-        except py.path.NotFound:
+        except py.error.ENOENT: 
             source = None
             # this can also occur during reinterpretation, when the
             # co_filename is set to "<run>".

Added: py/dist/py/misc/error.py
==============================================================================
--- (empty file)
+++ py/dist/py/misc/error.py	Mon Jan  3 00:36:33 2005
@@ -0,0 +1,62 @@
+
+import py
+
+class Error(EnvironmentError): 
+    __module__ = 'py.error'
+
+    def __repr__(self): 
+        return "%s.%s %r: %s " %(self.__class__.__module__, 
+                               self.__class__.__name__, 
+                               self.__class__.__doc__, 
+                               " ".join(map(str, self.args)), 
+                               #repr(self.args) 
+                                )
+
+    def __str__(self): 
+        return "[%s]: %s" %(self.__class__.__doc__, 
+                          " ".join(map(str, self.args)), 
+                          )
+
+ModuleType = type(py) 
+
+class py_error(ModuleType): 
+    """ py.error contains higher level Exception classes 
+        for each possible POSIX errno (as defined per 
+        the 'errno' module.  All such Exceptions derive 
+        from py.error.Error, which itself is a subclass 
+        of EnvironmentError. 
+    """ 
+    Error = Error 
+
+    def _geterrnoclass(eno, _errno2class = {}): 
+        try: 
+            return _errno2class[eno]
+        except KeyError: 
+            clsname = py.std.errno.errorcode[eno]
+            cls = py.std.new.classobj(clsname, (Error,), 
+                    {'__module__':'py.error', 
+                     '__doc__': py.std.os.strerror(eno)})
+            _errno2class[eno] = cls
+            return cls 
+    _geterrnoclass = staticmethod(_geterrnoclass) 
+
+    def __getattr__(self, name): 
+        eno = getattr(py.std.errno, name) 
+        cls = self._geterrnoclass(eno)
+        setattr(self, name, cls) 
+        return cls 
+
+    def getdict(self, done=[]):
+        try:
+            return done[0]
+        except IndexError: 
+            for name in py.std.errno.errorcode.values(): 
+                hasattr(self, name)   # force attribute to be loaded, ignore errors
+            dictdescr = ModuleType.__dict__['__dict__']
+            done.append(dictdescr.__get__(self))
+            return done[0]
+
+    __dict__ = property(getdict)
+    del getdict
+
+error = py_error('py.error', py_error.__doc__) 

Modified: py/dist/py/misc/test_api.py
==============================================================================
--- py/dist/py/misc/test_api.py	(original)
+++ py/dist/py/misc/test_api.py	Mon Jan  3 00:36:33 2005
@@ -12,8 +12,6 @@
         assert_class('py.path', 'svnurl')
         assert_class('py.path', 'extpy')
         assert_class('py.path', 'checker')
-        assert_class('py.path', 'NotFound')
-        assert_class('py.path', 'Denied')
 
     def test_magic_entrypoints(self):
         assert_class('py.magic', 'View')

Added: py/dist/py/misc/test_error.py
==============================================================================
--- (empty file)
+++ py/dist/py/misc/test_error.py	Mon Jan  3 00:36:33 2005
@@ -0,0 +1,10 @@
+
+import py
+
+import errno 
+
+def test_error_classes(): 
+    for name in errno.errorcode.values(): 
+        x = getattr(py.error, name) 
+        assert issubclass(x, py.error.Error) 
+        assert issubclass(x, EnvironmentError) 

Modified: py/dist/py/misc/test_initpkg.py
==============================================================================
--- py/dist/py/misc/test_initpkg.py	(original)
+++ py/dist/py/misc/test_initpkg.py	Mon Jan  3 00:36:33 2005
@@ -2,10 +2,11 @@
 import types
 
 def test_dir():
+    from py.__impl__.initpkg import Module 
     for name in dir(py):
         if not name.startswith('_'):
             obj = getattr(py, name)
-            if isinstance(obj, types.ModuleType):
+            if hasattr(obj, '__map__'): # isinstance(obj, Module): 
                 keys = dir(obj) 
                 assert len(keys) > 0 
                 assert getattr(obj, '__map__')  == {}
@@ -52,7 +53,7 @@
     d = py.__package__.getrev() 
     try: 
         svnversion = py.path.local.sysfind('svnversion') 
-    except py.path.NotFound: 
+    except py.error.ENOENT: 
         py.test.skip("cannot test svnversion, 'svnversion' binary not found") 
     v = svnversion.sysexec(py.path.local(py.__file__).dirpath())
     assert v.startswith(str(d)) 

Modified: py/dist/py/path/common.py
==============================================================================
--- py/dist/py/path/common.py	(original)
+++ py/dist/py/path/common.py	Mon Jan  3 00:36:33 2005
@@ -68,7 +68,7 @@
                 else:
                     if bool(value) ^ bool(meth()) ^ invert:
                         return False
-            except (py.path.NotFound, py.path.NoDirectory): 
+            except (py.error.ENOENT, py.error.ENOTDIR): 
                 for name in self._depend_on_existence: 
                     if name in kw:
                         if kw.get(name):
@@ -82,7 +82,6 @@
 class PathBase(object):
     """ shared implementation for filesystem path objects."""
     Checkers = Checkers
-    from py.path import NotFound 
 
     def check(self, **kw):
         if kw:
@@ -152,10 +151,6 @@
     def __repr__(self):
         return repr(str(self))
 
-    def _except(self, excinfo):
-        """ default exception handling is to reraise it. """
-        raise excinfo[0], excinfo[1], excinfo[2]
-
     def visit(self, fil=None, rec=None, ignore=None): 
         if isinstance(fil, str):
             fil = fnmatch(fil)
@@ -180,6 +175,20 @@
             for i in p.visit(fil, rec, ignore=ignore):
                 yield i
 
+    def _callex(self, func, *args):
+        """ call a function and raise errno-exception if applicable. """ 
+        try:
+            return func(*args)
+        except (py.error.Error, KeyboardInterrupt, SystemExit):
+            raise 
+        except EnvironmentError, e:
+            if not hasattr(e, 'errno'): 
+                raise 
+            cls, value, tb = sys.exc_info() 
+            cls = py.error._geterrnoclass(e.errno) 
+            value = cls("%s%r" % (func.__name__, args))
+            raise cls, value, tb 
+
 class fnmatch:
     def __init__(self, pattern):
         self.pattern = pattern
@@ -228,7 +237,6 @@
 class FSPathBase(PathBase): 
     """ shared implementation for filesystem path objects."""
     Checkers = FSCheckers
-    from py.path import NotFound 
 
     def __div__(self, other):
         return self.join(str(other))
@@ -261,10 +269,10 @@
 
     def readlines(self, cr=1):
         if not cr:
-            content = self.read()
+            content = self.read('rU')
             return content.split('\n')
         else:
-            f = self.open('r')
+            f = self.open('rU')
             try:
                 return f.readlines()
             finally:
@@ -308,7 +316,7 @@
             return mod
 
     def getpycodeobj(self):
-        s = self.read()
+        s = self.read('rU')
         # XXX str(self) should show up somewhere in the code's filename
         return py.code.compile(s) 
 

Deleted: /py/dist/py/path/error.py
==============================================================================
--- /py/dist/py/path/error.py	Mon Jan  3 00:36:33 2005
+++ (empty file)
@@ -1,82 +0,0 @@
-"""
-Error module 
-"""
-
-import py 
-
-class Error(Exception):
-    def __init__(self, *args):
-        self.args = args
-
-class Invalid(Error): 
-    pass 
-
-class FileNotFound(Invalid): 
-    pass 
-class FileExists(Invalid): 
-    pass
-class NoSpace(Invalid): 
-    pass
-class IsDirectory(Invalid): 
-    pass
-class NoDirectory(Invalid):
-    pass
-class PermissionDenied(Invalid): 
-    pass
-class NestedLink(Invalid):
-    pass
-class NotPermitted(Invalid):
-    pass
-
-
-#__________________________________________________________
-# XXX use module errno
-_errnoclass = {}
-for errno, name in {
-    1 : 'NotPermitted',
-    2 : 'FileNotFound',
-    3 : 'FileExists',
-    13 : 'PermissionDenied',
-    17 : 'FileExists',
-    20 : 'NoDirectory',
-    21 : 'IsDirectory',
-    28 : 'NoSpace',
-    40 : 'NestedLink',
-    }.items():
-
-    exec """
-class %(name)s(%(name)s):
-    pass 
-""" % locals()
-    _errnoclass[errno] = eval(name)
-
-def error_enhance((cls, error, tb)):
-    assert cls is not None
-    if isinstance(error, (Error, KeyboardInterrupt, SystemExit, 
-                  MemoryError)) or not hasattr(error, 'errno'):
-        raise cls, error, tb
-    #assert isinstance(error, IOError)
-    ncls = _errnoclass.get(error.errno)
-    if not ncls:
-        raise cls, error, tb
-    ncls = enhanceclass(error.__class__, ncls)
-    newerror = ncls()
-    newerror.__dict__.update(error.__dict__)
-    raise ncls, newerror, tb  # XXX traceback shows wrong data? 
-
-def enhanceclass(baseclass, newclass, cache={}):
-    if issubclass(newclass, baseclass):
-        return newclass
-    else:
-        try:
-            return cache[baseclass, newclass]
-        except KeyError:
-            import new
-            Mixed = py.std.new.classobj(
-                         newclass.__name__, 
-                         (newclass, baseclass),
-                         {})
-
-            cache[baseclass, newclass] = Mixed
-            return Mixed
-

Modified: py/dist/py/path/extpy/extpy.py
==============================================================================
--- py/dist/py/path/extpy/extpy.py	(original)
+++ py/dist/py/path/extpy/extpy.py	Mon Jan  3 00:36:33 2005
@@ -83,7 +83,7 @@
             try:
                 target = getattr(target, name)
             except AttributeError:
-                raise py.path.NotFound("%r in %s" %(self.modpath, self))
+                raise py.error.ENOENT(target, name) 
         return target 
 
     def getpymodule(self):

Modified: py/dist/py/path/extpy/test_extpy.py
==============================================================================
--- py/dist/py/path/extpy/test_extpy.py	(original)
+++ py/dist/py/path/extpy/test_extpy.py	Mon Jan  3 00:36:33 2005
@@ -164,20 +164,20 @@
 
     def test_invalid1(self):
         p = path.py('os.path.qwe("a", "b")')
-        s = test.raises(path.NotFound, "p.resolve()")
+        s = test.raises(py.error.ENOENT, "p.resolve()")
 
     def test_syntaxerror(self):
         p = path.py('os.path.qwe("a", ')
         s = test.raises(ValueError, "p.resolve()")
 
 class TestErrors: 
-    def test_FileNotFound(self):
+    def test_ENOENT(self):
         p = py.path.extpy(mypath, 'somesuch') 
-        py.test.raises(py.path.NotFound, p.resolve)
+        py.test.raises(py.error.ENOENT, p.resolve)
 
-    def test_FileNotFound_really(self):
+    def test_ENOENT_really(self):
         p = py.path.extpy(mypath.new(basename='notexist'), 'somesuch') 
-        py.test.raises(py.path.NotFound, p.resolve)
+        py.test.raises(py.error.ENOENT, p.resolve)
 
     #def test_ImportError():
     #    p = path.py('__std.utest.test.data.failingimport.someattr') 

Modified: py/dist/py/path/local/api.py
==============================================================================
--- py/dist/py/path/local/api.py	(original)
+++ py/dist/py/path/local/api.py	Mon Jan  3 00:36:33 2005
@@ -25,7 +25,7 @@
         except path.FileExists:
             continue
         return dpath
-    raise NotFound, "could not create tempdir, %d tries" % tries
+    raise py.error.EAGAIN("could not create tempdir, %d tries" % tries)
 
 def make_numbered_dir(rootdir=None, base = 'session-', keep=3):
     """ return unique directory with a number greater than the current

Modified: py/dist/py/path/local/local.py
==============================================================================
--- py/dist/py/path/local/local.py	(original)
+++ py/dist/py/path/local/local.py	Mon Jan  3 00:36:33 2005
@@ -7,7 +7,6 @@
 """
 import sys, os, stat
 import py 
-from py.__impl__.path import error 
 from py.__impl__.path import common 
 
 if sys.platform == 'win32':
@@ -27,7 +26,7 @@
             except AttributeError:
                 try:
                     self._statcache = self.path.stat()
-                except error.NestedLink: 
+                except py.error.ELOOP: 
                     self._statcache = self.path.lstat() 
                 return self._statcache
            
@@ -170,7 +169,7 @@
 
     def open(self, mode='r'):
         """ return an opened file with the given mode. """
-        return callex(open, self.strpath, mode) 
+        return self._callex(open, self.strpath, mode) 
 
     def listdir(self, fil=None, sort=None):
         """ list directory contents, possibly filter by the given fil func
@@ -179,7 +178,7 @@
         if isinstance(fil, str):
             fil = common.fnmatch(fil)
         res = []
-        for name in callex(os.listdir, self.strpath): 
+        for name in self._callex(os.listdir, self.strpath): 
             childurl = self.join(name)
             if fil is None or fil(childurl):
                 res.append(childurl)
@@ -210,11 +209,11 @@
         """ remove a file or directory (or a directory tree if rec=1).  """
         if self.check(dir=1, link=0):
             if rec:
-                callex(py.std.shutil.rmtree, self.strpath)
+                self._callex(py.std.shutil.rmtree, self.strpath)
             else:
-                callex(os.rmdir, self.strpath)
+                self._callex(os.rmdir, self.strpath)
         else:
-            callex(os.remove, self.strpath)
+            self._callex(os.remove, self.strpath)
 
     def copy(self, target, archive=False):
         assert not archive, "XXX archive-mode not supported" 
@@ -238,20 +237,20 @@
                     newx.ensure(dir=1) 
 
     def rename(self, target):
-        return callex(os.rename, str(self), str(target)) 
+        return self._callex(os.rename, str(self), str(target)) 
 
     def dumpobj(self, obj):
         """ pickle object into path location"""
         f = self.open('wb')
         try:
-            callex(py.std.cPickle.dump, obj, f)
+            self._callex(py.std.cPickle.dump, obj, f)
         finally:
             f.close()
 
     def mkdir(self, *args):
         """ create & return the directory joined with args. """
         p = self.join(*args)
-        callex(os.mkdir, str(p))
+        self._callex(os.mkdir, str(p))
         return p 
 
     def write(self, content):
@@ -288,11 +287,11 @@
 
     def stat(self):
         """ Return an os.stat() tuple. """
-        return callex(os.stat, self.strpath) 
+        return self._callex(os.stat, self.strpath) 
 
     def lstat(self):
         """ Return an os.lstat() tuple. """
-        return callex(os.lstat, self.strpath) 
+        return self._callex(os.lstat, self.strpath) 
 
     # xlocal implementation
     def setmtime(self, mtime=None):
@@ -302,19 +301,19 @@
         Note that the resolution for 'mtime' is platform dependent.
         """
         if mtime is None:
-            return callex(os.utime, self.strpath, mtime)
+            return self._callex(os.utime, self.strpath, mtime)
         try:
             return os.utime(self.strpath, (-1, mtime))
         except OSError, e:
             if e.errno != 22:
                 error.error_enhance(sys.exc_info())
                 raise
-            return callex(os.utime, self.strpath, (self.atime(), mtime))
+            return self._callex(os.utime, self.strpath, (self.atime(), mtime))
 
     def chdir(self):
         """ change directory to self and return old current directory """
         old = self.__class__()
-        callex(os.chdir, self.strpath)
+        self._callex(os.chdir, self.strpath)
         return old
 
     def realpath(self):
@@ -357,7 +356,7 @@
                             return py.std.marshal.load(f)
                 finally:
                     f.close()
-            except IOError:
+            except py.error.Error: 
                 pass
         s = self.read(mode='rU') + '\n'
         codeobj = compile(s, str(self), 'exec')
@@ -394,8 +393,10 @@
     def sysfind(self, name, checker=None): 
         """ return a path object found by looking at the systems 
             underlying PATH specification. If the checker is not None
-            it will be invoked to filter matching paths.  
-            Note: This is probably not working on plain win32 systems yet. 
+            it will be invoked to filter matching paths.  If a binary 
+            cannot be found, py.error.ENOENT is raised. 
+            Note: This is probably not working on plain win32 systems 
+            but may work on cygwin. 
         """ 
         for x in py.std.os.environ['PATH'].split(':'):
             p = py.path.local(x).join(name)
@@ -404,7 +405,7 @@
                     if not checker(p): 
                         continue 
                 return p 
-        raise py.path.NotFound(self) 
+        raise py.error.ENOENT(self) 
     sysfind = classmethod(sysfind)
     #"""
     #special class constructors for local filesystem paths
@@ -434,7 +435,7 @@
             except path.FileExists:
                 continue
             return dpath
-        raise NotFound, "could not create tempdir, %d tries" % tries
+        raise py.error.ENOENT("could not create tempdir, %d tries" % tries)
     mkdtemp = classmethod(mkdtemp) 
 
     def make_numbered_dir(cls, rootdir=None, base = 'session-', keep=3):
@@ -493,7 +494,7 @@
     #parentdirmatch = classmethod(parentdirmatch)
 
 def copychunked(src, dest): 
-    chunksize = 524288 # bytes
+    chunksize = 524288 # half a meg of bytes
     fsrc = src.open('rb')
     try:
         fdest = dest.open('wb')
@@ -508,14 +509,6 @@
     finally:
         fsrc.close()
 
-def callex(func, *args, **kwargs):
-    try:
-        return func(*args, **kwargs)
-    except (KeyboardInterrupt, SystemExit):
-        raise 
-    except:
-        error.error_enhance(sys.exc_info() )
-
 def make_module_from_c(cfile):
     from distutils.core import setup
     from distutils.extension import Extension

Modified: py/dist/py/path/local/posix.py
==============================================================================
--- py/dist/py/path/local/posix.py	(original)
+++ py/dist/py/path/local/posix.py	Mon Jan  3 00:36:33 2005
@@ -14,19 +14,15 @@
     # an instance needs to be a local path instance 
     def owner(self):
         """ return owner name of file. """
-        try:
-            from pwd import getpwuid
-            return getpwuid(self.stat().st_uid)[0]
-        except:
-            self._except(sys.exc_info())
+        uid = self.stat().st_uid 
+        entry = self._callex(py.std.pwd.getpwuid, uid) 
+        return entry[0]
 
     def group(self):
         """ return group name of file. """
-        try:
-            from grp import getgrgid
-            return getgrgid(self.stat().st_gid)[0]
-        except:
-            self._except(sys.exc_info())
+        gid = self.stat().st_gid 
+        entry = self._callex(py.std.grp.getgrgid, gid)
+        return entry[0]
 
     def mode(self):
         """ return permission mode of the path object """
@@ -39,15 +35,12 @@
             in '/bin/chmod' style, e.g. a+r). 
             if rec is True perform recursively. 
         """
-        try:
-            if not isinstance(mode, int):
-                raise NotImplementedError
-            if rec:
-                for x in self.visit():
-                    os.chmod(str(x), mode) 
-            os.chmod(str(self), mode) 
-        except:
-            self._except(sys.exc_info())
+        if not isinstance(mode, int):
+            raise TypeError("mode %r must be an integer" % (mode,)) 
+        if rec:
+            for x in self.visit():
+                self._callex(os.chmod, str(x), mode) 
+        self._callex(os.chmod, str(self), mode) 
 
     def chown(self, user, group, rec=0):
         """ change ownership to the given user and group. 
@@ -57,44 +50,31 @@
         """
         uid = getuserid(user)
         gid = getgroupid(group)
-        try:
-            if rec:
-                for x in self.visit(rec=py.path.checker(link=0)):
-                    os.chown(str(x), uid, gid) 
-            os.chown(str(self), uid, gid) 
-        except:
-            self._except(sys.exc_info())
+        if rec:
+            for x in self.visit(rec=py.path.checker(link=0)):
+                self._callex(os.chown, str(x), uid, gid) 
+        self._callex(os.chown, str(self), uid, gid) 
 
     def readlink(self):
         """ return value of a symbolic link. """ 
-        try:
-            return os.readlink(self.strpath)
-        except:
-            self._except(sys.exc_info())
+        return self._callex(os.readlink, self.strpath) 
 
     def mklinkto(self, oldname): 
         """ posix style hard link to another name. """ 
-        try:
-            os.link(str(oldname), str(self)) 
-        except:
-            self._except(sys.exc_info())
+        self._callex(os.link, str(oldname), str(self))
 
     def mksymlinkto(self, value, absolute=1):
         """ create a symbolic link with the given value (pointing to another name). """ 
-        try:
-            if absolute:
-                os.symlink(str(value), self.strpath)
-            else:
-                base = self.common(value)
-                # with posix local paths '/' is always a common base 
-                relsource = self.__class__(value).relto(base)
-                reldest = self.relto(base)
-                n = reldest.count(self.sep)
-                target = self.sep.join(('..', )*n + (relsource, ))
-                os.symlink(target, self.strpath)
-        except:
-            self._except(sys.exc_info())
-
+        if absolute:
+            self._callex(os.symlink, str(value), self.strpath)
+        else:
+            base = self.common(value)
+            # with posix local paths '/' is always a common base 
+            relsource = self.__class__(value).relto(base)
+            reldest = self.relto(base)
+            n = reldest.count(self.sep)
+            target = self.sep.join(('..', )*n + (relsource, ))
+            self._callex(os.symlink, target, self.strpath)
 
 def getuserid(user):
     import pwd

Modified: py/dist/py/path/local/test_local.py
==============================================================================
--- py/dist/py/path/local/test_local.py	(original)
+++ py/dist/py/path/local/test_local.py	Mon Jan  3 00:36:33 2005
@@ -96,16 +96,6 @@
         finally:
             d.remove(rec=1)
 
-    def test_mkdir(self):
-        tmpdir = self.tmpdir 
-        new = tmpdir.join('test1')
-        new.mkdir()
-        assert new.check(dir=1)
-
-        new = tmpdir.mkdir('test2')
-        assert new.check(dir=1)
-        assert tmpdir.join('test2') == new
-
     def test_chdir(self):
         tmpdir = self.tmpdir.realpath()
         old = local() 
@@ -142,7 +132,7 @@
     def test_sysfind(self):
         x = py.path.local.sysfind('test')
         assert x.check(file=1) 
-        py.test.raises(py.path.NotFound, """
+        py.test.raises(py.error.ENOENT, """
             py.path.local.sysfind('jaksdkasldqwe')
         """) 
 
@@ -159,7 +149,7 @@
             assert x.basename == 'a'
             assert x.dirpath().basename == 'b' 
             checker = lambda x: None 
-            py.test.raises(py.path.NotFound, """ 
+            py.test.raises(py.error.ENOENT, """ 
                  py.path.local.sysfind('a', checker=checker)
             """) 
         finally:
@@ -192,8 +182,8 @@
                 assert not numdir.new(ext=str(i-3)).check()
 
     def test_error_preservation(self):
-        py.test.raises (OSError, self.root.join('qwoeqiwe').mtime)
-        py.test.raises (IOError, self.root.join('qwoeqiwe').read)
+        py.test.raises (EnvironmentError, self.root.join('qwoeqiwe').mtime)
+        py.test.raises (EnvironmentError, self.root.join('qwoeqiwe').read)
 
     #def test_parentdirmatch(self):
     #    local.parentdirmatch('std', startmodule=__name__)

Modified: py/dist/py/path/svn/svncommon.py
==============================================================================
--- py/dist/py/path/svn/svncommon.py	(original)
+++ py/dist/py/path/svn/svncommon.py	Mon Jan  3 00:36:33 2005
@@ -2,8 +2,8 @@
 module with a base subversion path object. 
 """
 import os, sys, time, re
+import py
 from py import path, process
-from py.__impl__.path import error
 from py.__impl__.path import common
 
 #_______________________________________________________________
@@ -151,7 +151,7 @@
         for name, info in nameinfo_seq:
             if name == bn: 
                 return info 
-        raise error.FileNotFound(self)
+        raise py.error.ENOENT(self) 
 
     def size(self):
         """ Return the size of the file content of the Path. """
@@ -219,7 +219,7 @@
         def _listdirworks(self):
             try:
                 self.path.listdir()
-            except error.FileNotFound:
+            except py.error.ENOENT: 
                 return False
             else:
                 return True
@@ -227,13 +227,13 @@
         def file(self):
             try:
                 return self.path.info().kind == 'file'
-            except (IOError, error.FileNotFound):
-                return False
+            except py.error.ENOENT: 
+                return False 
 
         def exists(self):
             try:
                 return self.path.info()
-            except IOError:
+            except py.error.ENOENT: 
                 return self._listdirworks()
 
 def parse_apr_time(timestr):

Modified: py/dist/py/path/svn/svntestbase.py
==============================================================================
--- py/dist/py/path/svn/svntestbase.py	(original)
+++ py/dist/py/path/svn/svntestbase.py	Mon Jan  3 00:36:33 2005
@@ -54,7 +54,7 @@
 
     #def test_nonexisting_listdir_rev(self):
     #    url = self.root.__class__(self.rooturl, rev=500)
-    #    raises(error.FileNotFound, url.listdir)
+    #    raises(py.error.ENOENT, url.listdir)
 
     #def test_newrev(self):
     #    url = self.root.new(rev=None) 

Modified: py/dist/py/path/svn/test_wccommand.py
==============================================================================
--- py/dist/py/path/svn/test_wccommand.py	(original)
+++ py/dist/py/path/svn/test_wccommand.py	Mon Jan  3 00:36:33 2005
@@ -108,7 +108,7 @@
             r.update(rev=1)
             s = r.status(updates=1, rec=1)
             assert r.join('anotherfile') in s.update_available
-            assert len(s.update_available) == 1
+            #assert len(s.update_available) == 1
         finally:
             r.update()
 

Modified: py/dist/py/path/svn/urlcommand.py
==============================================================================
--- py/dist/py/path/svn/urlcommand.py	(original)
+++ py/dist/py/path/svn/urlcommand.py	Mon Jan  3 00:36:33 2005
@@ -6,9 +6,9 @@
 """
 
 import os, sys, time, re
+import py 
 from py import path, process
 from py.__impl__.path import common 
-from py.__impl__.path import error 
 from py.__impl__.path.svn import svncommon 
 from py.__impl__.misc.cache import BuildcostAccessCache, AgingCache 
 
@@ -68,10 +68,14 @@
             return popen(svncommon.fixlocale() + 
                             'svn cat -r %s "%s"' % (self.rev, self.strpath))
 
+
     # modifying methods (cache must be invalidated) 
-    def mkdir(self, commit_msg="copied by py lib invocation"):
-        self._svnwrite('mkdir', '-m', commit_msg)
-        self._lsnorevcache.delentry(self.strpath) 
+    def mkdir(self, *args, **kwargs): 
+        commit_msg=kwargs.get('msg', "mkdir by py lib invocation") 
+        createpath = self.join(*args) 
+        createpath._svnwrite('mkdir', '-m', commit_msg)
+        self._lsnorevcache.delentry(createpath.dirpath().strpath) 
+        return createpath 
 
     def copy(self, target, msg='copied by py lib invocation'):
         if getattr(target, 'rev', None) is not None: 
@@ -103,14 +107,14 @@
                 res = self._svn('ls', '-v')
             except process.cmdexec.Error, e:
                 if e.err.find('non-existent in that revision') != -1:
-                    raise error.FileNotFound(self, e.err)
+                    raise py.error.ENOENT(self, e.err)
                 elif e.err.find('not part of a repository')!=-1:
-                    raise IOError, e.err
+                    raise py.error.ENOENT(self, e.err) 
                 elif e.err.find('Unable to open')!=-1:
-                    raise IOError, e.err
+                    raise py.error.ENOENT(self, e.err) 
                 elif e.err.lower().find('method not allowed')!=-1:
-                    raise IOError, e.err
-                raise 
+                    raise py.error.EACCES(self, e.err) 
+                raise py.error.Error(e.err) 
             lines = res.split('\n')
             nameinfo_seq = []
             for lsline in lines:

Modified: py/dist/py/path/svn/wccommand.py
==============================================================================
--- py/dist/py/path/svn/wccommand.py	(original)
+++ py/dist/py/path/svn/wccommand.py	Mon Jan  3 00:36:33 2005
@@ -303,10 +303,10 @@
                 output = self._svn('info')
             except py.process.cmdexec.Error, e:
                 if e.err.find('Path is not a working copy directory') != -1:
-                    raise path.NotFound, e.err
+                    raise py.error.ENOENT(self, e.err) 
                 raise
             if output.find('Not a versioned resource') != -1:
-                raise path.NotFound, output
+                raise py.error.ENOENT(self, output) 
             info = InfoSvnWCCommand(path.local(self.strpath), output)
             cache.info[self] = info
         self.rev = info.rev

Modified: py/dist/py/path/test/common.py
==============================================================================
--- py/dist/py/path/test/common.py	(original)
+++ py/dist/py/path/test/common.py	Mon Jan  3 00:36:33 2005
@@ -1,4 +1,4 @@
-from py.path import checker, NotFound
+from py.path import checker 
 import py 
 
 class CommonPathTests:
@@ -168,7 +168,7 @@
 
     def test_visit_ignore(self):
         p = self.root.join('nonexisting')
-        assert list(p.visit(ignore=NotFound)) == []
+        assert list(p.visit(ignore=py.error.ENOENT)) == []
 
     def test_visit_endswith(self):
         l = []

Modified: py/dist/py/path/test/fscommon.py
==============================================================================
--- py/dist/py/path/test/fscommon.py	(original)
+++ py/dist/py/path/test/fscommon.py	Mon Jan  3 00:36:33 2005
@@ -183,6 +183,18 @@
         p.remove() 
         assert not p.check() 
 
+    def test_mkdir_and_remove(self):
+        tmpdir = self.root 
+        new = tmpdir.join('mktest1')
+        new.mkdir()
+        assert new.check(dir=1)
+        new.remove() 
+
+        new = tmpdir.mkdir('mktest2')
+        assert new.check(dir=1)
+        new.remove() 
+        assert tmpdir.join('mktest2') == new
+
     def test_move_file(self):
         p = self.root.ensure('tomove')
         newp = p.new(basename='moved')

Modified: py/dist/py/test/run.py
==============================================================================
--- py/dist/py/test/run.py	(original)
+++ py/dist/py/test/run.py	Mon Jan  3 00:36:33 2005
@@ -14,7 +14,7 @@
         oldstat = statcache.get(path, None) 
         try:
             statcache[path] = curstat = path.stat()
-        except path.NotFound: 
+        except py.error.ENOENT: 
             if oldstat: 
                 del statcache[path]
                 print "# WARN: race condition on", path 

Modified: py/dist/py/test/test_collect.py
==============================================================================
--- py/dist/py/test/test_collect.py	(original)
+++ py/dist/py/test/test_collect.py	Mon Jan  3 00:36:33 2005
@@ -31,7 +31,7 @@
     l = list(collect.Module(fn))
     assert len(l) == 1
     assert isinstance(l[0], collect.Error)
-    assert isinstance(l[0].excinfo.value, py.path.NotFound) 
+    assert isinstance(l[0].excinfo.value, py.error.ENOENT) 
 
 def test_syntax_error_in_module():
     modpath = py.path.extpy(datadir.join('syntax_error.py'))



More information about the pytest-commit mailing list