This commit is contained in:
Waylon Walker 2022-03-31 20:20:07 -05:00
commit 38355d2442
No known key found for this signature in database
GPG key ID: 66E2BF2B4190EFE4
9083 changed files with 1225834 additions and 0 deletions

View file

@ -0,0 +1,18 @@
from __future__ import absolute_import, unicode_literals
from ._pathlib import Path
from ._permission import make_exe, set_tree
from ._sync import copy, copytree, ensure_dir, safe_delete, symlink
from ._win import get_short_path_name
__all__ = (
"ensure_dir",
"symlink",
"copy",
"copytree",
"Path",
"make_exe",
"set_tree",
"safe_delete",
"get_short_path_name",
)

View file

@ -0,0 +1,17 @@
from __future__ import absolute_import, unicode_literals
import sys
import six
if six.PY3:
from pathlib import Path
else:
if sys.platform == "win32":
# workaround for https://github.com/mcmtroffaes/pathlib2/issues/56
from .via_os_path import Path
else:
from pathlib2 import Path
__all__ = ("Path",)

View file

@ -0,0 +1,151 @@
from __future__ import absolute_import, unicode_literals
import os
import platform
from contextlib import contextmanager
from virtualenv.util.six import ensure_str, ensure_text
IS_PYPY = platform.python_implementation() == "PyPy"
class Path(object):
def __init__(self, path):
if isinstance(path, Path):
_path = path._path
else:
_path = ensure_text(path)
if IS_PYPY:
_path = _path.encode("utf-8")
self._path = _path
def __repr__(self):
return ensure_str("Path({})".format(ensure_text(self._path)))
def __unicode__(self):
return ensure_text(self._path)
def __str__(self):
return ensure_str(self._path)
def __div__(self, other):
if isinstance(other, Path):
right = other._path
else:
right = ensure_text(other)
if IS_PYPY:
right = right.encode("utf-8")
return Path(os.path.join(self._path, right))
def __truediv__(self, other):
return self.__div__(other)
def __eq__(self, other):
return self._path == (other._path if isinstance(other, Path) else None)
def __ne__(self, other):
return not (self == other)
def __hash__(self):
return hash(self._path)
def as_posix(self):
return str(self).replace(os.sep, "/")
def exists(self):
return os.path.exists(self._path)
@property
def parent(self):
return Path(os.path.abspath(os.path.join(self._path, os.path.pardir)))
def resolve(self):
return Path(os.path.realpath(self._path))
@property
def name(self):
return os.path.basename(self._path)
@property
def parts(self):
return self._path.split(os.sep)
def is_file(self):
return os.path.isfile(self._path)
def is_dir(self):
return os.path.isdir(self._path)
def mkdir(self, parents=True, exist_ok=True):
try:
os.makedirs(self._path)
except OSError:
if not exist_ok:
raise
def read_text(self, encoding="utf-8"):
return self.read_bytes().decode(encoding)
def read_bytes(self):
with open(self._path, "rb") as file_handler:
return file_handler.read()
def write_bytes(self, content):
with open(self._path, "wb") as file_handler:
file_handler.write(content)
def write_text(self, text, encoding="utf-8"):
self.write_bytes(text.encode(encoding))
def iterdir(self):
for p in os.listdir(self._path):
yield Path(os.path.join(self._path, p))
@property
def suffix(self):
_, ext = os.path.splitext(self.name)
return ext
@property
def stem(self):
base, _ = os.path.splitext(self.name)
return base
@contextmanager
def open(self, mode="r"):
with open(self._path, mode) as file_handler:
yield file_handler
@property
def parents(self):
result = []
parts = self.parts
for i in range(len(parts) - 1):
result.append(Path(os.sep.join(parts[0 : i + 1])))
return result[::-1]
def unlink(self):
os.remove(self._path)
def with_name(self, name):
return self.parent / name
def is_symlink(self):
return os.path.islink(self._path)
def relative_to(self, other):
if not self._path.startswith(other._path):
raise ValueError("{} does not start with {}".format(self._path, other._path))
return Path(os.sep.join(self.parts[len(other.parts) :]))
def stat(self):
return os.stat(self._path)
def chmod(self, mode):
os.chmod(self._path, mode)
def absolute(self):
return Path(os.path.abspath(self._path))
__all__ = ("Path",)

