Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- lib/python3.12/site-packages/setuptools/_distutils/__init__.py +14 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_log.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_macos_compat.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_modified.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/core.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/debug.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dist.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/errors.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/extension.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/log.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/util.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/version.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/__pycache__/zosccompiler.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/_log.py +3 -0
- lib/python3.12/site-packages/setuptools/_distutils/_macos_compat.py +12 -0
- lib/python3.12/site-packages/setuptools/_distutils/_modified.py +95 -0
- lib/python3.12/site-packages/setuptools/_distutils/_msvccompiler.py +16 -0
- lib/python3.12/site-packages/setuptools/_distutils/archive_util.py +294 -0
- lib/python3.12/site-packages/setuptools/_distutils/ccompiler.py +26 -0
- lib/python3.12/site-packages/setuptools/_distutils/cmd.py +554 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__init__.py +23 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/_framework_compat.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-312.pyc +0 -0
- lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-312.pyc +0 -0
lib/python3.12/site-packages/setuptools/_distutils/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import importlib
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
__version__, _, _ = sys.version.partition(' ')
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
try:
|
| 8 |
+
# Allow Debian and pkgsrc (only) to customize system
|
| 9 |
+
# behavior. Ref pypa/distutils#2 and pypa/distutils#16.
|
| 10 |
+
# This hook is deprecated and no other environments
|
| 11 |
+
# should use it.
|
| 12 |
+
importlib.import_module('_distutils_system_mod')
|
| 13 |
+
except ImportError:
|
| 14 |
+
pass
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (536 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_log.cpython-312.pyc
ADDED
|
Binary file (284 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_macos_compat.cpython-312.pyc
ADDED
|
Binary file (573 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_modified.cpython-312.pyc
ADDED
|
Binary file (4.8 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-312.pyc
ADDED
|
Binary file (731 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-312.pyc
ADDED
|
Binary file (10.8 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-312.pyc
ADDED
|
Binary file (700 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-312.pyc
ADDED
|
Binary file (22.6 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/core.cpython-312.pyc
ADDED
|
Binary file (9.12 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-312.pyc
ADDED
|
Binary file (664 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/debug.cpython-312.pyc
ADDED
|
Binary file (327 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-312.pyc
ADDED
|
Binary file (721 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-312.pyc
ADDED
|
Binary file (10.4 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/dist.cpython-312.pyc
ADDED
|
Binary file (56.2 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/errors.cpython-312.pyc
ADDED
|
Binary file (4.54 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/extension.cpython-312.pyc
ADDED
|
Binary file (10.3 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-312.pyc
ADDED
|
Binary file (15.8 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-312.pyc
ADDED
|
Binary file (9.49 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-312.pyc
ADDED
|
Binary file (17.9 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/log.cpython-312.pyc
ADDED
|
Binary file (2.62 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-312.pyc
ADDED
|
Binary file (5.65 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-312.pyc
ADDED
|
Binary file (23.1 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-312.pyc
ADDED
|
Binary file (10.8 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-312.pyc
ADDED
|
Binary file (424 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/util.cpython-312.pyc
ADDED
|
Binary file (19.5 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/version.cpython-312.pyc
ADDED
|
Binary file (10.6 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-312.pyc
ADDED
|
Binary file (6.9 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/__pycache__/zosccompiler.cpython-312.pyc
ADDED
|
Binary file (303 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/_log.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import logging
|
| 2 |
+
|
| 3 |
+
log = logging.getLogger()
|
lib/python3.12/site-packages/setuptools/_distutils/_macos_compat.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import importlib
|
| 2 |
+
import sys
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def bypass_compiler_fixup(cmd, args):
|
| 6 |
+
return cmd
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
if sys.platform == 'darwin':
|
| 10 |
+
compiler_fixup = importlib.import_module('_osx_support').compiler_fixup
|
| 11 |
+
else:
|
| 12 |
+
compiler_fixup = bypass_compiler_fixup
|
lib/python3.12/site-packages/setuptools/_distutils/_modified.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Timestamp comparison of files and groups of files."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import functools
|
| 6 |
+
import os.path
|
| 7 |
+
from collections.abc import Callable, Iterable
|
| 8 |
+
from typing import Literal, TypeVar
|
| 9 |
+
|
| 10 |
+
from jaraco.functools import splat
|
| 11 |
+
|
| 12 |
+
from .compat.py39 import zip_strict
|
| 13 |
+
from .errors import DistutilsFileError
|
| 14 |
+
|
| 15 |
+
_SourcesT = TypeVar(
|
| 16 |
+
"_SourcesT", bound="str | bytes | os.PathLike[str] | os.PathLike[bytes]"
|
| 17 |
+
)
|
| 18 |
+
_TargetsT = TypeVar(
|
| 19 |
+
"_TargetsT", bound="str | bytes | os.PathLike[str] | os.PathLike[bytes]"
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def _newer(source, target):
|
| 24 |
+
return not os.path.exists(target) or (
|
| 25 |
+
os.path.getmtime(source) > os.path.getmtime(target)
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def newer(
|
| 30 |
+
source: str | bytes | os.PathLike[str] | os.PathLike[bytes],
|
| 31 |
+
target: str | bytes | os.PathLike[str] | os.PathLike[bytes],
|
| 32 |
+
) -> bool:
|
| 33 |
+
"""
|
| 34 |
+
Is source modified more recently than target.
|
| 35 |
+
|
| 36 |
+
Returns True if 'source' is modified more recently than
|
| 37 |
+
'target' or if 'target' does not exist.
|
| 38 |
+
|
| 39 |
+
Raises DistutilsFileError if 'source' does not exist.
|
| 40 |
+
"""
|
| 41 |
+
if not os.path.exists(source):
|
| 42 |
+
raise DistutilsFileError(f"file {os.path.abspath(source)!r} does not exist")
|
| 43 |
+
|
| 44 |
+
return _newer(source, target)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def newer_pairwise(
|
| 48 |
+
sources: Iterable[_SourcesT],
|
| 49 |
+
targets: Iterable[_TargetsT],
|
| 50 |
+
newer: Callable[[_SourcesT, _TargetsT], bool] = newer,
|
| 51 |
+
) -> tuple[list[_SourcesT], list[_TargetsT]]:
|
| 52 |
+
"""
|
| 53 |
+
Filter filenames where sources are newer than targets.
|
| 54 |
+
|
| 55 |
+
Walk two filename iterables in parallel, testing if each source is newer
|
| 56 |
+
than its corresponding target. Returns a pair of lists (sources,
|
| 57 |
+
targets) where source is newer than target, according to the semantics
|
| 58 |
+
of 'newer()'.
|
| 59 |
+
"""
|
| 60 |
+
newer_pairs = filter(splat(newer), zip_strict(sources, targets))
|
| 61 |
+
return tuple(map(list, zip(*newer_pairs))) or ([], [])
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def newer_group(
|
| 65 |
+
sources: Iterable[str | bytes | os.PathLike[str] | os.PathLike[bytes]],
|
| 66 |
+
target: str | bytes | os.PathLike[str] | os.PathLike[bytes],
|
| 67 |
+
missing: Literal["error", "ignore", "newer"] = "error",
|
| 68 |
+
) -> bool:
|
| 69 |
+
"""
|
| 70 |
+
Is target out-of-date with respect to any file in sources.
|
| 71 |
+
|
| 72 |
+
Return True if 'target' is out-of-date with respect to any file
|
| 73 |
+
listed in 'sources'. In other words, if 'target' exists and is newer
|
| 74 |
+
than every file in 'sources', return False; otherwise return True.
|
| 75 |
+
``missing`` controls how to handle a missing source file:
|
| 76 |
+
|
| 77 |
+
- error (default): allow the ``stat()`` call to fail.
|
| 78 |
+
- ignore: silently disregard any missing source files.
|
| 79 |
+
- newer: treat missing source files as "target out of date". This
|
| 80 |
+
mode is handy in "dry-run" mode: it will pretend to carry out
|
| 81 |
+
commands that wouldn't work because inputs are missing, but
|
| 82 |
+
that doesn't matter because dry-run won't run the commands.
|
| 83 |
+
"""
|
| 84 |
+
|
| 85 |
+
def missing_as_newer(source):
|
| 86 |
+
return missing == 'newer' and not os.path.exists(source)
|
| 87 |
+
|
| 88 |
+
ignored = os.path.exists if missing == 'ignore' else None
|
| 89 |
+
return not os.path.exists(target) or any(
|
| 90 |
+
missing_as_newer(source) or _newer(source, target)
|
| 91 |
+
for source in filter(ignored, sources)
|
| 92 |
+
)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
newer_pairwise_group = functools.partial(newer_pairwise, newer=newer_group)
|
lib/python3.12/site-packages/setuptools/_distutils/_msvccompiler.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import warnings
|
| 2 |
+
|
| 3 |
+
from .compilers.C import msvc
|
| 4 |
+
|
| 5 |
+
__all__ = ["MSVCCompiler"]
|
| 6 |
+
|
| 7 |
+
MSVCCompiler = msvc.Compiler
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def __getattr__(name):
|
| 11 |
+
if name == '_get_vc_env':
|
| 12 |
+
warnings.warn(
|
| 13 |
+
"_get_vc_env is private; find an alternative (pypa/distutils#340)"
|
| 14 |
+
)
|
| 15 |
+
return msvc._get_vc_env
|
| 16 |
+
raise AttributeError(name)
|
lib/python3.12/site-packages/setuptools/_distutils/archive_util.py
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.archive_util
|
| 2 |
+
|
| 3 |
+
Utility functions for creating archive files (tarballs, zip files,
|
| 4 |
+
that sort of thing)."""
|
| 5 |
+
|
| 6 |
+
from __future__ import annotations
|
| 7 |
+
|
| 8 |
+
import os
|
| 9 |
+
from typing import Literal, overload
|
| 10 |
+
|
| 11 |
+
try:
|
| 12 |
+
import zipfile
|
| 13 |
+
except ImportError:
|
| 14 |
+
zipfile = None
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
from ._log import log
|
| 18 |
+
from .dir_util import mkpath
|
| 19 |
+
from .errors import DistutilsExecError
|
| 20 |
+
from .spawn import spawn
|
| 21 |
+
|
| 22 |
+
try:
|
| 23 |
+
from pwd import getpwnam
|
| 24 |
+
except ImportError:
|
| 25 |
+
getpwnam = None
|
| 26 |
+
|
| 27 |
+
try:
|
| 28 |
+
from grp import getgrnam
|
| 29 |
+
except ImportError:
|
| 30 |
+
getgrnam = None
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def _get_gid(name):
|
| 34 |
+
"""Returns a gid, given a group name."""
|
| 35 |
+
if getgrnam is None or name is None:
|
| 36 |
+
return None
|
| 37 |
+
try:
|
| 38 |
+
result = getgrnam(name)
|
| 39 |
+
except KeyError:
|
| 40 |
+
result = None
|
| 41 |
+
if result is not None:
|
| 42 |
+
return result[2]
|
| 43 |
+
return None
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def _get_uid(name):
|
| 47 |
+
"""Returns an uid, given a user name."""
|
| 48 |
+
if getpwnam is None or name is None:
|
| 49 |
+
return None
|
| 50 |
+
try:
|
| 51 |
+
result = getpwnam(name)
|
| 52 |
+
except KeyError:
|
| 53 |
+
result = None
|
| 54 |
+
if result is not None:
|
| 55 |
+
return result[2]
|
| 56 |
+
return None
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def make_tarball(
|
| 60 |
+
base_name: str,
|
| 61 |
+
base_dir: str | os.PathLike[str],
|
| 62 |
+
compress: Literal["gzip", "bzip2", "xz"] | None = "gzip",
|
| 63 |
+
verbose: bool = False,
|
| 64 |
+
dry_run: bool = False,
|
| 65 |
+
owner: str | None = None,
|
| 66 |
+
group: str | None = None,
|
| 67 |
+
) -> str:
|
| 68 |
+
"""Create a (possibly compressed) tar file from all the files under
|
| 69 |
+
'base_dir'.
|
| 70 |
+
|
| 71 |
+
'compress' must be "gzip" (the default), "bzip2", "xz", or None.
|
| 72 |
+
|
| 73 |
+
'owner' and 'group' can be used to define an owner and a group for the
|
| 74 |
+
archive that is being built. If not provided, the current owner and group
|
| 75 |
+
will be used.
|
| 76 |
+
|
| 77 |
+
The output tar file will be named 'base_dir' + ".tar", possibly plus
|
| 78 |
+
the appropriate compression extension (".gz", ".bz2", ".xz" or ".Z").
|
| 79 |
+
|
| 80 |
+
Returns the output filename.
|
| 81 |
+
"""
|
| 82 |
+
tar_compression = {
|
| 83 |
+
'gzip': 'gz',
|
| 84 |
+
'bzip2': 'bz2',
|
| 85 |
+
'xz': 'xz',
|
| 86 |
+
None: '',
|
| 87 |
+
}
|
| 88 |
+
compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'xz': '.xz'}
|
| 89 |
+
|
| 90 |
+
# flags for compression program, each element of list will be an argument
|
| 91 |
+
if compress is not None and compress not in compress_ext.keys():
|
| 92 |
+
raise ValueError(
|
| 93 |
+
"bad value for 'compress': must be None, 'gzip', 'bzip2', 'xz'"
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
archive_name = base_name + '.tar'
|
| 97 |
+
archive_name += compress_ext.get(compress, '')
|
| 98 |
+
|
| 99 |
+
mkpath(os.path.dirname(archive_name), dry_run=dry_run)
|
| 100 |
+
|
| 101 |
+
# creating the tarball
|
| 102 |
+
import tarfile # late import so Python build itself doesn't break
|
| 103 |
+
|
| 104 |
+
log.info('Creating tar archive')
|
| 105 |
+
|
| 106 |
+
uid = _get_uid(owner)
|
| 107 |
+
gid = _get_gid(group)
|
| 108 |
+
|
| 109 |
+
def _set_uid_gid(tarinfo):
|
| 110 |
+
if gid is not None:
|
| 111 |
+
tarinfo.gid = gid
|
| 112 |
+
tarinfo.gname = group
|
| 113 |
+
if uid is not None:
|
| 114 |
+
tarinfo.uid = uid
|
| 115 |
+
tarinfo.uname = owner
|
| 116 |
+
return tarinfo
|
| 117 |
+
|
| 118 |
+
if not dry_run:
|
| 119 |
+
tar = tarfile.open(archive_name, f'w|{tar_compression[compress]}')
|
| 120 |
+
try:
|
| 121 |
+
tar.add(base_dir, filter=_set_uid_gid)
|
| 122 |
+
finally:
|
| 123 |
+
tar.close()
|
| 124 |
+
|
| 125 |
+
return archive_name
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
def make_zipfile( # noqa: C901
|
| 129 |
+
base_name: str,
|
| 130 |
+
base_dir: str | os.PathLike[str],
|
| 131 |
+
verbose: bool = False,
|
| 132 |
+
dry_run: bool = False,
|
| 133 |
+
) -> str:
|
| 134 |
+
"""Create a zip file from all the files under 'base_dir'.
|
| 135 |
+
|
| 136 |
+
The output zip file will be named 'base_name' + ".zip". Uses either the
|
| 137 |
+
"zipfile" Python module (if available) or the InfoZIP "zip" utility
|
| 138 |
+
(if installed and found on the default search path). If neither tool is
|
| 139 |
+
available, raises DistutilsExecError. Returns the name of the output zip
|
| 140 |
+
file.
|
| 141 |
+
"""
|
| 142 |
+
zip_filename = base_name + ".zip"
|
| 143 |
+
mkpath(os.path.dirname(zip_filename), dry_run=dry_run)
|
| 144 |
+
|
| 145 |
+
# If zipfile module is not available, try spawning an external
|
| 146 |
+
# 'zip' command.
|
| 147 |
+
if zipfile is None:
|
| 148 |
+
if verbose:
|
| 149 |
+
zipoptions = "-r"
|
| 150 |
+
else:
|
| 151 |
+
zipoptions = "-rq"
|
| 152 |
+
|
| 153 |
+
try:
|
| 154 |
+
spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
|
| 155 |
+
except DistutilsExecError:
|
| 156 |
+
# XXX really should distinguish between "couldn't find
|
| 157 |
+
# external 'zip' command" and "zip failed".
|
| 158 |
+
raise DistutilsExecError(
|
| 159 |
+
f"unable to create zip file '{zip_filename}': "
|
| 160 |
+
"could neither import the 'zipfile' module nor "
|
| 161 |
+
"find a standalone zip utility"
|
| 162 |
+
)
|
| 163 |
+
|
| 164 |
+
else:
|
| 165 |
+
log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir)
|
| 166 |
+
|
| 167 |
+
if not dry_run:
|
| 168 |
+
try:
|
| 169 |
+
zip = zipfile.ZipFile(
|
| 170 |
+
zip_filename, "w", compression=zipfile.ZIP_DEFLATED
|
| 171 |
+
)
|
| 172 |
+
except RuntimeError:
|
| 173 |
+
zip = zipfile.ZipFile(zip_filename, "w", compression=zipfile.ZIP_STORED)
|
| 174 |
+
|
| 175 |
+
with zip:
|
| 176 |
+
if base_dir != os.curdir:
|
| 177 |
+
path = os.path.normpath(os.path.join(base_dir, ''))
|
| 178 |
+
zip.write(path, path)
|
| 179 |
+
log.info("adding '%s'", path)
|
| 180 |
+
for dirpath, dirnames, filenames in os.walk(base_dir):
|
| 181 |
+
for name in dirnames:
|
| 182 |
+
path = os.path.normpath(os.path.join(dirpath, name, ''))
|
| 183 |
+
zip.write(path, path)
|
| 184 |
+
log.info("adding '%s'", path)
|
| 185 |
+
for name in filenames:
|
| 186 |
+
path = os.path.normpath(os.path.join(dirpath, name))
|
| 187 |
+
if os.path.isfile(path):
|
| 188 |
+
zip.write(path, path)
|
| 189 |
+
log.info("adding '%s'", path)
|
| 190 |
+
|
| 191 |
+
return zip_filename
|
| 192 |
+
|
| 193 |
+
|
| 194 |
+
ARCHIVE_FORMATS = {
|
| 195 |
+
'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
|
| 196 |
+
'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
|
| 197 |
+
'xztar': (make_tarball, [('compress', 'xz')], "xz'ed tar-file"),
|
| 198 |
+
'ztar': (make_tarball, [('compress', 'compress')], "compressed tar file"),
|
| 199 |
+
'tar': (make_tarball, [('compress', None)], "uncompressed tar file"),
|
| 200 |
+
'zip': (make_zipfile, [], "ZIP file"),
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
|
| 204 |
+
def check_archive_formats(formats):
|
| 205 |
+
"""Returns the first format from the 'format' list that is unknown.
|
| 206 |
+
|
| 207 |
+
If all formats are known, returns None
|
| 208 |
+
"""
|
| 209 |
+
for format in formats:
|
| 210 |
+
if format not in ARCHIVE_FORMATS:
|
| 211 |
+
return format
|
| 212 |
+
return None
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
@overload
|
| 216 |
+
def make_archive(
|
| 217 |
+
base_name: str,
|
| 218 |
+
format: str,
|
| 219 |
+
root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes] | None = None,
|
| 220 |
+
base_dir: str | None = None,
|
| 221 |
+
verbose: bool = False,
|
| 222 |
+
dry_run: bool = False,
|
| 223 |
+
owner: str | None = None,
|
| 224 |
+
group: str | None = None,
|
| 225 |
+
) -> str: ...
|
| 226 |
+
@overload
|
| 227 |
+
def make_archive(
|
| 228 |
+
base_name: str | os.PathLike[str],
|
| 229 |
+
format: str,
|
| 230 |
+
root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes],
|
| 231 |
+
base_dir: str | None = None,
|
| 232 |
+
verbose: bool = False,
|
| 233 |
+
dry_run: bool = False,
|
| 234 |
+
owner: str | None = None,
|
| 235 |
+
group: str | None = None,
|
| 236 |
+
) -> str: ...
|
| 237 |
+
def make_archive(
|
| 238 |
+
base_name: str | os.PathLike[str],
|
| 239 |
+
format: str,
|
| 240 |
+
root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes] | None = None,
|
| 241 |
+
base_dir: str | None = None,
|
| 242 |
+
verbose: bool = False,
|
| 243 |
+
dry_run: bool = False,
|
| 244 |
+
owner: str | None = None,
|
| 245 |
+
group: str | None = None,
|
| 246 |
+
) -> str:
|
| 247 |
+
"""Create an archive file (eg. zip or tar).
|
| 248 |
+
|
| 249 |
+
'base_name' is the name of the file to create, minus any format-specific
|
| 250 |
+
extension; 'format' is the archive format: one of "zip", "tar", "gztar",
|
| 251 |
+
"bztar", "xztar", or "ztar".
|
| 252 |
+
|
| 253 |
+
'root_dir' is a directory that will be the root directory of the
|
| 254 |
+
archive; ie. we typically chdir into 'root_dir' before creating the
|
| 255 |
+
archive. 'base_dir' is the directory where we start archiving from;
|
| 256 |
+
ie. 'base_dir' will be the common prefix of all files and
|
| 257 |
+
directories in the archive. 'root_dir' and 'base_dir' both default
|
| 258 |
+
to the current directory. Returns the name of the archive file.
|
| 259 |
+
|
| 260 |
+
'owner' and 'group' are used when creating a tar archive. By default,
|
| 261 |
+
uses the current owner and group.
|
| 262 |
+
"""
|
| 263 |
+
save_cwd = os.getcwd()
|
| 264 |
+
if root_dir is not None:
|
| 265 |
+
log.debug("changing into '%s'", root_dir)
|
| 266 |
+
base_name = os.path.abspath(base_name)
|
| 267 |
+
if not dry_run:
|
| 268 |
+
os.chdir(root_dir)
|
| 269 |
+
|
| 270 |
+
if base_dir is None:
|
| 271 |
+
base_dir = os.curdir
|
| 272 |
+
|
| 273 |
+
kwargs = {'dry_run': dry_run}
|
| 274 |
+
|
| 275 |
+
try:
|
| 276 |
+
format_info = ARCHIVE_FORMATS[format]
|
| 277 |
+
except KeyError:
|
| 278 |
+
raise ValueError(f"unknown archive format '{format}'")
|
| 279 |
+
|
| 280 |
+
func = format_info[0]
|
| 281 |
+
kwargs.update(format_info[1])
|
| 282 |
+
|
| 283 |
+
if format != 'zip':
|
| 284 |
+
kwargs['owner'] = owner
|
| 285 |
+
kwargs['group'] = group
|
| 286 |
+
|
| 287 |
+
try:
|
| 288 |
+
filename = func(base_name, base_dir, **kwargs)
|
| 289 |
+
finally:
|
| 290 |
+
if root_dir is not None:
|
| 291 |
+
log.debug("changing back to '%s'", save_cwd)
|
| 292 |
+
os.chdir(save_cwd)
|
| 293 |
+
|
| 294 |
+
return filename
|
lib/python3.12/site-packages/setuptools/_distutils/ccompiler.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .compat.numpy import ( # noqa: F401
|
| 2 |
+
_default_compilers,
|
| 3 |
+
compiler_class,
|
| 4 |
+
)
|
| 5 |
+
from .compilers.C import base
|
| 6 |
+
from .compilers.C.base import (
|
| 7 |
+
gen_lib_options,
|
| 8 |
+
gen_preprocess_options,
|
| 9 |
+
get_default_compiler,
|
| 10 |
+
new_compiler,
|
| 11 |
+
show_compilers,
|
| 12 |
+
)
|
| 13 |
+
from .compilers.C.errors import CompileError, LinkError
|
| 14 |
+
|
| 15 |
+
__all__ = [
|
| 16 |
+
'CompileError',
|
| 17 |
+
'LinkError',
|
| 18 |
+
'gen_lib_options',
|
| 19 |
+
'gen_preprocess_options',
|
| 20 |
+
'get_default_compiler',
|
| 21 |
+
'new_compiler',
|
| 22 |
+
'show_compilers',
|
| 23 |
+
]
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
CCompiler = base.Compiler
|
lib/python3.12/site-packages/setuptools/_distutils/cmd.py
ADDED
|
@@ -0,0 +1,554 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.cmd
|
| 2 |
+
|
| 3 |
+
Provides the Command class, the base class for the command classes
|
| 4 |
+
in the distutils.command package.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from __future__ import annotations
|
| 8 |
+
|
| 9 |
+
import logging
|
| 10 |
+
import os
|
| 11 |
+
import re
|
| 12 |
+
import sys
|
| 13 |
+
from abc import abstractmethod
|
| 14 |
+
from collections.abc import Callable, MutableSequence
|
| 15 |
+
from typing import TYPE_CHECKING, Any, ClassVar, TypeVar, overload
|
| 16 |
+
|
| 17 |
+
from . import _modified, archive_util, dir_util, file_util, util
|
| 18 |
+
from ._log import log
|
| 19 |
+
from .errors import DistutilsOptionError
|
| 20 |
+
|
| 21 |
+
if TYPE_CHECKING:
|
| 22 |
+
# type-only import because of mutual dependence between these classes
|
| 23 |
+
from distutils.dist import Distribution
|
| 24 |
+
|
| 25 |
+
from typing_extensions import TypeVarTuple, Unpack
|
| 26 |
+
|
| 27 |
+
_Ts = TypeVarTuple("_Ts")
|
| 28 |
+
|
| 29 |
+
_StrPathT = TypeVar("_StrPathT", bound="str | os.PathLike[str]")
|
| 30 |
+
_BytesPathT = TypeVar("_BytesPathT", bound="bytes | os.PathLike[bytes]")
|
| 31 |
+
_CommandT = TypeVar("_CommandT", bound="Command")
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class Command:
|
| 35 |
+
"""Abstract base class for defining command classes, the "worker bees"
|
| 36 |
+
of the Distutils. A useful analogy for command classes is to think of
|
| 37 |
+
them as subroutines with local variables called "options". The options
|
| 38 |
+
are "declared" in 'initialize_options()' and "defined" (given their
|
| 39 |
+
final values, aka "finalized") in 'finalize_options()', both of which
|
| 40 |
+
must be defined by every command class. The distinction between the
|
| 41 |
+
two is necessary because option values might come from the outside
|
| 42 |
+
world (command line, config file, ...), and any options dependent on
|
| 43 |
+
other options must be computed *after* these outside influences have
|
| 44 |
+
been processed -- hence 'finalize_options()'. The "body" of the
|
| 45 |
+
subroutine, where it does all its work based on the values of its
|
| 46 |
+
options, is the 'run()' method, which must also be implemented by every
|
| 47 |
+
command class.
|
| 48 |
+
"""
|
| 49 |
+
|
| 50 |
+
# 'sub_commands' formalizes the notion of a "family" of commands,
|
| 51 |
+
# eg. "install" as the parent with sub-commands "install_lib",
|
| 52 |
+
# "install_headers", etc. The parent of a family of commands
|
| 53 |
+
# defines 'sub_commands' as a class attribute; it's a list of
|
| 54 |
+
# (command_name : string, predicate : unbound_method | string | None)
|
| 55 |
+
# tuples, where 'predicate' is a method of the parent command that
|
| 56 |
+
# determines whether the corresponding command is applicable in the
|
| 57 |
+
# current situation. (Eg. we "install_headers" is only applicable if
|
| 58 |
+
# we have any C header files to install.) If 'predicate' is None,
|
| 59 |
+
# that command is always applicable.
|
| 60 |
+
#
|
| 61 |
+
# 'sub_commands' is usually defined at the *end* of a class, because
|
| 62 |
+
# predicates can be unbound methods, so they must already have been
|
| 63 |
+
# defined. The canonical example is the "install" command.
|
| 64 |
+
sub_commands: ClassVar[ # Any to work around variance issues
|
| 65 |
+
list[tuple[str, Callable[[Any], bool] | None]]
|
| 66 |
+
] = []
|
| 67 |
+
|
| 68 |
+
user_options: ClassVar[
|
| 69 |
+
# Specifying both because list is invariant. Avoids mypy override assignment issues
|
| 70 |
+
list[tuple[str, str, str]] | list[tuple[str, str | None, str]]
|
| 71 |
+
] = []
|
| 72 |
+
|
| 73 |
+
# -- Creation/initialization methods -------------------------------
|
| 74 |
+
|
| 75 |
+
def __init__(self, dist: Distribution) -> None:
|
| 76 |
+
"""Create and initialize a new Command object. Most importantly,
|
| 77 |
+
invokes the 'initialize_options()' method, which is the real
|
| 78 |
+
initializer and depends on the actual command being
|
| 79 |
+
instantiated.
|
| 80 |
+
"""
|
| 81 |
+
# late import because of mutual dependence between these classes
|
| 82 |
+
from distutils.dist import Distribution
|
| 83 |
+
|
| 84 |
+
if not isinstance(dist, Distribution):
|
| 85 |
+
raise TypeError("dist must be a Distribution instance")
|
| 86 |
+
if self.__class__ is Command:
|
| 87 |
+
raise RuntimeError("Command is an abstract class")
|
| 88 |
+
|
| 89 |
+
self.distribution = dist
|
| 90 |
+
self.initialize_options()
|
| 91 |
+
|
| 92 |
+
# Per-command versions of the global flags, so that the user can
|
| 93 |
+
# customize Distutils' behaviour command-by-command and let some
|
| 94 |
+
# commands fall back on the Distribution's behaviour. None means
|
| 95 |
+
# "not defined, check self.distribution's copy", while 0 or 1 mean
|
| 96 |
+
# false and true (duh). Note that this means figuring out the real
|
| 97 |
+
# value of each flag is a touch complicated -- hence "self._dry_run"
|
| 98 |
+
# will be handled by __getattr__, below.
|
| 99 |
+
# XXX This needs to be fixed.
|
| 100 |
+
self._dry_run = None
|
| 101 |
+
|
| 102 |
+
# verbose is largely ignored, but needs to be set for
|
| 103 |
+
# backwards compatibility (I think)?
|
| 104 |
+
self.verbose = dist.verbose
|
| 105 |
+
|
| 106 |
+
# Some commands define a 'self.force' option to ignore file
|
| 107 |
+
# timestamps, but methods defined *here* assume that
|
| 108 |
+
# 'self.force' exists for all commands. So define it here
|
| 109 |
+
# just to be safe.
|
| 110 |
+
self.force = None
|
| 111 |
+
|
| 112 |
+
# The 'help' flag is just used for command-line parsing, so
|
| 113 |
+
# none of that complicated bureaucracy is needed.
|
| 114 |
+
self.help = False
|
| 115 |
+
|
| 116 |
+
# 'finalized' records whether or not 'finalize_options()' has been
|
| 117 |
+
# called. 'finalize_options()' itself should not pay attention to
|
| 118 |
+
# this flag: it is the business of 'ensure_finalized()', which
|
| 119 |
+
# always calls 'finalize_options()', to respect/update it.
|
| 120 |
+
self.finalized = False
|
| 121 |
+
|
| 122 |
+
# XXX A more explicit way to customize dry_run would be better.
|
| 123 |
+
def __getattr__(self, attr):
|
| 124 |
+
if attr == 'dry_run':
|
| 125 |
+
myval = getattr(self, "_" + attr)
|
| 126 |
+
if myval is None:
|
| 127 |
+
return getattr(self.distribution, attr)
|
| 128 |
+
else:
|
| 129 |
+
return myval
|
| 130 |
+
else:
|
| 131 |
+
raise AttributeError(attr)
|
| 132 |
+
|
| 133 |
+
def ensure_finalized(self) -> None:
|
| 134 |
+
if not self.finalized:
|
| 135 |
+
self.finalize_options()
|
| 136 |
+
self.finalized = True
|
| 137 |
+
|
| 138 |
+
# Subclasses must define:
|
| 139 |
+
# initialize_options()
|
| 140 |
+
# provide default values for all options; may be customized by
|
| 141 |
+
# setup script, by options from config file(s), or by command-line
|
| 142 |
+
# options
|
| 143 |
+
# finalize_options()
|
| 144 |
+
# decide on the final values for all options; this is called
|
| 145 |
+
# after all possible intervention from the outside world
|
| 146 |
+
# (command-line, option file, etc.) has been processed
|
| 147 |
+
# run()
|
| 148 |
+
# run the command: do whatever it is we're here to do,
|
| 149 |
+
# controlled by the command's various option values
|
| 150 |
+
|
| 151 |
+
@abstractmethod
|
| 152 |
+
def initialize_options(self) -> None:
|
| 153 |
+
"""Set default values for all the options that this command
|
| 154 |
+
supports. Note that these defaults may be overridden by other
|
| 155 |
+
commands, by the setup script, by config files, or by the
|
| 156 |
+
command-line. Thus, this is not the place to code dependencies
|
| 157 |
+
between options; generally, 'initialize_options()' implementations
|
| 158 |
+
are just a bunch of "self.foo = None" assignments.
|
| 159 |
+
|
| 160 |
+
This method must be implemented by all command classes.
|
| 161 |
+
"""
|
| 162 |
+
raise RuntimeError(
|
| 163 |
+
f"abstract method -- subclass {self.__class__} must override"
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
@abstractmethod
|
| 167 |
+
def finalize_options(self) -> None:
|
| 168 |
+
"""Set final values for all the options that this command supports.
|
| 169 |
+
This is always called as late as possible, ie. after any option
|
| 170 |
+
assignments from the command-line or from other commands have been
|
| 171 |
+
done. Thus, this is the place to code option dependencies: if
|
| 172 |
+
'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
|
| 173 |
+
long as 'foo' still has the same value it was assigned in
|
| 174 |
+
'initialize_options()'.
|
| 175 |
+
|
| 176 |
+
This method must be implemented by all command classes.
|
| 177 |
+
"""
|
| 178 |
+
raise RuntimeError(
|
| 179 |
+
f"abstract method -- subclass {self.__class__} must override"
|
| 180 |
+
)
|
| 181 |
+
|
| 182 |
+
def dump_options(self, header=None, indent=""):
|
| 183 |
+
from distutils.fancy_getopt import longopt_xlate
|
| 184 |
+
|
| 185 |
+
if header is None:
|
| 186 |
+
header = f"command options for '{self.get_command_name()}':"
|
| 187 |
+
self.announce(indent + header, level=logging.INFO)
|
| 188 |
+
indent = indent + " "
|
| 189 |
+
for option, _, _ in self.user_options:
|
| 190 |
+
option = option.translate(longopt_xlate)
|
| 191 |
+
if option[-1] == "=":
|
| 192 |
+
option = option[:-1]
|
| 193 |
+
value = getattr(self, option)
|
| 194 |
+
self.announce(indent + f"{option} = {value}", level=logging.INFO)
|
| 195 |
+
|
| 196 |
+
@abstractmethod
|
| 197 |
+
def run(self) -> None:
|
| 198 |
+
"""A command's raison d'etre: carry out the action it exists to
|
| 199 |
+
perform, controlled by the options initialized in
|
| 200 |
+
'initialize_options()', customized by other commands, the setup
|
| 201 |
+
script, the command-line, and config files, and finalized in
|
| 202 |
+
'finalize_options()'. All terminal output and filesystem
|
| 203 |
+
interaction should be done by 'run()'.
|
| 204 |
+
|
| 205 |
+
This method must be implemented by all command classes.
|
| 206 |
+
"""
|
| 207 |
+
raise RuntimeError(
|
| 208 |
+
f"abstract method -- subclass {self.__class__} must override"
|
| 209 |
+
)
|
| 210 |
+
|
| 211 |
+
def announce(self, msg: object, level: int = logging.DEBUG) -> None:
|
| 212 |
+
log.log(level, msg)
|
| 213 |
+
|
| 214 |
+
def debug_print(self, msg: object) -> None:
|
| 215 |
+
"""Print 'msg' to stdout if the global DEBUG (taken from the
|
| 216 |
+
DISTUTILS_DEBUG environment variable) flag is true.
|
| 217 |
+
"""
|
| 218 |
+
from distutils.debug import DEBUG
|
| 219 |
+
|
| 220 |
+
if DEBUG:
|
| 221 |
+
print(msg)
|
| 222 |
+
sys.stdout.flush()
|
| 223 |
+
|
| 224 |
+
# -- Option validation methods -------------------------------------
|
| 225 |
+
# (these are very handy in writing the 'finalize_options()' method)
|
| 226 |
+
#
|
| 227 |
+
# NB. the general philosophy here is to ensure that a particular option
|
| 228 |
+
# value meets certain type and value constraints. If not, we try to
|
| 229 |
+
# force it into conformance (eg. if we expect a list but have a string,
|
| 230 |
+
# split the string on comma and/or whitespace). If we can't force the
|
| 231 |
+
# option into conformance, raise DistutilsOptionError. Thus, command
|
| 232 |
+
# classes need do nothing more than (eg.)
|
| 233 |
+
# self.ensure_string_list('foo')
|
| 234 |
+
# and they can be guaranteed that thereafter, self.foo will be
|
| 235 |
+
# a list of strings.
|
| 236 |
+
|
| 237 |
+
def _ensure_stringlike(self, option, what, default=None):
|
| 238 |
+
val = getattr(self, option)
|
| 239 |
+
if val is None:
|
| 240 |
+
setattr(self, option, default)
|
| 241 |
+
return default
|
| 242 |
+
elif not isinstance(val, str):
|
| 243 |
+
raise DistutilsOptionError(f"'{option}' must be a {what} (got `{val}`)")
|
| 244 |
+
return val
|
| 245 |
+
|
| 246 |
+
def ensure_string(self, option: str, default: str | None = None) -> None:
|
| 247 |
+
"""Ensure that 'option' is a string; if not defined, set it to
|
| 248 |
+
'default'.
|
| 249 |
+
"""
|
| 250 |
+
self._ensure_stringlike(option, "string", default)
|
| 251 |
+
|
| 252 |
+
def ensure_string_list(self, option: str) -> None:
|
| 253 |
+
r"""Ensure that 'option' is a list of strings. If 'option' is
|
| 254 |
+
currently a string, we split it either on /,\s*/ or /\s+/, so
|
| 255 |
+
"foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
|
| 256 |
+
["foo", "bar", "baz"].
|
| 257 |
+
"""
|
| 258 |
+
val = getattr(self, option)
|
| 259 |
+
if val is None:
|
| 260 |
+
return
|
| 261 |
+
elif isinstance(val, str):
|
| 262 |
+
setattr(self, option, re.split(r',\s*|\s+', val))
|
| 263 |
+
else:
|
| 264 |
+
if isinstance(val, list):
|
| 265 |
+
ok = all(isinstance(v, str) for v in val)
|
| 266 |
+
else:
|
| 267 |
+
ok = False
|
| 268 |
+
if not ok:
|
| 269 |
+
raise DistutilsOptionError(
|
| 270 |
+
f"'{option}' must be a list of strings (got {val!r})"
|
| 271 |
+
)
|
| 272 |
+
|
| 273 |
+
def _ensure_tested_string(self, option, tester, what, error_fmt, default=None):
|
| 274 |
+
val = self._ensure_stringlike(option, what, default)
|
| 275 |
+
if val is not None and not tester(val):
|
| 276 |
+
raise DistutilsOptionError(
|
| 277 |
+
("error in '%s' option: " + error_fmt) % (option, val)
|
| 278 |
+
)
|
| 279 |
+
|
| 280 |
+
def ensure_filename(self, option: str) -> None:
|
| 281 |
+
"""Ensure that 'option' is the name of an existing file."""
|
| 282 |
+
self._ensure_tested_string(
|
| 283 |
+
option, os.path.isfile, "filename", "'%s' does not exist or is not a file"
|
| 284 |
+
)
|
| 285 |
+
|
| 286 |
+
def ensure_dirname(self, option: str) -> None:
|
| 287 |
+
self._ensure_tested_string(
|
| 288 |
+
option,
|
| 289 |
+
os.path.isdir,
|
| 290 |
+
"directory name",
|
| 291 |
+
"'%s' does not exist or is not a directory",
|
| 292 |
+
)
|
| 293 |
+
|
| 294 |
+
# -- Convenience methods for commands ------------------------------
|
| 295 |
+
|
| 296 |
+
def get_command_name(self) -> str:
|
| 297 |
+
if hasattr(self, 'command_name'):
|
| 298 |
+
return self.command_name
|
| 299 |
+
else:
|
| 300 |
+
return self.__class__.__name__
|
| 301 |
+
|
| 302 |
+
def set_undefined_options(
|
| 303 |
+
self, src_cmd: str, *option_pairs: tuple[str, str]
|
| 304 |
+
) -> None:
|
| 305 |
+
"""Set the values of any "undefined" options from corresponding
|
| 306 |
+
option values in some other command object. "Undefined" here means
|
| 307 |
+
"is None", which is the convention used to indicate that an option
|
| 308 |
+
has not been changed between 'initialize_options()' and
|
| 309 |
+
'finalize_options()'. Usually called from 'finalize_options()' for
|
| 310 |
+
options that depend on some other command rather than another
|
| 311 |
+
option of the same command. 'src_cmd' is the other command from
|
| 312 |
+
which option values will be taken (a command object will be created
|
| 313 |
+
for it if necessary); the remaining arguments are
|
| 314 |
+
'(src_option,dst_option)' tuples which mean "take the value of
|
| 315 |
+
'src_option' in the 'src_cmd' command object, and copy it to
|
| 316 |
+
'dst_option' in the current command object".
|
| 317 |
+
"""
|
| 318 |
+
# Option_pairs: list of (src_option, dst_option) tuples
|
| 319 |
+
src_cmd_obj = self.distribution.get_command_obj(src_cmd)
|
| 320 |
+
src_cmd_obj.ensure_finalized()
|
| 321 |
+
for src_option, dst_option in option_pairs:
|
| 322 |
+
if getattr(self, dst_option) is None:
|
| 323 |
+
setattr(self, dst_option, getattr(src_cmd_obj, src_option))
|
| 324 |
+
|
| 325 |
+
# NOTE: Because distutils is private to Setuptools and not all commands are exposed here,
|
| 326 |
+
# not every possible command is enumerated in the signature.
|
| 327 |
+
def get_finalized_command(self, command: str, create: bool = True) -> Command:
|
| 328 |
+
"""Wrapper around Distribution's 'get_command_obj()' method: find
|
| 329 |
+
(create if necessary and 'create' is true) the command object for
|
| 330 |
+
'command', call its 'ensure_finalized()' method, and return the
|
| 331 |
+
finalized command object.
|
| 332 |
+
"""
|
| 333 |
+
cmd_obj = self.distribution.get_command_obj(command, create)
|
| 334 |
+
cmd_obj.ensure_finalized()
|
| 335 |
+
return cmd_obj
|
| 336 |
+
|
| 337 |
+
# XXX rename to 'get_reinitialized_command()'? (should do the
|
| 338 |
+
# same in dist.py, if so)
|
| 339 |
+
@overload
|
| 340 |
+
def reinitialize_command(
|
| 341 |
+
self, command: str, reinit_subcommands: bool = False
|
| 342 |
+
) -> Command: ...
|
| 343 |
+
@overload
|
| 344 |
+
def reinitialize_command(
|
| 345 |
+
self, command: _CommandT, reinit_subcommands: bool = False
|
| 346 |
+
) -> _CommandT: ...
|
| 347 |
+
def reinitialize_command(
|
| 348 |
+
self, command: str | Command, reinit_subcommands=False
|
| 349 |
+
) -> Command:
|
| 350 |
+
return self.distribution.reinitialize_command(command, reinit_subcommands)
|
| 351 |
+
|
| 352 |
+
def run_command(self, command: str) -> None:
|
| 353 |
+
"""Run some other command: uses the 'run_command()' method of
|
| 354 |
+
Distribution, which creates and finalizes the command object if
|
| 355 |
+
necessary and then invokes its 'run()' method.
|
| 356 |
+
"""
|
| 357 |
+
self.distribution.run_command(command)
|
| 358 |
+
|
| 359 |
+
def get_sub_commands(self) -> list[str]:
|
| 360 |
+
"""Determine the sub-commands that are relevant in the current
|
| 361 |
+
distribution (ie., that need to be run). This is based on the
|
| 362 |
+
'sub_commands' class attribute: each tuple in that list may include
|
| 363 |
+
a method that we call to determine if the subcommand needs to be
|
| 364 |
+
run for the current distribution. Return a list of command names.
|
| 365 |
+
"""
|
| 366 |
+
commands = []
|
| 367 |
+
for cmd_name, method in self.sub_commands:
|
| 368 |
+
if method is None or method(self):
|
| 369 |
+
commands.append(cmd_name)
|
| 370 |
+
return commands
|
| 371 |
+
|
| 372 |
+
# -- External world manipulation -----------------------------------
|
| 373 |
+
|
| 374 |
+
def warn(self, msg: object) -> None:
|
| 375 |
+
log.warning("warning: %s: %s\n", self.get_command_name(), msg)
|
| 376 |
+
|
| 377 |
+
def execute(
|
| 378 |
+
self,
|
| 379 |
+
func: Callable[[Unpack[_Ts]], object],
|
| 380 |
+
args: tuple[Unpack[_Ts]],
|
| 381 |
+
msg: object = None,
|
| 382 |
+
level: int = 1,
|
| 383 |
+
) -> None:
|
| 384 |
+
util.execute(func, args, msg, dry_run=self.dry_run)
|
| 385 |
+
|
| 386 |
+
def mkpath(self, name: str, mode: int = 0o777) -> None:
|
| 387 |
+
dir_util.mkpath(name, mode, dry_run=self.dry_run)
|
| 388 |
+
|
| 389 |
+
@overload
|
| 390 |
+
def copy_file(
|
| 391 |
+
self,
|
| 392 |
+
infile: str | os.PathLike[str],
|
| 393 |
+
outfile: _StrPathT,
|
| 394 |
+
preserve_mode: bool = True,
|
| 395 |
+
preserve_times: bool = True,
|
| 396 |
+
link: str | None = None,
|
| 397 |
+
level: int = 1,
|
| 398 |
+
) -> tuple[_StrPathT | str, bool]: ...
|
| 399 |
+
@overload
|
| 400 |
+
def copy_file(
|
| 401 |
+
self,
|
| 402 |
+
infile: bytes | os.PathLike[bytes],
|
| 403 |
+
outfile: _BytesPathT,
|
| 404 |
+
preserve_mode: bool = True,
|
| 405 |
+
preserve_times: bool = True,
|
| 406 |
+
link: str | None = None,
|
| 407 |
+
level: int = 1,
|
| 408 |
+
) -> tuple[_BytesPathT | bytes, bool]: ...
|
| 409 |
+
def copy_file(
|
| 410 |
+
self,
|
| 411 |
+
infile: str | os.PathLike[str] | bytes | os.PathLike[bytes],
|
| 412 |
+
outfile: str | os.PathLike[str] | bytes | os.PathLike[bytes],
|
| 413 |
+
preserve_mode: bool = True,
|
| 414 |
+
preserve_times: bool = True,
|
| 415 |
+
link: str | None = None,
|
| 416 |
+
level: int = 1,
|
| 417 |
+
) -> tuple[str | os.PathLike[str] | bytes | os.PathLike[bytes], bool]:
|
| 418 |
+
"""Copy a file respecting verbose, dry-run and force flags. (The
|
| 419 |
+
former two default to whatever is in the Distribution object, and
|
| 420 |
+
the latter defaults to false for commands that don't define it.)"""
|
| 421 |
+
return file_util.copy_file(
|
| 422 |
+
infile,
|
| 423 |
+
outfile,
|
| 424 |
+
preserve_mode,
|
| 425 |
+
preserve_times,
|
| 426 |
+
not self.force,
|
| 427 |
+
link,
|
| 428 |
+
dry_run=self.dry_run,
|
| 429 |
+
)
|
| 430 |
+
|
| 431 |
+
def copy_tree(
|
| 432 |
+
self,
|
| 433 |
+
infile: str | os.PathLike[str],
|
| 434 |
+
outfile: str,
|
| 435 |
+
preserve_mode: bool = True,
|
| 436 |
+
preserve_times: bool = True,
|
| 437 |
+
preserve_symlinks: bool = False,
|
| 438 |
+
level: int = 1,
|
| 439 |
+
) -> list[str]:
|
| 440 |
+
"""Copy an entire directory tree respecting verbose, dry-run,
|
| 441 |
+
and force flags.
|
| 442 |
+
"""
|
| 443 |
+
return dir_util.copy_tree(
|
| 444 |
+
infile,
|
| 445 |
+
outfile,
|
| 446 |
+
preserve_mode,
|
| 447 |
+
preserve_times,
|
| 448 |
+
preserve_symlinks,
|
| 449 |
+
not self.force,
|
| 450 |
+
dry_run=self.dry_run,
|
| 451 |
+
)
|
| 452 |
+
|
| 453 |
+
@overload
|
| 454 |
+
def move_file(
|
| 455 |
+
self, src: str | os.PathLike[str], dst: _StrPathT, level: int = 1
|
| 456 |
+
) -> _StrPathT | str: ...
|
| 457 |
+
@overload
|
| 458 |
+
def move_file(
|
| 459 |
+
self, src: bytes | os.PathLike[bytes], dst: _BytesPathT, level: int = 1
|
| 460 |
+
) -> _BytesPathT | bytes: ...
|
| 461 |
+
def move_file(
|
| 462 |
+
self,
|
| 463 |
+
src: str | os.PathLike[str] | bytes | os.PathLike[bytes],
|
| 464 |
+
dst: str | os.PathLike[str] | bytes | os.PathLike[bytes],
|
| 465 |
+
level: int = 1,
|
| 466 |
+
) -> str | os.PathLike[str] | bytes | os.PathLike[bytes]:
|
| 467 |
+
"""Move a file respecting dry-run flag."""
|
| 468 |
+
return file_util.move_file(src, dst, dry_run=self.dry_run)
|
| 469 |
+
|
| 470 |
+
def spawn(
|
| 471 |
+
self, cmd: MutableSequence[str], search_path: bool = True, level: int = 1
|
| 472 |
+
) -> None:
|
| 473 |
+
"""Spawn an external command respecting dry-run flag."""
|
| 474 |
+
from distutils.spawn import spawn
|
| 475 |
+
|
| 476 |
+
spawn(cmd, search_path, dry_run=self.dry_run)
|
| 477 |
+
|
| 478 |
+
@overload
|
| 479 |
+
def make_archive(
|
| 480 |
+
self,
|
| 481 |
+
base_name: str,
|
| 482 |
+
format: str,
|
| 483 |
+
root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes] | None = None,
|
| 484 |
+
base_dir: str | None = None,
|
| 485 |
+
owner: str | None = None,
|
| 486 |
+
group: str | None = None,
|
| 487 |
+
) -> str: ...
|
| 488 |
+
@overload
|
| 489 |
+
def make_archive(
|
| 490 |
+
self,
|
| 491 |
+
base_name: str | os.PathLike[str],
|
| 492 |
+
format: str,
|
| 493 |
+
root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes],
|
| 494 |
+
base_dir: str | None = None,
|
| 495 |
+
owner: str | None = None,
|
| 496 |
+
group: str | None = None,
|
| 497 |
+
) -> str: ...
|
| 498 |
+
def make_archive(
|
| 499 |
+
self,
|
| 500 |
+
base_name: str | os.PathLike[str],
|
| 501 |
+
format: str,
|
| 502 |
+
root_dir: str | os.PathLike[str] | bytes | os.PathLike[bytes] | None = None,
|
| 503 |
+
base_dir: str | None = None,
|
| 504 |
+
owner: str | None = None,
|
| 505 |
+
group: str | None = None,
|
| 506 |
+
) -> str:
|
| 507 |
+
return archive_util.make_archive(
|
| 508 |
+
base_name,
|
| 509 |
+
format,
|
| 510 |
+
root_dir,
|
| 511 |
+
base_dir,
|
| 512 |
+
dry_run=self.dry_run,
|
| 513 |
+
owner=owner,
|
| 514 |
+
group=group,
|
| 515 |
+
)
|
| 516 |
+
|
| 517 |
+
def make_file(
|
| 518 |
+
self,
|
| 519 |
+
infiles: str | list[str] | tuple[str, ...],
|
| 520 |
+
outfile: str | os.PathLike[str] | bytes | os.PathLike[bytes],
|
| 521 |
+
func: Callable[[Unpack[_Ts]], object],
|
| 522 |
+
args: tuple[Unpack[_Ts]],
|
| 523 |
+
exec_msg: object = None,
|
| 524 |
+
skip_msg: object = None,
|
| 525 |
+
level: int = 1,
|
| 526 |
+
) -> None:
|
| 527 |
+
"""Special case of 'execute()' for operations that process one or
|
| 528 |
+
more input files and generate one output file. Works just like
|
| 529 |
+
'execute()', except the operation is skipped and a different
|
| 530 |
+
message printed if 'outfile' already exists and is newer than all
|
| 531 |
+
files listed in 'infiles'. If the command defined 'self.force',
|
| 532 |
+
and it is true, then the command is unconditionally run -- does no
|
| 533 |
+
timestamp checks.
|
| 534 |
+
"""
|
| 535 |
+
if skip_msg is None:
|
| 536 |
+
skip_msg = f"skipping {outfile} (inputs unchanged)"
|
| 537 |
+
|
| 538 |
+
# Allow 'infiles' to be a single string
|
| 539 |
+
if isinstance(infiles, str):
|
| 540 |
+
infiles = (infiles,)
|
| 541 |
+
elif not isinstance(infiles, (list, tuple)):
|
| 542 |
+
raise TypeError("'infiles' must be a string, or a list or tuple of strings")
|
| 543 |
+
|
| 544 |
+
if exec_msg is None:
|
| 545 |
+
exec_msg = "generating {} from {}".format(outfile, ', '.join(infiles))
|
| 546 |
+
|
| 547 |
+
# If 'outfile' must be regenerated (either because it doesn't
|
| 548 |
+
# exist, is out-of-date, or the 'force' flag is true) then
|
| 549 |
+
# perform the action that presumably regenerates it
|
| 550 |
+
if self.force or _modified.newer_group(infiles, outfile):
|
| 551 |
+
self.execute(func, args, exec_msg, level)
|
| 552 |
+
# Otherwise, print the "skip" message
|
| 553 |
+
else:
|
| 554 |
+
log.debug(skip_msg)
|
lib/python3.12/site-packages/setuptools/_distutils/command/__init__.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""distutils.command
|
| 2 |
+
|
| 3 |
+
Package containing implementation of all the standard Distutils
|
| 4 |
+
commands."""
|
| 5 |
+
|
| 6 |
+
__all__ = [
|
| 7 |
+
'build',
|
| 8 |
+
'build_py',
|
| 9 |
+
'build_ext',
|
| 10 |
+
'build_clib',
|
| 11 |
+
'build_scripts',
|
| 12 |
+
'clean',
|
| 13 |
+
'install',
|
| 14 |
+
'install_lib',
|
| 15 |
+
'install_headers',
|
| 16 |
+
'install_scripts',
|
| 17 |
+
'install_data',
|
| 18 |
+
'sdist',
|
| 19 |
+
'bdist',
|
| 20 |
+
'bdist_dumb',
|
| 21 |
+
'bdist_rpm',
|
| 22 |
+
'check',
|
| 23 |
+
]
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (519 Bytes). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/_framework_compat.cpython-312.pyc
ADDED
|
Binary file (2.62 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-312.pyc
ADDED
|
Binary file (6.46 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-312.pyc
ADDED
|
Binary file (5.59 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-312.pyc
ADDED
|
Binary file (21.6 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-312.pyc
ADDED
|
Binary file (6.28 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-312.pyc
ADDED
|
Binary file (7.6 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-312.pyc
ADDED
|
Binary file (30.2 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-312.pyc
ADDED
|
Binary file (16.2 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-312.pyc
ADDED
|
Binary file (6.8 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-312.pyc
ADDED
|
Binary file (7.17 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-312.pyc
ADDED
|
Binary file (3.14 kB). View file
|
|
|
lib/python3.12/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-312.pyc
ADDED
|
Binary file (15.2 kB). View file
|
|
|