first commit
This commit is contained in:
commit
417e54da96
5696 changed files with 900003 additions and 0 deletions
|
@ -0,0 +1,16 @@
|
|||
from __future__ import annotations
|
||||
|
||||
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__ = [
|
||||
"copy",
|
||||
"copytree",
|
||||
"ensure_dir",
|
||||
"get_short_path_name",
|
||||
"make_exe",
|
||||
"safe_delete",
|
||||
"set_tree",
|
||||
"symlink",
|
||||
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,30 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from stat import S_IXGRP, S_IXOTH, S_IXUSR
|
||||
|
||||
|
||||
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(str(folder)):
|
||||
for filename in files:
|
||||
os.chmod(os.path.join(root, filename), stat)
|
||||
|
||||
|
||||
__all__ = (
|
||||
"make_exe",
|
||||
"set_tree",
|
||||
)
|
|
@ -0,0 +1,83 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from stat import S_IWUSR
|
||||
|
||||
|
||||
def ensure_dir(path):
|
||||
if not path.exists():
|
||||
logging.debug("create folder %s", str(path))
|
||||
os.makedirs(str(path))
|
||||
|
||||
|
||||
def ensure_safe_to_do(src, dest):
|
||||
if src == dest:
|
||||
msg = f"source and destination is the same {src}"
|
||||
raise ValueError(msg)
|
||||
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(str(src), str(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): # noqa: ARG001
|
||||
if not os.access(path, os.W_OK):
|
||||
os.chmod(path, S_IWUSR)
|
||||
func(path)
|
||||
else:
|
||||
raise # noqa: PLE0704
|
||||
|
||||
kwargs = {"onexc" if sys.version_info >= (3, 12) else "onerror": onerror}
|
||||
shutil.rmtree(str(dest), ignore_errors=True, **kwargs)
|
||||
|
||||
|
||||
class _Debug:
|
||||
def __init__(self, src, dest) -> None:
|
||||
self.src = src
|
||||
self.dest = dest
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{'directory ' if self.src.is_dir() else ''}{self.src!s} to {self.dest!s}"
|
||||
|
||||
|
||||
__all__ = [
|
||||
"copy",
|
||||
"copytree",
|
||||
"ensure_dir",
|
||||
"safe_delete",
|
||||
"symlink",
|
||||
"symlink",
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
from __future__ import annotations
|
||||
|
||||
|
||||
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 # noqa: PLC0415
|
||||
from ctypes import wintypes # noqa: PLC0415
|
||||
|
||||
_GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW # noqa: N806
|
||||
_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
|
||||
output_buf_size = needed
|
||||
|
||||
|
||||
__all__ = [
|
||||
"get_short_path_name",
|
||||
]
|
Loading…
Add table
Add a link
Reference in a new issue