[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
parent
19dda7c9bd
commit
49abbf2485
|
@ -2,12 +2,16 @@
|
||||||
create errno-specific classes for IO or os calls.
|
create errno-specific classes for IO or os calls.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import errno
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
import sys, os, errno
|
|
||||||
|
|
||||||
class Error(EnvironmentError):
|
class Error(EnvironmentError):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s.%s %r: %s " %(self.__class__.__module__,
|
return "{}.{} {!r}: {} ".format(
|
||||||
|
self.__class__.__module__,
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
self.__class__.__doc__,
|
self.__class__.__doc__,
|
||||||
" ".join(map(str, self.args)),
|
" ".join(map(str, self.args)),
|
||||||
|
@ -15,11 +19,13 @@ class Error(EnvironmentError):
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = "[%s]: %s" %(self.__class__.__doc__,
|
s = "[{}]: {}".format(
|
||||||
|
self.__class__.__doc__,
|
||||||
" ".join(map(str, self.args)),
|
" ".join(map(str, self.args)),
|
||||||
)
|
)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
_winerrnomap = {
|
_winerrnomap = {
|
||||||
2: errno.ENOENT,
|
2: errno.ENOENT,
|
||||||
3: errno.ENOENT,
|
3: errno.ENOENT,
|
||||||
|
@ -32,11 +38,13 @@ _winerrnomap = {
|
||||||
5: errno.EACCES, # anything better?
|
5: errno.EACCES, # anything better?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ErrorMaker(ModuleType):
|
class ErrorMaker(ModuleType):
|
||||||
"""lazily provides Exception classes for each possible POSIX errno
|
"""lazily provides Exception classes for each possible POSIX errno
|
||||||
(as defined per the 'errno' module). All such instances
|
(as defined per the 'errno' module). All such instances
|
||||||
subclass EnvironmentError.
|
subclass EnvironmentError.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Error = Error
|
Error = Error
|
||||||
_errno2class = {}
|
_errno2class = {}
|
||||||
|
|
||||||
|
@ -53,9 +61,11 @@ class ErrorMaker(ModuleType):
|
||||||
return self._errno2class[eno]
|
return self._errno2class[eno]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
clsname = errno.errorcode.get(eno, "UnknownErrno%d" % (eno,))
|
clsname = errno.errorcode.get(eno, "UnknownErrno%d" % (eno,))
|
||||||
errorcls = type(Error)(clsname, (Error,),
|
errorcls = type(Error)(
|
||||||
{'__module__':'py.error',
|
clsname,
|
||||||
'__doc__': os.strerror(eno)})
|
(Error,),
|
||||||
|
{"__module__": "py.error", "__doc__": os.strerror(eno)},
|
||||||
|
)
|
||||||
self._errno2class[eno] = errorcls
|
self._errno2class[eno] = errorcls
|
||||||
return errorcls
|
return errorcls
|
||||||
|
|
||||||
|
@ -66,9 +76,9 @@ class ErrorMaker(ModuleType):
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
except self.Error:
|
except self.Error:
|
||||||
raise
|
raise
|
||||||
except (OSError, EnvironmentError):
|
except OSError:
|
||||||
cls, value, tb = sys.exc_info()
|
cls, value, tb = sys.exc_info()
|
||||||
if not hasattr(value, 'errno'):
|
if not hasattr(value, "errno"):
|
||||||
raise
|
raise
|
||||||
__tracebackhide__ = False
|
__tracebackhide__ = False
|
||||||
errno = value.errno
|
errno = value.errno
|
||||||
|
@ -83,9 +93,9 @@ class ErrorMaker(ModuleType):
|
||||||
cls = self._geterrnoclass(_winerrnomap[errno])
|
cls = self._geterrnoclass(_winerrnomap[errno])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise value
|
raise value
|
||||||
raise cls("%s%r" % (func.__name__, args))
|
raise cls(f"{func.__name__}{args!r}")
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
|
|
||||||
|
|
||||||
error = ErrorMaker('_pytest._py.error')
|
error = ErrorMaker("_pytest._py.error")
|
||||||
sys.modules[error.__name__] = error
|
sys.modules[error.__name__] = error
|
||||||
|
|
|
@ -1,24 +1,31 @@
|
||||||
"""
|
"""
|
||||||
local path implementation.
|
local path implementation.
|
||||||
"""
|
"""
|
||||||
from __future__ import with_statement
|
import atexit
|
||||||
|
|
||||||
from contextlib import contextmanager
|
|
||||||
import sys, os, atexit, io, uuid
|
|
||||||
from stat import S_ISLNK, S_ISDIR, S_ISREG
|
|
||||||
|
|
||||||
from os.path import abspath, normpath, isabs, exists, isdir, isfile, islink, dirname
|
|
||||||
|
|
||||||
import warnings
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import posixpath
|
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import posixpath
|
||||||
|
import sys
|
||||||
|
import uuid
|
||||||
|
import warnings
|
||||||
|
from contextlib import contextmanager
|
||||||
|
from os.path import abspath
|
||||||
|
from os.path import dirname
|
||||||
|
from os.path import exists
|
||||||
|
from os.path import isabs
|
||||||
|
from os.path import isdir
|
||||||
|
from os.path import isfile
|
||||||
|
from os.path import islink
|
||||||
|
from os.path import normpath
|
||||||
|
from stat import S_ISDIR
|
||||||
|
from stat import S_ISLNK
|
||||||
|
from stat import S_ISREG
|
||||||
|
|
||||||
from . import error
|
from . import error
|
||||||
|
|
||||||
# Moved from local.py.
|
# Moved from local.py.
|
||||||
iswin32 = sys.platform == "win32" or (getattr(os, '_name', False) == 'nt')
|
iswin32 = sys.platform == "win32" or (getattr(os, "_name", False) == "nt")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# FileNotFoundError might happen in py34, and is not available with py27.
|
# FileNotFoundError might happen in py34, and is not available with py27.
|
||||||
|
@ -29,6 +36,7 @@ except NameError:
|
||||||
try:
|
try:
|
||||||
from os import fspath
|
from os import fspath
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
||||||
def fspath(path):
|
def fspath(path):
|
||||||
"""
|
"""
|
||||||
Return the string representation of the path.
|
Return the string representation of the path.
|
||||||
|
@ -47,7 +55,7 @@ except ImportError:
|
||||||
try:
|
try:
|
||||||
return path_type.__fspath__(path)
|
return path_type.__fspath__(path)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
if hasattr(path_type, '__fspath__'):
|
if hasattr(path_type, "__fspath__"):
|
||||||
raise
|
raise
|
||||||
try:
|
try:
|
||||||
import pathlib
|
import pathlib
|
||||||
|
@ -57,11 +65,13 @@ except ImportError:
|
||||||
if isinstance(path, pathlib.PurePath):
|
if isinstance(path, pathlib.PurePath):
|
||||||
return str(path)
|
return str(path)
|
||||||
|
|
||||||
raise TypeError("expected str, bytes or os.PathLike object, not "
|
raise TypeError(
|
||||||
+ path_type.__name__)
|
"expected str, bytes or os.PathLike object, not " + path_type.__name__
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Checkers:
|
class Checkers:
|
||||||
_depend_on_existence = 'exists', 'link', 'dir', 'file'
|
_depend_on_existence = "exists", "link", "dir", "file"
|
||||||
|
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
self.path = path
|
self.path = path
|
||||||
|
@ -73,11 +83,11 @@ class Checkers:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def dotfile(self):
|
def dotfile(self):
|
||||||
return self.path.basename.startswith('.')
|
return self.path.basename.startswith(".")
|
||||||
|
|
||||||
def ext(self, arg):
|
def ext(self, arg):
|
||||||
if not arg.startswith('.'):
|
if not arg.startswith("."):
|
||||||
arg = '.' + arg
|
arg = "." + arg
|
||||||
return self.path.ext == arg
|
return self.path.ext == arg
|
||||||
|
|
||||||
def exists(self):
|
def exists(self):
|
||||||
|
@ -105,15 +115,14 @@ class Checkers:
|
||||||
try:
|
try:
|
||||||
meth = getattr(self, name)
|
meth = getattr(self, name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
if name[:3] == 'not':
|
if name[:3] == "not":
|
||||||
invert = True
|
invert = True
|
||||||
try:
|
try:
|
||||||
meth = getattr(self, name[3:])
|
meth = getattr(self, name[3:])
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
if meth is None:
|
if meth is None:
|
||||||
raise TypeError(
|
raise TypeError(f"no {name!r} checker available for {self.path!r}")
|
||||||
"no %r checker available for %r" % (name, self.path))
|
|
||||||
try:
|
try:
|
||||||
if py.code.getrawcode(meth).co_argcount > 1:
|
if py.code.getrawcode(meth).co_argcount > 1:
|
||||||
if (not meth(value)) ^ invert:
|
if (not meth(value)) ^ invert:
|
||||||
|
@ -129,50 +138,58 @@ class Checkers:
|
||||||
if name in kw:
|
if name in kw:
|
||||||
if kw.get(name):
|
if kw.get(name):
|
||||||
return False
|
return False
|
||||||
name = 'not' + name
|
name = "not" + name
|
||||||
if name in kw:
|
if name in kw:
|
||||||
if not kw.get(name):
|
if not kw.get(name):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class NeverRaised(Exception):
|
class NeverRaised(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class PathBase(object):
|
|
||||||
|
class PathBase:
|
||||||
"""shared implementation for filesystem path objects."""
|
"""shared implementation for filesystem path objects."""
|
||||||
|
|
||||||
Checkers = Checkers
|
Checkers = Checkers
|
||||||
|
|
||||||
def __div__(self, other):
|
def __div__(self, other):
|
||||||
return self.join(fspath(other))
|
return self.join(fspath(other))
|
||||||
|
|
||||||
__truediv__ = __div__ # py3k
|
__truediv__ = __div__ # py3k
|
||||||
|
|
||||||
def basename(self):
|
def basename(self):
|
||||||
"""basename part of path."""
|
"""basename part of path."""
|
||||||
return self._getbyspec('basename')[0]
|
return self._getbyspec("basename")[0]
|
||||||
|
|
||||||
basename = property(basename, None, None, basename.__doc__)
|
basename = property(basename, None, None, basename.__doc__)
|
||||||
|
|
||||||
def dirname(self):
|
def dirname(self):
|
||||||
"""dirname part of path."""
|
"""dirname part of path."""
|
||||||
return self._getbyspec('dirname')[0]
|
return self._getbyspec("dirname")[0]
|
||||||
|
|
||||||
dirname = property(dirname, None, None, dirname.__doc__)
|
dirname = property(dirname, None, None, dirname.__doc__)
|
||||||
|
|
||||||
def purebasename(self):
|
def purebasename(self):
|
||||||
"""pure base name of the path."""
|
"""pure base name of the path."""
|
||||||
return self._getbyspec('purebasename')[0]
|
return self._getbyspec("purebasename")[0]
|
||||||
|
|
||||||
purebasename = property(purebasename, None, None, purebasename.__doc__)
|
purebasename = property(purebasename, None, None, purebasename.__doc__)
|
||||||
|
|
||||||
def ext(self):
|
def ext(self):
|
||||||
"""extension of the path (including the '.')."""
|
"""extension of the path (including the '.')."""
|
||||||
return self._getbyspec('ext')[0]
|
return self._getbyspec("ext")[0]
|
||||||
|
|
||||||
ext = property(ext, None, None, ext.__doc__)
|
ext = property(ext, None, None, ext.__doc__)
|
||||||
|
|
||||||
def dirpath(self, *args, **kwargs):
|
def dirpath(self, *args, **kwargs):
|
||||||
"""return the directory path joined with any given path arguments."""
|
"""return the directory path joined with any given path arguments."""
|
||||||
return self.new(basename='').join(*args, **kwargs)
|
return self.new(basename="").join(*args, **kwargs)
|
||||||
|
|
||||||
def read_binary(self):
|
def read_binary(self):
|
||||||
"""read and return a bytestring from reading the path."""
|
"""read and return a bytestring from reading the path."""
|
||||||
with self.open('rb') as f:
|
with self.open("rb") as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
def read_text(self, encoding):
|
def read_text(self, encoding):
|
||||||
|
@ -180,8 +197,7 @@ class PathBase(object):
|
||||||
with self.open("r", encoding=encoding) as f:
|
with self.open("r", encoding=encoding) as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
|
||||||
|
def read(self, mode="r"):
|
||||||
def read(self, mode='r'):
|
|
||||||
"""read and return a bytestring from reading the path."""
|
"""read and return a bytestring from reading the path."""
|
||||||
with self.open(mode) as f:
|
with self.open(mode) as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
|
@ -189,14 +205,11 @@ class PathBase(object):
|
||||||
def readlines(self, cr=1):
|
def readlines(self, cr=1):
|
||||||
"""read and return a list of lines from the path. if cr is False, the
|
"""read and return a list of lines from the path. if cr is False, the
|
||||||
newline will be removed from the end of each line."""
|
newline will be removed from the end of each line."""
|
||||||
if sys.version_info < (3, ):
|
mode = "r"
|
||||||
mode = 'rU'
|
|
||||||
else: # python 3 deprecates mode "U" in favor of "newline" option
|
|
||||||
mode = 'r'
|
|
||||||
|
|
||||||
if not cr:
|
if not cr:
|
||||||
content = self.read(mode)
|
content = self.read(mode)
|
||||||
return content.split('\n')
|
return content.split("\n")
|
||||||
else:
|
else:
|
||||||
f = self.open(mode)
|
f = self.open(mode)
|
||||||
try:
|
try:
|
||||||
|
@ -206,9 +219,10 @@ newline will be removed from the end of each line. """
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
"""(deprecated) return object unpickled from self.read()"""
|
"""(deprecated) return object unpickled from self.read()"""
|
||||||
f = self.open('rb')
|
f = self.open("rb")
|
||||||
try:
|
try:
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
return error.checked_call(pickle.load, f)
|
return error.checked_call(pickle.load, f)
|
||||||
finally:
|
finally:
|
||||||
f.close()
|
f.close()
|
||||||
|
@ -216,9 +230,7 @@ newline will be removed from the end of each line. """
|
||||||
def move(self, target):
|
def move(self, target):
|
||||||
"""move this path to target."""
|
"""move this path to target."""
|
||||||
if target.relto(self):
|
if target.relto(self):
|
||||||
raise error.EINVAL(
|
raise error.EINVAL(target, "cannot move path into a subdirectory of itself")
|
||||||
target,
|
|
||||||
"cannot move path into a subdirectory of itself")
|
|
||||||
try:
|
try:
|
||||||
self.rename(target)
|
self.rename(target)
|
||||||
except error.EXDEV: # invalid cross-device link
|
except error.EXDEV: # invalid cross-device link
|
||||||
|
@ -247,7 +259,7 @@ newline will be removed from the end of each line. """
|
||||||
path.check(file=1, link=1) # a link pointing to a file
|
path.check(file=1, link=1) # a link pointing to a file
|
||||||
"""
|
"""
|
||||||
if not kw:
|
if not kw:
|
||||||
kw = {'exists': 1}
|
kw = {"exists": 1}
|
||||||
return self.Checkers(self)._evaluate(kw)
|
return self.Checkers(self)._evaluate(kw)
|
||||||
|
|
||||||
def fnmatch(self, pattern):
|
def fnmatch(self, pattern):
|
||||||
|
@ -274,16 +286,15 @@ newline will be removed from the end of each line. """
|
||||||
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,))
|
raise TypeError(f"{relpath!r}: not a string or path object")
|
||||||
strrelpath = str(relpath)
|
strrelpath = str(relpath)
|
||||||
if strrelpath and strrelpath[-1] != self.sep:
|
if strrelpath and strrelpath[-1] != self.sep:
|
||||||
strrelpath += self.sep
|
strrelpath += self.sep
|
||||||
# assert strrelpath[-1] == self.sep
|
# assert strrelpath[-1] == self.sep
|
||||||
# assert strrelpath[-2] != self.sep
|
# assert strrelpath[-2] != self.sep
|
||||||
strself = self.strpath
|
strself = self.strpath
|
||||||
if sys.platform == "win32" or getattr(os, '_name', None) == 'nt':
|
if sys.platform == "win32" or getattr(os, "_name", None) == "nt":
|
||||||
if os.path.normcase(strself).startswith(
|
if os.path.normcase(strself).startswith(os.path.normcase(strrelpath)):
|
||||||
os.path.normcase(strrelpath)):
|
|
||||||
return strself[len(strrelpath) :]
|
return strself[len(strrelpath) :]
|
||||||
elif strself.startswith(strrelpath):
|
elif strself.startswith(strrelpath):
|
||||||
return strself[len(strrelpath) :]
|
return strself[len(strrelpath) :]
|
||||||
|
@ -390,15 +401,17 @@ newline will be removed from the end of each line. """
|
||||||
|
|
||||||
sort if True will sort entries within each directory level.
|
sort if True will sort entries within each directory level.
|
||||||
"""
|
"""
|
||||||
for x in Visitor(fil, rec, ignore, bf, sort).gen(self):
|
yield from Visitor(fil, rec, ignore, bf, sort).gen(self)
|
||||||
yield x
|
|
||||||
|
|
||||||
def _sortlist(self, res, sort):
|
def _sortlist(self, res, sort):
|
||||||
if sort:
|
if sort:
|
||||||
if hasattr(sort, '__call__'):
|
if hasattr(sort, "__call__"):
|
||||||
warnings.warn(DeprecationWarning(
|
warnings.warn(
|
||||||
|
DeprecationWarning(
|
||||||
"listdir(sort=callable) is deprecated and breaks on python3"
|
"listdir(sort=callable) is deprecated and breaks on python3"
|
||||||
), stacklevel=3)
|
),
|
||||||
|
stacklevel=3,
|
||||||
|
)
|
||||||
res.sort(sort)
|
res.sort(sort)
|
||||||
else:
|
else:
|
||||||
res.sort()
|
res.sort()
|
||||||
|
@ -410,13 +423,14 @@ newline will be removed from the end of each line. """
|
||||||
def __fspath__(self):
|
def __fspath__(self):
|
||||||
return self.strpath
|
return self.strpath
|
||||||
|
|
||||||
|
|
||||||
class Visitor:
|
class Visitor:
|
||||||
def __init__(self, fil, rec, ignore, bf, sort):
|
def __init__(self, fil, rec, ignore, bf, sort):
|
||||||
if isinstance(fil, py.builtin._basestring):
|
if isinstance(fil, py.builtin._basestring):
|
||||||
fil = FNMatcher(fil)
|
fil = FNMatcher(fil)
|
||||||
if isinstance(rec, py.builtin._basestring):
|
if isinstance(rec, py.builtin._basestring):
|
||||||
self.rec = FNMatcher(rec)
|
self.rec = FNMatcher(rec)
|
||||||
elif not hasattr(rec, '__call__') and rec:
|
elif not hasattr(rec, "__call__") and rec:
|
||||||
self.rec = lambda path: True
|
self.rec = lambda path: True
|
||||||
else:
|
else:
|
||||||
self.rec = rec
|
self.rec = rec
|
||||||
|
@ -431,8 +445,9 @@ class Visitor:
|
||||||
except self.ignore:
|
except self.ignore:
|
||||||
return
|
return
|
||||||
rec = self.rec
|
rec = self.rec
|
||||||
dirs = self.optsort([p for p in entries
|
dirs = self.optsort(
|
||||||
if p.check(dir=1) and (rec is None or rec(p))])
|
[p for p in entries if p.check(dir=1) and (rec is None or rec(p))]
|
||||||
|
)
|
||||||
if not self.breadthfirst:
|
if not self.breadthfirst:
|
||||||
for subdir in dirs:
|
for subdir in dirs:
|
||||||
for p in self.gen(subdir):
|
for p in self.gen(subdir):
|
||||||
|
@ -445,6 +460,7 @@ class Visitor:
|
||||||
for p in self.gen(subdir):
|
for p in self.gen(subdir):
|
||||||
yield p
|
yield p
|
||||||
|
|
||||||
|
|
||||||
class FNMatcher:
|
class FNMatcher:
|
||||||
def __init__(self, pattern):
|
def __init__(self, pattern):
|
||||||
self.pattern = pattern
|
self.pattern = pattern
|
||||||
|
@ -452,9 +468,11 @@ class FNMatcher:
|
||||||
def __call__(self, path):
|
def __call__(self, path):
|
||||||
pattern = self.pattern
|
pattern = self.pattern
|
||||||
|
|
||||||
if (pattern.find(path.sep) == -1 and
|
if (
|
||||||
iswin32 and
|
pattern.find(path.sep) == -1
|
||||||
pattern.find(posixpath.sep) != -1):
|
and iswin32
|
||||||
|
and pattern.find(posixpath.sep) != -1
|
||||||
|
):
|
||||||
# Running on Windows, the pattern has no Windows path separators,
|
# Running on Windows, the pattern has no Windows path separators,
|
||||||
# and the pattern has one or more Posix path separators. Replace
|
# and the pattern has one or more Posix path separators. Replace
|
||||||
# the Posix path separators with the Windows path separator.
|
# the Posix path separators with the Windows path separator.
|
||||||
|
@ -465,22 +483,20 @@ class FNMatcher:
|
||||||
else:
|
else:
|
||||||
name = str(path) # path.strpath # XXX svn?
|
name = str(path) # path.strpath # XXX svn?
|
||||||
if not os.path.isabs(pattern):
|
if not os.path.isabs(pattern):
|
||||||
pattern = '*' + path.sep + pattern
|
pattern = "*" + path.sep + pattern
|
||||||
return fnmatch.fnmatch(name, pattern)
|
return fnmatch.fnmatch(name, pattern)
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info > (3,0):
|
|
||||||
def map_as_list(func, iter):
|
def map_as_list(func, iter):
|
||||||
return list(map(func, iter))
|
return list(map(func, iter))
|
||||||
else:
|
|
||||||
map_as_list = map
|
|
||||||
|
|
||||||
ALLOW_IMPORTLIB_MODE = sys.version_info > (3, 5)
|
ALLOW_IMPORTLIB_MODE = sys.version_info > (3, 5)
|
||||||
if ALLOW_IMPORTLIB_MODE:
|
if ALLOW_IMPORTLIB_MODE:
|
||||||
import importlib
|
import importlib
|
||||||
|
|
||||||
|
|
||||||
class Stat(object):
|
class Stat:
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return getattr(self._osstatresult, "st_" + name)
|
return getattr(self._osstatresult, "st_" + name)
|
||||||
|
|
||||||
|
@ -493,6 +509,7 @@ class Stat(object):
|
||||||
if iswin32:
|
if iswin32:
|
||||||
raise NotImplementedError("XXX win32")
|
raise NotImplementedError("XXX win32")
|
||||||
import pwd
|
import pwd
|
||||||
|
|
||||||
entry = error.checked_call(pwd.getpwuid, self.uid)
|
entry = error.checked_call(pwd.getpwuid, self.uid)
|
||||||
return entry[0]
|
return entry[0]
|
||||||
|
|
||||||
|
@ -502,6 +519,7 @@ class Stat(object):
|
||||||
if iswin32:
|
if iswin32:
|
||||||
raise NotImplementedError("XXX win32")
|
raise NotImplementedError("XXX win32")
|
||||||
import grp
|
import grp
|
||||||
|
|
||||||
entry = error.checked_call(grp.getgrgid, self.gid)
|
entry = error.checked_call(grp.getgrgid, self.gid)
|
||||||
return entry[0]
|
return entry[0]
|
||||||
|
|
||||||
|
@ -512,9 +530,10 @@ class Stat(object):
|
||||||
return S_ISREG(self._osstatresult.st_mode)
|
return S_ISREG(self._osstatresult.st_mode)
|
||||||
|
|
||||||
def islink(self):
|
def islink(self):
|
||||||
st = self.path.lstat()
|
self.path.lstat()
|
||||||
return S_ISLNK(self._osstatresult.st_mode)
|
return S_ISLNK(self._osstatresult.st_mode)
|
||||||
|
|
||||||
|
|
||||||
class PosixPath(PathBase):
|
class PosixPath(PathBase):
|
||||||
def chown(self, user, group, rec=0):
|
def chown(self, user, group, rec=0):
|
||||||
"""change ownership to the given user and group.
|
"""change ownership to the given user and group.
|
||||||
|
@ -548,31 +567,39 @@ class PosixPath(PathBase):
|
||||||
relsource = self.__class__(value).relto(base)
|
relsource = self.__class__(value).relto(base)
|
||||||
reldest = self.relto(base)
|
reldest = self.relto(base)
|
||||||
n = reldest.count(self.sep)
|
n = reldest.count(self.sep)
|
||||||
target = self.sep.join(('..', )*n + (relsource, ))
|
target = self.sep.join(("..",) * n + (relsource,))
|
||||||
error.checked_call(os.symlink, target, self.strpath)
|
error.checked_call(os.symlink, target, self.strpath)
|
||||||
|
|
||||||
|
|
||||||
def getuserid(user):
|
def getuserid(user):
|
||||||
import pwd
|
import pwd
|
||||||
|
|
||||||
if not isinstance(user, int):
|
if not isinstance(user, int):
|
||||||
user = pwd.getpwnam(user)[2]
|
user = pwd.getpwnam(user)[2]
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
def getgroupid(group):
|
def getgroupid(group):
|
||||||
import grp
|
import grp
|
||||||
|
|
||||||
if not isinstance(group, int):
|
if not isinstance(group, int):
|
||||||
group = grp.getgrnam(group)[2]
|
group = grp.getgrnam(group)[2]
|
||||||
return group
|
return group
|
||||||
|
|
||||||
|
|
||||||
FSBase = not iswin32 and PosixPath or PathBase
|
FSBase = not iswin32 and PosixPath or PathBase
|
||||||
|
|
||||||
|
|
||||||
class LocalPath(FSBase):
|
class LocalPath(FSBase):
|
||||||
"""object oriented interface to os.path and other local filesystem
|
"""object oriented interface to os.path and other local filesystem
|
||||||
related information.
|
related information.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class ImportMismatchError(ImportError):
|
class ImportMismatchError(ImportError):
|
||||||
"""raised on pyimport() if there is a mismatch of __file__'s"""
|
"""raised on pyimport() if there is a mismatch of __file__'s"""
|
||||||
|
|
||||||
sep = os.sep
|
sep = os.sep
|
||||||
|
|
||||||
class Checkers(Checkers):
|
class Checkers(Checkers):
|
||||||
def _stat(self):
|
def _stat(self):
|
||||||
try:
|
try:
|
||||||
|
@ -613,8 +640,10 @@ class LocalPath(FSBase):
|
||||||
try:
|
try:
|
||||||
path = fspath(path)
|
path = fspath(path)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
raise ValueError("can only pass None, Path instances "
|
raise ValueError(
|
||||||
"or non-empty strings to LocalPath")
|
"can only pass None, Path instances "
|
||||||
|
"or non-empty strings to LocalPath"
|
||||||
|
)
|
||||||
if expanduser:
|
if expanduser:
|
||||||
path = os.path.expanduser(path)
|
path = os.path.expanduser(path)
|
||||||
self.strpath = abspath(path)
|
self.strpath = abspath(path)
|
||||||
|
@ -649,8 +678,7 @@ class LocalPath(FSBase):
|
||||||
return fspath(self) > fspath(other)
|
return fspath(self) > fspath(other)
|
||||||
|
|
||||||
def samefile(self, other):
|
def samefile(self, other):
|
||||||
""" return True if 'other' references the same file as 'self'.
|
"""return True if 'other' references the same file as 'self'."""
|
||||||
"""
|
|
||||||
other = fspath(other)
|
other = fspath(other)
|
||||||
if not isabs(other):
|
if not isabs(other):
|
||||||
other = abspath(other)
|
other = abspath(other)
|
||||||
|
@ -658,8 +686,7 @@ class LocalPath(FSBase):
|
||||||
return True
|
return True
|
||||||
if not hasattr(os.path, "samefile"):
|
if not hasattr(os.path, "samefile"):
|
||||||
return False
|
return False
|
||||||
return error.checked_call(
|
return error.checked_call(os.path.samefile, self.strpath, other)
|
||||||
os.path.samefile, self.strpath, other)
|
|
||||||
|
|
||||||
def remove(self, rec=1, ignore_errors=False):
|
def remove(self, rec=1, ignore_errors=False):
|
||||||
"""remove a file or directory (or a directory tree if rec=1).
|
"""remove a file or directory (or a directory tree if rec=1).
|
||||||
|
@ -672,9 +699,10 @@ class LocalPath(FSBase):
|
||||||
if iswin32:
|
if iswin32:
|
||||||
self.chmod(0o700, rec=1)
|
self.chmod(0o700, rec=1)
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
error.checked_call(
|
error.checked_call(
|
||||||
shutil.rmtree, self.strpath,
|
shutil.rmtree, self.strpath, ignore_errors=ignore_errors
|
||||||
ignore_errors=ignore_errors)
|
)
|
||||||
else:
|
else:
|
||||||
error.checked_call(os.rmdir, self.strpath)
|
error.checked_call(os.rmdir, self.strpath)
|
||||||
else:
|
else:
|
||||||
|
@ -693,8 +721,8 @@ class LocalPath(FSBase):
|
||||||
mod = __import__(hashtype)
|
mod = __import__(hashtype)
|
||||||
hash = getattr(mod, hashtype)()
|
hash = getattr(mod, hashtype)()
|
||||||
except (AttributeError, ImportError):
|
except (AttributeError, ImportError):
|
||||||
raise ValueError("Don't know how to compute %r hash" %(hashtype,))
|
raise ValueError(f"Don't know how to compute {hashtype!r} hash")
|
||||||
f = self.open('rb')
|
f = self.open("rb")
|
||||||
try:
|
try:
|
||||||
while 1:
|
while 1:
|
||||||
buf = f.read(chunksize)
|
buf = f.read(chunksize)
|
||||||
|
@ -720,28 +748,28 @@ class LocalPath(FSBase):
|
||||||
obj.strpath = self.strpath
|
obj.strpath = self.strpath
|
||||||
return obj
|
return obj
|
||||||
drive, dirname, basename, purebasename, ext = self._getbyspec(
|
drive, dirname, basename, purebasename, ext = self._getbyspec(
|
||||||
"drive,dirname,basename,purebasename,ext")
|
"drive,dirname,basename,purebasename,ext"
|
||||||
if 'basename' in kw:
|
)
|
||||||
if 'purebasename' in kw or 'ext' in kw:
|
if "basename" in kw:
|
||||||
|
if "purebasename" in kw or "ext" in kw:
|
||||||
raise ValueError("invalid specification %r" % kw)
|
raise ValueError("invalid specification %r" % kw)
|
||||||
else:
|
else:
|
||||||
pb = kw.setdefault('purebasename', purebasename)
|
pb = kw.setdefault("purebasename", purebasename)
|
||||||
try:
|
try:
|
||||||
ext = kw['ext']
|
ext = kw["ext"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if ext and not ext.startswith('.'):
|
if ext and not ext.startswith("."):
|
||||||
ext = '.' + ext
|
ext = "." + ext
|
||||||
kw['basename'] = pb + ext
|
kw["basename"] = pb + ext
|
||||||
|
|
||||||
if ('dirname' in kw and not kw['dirname']):
|
if "dirname" in kw and not kw["dirname"]:
|
||||||
kw['dirname'] = drive
|
kw["dirname"] = drive
|
||||||
else:
|
else:
|
||||||
kw.setdefault('dirname', dirname)
|
kw.setdefault("dirname", dirname)
|
||||||
kw.setdefault('sep', self.sep)
|
kw.setdefault("sep", self.sep)
|
||||||
obj.strpath = normpath(
|
obj.strpath = normpath("%(dirname)s%(sep)s%(basename)s" % kw)
|
||||||
"%(dirname)s%(sep)s%(basename)s" % kw)
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def _getbyspec(self, spec):
|
def _getbyspec(self, spec):
|
||||||
|
@ -749,26 +777,26 @@ class LocalPath(FSBase):
|
||||||
res = []
|
res = []
|
||||||
parts = self.strpath.split(self.sep)
|
parts = self.strpath.split(self.sep)
|
||||||
|
|
||||||
args = filter(None, spec.split(',') )
|
args = filter(None, spec.split(","))
|
||||||
append = res.append
|
append = res.append
|
||||||
for name in args:
|
for name in args:
|
||||||
if name == 'drive':
|
if name == "drive":
|
||||||
append(parts[0])
|
append(parts[0])
|
||||||
elif name == 'dirname':
|
elif name == "dirname":
|
||||||
append(self.sep.join(parts[:-1]))
|
append(self.sep.join(parts[:-1]))
|
||||||
else:
|
else:
|
||||||
basename = parts[-1]
|
basename = parts[-1]
|
||||||
if name == 'basename':
|
if name == "basename":
|
||||||
append(basename)
|
append(basename)
|
||||||
else:
|
else:
|
||||||
i = basename.rfind('.')
|
i = basename.rfind(".")
|
||||||
if i == -1:
|
if i == -1:
|
||||||
purebasename, ext = basename, ''
|
purebasename, ext = basename, ""
|
||||||
else:
|
else:
|
||||||
purebasename, ext = basename[:i], basename[i:]
|
purebasename, ext = basename[:i], basename[i:]
|
||||||
if name == 'purebasename':
|
if name == "purebasename":
|
||||||
append(purebasename)
|
append(purebasename)
|
||||||
elif name == 'ext':
|
elif name == "ext":
|
||||||
append(ext)
|
append(ext)
|
||||||
else:
|
else:
|
||||||
raise ValueError("invalid part specification %r" % name)
|
raise ValueError("invalid part specification %r" % name)
|
||||||
|
@ -782,7 +810,7 @@ class LocalPath(FSBase):
|
||||||
if args:
|
if args:
|
||||||
path = path.join(*args)
|
path = path.join(*args)
|
||||||
return path
|
return path
|
||||||
return super(LocalPath, self).dirpath(*args, **kwargs)
|
return super().dirpath(*args, **kwargs)
|
||||||
|
|
||||||
def join(self, *args, **kwargs):
|
def join(self, *args, **kwargs):
|
||||||
"""return a new path by appending all 'args' as path
|
"""return a new path by appending all 'args' as path
|
||||||
|
@ -792,7 +820,7 @@ class LocalPath(FSBase):
|
||||||
sep = self.sep
|
sep = self.sep
|
||||||
strargs = [fspath(arg) for arg in args]
|
strargs = [fspath(arg) for arg in args]
|
||||||
strpath = self.strpath
|
strpath = self.strpath
|
||||||
if kwargs.get('abs'):
|
if kwargs.get("abs"):
|
||||||
newargs = []
|
newargs = []
|
||||||
for arg in reversed(strargs):
|
for arg in reversed(strargs):
|
||||||
if isabs(arg):
|
if isabs(arg):
|
||||||
|
@ -806,15 +834,15 @@ class LocalPath(FSBase):
|
||||||
arg = arg.strip(sep)
|
arg = arg.strip(sep)
|
||||||
if iswin32:
|
if iswin32:
|
||||||
# allow unix style paths even on windows.
|
# allow unix style paths even on windows.
|
||||||
arg = arg.strip('/')
|
arg = arg.strip("/")
|
||||||
arg = arg.replace('/', sep)
|
arg = arg.replace("/", sep)
|
||||||
strpath = strpath + actual_sep + arg
|
strpath = strpath + actual_sep + arg
|
||||||
actual_sep = sep
|
actual_sep = sep
|
||||||
obj = object.__new__(self.__class__)
|
obj = object.__new__(self.__class__)
|
||||||
obj.strpath = normpath(strpath)
|
obj.strpath = normpath(strpath)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def open(self, mode='r', ensure=False, encoding=None):
|
def open(self, mode="r", ensure=False, encoding=None):
|
||||||
"""return an opened file with the given mode.
|
"""return an opened file with the given mode.
|
||||||
|
|
||||||
If ensure is True, create parent directories if needed.
|
If ensure is True, create parent directories if needed.
|
||||||
|
@ -841,9 +869,10 @@ class LocalPath(FSBase):
|
||||||
return not kw["dir"] ^ isdir(self.strpath)
|
return not kw["dir"] ^ isdir(self.strpath)
|
||||||
if "file" in kw:
|
if "file" in kw:
|
||||||
return not kw["file"] ^ isfile(self.strpath)
|
return not kw["file"] ^ isfile(self.strpath)
|
||||||
return super(LocalPath, self).check(**kw)
|
return super().check(**kw)
|
||||||
|
|
||||||
_patternchars = set("*?[" + os.path.sep)
|
_patternchars = set("*?[" + os.path.sep)
|
||||||
|
|
||||||
def listdir(self, fil=None, sort=None):
|
def listdir(self, fil=None, sort=None):
|
||||||
"""list directory contents, possibly filter by the given fil func
|
"""list directory contents, possibly filter by the given fil func
|
||||||
and possibly sorted.
|
and possibly sorted.
|
||||||
|
@ -892,8 +921,10 @@ class LocalPath(FSBase):
|
||||||
if stat:
|
if stat:
|
||||||
copystat(self, target)
|
copystat(self, target)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
def rec(p):
|
def rec(p):
|
||||||
return p.check(link=0)
|
return p.check(link=0)
|
||||||
|
|
||||||
for x in self.visit(rec=rec):
|
for x in self.visit(rec=rec):
|
||||||
relpath = x.relto(self)
|
relpath = x.relto(self)
|
||||||
newx = target.join(relpath)
|
newx = target.join(relpath)
|
||||||
|
@ -917,8 +948,9 @@ class LocalPath(FSBase):
|
||||||
|
|
||||||
def dump(self, obj, bin=1):
|
def dump(self, obj, bin=1):
|
||||||
"""pickle object into path location"""
|
"""pickle object into path location"""
|
||||||
f = self.open('wb')
|
f = self.open("wb")
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
try:
|
try:
|
||||||
error.checked_call(pickle.dump, obj, f, bin)
|
error.checked_call(pickle.dump, obj, f, bin)
|
||||||
finally:
|
finally:
|
||||||
|
@ -936,7 +968,7 @@ class LocalPath(FSBase):
|
||||||
"""
|
"""
|
||||||
if ensure:
|
if ensure:
|
||||||
self.dirpath().ensure(dir=1)
|
self.dirpath().ensure(dir=1)
|
||||||
with self.open('wb') as f:
|
with self.open("wb") as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
|
|
||||||
def write_text(self, data, encoding, ensure=False):
|
def write_text(self, data, encoding, ensure=False):
|
||||||
|
@ -945,16 +977,16 @@ class LocalPath(FSBase):
|
||||||
"""
|
"""
|
||||||
if ensure:
|
if ensure:
|
||||||
self.dirpath().ensure(dir=1)
|
self.dirpath().ensure(dir=1)
|
||||||
with self.open('w', encoding=encoding) as f:
|
with self.open("w", encoding=encoding) as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
|
|
||||||
def write(self, data, mode='w', ensure=False):
|
def write(self, data, mode="w", ensure=False):
|
||||||
"""write data into path. If ensure is True create
|
"""write data into path. If ensure is True create
|
||||||
missing parent directories.
|
missing parent directories.
|
||||||
"""
|
"""
|
||||||
if ensure:
|
if ensure:
|
||||||
self.dirpath().ensure(dir=1)
|
self.dirpath().ensure(dir=1)
|
||||||
if 'b' in mode:
|
if "b" in mode:
|
||||||
if not py.builtin._isbytes(data):
|
if not py.builtin._isbytes(data):
|
||||||
raise ValueError("can only process bytes")
|
raise ValueError("can only process bytes")
|
||||||
else:
|
else:
|
||||||
|
@ -991,12 +1023,12 @@ class LocalPath(FSBase):
|
||||||
then the path is forced to be a directory path.
|
then the path is forced to be a directory path.
|
||||||
"""
|
"""
|
||||||
p = self.join(*args)
|
p = self.join(*args)
|
||||||
if kwargs.get('dir', 0):
|
if kwargs.get("dir", 0):
|
||||||
return p._ensuredirs()
|
return p._ensuredirs()
|
||||||
else:
|
else:
|
||||||
p.dirpath()._ensuredirs()
|
p.dirpath()._ensuredirs()
|
||||||
if not p.check(file=1):
|
if not p.check(file=1):
|
||||||
p.open('w').close()
|
p.open("w").close()
|
||||||
return p
|
return p
|
||||||
|
|
||||||
def stat(self, raising=True):
|
def stat(self, raising=True):
|
||||||
|
@ -1036,7 +1068,6 @@ class LocalPath(FSBase):
|
||||||
error.checked_call(os.chdir, self.strpath)
|
error.checked_call(os.chdir, self.strpath)
|
||||||
return old
|
return old
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def as_cwd(self):
|
def as_cwd(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1060,7 +1091,7 @@ class LocalPath(FSBase):
|
||||||
return self.stat().atime
|
return self.stat().atime
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'local(%r)' % self.strpath
|
return "local(%r)" % self.strpath
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""return string representation of the Path."""
|
"""return string representation of the Path."""
|
||||||
|
@ -1072,7 +1103,7 @@ class LocalPath(FSBase):
|
||||||
if rec is True perform recursively.
|
if rec is True perform recursively.
|
||||||
"""
|
"""
|
||||||
if not isinstance(mode, int):
|
if not isinstance(mode, int):
|
||||||
raise TypeError("mode %r must be an integer" % (mode,))
|
raise TypeError(f"mode {mode!r} must be an integer")
|
||||||
if rec:
|
if rec:
|
||||||
for x in self.visit(rec=rec):
|
for x in self.visit(rec=rec):
|
||||||
error.checked_call(os.chmod, str(x), mode)
|
error.checked_call(os.chmod, str(x), mode)
|
||||||
|
@ -1086,7 +1117,7 @@ class LocalPath(FSBase):
|
||||||
pkgpath = None
|
pkgpath = None
|
||||||
for parent in self.parts(reverse=True):
|
for parent in self.parts(reverse=True):
|
||||||
if parent.isdir():
|
if parent.isdir():
|
||||||
if not parent.join('__init__.py').exists():
|
if not parent.join("__init__.py").exists():
|
||||||
break
|
break
|
||||||
if not isimportable(parent.basename):
|
if not isimportable(parent.basename):
|
||||||
break
|
break
|
||||||
|
@ -1127,18 +1158,15 @@ class LocalPath(FSBase):
|
||||||
if not self.check():
|
if not self.check():
|
||||||
raise error.ENOENT(self)
|
raise error.ENOENT(self)
|
||||||
|
|
||||||
if ensuresyspath == 'importlib':
|
if ensuresyspath == "importlib":
|
||||||
if modname is None:
|
if modname is None:
|
||||||
modname = self.purebasename
|
modname = self.purebasename
|
||||||
if not ALLOW_IMPORTLIB_MODE:
|
if not ALLOW_IMPORTLIB_MODE:
|
||||||
raise ImportError(
|
raise ImportError("Can't use importlib due to old version of Python")
|
||||||
"Can't use importlib due to old version of Python")
|
spec = importlib.util.spec_from_file_location(modname, str(self))
|
||||||
spec = importlib.util.spec_from_file_location(
|
|
||||||
modname, str(self))
|
|
||||||
if spec is None:
|
if spec is None:
|
||||||
raise ImportError(
|
raise ImportError(
|
||||||
"Can't find module %s at location %s" %
|
f"Can't find module {modname} at location {str(self)}"
|
||||||
(modname, str(self))
|
|
||||||
)
|
)
|
||||||
mod = importlib.util.module_from_spec(spec)
|
mod = importlib.util.module_from_spec(spec)
|
||||||
spec.loader.exec_module(mod)
|
spec.loader.exec_module(mod)
|
||||||
|
@ -1164,10 +1192,10 @@ class LocalPath(FSBase):
|
||||||
return mod # we don't check anything as we might
|
return mod # we don't check anything as we might
|
||||||
# be in a namespace package ... too icky to check
|
# be in a namespace package ... too icky to check
|
||||||
modfile = mod.__file__
|
modfile = mod.__file__
|
||||||
if modfile[-4:] in ('.pyc', '.pyo'):
|
if modfile[-4:] in (".pyc", ".pyo"):
|
||||||
modfile = modfile[:-1]
|
modfile = modfile[:-1]
|
||||||
elif modfile.endswith('$py.class'):
|
elif modfile.endswith("$py.class"):
|
||||||
modfile = modfile[:-9] + '.py'
|
modfile = modfile[:-9] + ".py"
|
||||||
if modfile.endswith(os.path.sep + "__init__.py"):
|
if modfile.endswith(os.path.sep + "__init__.py"):
|
||||||
if self.basename != "__init__.py":
|
if self.basename != "__init__.py":
|
||||||
modfile = modfile[:-12]
|
modfile = modfile[:-12]
|
||||||
|
@ -1176,8 +1204,8 @@ class LocalPath(FSBase):
|
||||||
except error.ENOENT:
|
except error.ENOENT:
|
||||||
issame = False
|
issame = False
|
||||||
if not issame:
|
if not issame:
|
||||||
ignore = os.getenv('PY_IGNORE_IMPORTMISMATCH')
|
ignore = os.getenv("PY_IGNORE_IMPORTMISMATCH")
|
||||||
if ignore != '1':
|
if ignore != "1":
|
||||||
raise self.ImportMismatchError(modname, modfile, self)
|
raise self.ImportMismatchError(modname, modfile, self)
|
||||||
return mod
|
return mod
|
||||||
else:
|
else:
|
||||||
|
@ -1186,6 +1214,7 @@ class LocalPath(FSBase):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# we have a custom modname, do a pseudo-import
|
# we have a custom modname, do a pseudo-import
|
||||||
import types
|
import types
|
||||||
|
|
||||||
mod = types.ModuleType(modname)
|
mod = types.ModuleType(modname)
|
||||||
mod.__file__ = str(self)
|
mod.__file__ = str(self)
|
||||||
sys.modules[modname] = mod
|
sys.modules[modname] = mod
|
||||||
|
@ -1202,8 +1231,9 @@ class LocalPath(FSBase):
|
||||||
The process is directly invoked and not through a system shell.
|
The process is directly invoked and not through a system shell.
|
||||||
"""
|
"""
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
argv = map_as_list(str, argv)
|
argv = map_as_list(str, argv)
|
||||||
popen_opts['stdout'] = popen_opts['stderr'] = PIPE
|
popen_opts["stdout"] = popen_opts["stderr"] = PIPE
|
||||||
proc = Popen([str(self)] + argv, **popen_opts)
|
proc = Popen([str(self)] + argv, **popen_opts)
|
||||||
stdout, stderr = proc.communicate()
|
stdout, stderr = proc.communicate()
|
||||||
ret = proc.wait()
|
ret = proc.wait()
|
||||||
|
@ -1212,8 +1242,13 @@ class LocalPath(FSBase):
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
if py.builtin._isbytes(stderr):
|
if py.builtin._isbytes(stderr):
|
||||||
stderr = py.builtin._totext(stderr, sys.getdefaultencoding())
|
stderr = py.builtin._totext(stderr, sys.getdefaultencoding())
|
||||||
raise py.process.cmdexec.Error(ret, ret, str(self),
|
raise py.process.cmdexec.Error(
|
||||||
stdout, stderr,)
|
ret,
|
||||||
|
ret,
|
||||||
|
str(self),
|
||||||
|
stdout,
|
||||||
|
stderr,
|
||||||
|
)
|
||||||
return stdout
|
return stdout
|
||||||
|
|
||||||
def sysfind(cls, name, checker=None, paths=None):
|
def sysfind(cls, name, checker=None, paths=None):
|
||||||
|
@ -1231,21 +1266,22 @@ class LocalPath(FSBase):
|
||||||
else:
|
else:
|
||||||
if paths is None:
|
if paths is None:
|
||||||
if iswin32:
|
if iswin32:
|
||||||
paths = os.environ['Path'].split(';')
|
paths = os.environ["Path"].split(";")
|
||||||
if '' not in paths and '.' not in paths:
|
if "" not in paths and "." not in paths:
|
||||||
paths.append('.')
|
paths.append(".")
|
||||||
try:
|
try:
|
||||||
systemroot = os.environ['SYSTEMROOT']
|
systemroot = os.environ["SYSTEMROOT"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
paths = [path.replace('%SystemRoot%', systemroot)
|
paths = [
|
||||||
for path in paths]
|
path.replace("%SystemRoot%", systemroot) for path in paths
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
paths = os.environ['PATH'].split(':')
|
paths = os.environ["PATH"].split(":")
|
||||||
tryadd = []
|
tryadd = []
|
||||||
if iswin32:
|
if iswin32:
|
||||||
tryadd += os.environ['PATHEXT'].split(os.pathsep)
|
tryadd += os.environ["PATHEXT"].split(os.pathsep)
|
||||||
tryadd.append("")
|
tryadd.append("")
|
||||||
|
|
||||||
for x in paths:
|
for x in paths:
|
||||||
|
@ -1260,17 +1296,19 @@ class LocalPath(FSBase):
|
||||||
except error.EACCES:
|
except error.EACCES:
|
||||||
pass
|
pass
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sysfind = classmethod(sysfind)
|
sysfind = classmethod(sysfind)
|
||||||
|
|
||||||
def _gethomedir(cls):
|
def _gethomedir(cls):
|
||||||
try:
|
try:
|
||||||
x = os.environ['HOME']
|
x = os.environ["HOME"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
try:
|
try:
|
||||||
x = os.environ["HOMEDRIVE"] + os.environ['HOMEPATH']
|
x = os.environ["HOMEDRIVE"] + os.environ["HOMEPATH"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return None
|
return None
|
||||||
return cls(x)
|
return cls(x)
|
||||||
|
|
||||||
_gethomedir = classmethod(_gethomedir)
|
_gethomedir = classmethod(_gethomedir)
|
||||||
|
|
||||||
# """
|
# """
|
||||||
|
@ -1282,6 +1320,7 @@ class LocalPath(FSBase):
|
||||||
(where tempfiles are usually created in)
|
(where tempfiles are usually created in)
|
||||||
"""
|
"""
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
return py.path.local(tempfile.gettempdir())
|
return py.path.local(tempfile.gettempdir())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -1290,12 +1329,14 @@ class LocalPath(FSBase):
|
||||||
(which we created ourself).
|
(which we created ourself).
|
||||||
"""
|
"""
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
if rootdir is None:
|
if rootdir is None:
|
||||||
rootdir = cls.get_temproot()
|
rootdir = cls.get_temproot()
|
||||||
return cls(error.checked_call(tempfile.mkdtemp, dir=str(rootdir)))
|
return cls(error.checked_call(tempfile.mkdtemp, dir=str(rootdir)))
|
||||||
|
|
||||||
def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3,
|
def make_numbered_dir(
|
||||||
lock_timeout=172800): # two days
|
cls, prefix="session-", rootdir=None, keep=3, lock_timeout=172800
|
||||||
|
): # two days
|
||||||
"""return unique directory with a number greater than the current
|
"""return unique directory with a number greater than the current
|
||||||
maximum one. The number is assumed to start directly after prefix.
|
maximum one. The number is assumed to start directly after prefix.
|
||||||
if keep is true directories with a number less than (maxnum-keep)
|
if keep is true directories with a number less than (maxnum-keep)
|
||||||
|
@ -1306,6 +1347,7 @@ class LocalPath(FSBase):
|
||||||
rootdir = cls.get_temproot()
|
rootdir = cls.get_temproot()
|
||||||
|
|
||||||
nprefix = prefix.lower()
|
nprefix = prefix.lower()
|
||||||
|
|
||||||
def parse_num(path):
|
def parse_num(path):
|
||||||
"""parse the number out of a path (if it matches the prefix)"""
|
"""parse the number out of a path (if it matches the prefix)"""
|
||||||
nbasename = path.basename.lower()
|
nbasename = path.basename.lower()
|
||||||
|
@ -1318,18 +1360,21 @@ class LocalPath(FSBase):
|
||||||
def create_lockfile(path):
|
def create_lockfile(path):
|
||||||
"""exclusively create lockfile. Throws when failed"""
|
"""exclusively create lockfile. Throws when failed"""
|
||||||
mypid = os.getpid()
|
mypid = os.getpid()
|
||||||
lockfile = path.join('.lock')
|
lockfile = path.join(".lock")
|
||||||
if hasattr(lockfile, 'mksymlinkto'):
|
if hasattr(lockfile, "mksymlinkto"):
|
||||||
lockfile.mksymlinkto(str(mypid))
|
lockfile.mksymlinkto(str(mypid))
|
||||||
else:
|
else:
|
||||||
fd = error.checked_call(os.open, str(lockfile), os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644)
|
fd = error.checked_call(
|
||||||
with os.fdopen(fd, 'w') as f:
|
os.open, str(lockfile), os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644
|
||||||
|
)
|
||||||
|
with os.fdopen(fd, "w") as f:
|
||||||
f.write(str(mypid))
|
f.write(str(mypid))
|
||||||
return lockfile
|
return lockfile
|
||||||
|
|
||||||
def atexit_remove_lockfile(lockfile):
|
def atexit_remove_lockfile(lockfile):
|
||||||
"""ensure lockfile is removed at process exit"""
|
"""ensure lockfile is removed at process exit"""
|
||||||
mypid = os.getpid()
|
mypid = os.getpid()
|
||||||
|
|
||||||
def try_remove_lockfile():
|
def try_remove_lockfile():
|
||||||
# in a fork() situation, only the last process should
|
# in a fork() situation, only the last process should
|
||||||
# remove the .lock, otherwise the other processes run the
|
# remove the .lock, otherwise the other processes run the
|
||||||
|
@ -1342,6 +1387,7 @@ class LocalPath(FSBase):
|
||||||
lockfile.remove()
|
lockfile.remove()
|
||||||
except error.Error:
|
except error.Error:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
atexit.register(try_remove_lockfile)
|
atexit.register(try_remove_lockfile)
|
||||||
|
|
||||||
# compute the maximum number currently in use with the prefix
|
# compute the maximum number currently in use with the prefix
|
||||||
|
@ -1381,7 +1427,7 @@ class LocalPath(FSBase):
|
||||||
except error.Error:
|
except error.Error:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
garbage_prefix = prefix + 'garbage-'
|
garbage_prefix = prefix + "garbage-"
|
||||||
|
|
||||||
def is_garbage(path):
|
def is_garbage(path):
|
||||||
"""check if path denotes directory scheduled for removal"""
|
"""check if path denotes directory scheduled for removal"""
|
||||||
|
@ -1429,15 +1475,15 @@ class LocalPath(FSBase):
|
||||||
|
|
||||||
# make link...
|
# make link...
|
||||||
try:
|
try:
|
||||||
username = os.environ['USER'] #linux, et al
|
username = os.environ["USER"] # linux, et al
|
||||||
except KeyError:
|
except KeyError:
|
||||||
try:
|
try:
|
||||||
username = os.environ['USERNAME'] #windows
|
username = os.environ["USERNAME"] # windows
|
||||||
except KeyError:
|
except KeyError:
|
||||||
username = 'current'
|
username = "current"
|
||||||
|
|
||||||
src = str(udir)
|
src = str(udir)
|
||||||
dest = src[:src.rfind('-')] + '-' + username
|
dest = src[: src.rfind("-")] + "-" + username
|
||||||
try:
|
try:
|
||||||
os.unlink(dest)
|
os.unlink(dest)
|
||||||
except OSError:
|
except OSError:
|
||||||
|
@ -1448,12 +1494,14 @@ class LocalPath(FSBase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return udir
|
return udir
|
||||||
|
|
||||||
make_numbered_dir = classmethod(make_numbered_dir)
|
make_numbered_dir = classmethod(make_numbered_dir)
|
||||||
|
|
||||||
|
|
||||||
def copymode(src, dest):
|
def copymode(src, dest):
|
||||||
"""copy permission from src to dst."""
|
"""copy permission from src to dst."""
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
shutil.copymode(src, dest)
|
shutil.copymode(src, dest)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1461,14 +1509,15 @@ def copystat(src, dest):
|
||||||
"""copy permission, last modification time,
|
"""copy permission, last modification time,
|
||||||
last access time, and flags from src to dst."""
|
last access time, and flags from src to dst."""
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
shutil.copystat(str(src), str(dest))
|
shutil.copystat(str(src), str(dest))
|
||||||
|
|
||||||
|
|
||||||
def copychunked(src, dest):
|
def copychunked(src, dest):
|
||||||
chunksize = 524288 # half a meg of bytes
|
chunksize = 524288 # half a meg of bytes
|
||||||
fsrc = src.open('rb')
|
fsrc = src.open("rb")
|
||||||
try:
|
try:
|
||||||
fdest = dest.open('wb')
|
fdest = dest.open("wb")
|
||||||
try:
|
try:
|
||||||
while 1:
|
while 1:
|
||||||
buf = fsrc.read(chunksize)
|
buf = fsrc.read(chunksize)
|
||||||
|
@ -1482,8 +1531,9 @@ def copychunked(src, dest):
|
||||||
|
|
||||||
|
|
||||||
def isimportable(name):
|
def isimportable(name):
|
||||||
if name and (name[0].isalpha() or name[0] == '_'):
|
if name and (name[0].isalpha() or name[0] == "_"):
|
||||||
name = name.replace("_", '')
|
name = name.replace("_", "")
|
||||||
return not name or name.isalnum()
|
return not name or name.isalnum()
|
||||||
|
|
||||||
|
|
||||||
local = LocalPath
|
local = LocalPath
|
||||||
|
|
|
@ -18,6 +18,7 @@ from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
|
|
|
@ -6,5 +6,5 @@ import sys
|
||||||
import _pytest._py.error as error
|
import _pytest._py.error as error
|
||||||
import _pytest._py.path as path
|
import _pytest._py.path as path
|
||||||
|
|
||||||
sys.modules['py.error'] = error
|
sys.modules["py.error"] = error
|
||||||
sys.modules['py.path'] = path
|
sys.modules["py.path"] = path
|
||||||
|
|
Loading…
Reference in New Issue