diff options
author | holger krekel <holger@merlinux.eu> | 2011-01-18 14:13:31 +0100 |
---|---|---|
committer | holger krekel <holger@merlinux.eu> | 2011-01-18 14:13:31 +0100 |
commit | cd173a7f26ee3df1e038c131a3270036d7f561d0 (patch) | |
tree | 9c7db1502305a2419243f9a8e852c2323f2b1088 /py/_path | |
parent | Fix test_compile_framework_vref on 64-bit. (diff) | |
download | pypy-cd173a7f26ee3df1e038c131a3270036d7f561d0.tar.gz pypy-cd173a7f26ee3df1e038c131a3270036d7f561d0.tar.bz2 pypy-cd173a7f26ee3df1e038c131a3270036d7f561d0.zip |
remove old py copy, add current pytest and py lib snapshots (from pytest-2.0.1dev and py-1.4.1dev)
and some initial tweeks to conftest.py
Diffstat (limited to 'py/_path')
-rw-r--r-- | py/_path/cacheutil.py | 22 | ||||
-rw-r--r-- | py/_path/common.py | 154 | ||||
-rw-r--r-- | py/_path/gateway/__init__.py | 1 | ||||
-rw-r--r-- | py/_path/gateway/channeltest.py | 65 | ||||
-rw-r--r-- | py/_path/gateway/channeltest2.py | 21 | ||||
-rw-r--r-- | py/_path/gateway/remotepath.py | 47 | ||||
-rw-r--r-- | py/_path/local.py | 166 | ||||
-rw-r--r-- | py/_path/svnurl.py | 64 | ||||
-rw-r--r-- | py/_path/svnwc.py | 68 |
9 files changed, 241 insertions, 367 deletions
diff --git a/py/_path/cacheutil.py b/py/_path/cacheutil.py index bac07a9818..9922504750 100644 --- a/py/_path/cacheutil.py +++ b/py/_path/cacheutil.py @@ -1,12 +1,12 @@ """ This module contains multithread-safe cache implementations. -All Caches have +All Caches have - getorbuild(key, builder) - delentry(key) + getorbuild(key, builder) + delentry(key) -methods and allow configuration when instantiating the cache class. +methods and allow configuration when instantiating the cache class. """ from time import time as gettime @@ -24,7 +24,7 @@ class BasicCache(object): def _putentry(self, key, entry): self._prunelowestweight() - self._dict[key] = entry + self._dict[key] = entry def delentry(self, key, raising=False): try: @@ -46,14 +46,14 @@ class BasicCache(object): numentries = len(self._dict) if numentries >= self.maxentries: # evict according to entry's weight - items = [(entry.weight, key) + items = [(entry.weight, key) for key, entry in self._dict.items()] items.sort() index = numentries - self.prunenum if index > 0: for weight, key in items[:index]: # in MT situations the element might be gone - self.delentry(key, raising=False) + self.delentry(key, raising=False) class BuildcostAccessCache(BasicCache): """ A BuildTime/Access-counting cache implementation. @@ -78,7 +78,7 @@ class BuildcostAccessCache(BasicCache): class WeightedCountingEntry(object): def __init__(self, value, oneweight): self._value = value - self.weight = self._oneweight = oneweight + self.weight = self._oneweight = oneweight def value(self): self.weight += self._oneweight @@ -95,8 +95,8 @@ class AgingCache(BasicCache): def _getentry(self, key): entry = self._dict[key] if entry.isexpired(): - self.delentry(key) - raise KeyError(key) + self.delentry(key) + raise KeyError(key) return entry def _build(self, key, builder): @@ -111,4 +111,4 @@ class AgingEntry(object): def isexpired(self): t = gettime() - return t >= self.weight + return t >= self.weight diff --git a/py/_path/common.py b/py/_path/common.py index 15aa80f3cf..42f50295b3 100644 --- a/py/_path/common.py +++ b/py/_path/common.py @@ -36,7 +36,7 @@ class Checkers: return self.path.relto(arg) def fnmatch(self, arg): - return FNMatcher(arg)(self.path) + return self.path.fnmatch(arg) def endswith(self, arg): return str(self.path).endswith(arg) @@ -75,7 +75,7 @@ class Checkers: return False return True -class NeverRaised(Exception): +class NeverRaised(Exception): pass class PathBase(object): @@ -91,6 +91,11 @@ class PathBase(object): return self._getbyspec('basename')[0] basename = property(basename, None, None, basename.__doc__) + def dirname(self): + """ dirname part of path. """ + return self._getbyspec('dirname')[0] + dirname = property(dirname, None, None, dirname.__doc__) + def purebasename(self): """ pure base name of the path.""" return self._getbyspec('purebasename')[0] @@ -143,7 +148,7 @@ newline will be removed from the end of each line. """ def move(self, target): """ move this path to target. """ if target.relto(self): - raise py.error.EINVAL(target, + raise py.error.EINVAL(target, "cannot move path into a subdirectory of itself") try: self.rename(target) @@ -156,27 +161,50 @@ newline will be removed from the end of each line. """ return repr(str(self)) def check(self, **kw): - """ check a path for existence, or query its properties + """ check a path for existence and properties. + + Without arguments, return True if the path exists, otherwise False. - without arguments, this returns True if the path exists (on the - filesystem), False if not + valid checkers:: - with (keyword only) arguments, the object compares the value - of the argument with the value of a property with the same name - (if it has one, else it raises a TypeError) + file=1 # is a file + file=0 # is not a file (may not even exist) + dir=1 # is a dir + link=1 # is a link + exists=1 # exists - when for example the keyword argument 'ext' is '.py', this will - return True if self.ext == '.py', False otherwise + You can specify multiple checker definitions, for example:: + + path.check(file=1, link=1) # a link pointing to a file """ if not kw: kw = {'exists' : 1} return self.Checkers(self)._evaluate(kw) + def fnmatch(self, pattern): + """return true if the basename/fullname matches the glob-'pattern'. + + valid pattern characters:: + + * matches everything + ? matches any single character + [seq] matches any character in seq + [!seq] matches any char not in seq + + If the pattern contains a path-separator then the full path + is used for pattern matching and a '*' is prepended to the + pattern. + + if the pattern doesn't contain a path-separator the pattern + is only matched against the basename. + """ + return FNMatcher(pattern)(self) + def relto(self, relpath): """ return a string which is the relative part of the path - to the given 'relpath'. + to the given 'relpath'. """ - if not isinstance(relpath, (str, PathBase)): + if not isinstance(relpath, (str, PathBase)): raise TypeError("%r: not a string or path object" %(relpath,)) strrelpath = str(relpath) if strrelpath and strrelpath[-1] != self.sep: @@ -187,17 +215,20 @@ newline will be removed from the end of each line. """ if sys.platform == "win32" or getattr(os, '_name', None) == 'nt': if os.path.normcase(strself).startswith( os.path.normcase(strrelpath)): - return strself[len(strrelpath):] + return strself[len(strrelpath):] elif strself.startswith(strrelpath): return strself[len(strrelpath):] return "" - def bestrelpath(self, dest): - """ return a string which is a relative path from self - to dest such that self.join(bestrelpath) == dest and - if not such path can be determined return dest. - """ + def bestrelpath(self, dest): + """ return a string which is a relative path from self + (assumed to be a directory) to dest such that + self.join(bestrelpath) == dest and if not such + path can be determined return dest. + """ try: + if self == dest: + return os.curdir base = self.common(dest) if not base: # can be the case on windows return str(dest) @@ -207,11 +238,11 @@ newline will be removed from the end of each line. """ n = self2base.count(self.sep) + 1 else: n = 0 - l = ['..'] * n + l = [os.pardir] * n if reldest: - l.append(reldest) + l.append(reldest) target = dest.sep.join(l) - return target + return target except AttributeError: return str(dest) @@ -256,11 +287,11 @@ newline will be removed from the end of each line. """ def __lt__(self, other): try: - return self.strpath < other.strpath + return self.strpath < other.strpath except AttributeError: return str(self) < str(other) - def visit(self, fil=None, rec=None, ignore=NeverRaised): + def visit(self, fil=None, rec=None, ignore=NeverRaised, bf=False, sort=False): """ yields all paths below the current one fil is a filter (glob pattern or callable), if not matching the @@ -272,26 +303,14 @@ newline will be removed from the end of each line. """ ignore is an Exception class that is ignoredwhen calling dirlist() on any of the paths (by default, all exceptions are reported) + + bf if True will cause a breadthfirst search instead of the + default depthfirst. Default: False + + sort if True will sort entries within each directory level. """ - if isinstance(fil, str): - fil = FNMatcher(fil) - if rec: - if isinstance(rec, str): - rec = fnmatch(fil) - elif not hasattr(rec, '__call__'): - rec = None - try: - entries = self.listdir() - except ignore: - return - dirs = [p for p in entries - if p.check(dir=1) and (rec is None or rec(p))] - for subdir in dirs: - for p in subdir.visit(fil=fil, rec=rec, ignore=ignore): - yield p - for p in entries: - if fil is None or fil(p): - yield p + for x in Visitor(fil, rec, ignore, bf, sort).gen(self): + yield x def _sortlist(self, res, sort): if sort: @@ -304,24 +323,45 @@ newline will be removed from the end of each line. """ """ return True if other refers to the same stat object as self. """ return self.strpath == str(other) +class Visitor: + def __init__(self, fil, rec, ignore, bf, sort): + if isinstance(fil, str): + fil = FNMatcher(fil) + if isinstance(rec, str): + self.rec = fnmatch(fil) + elif not hasattr(rec, '__call__') and rec: + self.rec = lambda path: True + else: + self.rec = rec + self.fil = fil + self.ignore = ignore + self.breadthfirst = bf + self.optsort = sort and sorted or (lambda x: x) + + def gen(self, path): + try: + entries = path.listdir() + except self.ignore: + return + rec = self.rec + dirs = self.optsort([p for p in entries + if p.check(dir=1) and (rec is None or rec(p))]) + if not self.breadthfirst: + for subdir in dirs: + for p in self.gen(subdir): + yield p + for p in self.optsort(entries): + if self.fil is None or self.fil(p): + yield p + if self.breadthfirst: + for subdir in dirs: + for p in self.gen(subdir): + yield p + class FNMatcher: def __init__(self, pattern): self.pattern = pattern def __call__(self, path): - """return true if the basename/fullname matches the glob-'pattern'. - - * matches everything - ? matches any single character - [seq] matches any character in seq - [!seq] matches any char not in seq - - if the pattern contains a path-separator then the full path - is used for pattern matching and a '*' is prepended to the - pattern. - - if the pattern doesn't contain a path-separator the pattern - is only matched against the basename. - """ pattern = self.pattern if pattern.find(path.sep) == -1: name = path.basename diff --git a/py/_path/gateway/__init__.py b/py/_path/gateway/__init__.py deleted file mode 100644 index 792d600548..0000000000 --- a/py/_path/gateway/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# diff --git a/py/_path/gateway/channeltest.py b/py/_path/gateway/channeltest.py deleted file mode 100644 index ac821aeb92..0000000000 --- a/py/_path/gateway/channeltest.py +++ /dev/null @@ -1,65 +0,0 @@ -import threading - - -class PathServer: - - def __init__(self, channel): - self.channel = channel - self.C2P = {} - self.next_id = 0 - threading.Thread(target=self.serve).start() - - def p2c(self, path): - id = self.next_id - self.next_id += 1 - self.C2P[id] = path - return id - - def command_LIST(self, id, *args): - path = self.C2P[id] - answer = [(self.p2c(p), p.basename) for p in path.listdir(*args)] - self.channel.send(answer) - - def command_DEL(self, id): - del self.C2P[id] - - def command_GET(self, id, spec): - path = self.C2P[id] - self.channel.send(path._getbyspec(spec)) - - def command_READ(self, id): - path = self.C2P[id] - self.channel.send(path.read()) - - def command_JOIN(self, id, resultid, *args): - path = self.C2P[id] - assert resultid not in self.C2P - self.C2P[resultid] = path.join(*args) - - def command_DIRPATH(self, id, resultid): - path = self.C2P[id] - assert resultid not in self.C2P - self.C2P[resultid] = path.dirpath() - - def serve(self): - try: - while 1: - msg = self.channel.receive() - meth = getattr(self, 'command_' + msg[0]) - meth(*msg[1:]) - except EOFError: - pass - -if __name__ == '__main__': - import py - gw = execnet.PopenGateway() - channel = gw._channelfactory.new() - srv = PathServer(channel) - c = gw.remote_exec(""" - import remotepath - p = remotepath.RemotePath(channel.receive(), channel.receive()) - channel.send(len(p.listdir())) - """) - c.send(channel) - c.send(srv.p2c(py.path.local('/tmp'))) - print(c.receive()) diff --git a/py/_path/gateway/channeltest2.py b/py/_path/gateway/channeltest2.py deleted file mode 100644 index 827abb7d32..0000000000 --- a/py/_path/gateway/channeltest2.py +++ /dev/null @@ -1,21 +0,0 @@ -import py -from remotepath import RemotePath - - -SRC = open('channeltest.py', 'r').read() - -SRC += ''' -import py -srv = PathServer(channel.receive()) -channel.send(srv.p2c(py.path.local("/tmp"))) -''' - - -#gw = execnet.SshGateway('codespeak.net') -gw = execnet.PopenGateway() -gw.remote_init_threads(5) -c = gw.remote_exec(SRC, stdout=py.std.sys.stdout, stderr=py.std.sys.stderr) -subchannel = gw._channelfactory.new() -c.send(subchannel) - -p = RemotePath(subchannel, c.receive()) diff --git a/py/_path/gateway/remotepath.py b/py/_path/gateway/remotepath.py deleted file mode 100644 index 149baa4354..0000000000 --- a/py/_path/gateway/remotepath.py +++ /dev/null @@ -1,47 +0,0 @@ -import py, itertools -from py._path import common - -COUNTER = itertools.count() - -class RemotePath(common.PathBase): - sep = '/' - - def __init__(self, channel, id, basename=None): - self._channel = channel - self._id = id - self._basename = basename - self._specs = {} - - def __del__(self): - self._channel.send(('DEL', self._id)) - - def __repr__(self): - return 'RemotePath(%s)' % self.basename - - def listdir(self, *args): - self._channel.send(('LIST', self._id) + args) - return [RemotePath(self._channel, id, basename) - for (id, basename) in self._channel.receive()] - - def dirpath(self): - id = ~COUNTER.next() - self._channel.send(('DIRPATH', self._id, id)) - return RemotePath(self._channel, id) - - def join(self, *args): - id = ~COUNTER.next() - self._channel.send(('JOIN', self._id, id) + args) - return RemotePath(self._channel, id) - - def _getbyspec(self, spec): - parts = spec.split(',') - ask = [x for x in parts if x not in self._specs] - if ask: - self._channel.send(('GET', self._id, ",".join(ask))) - for part, value in zip(ask, self._channel.receive()): - self._specs[part] = value - return [self._specs[x] for x in parts] - - def read(self): - self._channel.send(('READ', self._id)) - return self._channel.receive() diff --git a/py/_path/local.py b/py/_path/local.py index 8878fed3cd..fbe3ae5eb5 100644 --- a/py/_path/local.py +++ b/py/_path/local.py @@ -11,17 +11,17 @@ class Stat(object): def __getattr__(self, name): return getattr(self._osstatresult, "st_" + name) - def __init__(self, path, osstatresult): - self.path = path + def __init__(self, path, osstatresult): + self.path = path self._osstatresult = osstatresult def owner(self): if iswin32: raise NotImplementedError("XXX win32") - import pwd + import pwd entry = py.error.checked_call(pwd.getpwuid, self.uid) return entry[0] - owner = property(owner, None, None, "owner of path") + owner = property(owner, None, None, "owner of path") def group(self): """ return group name of file. """ @@ -30,7 +30,7 @@ class Stat(object): import grp entry = py.error.checked_call(grp.getgrgid, self.gid) return entry[0] - group = property(group) + group = property(group) class PosixPath(common.PathBase): def chown(self, user, group, rec=0): @@ -42,7 +42,7 @@ class PosixPath(common.PathBase): uid = getuserid(user) gid = getgroupid(group) if rec: - for x in self.visit(rec=lambda x: x.check(link=0)): + for x in self.visit(rec=lambda x: x.check(link=0)): if x.check(link=0): py.error.checked_call(os.chown, str(x), uid, gid) py.error.checked_call(os.chown, str(self), uid, gid) @@ -68,10 +68,6 @@ class PosixPath(common.PathBase): target = self.sep.join(('..', )*n + (relsource, )) py.error.checked_call(os.symlink, target, self.strpath) - def samefile(self, other): - """ return True if other refers to the same stat object as self. """ - return py.error.checked_call(os.path.samefile, str(self), str(other)) - def getuserid(user): import pwd if not isinstance(user, int): @@ -87,9 +83,12 @@ def getgroupid(group): FSBase = not iswin32 and PosixPath or common.PathBase class LocalPath(FSBase): - """ object oriented interface to os.path and other local filesystem - related information. + """ object oriented interface to os.path and other local filesystem + related information. """ + class ImportMismatchError(ImportError): + """ raised on pyimport() if there is a mismatch of __file__'s""" + sep = os.sep class Checkers(common.Checkers): def _stat(self): @@ -146,7 +145,7 @@ class LocalPath(FSBase): def __eq__(self, other): s1 = str(self) s2 = str(other) - if iswin32: + if iswin32: s1 = s1.lower() s2 = s2.lower() return s1 == s2 @@ -157,18 +156,30 @@ class LocalPath(FSBase): def __lt__(self, other): return str(self) < str(other) - def remove(self, rec=1): - """ remove a file or directory (or a directory tree if rec=1). """ + def samefile(self, other): + """ return True if 'other' references the same file as 'self'. """ + if self == other: + return True + if not iswin32: + return py.error.checked_call(os.path.samefile, str(self), str(other)) + return False + + def remove(self, rec=1, ignore_errors=False): + """ remove a file or directory (or a directory tree if rec=1). + if ignore_errors is True, errors while removing directories will + be ignored. + """ if self.check(dir=1, link=0): if rec: - # force remove of readonly files on windows - if iswin32: + # force remove of readonly files on windows + if iswin32: self.chmod(448, rec=1) # octcal 0700 - py.error.checked_call(py.std.shutil.rmtree, self.strpath) + py.error.checked_call(py.std.shutil.rmtree, self.strpath, + ignore_errors=ignore_errors) else: py.error.checked_call(os.rmdir, self.strpath) else: - if iswin32: + if iswin32: self.chmod(448) # octcal 0700 py.error.checked_call(os.remove, self.strpath) @@ -190,20 +201,20 @@ class LocalPath(FSBase): buf = f.read(chunksize) if not buf: return hash.hexdigest() - hash.update(buf) + hash.update(buf) finally: f.close() def new(self, **kw): """ create a modified version of this path. - the following keyword arguments modify various path parts: + the following keyword arguments modify various path parts:: a:/some/path/to/a/file.ext - || drive - |-------------| dirname - |------| basename - |--| purebasename - |--| ext + xx drive + xxxxxxxxxxxxxxxxx dirname + xxxxxxxx basename + xxxx purebasename + xxx ext """ obj = object.__new__(self.__class__) drive, dirname, basename, purebasename,ext = self._getbyspec( @@ -222,24 +233,17 @@ class LocalPath(FSBase): ext = '.' + ext kw['basename'] = pb + ext - kw.setdefault('drive', drive) - kw.setdefault('dirname', dirname) + if ('dirname' in kw and not kw['dirname']): + kw['dirname'] = drive + else: + kw.setdefault('dirname', dirname) kw.setdefault('sep', self.sep) obj.strpath = os.path.normpath( - "%(drive)s%(dirname)s%(sep)s%(basename)s" % kw) + "%(dirname)s%(sep)s%(basename)s" % kw) return obj - + def _getbyspec(self, spec): - """ return a sequence of specified path parts. 'spec' is - a comma separated string containing path part names. - according to the following convention: - a:/some/path/to/a/file.ext - || drive - |-------------| dirname - |------| basename - |--| purebasename - |--| ext - """ + """ see new for what 'spec' can be. """ res = [] parts = self.strpath.split(self.sep) @@ -249,7 +253,7 @@ class LocalPath(FSBase): if name == 'drive': append(parts[0]) elif name == 'dirname': - append(self.sep.join(['']+parts[1:-1])) + append(self.sep.join(parts[:-1])) else: basename = parts[-1] if name == 'basename': @@ -314,7 +318,7 @@ class LocalPath(FSBase): if fil is None or fil(childurl): res.append(childurl) self._sortlist(res, sort) - return res + return res def size(self): """ return size of the underlying file object """ @@ -454,8 +458,8 @@ class LocalPath(FSBase): return self.strpath def pypkgpath(self, pkgname=None): - """ return the path's package path by looking for the given - pkgname. If pkgname is None then look for the last + """ return the Python package path by looking for a + pkgname. If pkgname is None look for the last directory upwards which still contains an __init__.py and whose basename is python-importable. Return None if a pkgpath can not be determined. @@ -512,6 +516,8 @@ class LocalPath(FSBase): pkg = __import__(pkgpath.basename, None, None, []) names = self.new(ext='').relto(pkgpath.dirpath()) names = names.split(self.sep) + if names and names[-1] == "__init__": + names.pop() modname = ".".join(names) else: # no package scope, still make it possible @@ -519,16 +525,20 @@ class LocalPath(FSBase): self._prependsyspath(self.dirpath()) modname = self.purebasename mod = __import__(modname, None, None, ['__doc__']) + if self.basename == "__init__.py": + return mod # we don't check anything as we might + # we in a namespace package ... too icky to check modfile = mod.__file__ if modfile[-4:] in ('.pyc', '.pyo'): modfile = modfile[:-1] elif modfile.endswith('$py.class'): modfile = modfile[:-9] + '.py' + if modfile.endswith(os.path.sep + "__init__.py"): + if self.basename != "__init__.py": + modfile = modfile[:-12] + if not self.samefile(modfile): - raise EnvironmentError("mismatch:\n" - "imported module %r\n" - "does not stem from %r\n" - "maybe __init__.py files are missing?" % (mod, str(self))) + raise self.ImportMismatchError(modname, modfile, self) return mod else: try: @@ -547,8 +557,8 @@ class LocalPath(FSBase): def sysexec(self, *argv, **popen_opts): """ return stdout text from executing a system child process, - where the 'self' path points to executable. - The process is directly invoked and not through a system shell. + where the 'self' path points to executable. + The process is directly invoked and not through a system shell. """ from subprocess import Popen, PIPE argv = map(str, argv) @@ -589,7 +599,7 @@ class LocalPath(FSBase): else: paths = [re.sub('%SystemRoot%', systemroot, path) for path in paths] - tryadd = '', '.exe', '.com', '.bat', '.cmd' # XXX add more? + tryadd = [''] + os.environ['PATHEXT'].split(os.pathsep) else: paths = py.std.os.environ['PATH'].split(':') tryadd = ('',) @@ -612,7 +622,7 @@ class LocalPath(FSBase): try: x = os.environ['HOME'] except KeyError: - x = os.environ['HOMEPATH'] + x = os.environ["HOMEDRIVE"] + os.environ['HOMEPATH'] return cls(x) _gethomedir = classmethod(_gethomedir) @@ -626,21 +636,14 @@ class LocalPath(FSBase): return py.path.local(py.std.tempfile.gettempdir()) get_temproot = classmethod(get_temproot) - def mkdtemp(cls): + def mkdtemp(cls, rootdir=None): """ return a Path object pointing to a fresh new temporary directory (which we created ourself). """ import tempfile - tries = 10 - for i in range(tries): - dname = tempfile.mktemp() - dpath = cls(tempfile.mktemp()) - try: - dpath.mkdir() - except (py.error.EEXIST, py.error.EPERM, py.error.EACCES): - continue - return dpath - raise py.error.ENOENT(dpath, "could not create tempdir, %d tries" % tries) + if rootdir is None: + rootdir = cls.get_temproot() + return cls(py.error.checked_call(tempfile.mkdtemp, dir=str(rootdir))) mkdtemp = classmethod(mkdtemp) def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3, @@ -726,7 +729,7 @@ class LocalPath(FSBase): raise except: # this might be py.error.Error, WindowsError ... pass - + # make link... try: username = os.environ['USER'] #linux, et al @@ -766,41 +769,6 @@ def copychunked(src, dest): finally: fsrc.close() -def autopath(globs=None): - """ (deprecated) return the (local) path of the "current" file pointed to by globals or - if it is none - alternatively the callers frame globals. - - the path will always point to a .py file or to None. - the path will have the following payload: - pkgdir is the last parent directory path containing __init__.py - """ - py.log._apiwarn("1.1", "py.magic.autopath deprecated, " - "use py.path.local(__file__) and maybe pypkgpath/pyimport().") - if globs is None: - globs = sys._getframe(1).f_globals - try: - __file__ = globs['__file__'] - except KeyError: - if not sys.argv[0]: - raise ValueError("cannot compute autopath in interactive mode") - __file__ = os.path.abspath(sys.argv[0]) - - ret = py.path.local(__file__) - if ret.ext in ('.pyc', '.pyo'): - ret = ret.new(ext='.py') - current = pkgdir = ret.dirpath() - while 1: - if current.join('__init__.py').check(): - pkgdir = current - current = current.dirpath() - if pkgdir != current: - continue - elif str(current) not in sys.path: - sys.path.insert(0, str(current)) - break - ret.pkgdir = pkgdir - return ret - - def isimportable(name): if name: if not (name[0].isalpha() or name[0] == '_'): diff --git a/py/_path/svnurl.py b/py/_path/svnurl.py index 383b01ed4e..f55b6c65da 100644 --- a/py/_path/svnurl.py +++ b/py/_path/svnurl.py @@ -1,7 +1,7 @@ """ module defining a subversion path object based on the external command 'svn'. This modules aims to work with svn 1.3 and higher -but might also interact well with earlier versions. +but might also interact well with earlier versions. """ import os, sys, time, re @@ -11,7 +11,7 @@ from py._path import common from py._path import svnwc as svncommon from py._path.cacheutil import BuildcostAccessCache, AgingCache -DEBUG=False +DEBUG=False class SvnCommandPath(svncommon.SvnPathBase): """ path implementation that offers access to (possibly remote) subversion @@ -22,10 +22,10 @@ class SvnCommandPath(svncommon.SvnPathBase): def __new__(cls, path, rev=None, auth=None): self = object.__new__(cls) - if isinstance(path, cls): - rev = path.rev + if isinstance(path, cls): + rev = path.rev auth = path.auth - path = path.strpath + path = path.strpath svncommon.checkbadchars(path) path = path.rstrip('/') self.strpath = path @@ -97,7 +97,7 @@ class SvnCommandPath(svncommon.SvnPathBase): def open(self, mode='r'): """ return an opened file with the given mode. """ - if mode not in ("r", "rU",): + if mode not in ("r", "rU",): raise ValueError("mode %r not supported" % (mode,)) assert self.check(file=1) # svn cat returns an empty file otherwise if self.rev is None: @@ -111,17 +111,17 @@ class SvnCommandPath(svncommon.SvnPathBase): """ return the directory path of the current path joined with any given path arguments. """ - l = self.strpath.split(self.sep) - if len(l) < 4: - raise py.error.EINVAL(self, "base is not valid") - elif len(l) == 4: - return self.join(*args, **kwargs) - else: + l = self.strpath.split(self.sep) + if len(l) < 4: + raise py.error.EINVAL(self, "base is not valid") + elif len(l) == 4: + return self.join(*args, **kwargs) + else: return self.new(basename='').join(*args, **kwargs) # modifying methods (cache must be invalidated) def mkdir(self, *args, **kwargs): - """ create & return the directory joined with args. + """ create & return the directory joined with args. pass a 'msg' keyword argument to set the commit message. """ commit_msg = kwargs.get('msg', "mkdir by py lib invocation") @@ -177,29 +177,29 @@ checkin message msg.""" if getattr(self, 'rev', None) is not None: raise py.error.EINVAL(self, "revisions are immutable") target = self.join(*args) - dir = kwargs.get('dir', 0) - for x in target.parts(reverse=True): - if x.check(): - break - else: - raise py.error.ENOENT(target, "has not any valid base!") - if x == target: - if not x.check(dir=dir): - raise dir and py.error.ENOTDIR(x) or py.error.EISDIR(x) - return x - tocreate = target.relto(x) + dir = kwargs.get('dir', 0) + for x in target.parts(reverse=True): + if x.check(): + break + else: + raise py.error.ENOENT(target, "has not any valid base!") + if x == target: + if not x.check(dir=dir): + raise dir and py.error.ENOTDIR(x) or py.error.EISDIR(x) + return x + tocreate = target.relto(x) basename = tocreate.split(self.sep, 1)[0] tempdir = py.path.local.mkdtemp() - try: - tempdir.ensure(tocreate, dir=dir) + try: + tempdir.ensure(tocreate, dir=dir) cmd = 'svn import -m "%s" "%s" "%s"' % ( - "ensure %s" % self._escape(tocreate), - self._escape(tempdir.join(basename)), + "ensure %s" % self._escape(tocreate), + self._escape(tempdir.join(basename)), x.join(basename)._encodedurl()) - self._svncmdexecauth(cmd) + self._svncmdexecauth(cmd) self._norev_delentry(x) - finally: - tempdir.remove() + finally: + tempdir.remove() return target # end of modifying methods @@ -247,7 +247,7 @@ checkin message msg.""" for lsline in lines: if lsline: info = InfoSvnCommand(lsline) - if info._name != '.': # svn 1.5 produces '.' dirs, + if info._name != '.': # svn 1.5 produces '.' dirs, nameinfo_seq.append((info._name, info)) nameinfo_seq.sort() return nameinfo_seq diff --git a/py/_path/svnwc.py b/py/_path/svnwc.py index 5a25d0f230..72769dbbb0 100644 --- a/py/_path/svnwc.py +++ b/py/_path/svnwc.py @@ -75,13 +75,13 @@ class RepoCache: repositories = RepoCache() -# svn support code +# svn support code ALLOWED_CHARS = "_ -/\\=$.~+%" #add characters as necessary when tested if sys.platform == "win32": ALLOWED_CHARS += ":" ALLOWED_CHARS_HOST = ALLOWED_CHARS + '@:' - + def _getsvnversion(ver=[]): try: return ver[0] @@ -108,7 +108,7 @@ def _check_for_bad_chars(text, allowed_chars=ALLOWED_CHARS): return False def checkbadchars(url): - # (hpk) not quite sure about the exact purpose, guido w.? + # (hpk) not quite sure about the exact purpose, guido w.? proto, uri = url.split("://", 1) if proto != "file": host, uripath = uri.split('/', 1) @@ -116,7 +116,7 @@ def checkbadchars(url): if (_check_for_bad_chars(host, ALLOWED_CHARS_HOST) \ or _check_for_bad_chars(uripath, ALLOWED_CHARS)): raise ValueError("bad char in %r" % (url, )) - + #_______________________________________________________________ @@ -138,7 +138,7 @@ class SvnPathBase(common.PathBase): def new(self, **kw): """ create a modified version of this path. A 'rev' argument indicates a new revision. - the following keyword arguments modify various path parts: + the following keyword arguments modify various path parts:: http://host.com/repo/path/file.ext |-----------------------| dirname @@ -351,7 +351,7 @@ def path_to_fspath(path, addat=True): elif addat: sp = '%s@HEAD' % (sp,) return sp - + def url_from_path(path): fspath = path_to_fspath(path, False) quote = py.std.urllib.quote @@ -460,7 +460,7 @@ class SvnWCCommandPath(common.PathBase): args = args and list(args) or [] args.append(self._makeauthoptions()) return self._svn(cmd, *args) - + def _svn(self, cmd, *args): l = ['svn %s' % cmd] args = [self._escape(item) for item in args] @@ -482,9 +482,9 @@ class SvnWCCommandPath(common.PathBase): except py.process.cmdexec.Error: e = sys.exc_info()[1] strerr = e.err.lower() - if strerr.find('file not found') != -1: - raise py.error.ENOENT(self) - if (strerr.find('file exists') != -1 or + if strerr.find('file not found') != -1: + raise py.error.ENOENT(self) + if (strerr.find('file exists') != -1 or strerr.find('file already exists') != -1 or strerr.find("can't create directory") != -1): raise py.error.EEXIST(self) @@ -503,7 +503,7 @@ class SvnWCCommandPath(common.PathBase): if rev is None or rev == -1: if (py.std.sys.platform != 'win32' and _getsvnversion() == '1.3'): - url += "@HEAD" + url += "@HEAD" else: if _getsvnversion() == '1.3': url += "@%d" % rev @@ -544,7 +544,7 @@ class SvnWCCommandPath(common.PathBase): if p.check(): if p.check(versioned=False): p.add() - return p + return p if kwargs.get('dir', 0): return p._ensuredirs() parent = p.dirpath() @@ -594,7 +594,7 @@ class SvnWCCommandPath(common.PathBase): if not out: # warning or error, raise exception raise Exception(out[4:]) - + def unlock(self): """ unset a previously set lock """ out = self._authsvn('unlock').strip() @@ -627,8 +627,8 @@ class SvnWCCommandPath(common.PathBase): rec = '--non-recursive' # XXX does not work on all subversion versions - #if not externals: - # externals = '--ignore-externals' + #if not externals: + # externals = '--ignore-externals' if updates: updates = '-u' @@ -688,19 +688,19 @@ class SvnWCCommandPath(common.PathBase): del cache.info[self] except KeyError: pass - if out: + if out: m = self._rex_commit.match(out) return int(m.group(1)) def propset(self, name, value, *args): """ set property name to value on this path. """ - d = py.path.local.mkdtemp() - try: - p = d.join('value') - p.write(value) + d = py.path.local.mkdtemp() + try: + p = d.join('value') + p.write(value) self._svn('propset', name, '--file', str(p), *args) - finally: - d.remove() + finally: + d.remove() def propget(self, name): """ get property name on this path. """ @@ -776,16 +776,16 @@ recursively. """ # XXX SVN 1.3 has output on stderr instead of stdout (while it does # return 0!), so a bit nasty, but we assume no output is output # to stderr... - if (output.strip() == '' or + if (output.strip() == '' or output.lower().find('not a versioned resource') != -1): raise py.error.ENOENT(self, output) info = InfoSvnWCCommand(output) # Can't reliably compare on Windows without access to win32api - if py.std.sys.platform != 'win32': - if info.path != self.localpath: - raise py.error.ENOENT(self, "not a versioned resource:" + - " %s != %s" % (info.path, self.localpath)) + if py.std.sys.platform != 'win32': + if info.path != self.localpath: + raise py.error.ENOENT(self, "not a versioned resource:" + + " %s != %s" % (info.path, self.localpath)) cache.info[self] = info return info @@ -799,7 +799,7 @@ recursively. """ fil = common.FNMatcher(fil) # XXX unify argument naming with LocalPath.listdir def notsvn(path): - return path.basename != '.svn' + return path.basename != '.svn' paths = [] for localpath in self.localpath.listdir(notsvn): @@ -823,8 +823,8 @@ recursively. """ def versioned(self): try: s = self.svnwcpath.info() - except (py.error.ENOENT, py.error.EEXIST): - return False + except (py.error.ENOENT, py.error.EEXIST): + return False except py.process.cmdexec.Error: e = sys.exc_info()[1] if e.err.find('is not a working copy')!=-1: @@ -833,7 +833,7 @@ recursively. """ return False raise else: - return True + return True def log(self, rev_start=None, rev_end=1, verbose=False): """ return a list of LogEntry instances for this path. @@ -859,9 +859,9 @@ if verbose is True, then the LogEntry instances also know which files changed. cmd = locale_env + 'svn log --xml %s %s %s "%s"' % ( rev_opt, verbose_opt, auth_opt, self.strpath) - popen = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + popen = subprocess.Popen(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, shell=True, ) stdout, stderr = popen.communicate() |