View file

@ -0,0 +1,32 @@
from __future__ import absolute_import, unicode_literals
import os
from stat import S_IXGRP, S_IXOTH, S_IXUSR
from virtualenv.util.six import ensure_text
def make_exe(filename):
original_mode = filename.stat().st_mode
levels = [S_IXUSR, S_IXGRP, S_IXOTH]
for at in range(len(levels), 0, -1):
try:
mode = original_mode
for level in levels[:at]:
mode |= level
filename.chmod(mode)
break
except OSError:
continue
def set_tree(folder, stat):
for root, _, files in os.walk(ensure_text(str(folder))):
for filename in files:
os.chmod(os.path.join(root, filename), stat)
__all__ = (
"make_exe",
"set_tree",
)

View file

@ -0,0 +1,97 @@
from __future__ import absolute_import, unicode_literals
import logging
import os
import shutil
from stat import S_IWUSR
from six import PY2
from virtualenv.info import IS_CPYTHON, IS_WIN
from virtualenv.util.six import ensure_text
if PY2 and IS_CPYTHON and IS_WIN: # CPython2 on Windows supports unicode paths if passed as unicode
def norm(src):
return ensure_text(str(src))
else:
norm = str
def ensure_dir(path):
if not path.exists():
logging.debug("create folder %s", ensure_text(str(path)))
os.makedirs(norm(path))
def ensure_safe_to_do(src, dest):
if src == dest:
raise ValueError("source and destination is the same {}".format(src))
if not dest.exists():
return
if dest.is_dir() and not dest.is_symlink():
logging.debug("remove directory %s", dest)
safe_delete(dest)
else:
logging.debug("remove file %s", dest)
dest.unlink()
def symlink(src, dest):
ensure_safe_to_do(src, dest)
logging.debug("symlink %s", _Debug(src, dest))
dest.symlink_to(src, target_is_directory=src.is_dir())
def copy(src, dest):
ensure_safe_to_do(src, dest)
is_dir = src.is_dir()
method = copytree if is_dir else shutil.copy
logging.debug("copy %s", _Debug(src, dest))
method(norm(src), norm(dest))
def copytree(src, dest):
for root, _, files in os.walk(src):
dest_dir = os.path.join(dest, os.path.relpath(root, src))
if not os.path.isdir(dest_dir):
os.makedirs(dest_dir)
for name in files:
src_f = os.path.join(root, name)
dest_f = os.path.join(dest_dir, name)
shutil.copy(src_f, dest_f)
def safe_delete(dest):
def onerror(func, path, exc_info):
if not os.access(path, os.W_OK):
os.chmod(path, S_IWUSR)
func(path)
else:
raise
shutil.rmtree(ensure_text(str(dest)), ignore_errors=True, onerror=onerror)
class _Debug(object):
def __init__(self, src, dest):
self.src = src
self.dest = dest
def __str__(self):
return "{}{} to {}".format(
"directory " if self.src.is_dir() else "",
ensure_text(str(self.src)),
ensure_text(str(self.dest)),
)
__all__ = (
"ensure_dir",
"symlink",
"copy",
"symlink",
"copytree",
"safe_delete",
)

View file

@ -0,0 +1,19 @@
def get_short_path_name(long_name):
"""
Gets the short path name of a given long path.
http://stackoverflow.com/a/23598461/200291
"""
import ctypes
from ctypes import wintypes
_GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW
_GetShortPathNameW.argtypes = [wintypes.LPCWSTR, wintypes.LPWSTR, wintypes.DWORD]
_GetShortPathNameW.restype = wintypes.DWORD
output_buf_size = 0
while True:
output_buf = ctypes.create_unicode_buffer(output_buf_size)
needed = _GetShortPathNameW(long_name, output_buf, output_buf_size)
if output_buf_size >= needed:
return output_buf.value
else:
output_buf_size = needed