update
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import sys
|
||||
import importlib
|
||||
import sys
|
||||
|
||||
__version__, _, _ = sys.version.partition(' ')
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/__pycache__/_modified.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/__pycache__/_modified.cpython-312.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/__pycache__/zosccompiler.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/__pycache__/zosccompiler.cpython-312.pyc
vendored
Normal file
Binary file not shown.
@@ -1,194 +0,0 @@
|
||||
import collections
|
||||
import functools
|
||||
import itertools
|
||||
import operator
|
||||
|
||||
|
||||
# from jaraco.collections 3.5.1
|
||||
class DictStack(list, collections.abc.Mapping):
|
||||
"""
|
||||
A stack of dictionaries that behaves as a view on those dictionaries,
|
||||
giving preference to the last.
|
||||
|
||||
>>> stack = DictStack([dict(a=1, c=2), dict(b=2, a=2)])
|
||||
>>> stack['a']
|
||||
2
|
||||
>>> stack['b']
|
||||
2
|
||||
>>> stack['c']
|
||||
2
|
||||
>>> len(stack)
|
||||
3
|
||||
>>> stack.push(dict(a=3))
|
||||
>>> stack['a']
|
||||
3
|
||||
>>> set(stack.keys()) == set(['a', 'b', 'c'])
|
||||
True
|
||||
>>> set(stack.items()) == set([('a', 3), ('b', 2), ('c', 2)])
|
||||
True
|
||||
>>> dict(**stack) == dict(stack) == dict(a=3, c=2, b=2)
|
||||
True
|
||||
>>> d = stack.pop()
|
||||
>>> stack['a']
|
||||
2
|
||||
>>> d = stack.pop()
|
||||
>>> stack['a']
|
||||
1
|
||||
>>> stack.get('b', None)
|
||||
>>> 'c' in stack
|
||||
True
|
||||
"""
|
||||
|
||||
def __iter__(self):
|
||||
dicts = list.__iter__(self)
|
||||
return iter(set(itertools.chain.from_iterable(c.keys() for c in dicts)))
|
||||
|
||||
def __getitem__(self, key):
|
||||
for scope in reversed(tuple(list.__iter__(self))):
|
||||
if key in scope:
|
||||
return scope[key]
|
||||
raise KeyError(key)
|
||||
|
||||
push = list.append
|
||||
|
||||
def __contains__(self, other):
|
||||
return collections.abc.Mapping.__contains__(self, other)
|
||||
|
||||
def __len__(self):
|
||||
return len(list(iter(self)))
|
||||
|
||||
|
||||
# from jaraco.collections 3.7
|
||||
class RangeMap(dict):
|
||||
"""
|
||||
A dictionary-like object that uses the keys as bounds for a range.
|
||||
Inclusion of the value for that range is determined by the
|
||||
key_match_comparator, which defaults to less-than-or-equal.
|
||||
A value is returned for a key if it is the first key that matches in
|
||||
the sorted list of keys.
|
||||
|
||||
One may supply keyword parameters to be passed to the sort function used
|
||||
to sort keys (i.e. key, reverse) as sort_params.
|
||||
|
||||
Let's create a map that maps 1-3 -> 'a', 4-6 -> 'b'
|
||||
|
||||
>>> r = RangeMap({3: 'a', 6: 'b'}) # boy, that was easy
|
||||
>>> r[1], r[2], r[3], r[4], r[5], r[6]
|
||||
('a', 'a', 'a', 'b', 'b', 'b')
|
||||
|
||||
Even float values should work so long as the comparison operator
|
||||
supports it.
|
||||
|
||||
>>> r[4.5]
|
||||
'b'
|
||||
|
||||
But you'll notice that the way rangemap is defined, it must be open-ended
|
||||
on one side.
|
||||
|
||||
>>> r[0]
|
||||
'a'
|
||||
>>> r[-1]
|
||||
'a'
|
||||
|
||||
One can close the open-end of the RangeMap by using undefined_value
|
||||
|
||||
>>> r = RangeMap({0: RangeMap.undefined_value, 3: 'a', 6: 'b'})
|
||||
>>> r[0]
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
KeyError: 0
|
||||
|
||||
One can get the first or last elements in the range by using RangeMap.Item
|
||||
|
||||
>>> last_item = RangeMap.Item(-1)
|
||||
>>> r[last_item]
|
||||
'b'
|
||||
|
||||
.last_item is a shortcut for Item(-1)
|
||||
|
||||
>>> r[RangeMap.last_item]
|
||||
'b'
|
||||
|
||||
Sometimes it's useful to find the bounds for a RangeMap
|
||||
|
||||
>>> r.bounds()
|
||||
(0, 6)
|
||||
|
||||
RangeMap supports .get(key, default)
|
||||
|
||||
>>> r.get(0, 'not found')
|
||||
'not found'
|
||||
|
||||
>>> r.get(7, 'not found')
|
||||
'not found'
|
||||
|
||||
One often wishes to define the ranges by their left-most values,
|
||||
which requires use of sort params and a key_match_comparator.
|
||||
|
||||
>>> r = RangeMap({1: 'a', 4: 'b'},
|
||||
... sort_params=dict(reverse=True),
|
||||
... key_match_comparator=operator.ge)
|
||||
>>> r[1], r[2], r[3], r[4], r[5], r[6]
|
||||
('a', 'a', 'a', 'b', 'b', 'b')
|
||||
|
||||
That wasn't nearly as easy as before, so an alternate constructor
|
||||
is provided:
|
||||
|
||||
>>> r = RangeMap.left({1: 'a', 4: 'b', 7: RangeMap.undefined_value})
|
||||
>>> r[1], r[2], r[3], r[4], r[5], r[6]
|
||||
('a', 'a', 'a', 'b', 'b', 'b')
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, source, sort_params={}, key_match_comparator=operator.le):
|
||||
dict.__init__(self, source)
|
||||
self.sort_params = sort_params
|
||||
self.match = key_match_comparator
|
||||
|
||||
@classmethod
|
||||
def left(cls, source):
|
||||
return cls(
|
||||
source, sort_params=dict(reverse=True), key_match_comparator=operator.ge
|
||||
)
|
||||
|
||||
def __getitem__(self, item):
|
||||
sorted_keys = sorted(self.keys(), **self.sort_params)
|
||||
if isinstance(item, RangeMap.Item):
|
||||
result = self.__getitem__(sorted_keys[item])
|
||||
else:
|
||||
key = self._find_first_match_(sorted_keys, item)
|
||||
result = dict.__getitem__(self, key)
|
||||
if result is RangeMap.undefined_value:
|
||||
raise KeyError(key)
|
||||
return result
|
||||
|
||||
def get(self, key, default=None):
|
||||
"""
|
||||
Return the value for key if key is in the dictionary, else default.
|
||||
If default is not given, it defaults to None, so that this method
|
||||
never raises a KeyError.
|
||||
"""
|
||||
try:
|
||||
return self[key]
|
||||
except KeyError:
|
||||
return default
|
||||
|
||||
def _find_first_match_(self, keys, item):
|
||||
is_match = functools.partial(self.match, item)
|
||||
matches = list(filter(is_match, keys))
|
||||
if matches:
|
||||
return matches[0]
|
||||
raise KeyError(item)
|
||||
|
||||
def bounds(self):
|
||||
sorted_keys = sorted(self.keys(), **self.sort_params)
|
||||
return (sorted_keys[RangeMap.first_item], sorted_keys[RangeMap.last_item])
|
||||
|
||||
# some special values for the RangeMap
|
||||
undefined_value = type('RangeValueUndefined', (), {})()
|
||||
|
||||
class Item(int):
|
||||
"RangeMap Item"
|
||||
|
||||
first_item = Item(0)
|
||||
last_item = Item(-1)
|
||||
@@ -1,20 +0,0 @@
|
||||
import functools
|
||||
|
||||
|
||||
# from jaraco.functools 3.5
|
||||
def pass_none(func):
|
||||
"""
|
||||
Wrap func so it's not called if its first param is None
|
||||
|
||||
>>> print_text = pass_none(print)
|
||||
>>> print_text('text')
|
||||
text
|
||||
>>> print_text(None)
|
||||
"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(param, *args, **kwargs):
|
||||
if param is not None:
|
||||
return func(param, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
@@ -1,4 +1,3 @@
|
||||
import logging
|
||||
|
||||
|
||||
log = logging.getLogger()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import sys
|
||||
import importlib
|
||||
import sys
|
||||
|
||||
|
||||
def bypass_compiler_fixup(cmd, args):
|
||||
|
||||
73
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/_modified.py
vendored
Normal file
73
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/_modified.py
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
"""Timestamp comparison of files and groups of files."""
|
||||
|
||||
import functools
|
||||
import os.path
|
||||
|
||||
from jaraco.functools import splat
|
||||
|
||||
from .compat.py39 import zip_strict
|
||||
from .errors import DistutilsFileError
|
||||
|
||||
|
||||
def _newer(source, target):
|
||||
return not os.path.exists(target) or (
|
||||
os.path.getmtime(source) > os.path.getmtime(target)
|
||||
)
|
||||
|
||||
|
||||
def newer(source, target):
|
||||
"""
|
||||
Is source modified more recently than target.
|
||||
|
||||
Returns True if 'source' is modified more recently than
|
||||
'target' or if 'target' does not exist.
|
||||
|
||||
Raises DistutilsFileError if 'source' does not exist.
|
||||
"""
|
||||
if not os.path.exists(source):
|
||||
raise DistutilsFileError(f"file '{os.path.abspath(source)}' does not exist")
|
||||
|
||||
return _newer(source, target)
|
||||
|
||||
|
||||
def newer_pairwise(sources, targets, newer=newer):
|
||||
"""
|
||||
Filter filenames where sources are newer than targets.
|
||||
|
||||
Walk two filename iterables in parallel, testing if each source is newer
|
||||
than its corresponding target. Returns a pair of lists (sources,
|
||||
targets) where source is newer than target, according to the semantics
|
||||
of 'newer()'.
|
||||
"""
|
||||
newer_pairs = filter(splat(newer), zip_strict(sources, targets))
|
||||
return tuple(map(list, zip(*newer_pairs))) or ([], [])
|
||||
|
||||
|
||||
def newer_group(sources, target, missing='error'):
|
||||
"""
|
||||
Is target out-of-date with respect to any file in sources.
|
||||
|
||||
Return True if 'target' is out-of-date with respect to any file
|
||||
listed in 'sources'. In other words, if 'target' exists and is newer
|
||||
than every file in 'sources', return False; otherwise return True.
|
||||
``missing`` controls how to handle a missing source file:
|
||||
|
||||
- error (default): allow the ``stat()`` call to fail.
|
||||
- ignore: silently disregard any missing source files.
|
||||
- newer: treat missing source files as "target out of date". This
|
||||
mode is handy in "dry-run" mode: it will pretend to carry out
|
||||
commands that wouldn't work because inputs are missing, but
|
||||
that doesn't matter because dry-run won't run the commands.
|
||||
"""
|
||||
|
||||
def missing_as_newer(source):
|
||||
return missing == 'newer' and not os.path.exists(source)
|
||||
|
||||
ignored = os.path.exists if missing == 'ignore' else None
|
||||
return not os.path.exists(target) or any(
|
||||
missing_as_newer(source) or _newer(source, target)
|
||||
for source in filter(ignored, sources)
|
||||
)
|
||||
|
||||
|
||||
newer_pairwise_group = functools.partial(newer_pairwise, newer=newer_group)
|
||||
@@ -3,8 +3,7 @@
|
||||
Contains MSVCCompiler, an implementation of the abstract CCompiler class
|
||||
for Microsoft Visual Studio 2015.
|
||||
|
||||
The module is compatible with VS 2015 and later. You can find legacy support
|
||||
for older versions in distutils.msvc9compiler and distutils.msvccompiler.
|
||||
This module requires VS 2015 or later.
|
||||
"""
|
||||
|
||||
# Written by Perry Stoll
|
||||
@@ -13,27 +12,27 @@ for older versions in distutils.msvc9compiler and distutils.msvccompiler.
|
||||
# ported to VS 2005 and VS 2008 by Christian Heimes
|
||||
# ported to VS 2015 by Steve Dower
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import subprocess
|
||||
import contextlib
|
||||
import warnings
|
||||
import unittest.mock as mock
|
||||
import warnings
|
||||
|
||||
with contextlib.suppress(ImportError):
|
||||
import winreg
|
||||
|
||||
from itertools import count
|
||||
|
||||
from ._log import log
|
||||
from .ccompiler import CCompiler, gen_lib_options
|
||||
from .errors import (
|
||||
CompileError,
|
||||
DistutilsExecError,
|
||||
DistutilsPlatformError,
|
||||
CompileError,
|
||||
LibError,
|
||||
LinkError,
|
||||
)
|
||||
from .ccompiler import CCompiler, gen_lib_options
|
||||
from ._log import log
|
||||
from .util import get_platform
|
||||
|
||||
from itertools import count
|
||||
from .util import get_host_platform, get_platform
|
||||
|
||||
|
||||
def _find_vc2015():
|
||||
@@ -79,32 +78,40 @@ def _find_vc2017():
|
||||
if not root:
|
||||
return None, None
|
||||
|
||||
try:
|
||||
path = subprocess.check_output(
|
||||
[
|
||||
os.path.join(
|
||||
root, "Microsoft Visual Studio", "Installer", "vswhere.exe"
|
||||
),
|
||||
"-latest",
|
||||
"-prerelease",
|
||||
"-requires",
|
||||
"Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
||||
"-property",
|
||||
"installationPath",
|
||||
"-products",
|
||||
"*",
|
||||
],
|
||||
encoding="mbcs",
|
||||
errors="strict",
|
||||
).strip()
|
||||
except (subprocess.CalledProcessError, OSError, UnicodeDecodeError):
|
||||
return None, None
|
||||
variant = 'arm64' if get_platform() == 'win-arm64' else 'x86.x64'
|
||||
suitable_components = (
|
||||
f"Microsoft.VisualStudio.Component.VC.Tools.{variant}",
|
||||
"Microsoft.VisualStudio.Workload.WDExpress",
|
||||
)
|
||||
|
||||
path = os.path.join(path, "VC", "Auxiliary", "Build")
|
||||
if os.path.isdir(path):
|
||||
return 15, path
|
||||
for component in suitable_components:
|
||||
# Workaround for `-requiresAny` (only available on VS 2017 > 15.6)
|
||||
with contextlib.suppress(
|
||||
subprocess.CalledProcessError, OSError, UnicodeDecodeError
|
||||
):
|
||||
path = (
|
||||
subprocess.check_output([
|
||||
os.path.join(
|
||||
root, "Microsoft Visual Studio", "Installer", "vswhere.exe"
|
||||
),
|
||||
"-latest",
|
||||
"-prerelease",
|
||||
"-requires",
|
||||
component,
|
||||
"-property",
|
||||
"installationPath",
|
||||
"-products",
|
||||
"*",
|
||||
])
|
||||
.decode(encoding="mbcs", errors="strict")
|
||||
.strip()
|
||||
)
|
||||
|
||||
return None, None
|
||||
path = os.path.join(path, "VC", "Auxiliary", "Build")
|
||||
if os.path.isdir(path):
|
||||
return 15, path
|
||||
|
||||
return None, None # no suitable component found
|
||||
|
||||
|
||||
PLAT_SPEC_TO_RUNTIME = {
|
||||
@@ -140,7 +147,11 @@ def _get_vc_env(plat_spec):
|
||||
|
||||
vcvarsall, _ = _find_vcvarsall(plat_spec)
|
||||
if not vcvarsall:
|
||||
raise DistutilsPlatformError("Unable to find vcvarsall.bat")
|
||||
raise DistutilsPlatformError(
|
||||
'Microsoft Visual C++ 14.0 or greater is required. '
|
||||
'Get it with "Microsoft C++ Build Tools": '
|
||||
'https://visualstudio.microsoft.com/visual-cpp-build-tools/'
|
||||
)
|
||||
|
||||
try:
|
||||
out = subprocess.check_output(
|
||||
@@ -178,17 +189,43 @@ def _find_exe(exe, paths=None):
|
||||
return exe
|
||||
|
||||
|
||||
# A map keyed by get_platform() return values to values accepted by
|
||||
# 'vcvarsall.bat'. Always cross-compile from x86 to work with the
|
||||
# lighter-weight MSVC installs that do not include native 64-bit tools.
|
||||
PLAT_TO_VCVARS = {
|
||||
_vcvars_names = {
|
||||
'win32': 'x86',
|
||||
'win-amd64': 'x86_amd64',
|
||||
'win-arm32': 'x86_arm',
|
||||
'win-arm64': 'x86_arm64',
|
||||
'win-amd64': 'amd64',
|
||||
'win-arm32': 'arm',
|
||||
'win-arm64': 'arm64',
|
||||
}
|
||||
|
||||
|
||||
def _get_vcvars_spec(host_platform, platform):
|
||||
"""
|
||||
Given a host platform and platform, determine the spec for vcvarsall.
|
||||
|
||||
Uses the native MSVC host if the host platform would need expensive
|
||||
emulation for x86.
|
||||
|
||||
>>> _get_vcvars_spec('win-arm64', 'win32')
|
||||
'arm64_x86'
|
||||
>>> _get_vcvars_spec('win-arm64', 'win-amd64')
|
||||
'arm64_amd64'
|
||||
|
||||
Otherwise, always cross-compile from x86 to work with the
|
||||
lighter-weight MSVC installs that do not include native 64-bit tools.
|
||||
|
||||
>>> _get_vcvars_spec('win32', 'win32')
|
||||
'x86'
|
||||
>>> _get_vcvars_spec('win-arm32', 'win-arm32')
|
||||
'x86_arm'
|
||||
>>> _get_vcvars_spec('win-amd64', 'win-arm64')
|
||||
'x86_arm64'
|
||||
"""
|
||||
if host_platform != 'win-arm64':
|
||||
host_platform = 'win32'
|
||||
vc_hp = _vcvars_names[host_platform]
|
||||
vc_plat = _vcvars_names[platform]
|
||||
return vc_hp if vc_hp == vc_plat else f'{vc_hp}_{vc_plat}'
|
||||
|
||||
|
||||
class MSVCCompiler(CCompiler):
|
||||
"""Concrete class that implements an interface to Microsoft Visual C++,
|
||||
as defined by the CCompiler abstract class."""
|
||||
@@ -218,7 +255,7 @@ class MSVCCompiler(CCompiler):
|
||||
static_lib_format = shared_lib_format = '%s%s'
|
||||
exe_extension = '.exe'
|
||||
|
||||
def __init__(self, verbose=0, dry_run=0, force=0):
|
||||
def __init__(self, verbose=False, dry_run=False, force=False):
|
||||
super().__init__(verbose, dry_run, force)
|
||||
# target platform (.plat_name is consistent with 'bdist')
|
||||
self.plat_name = None
|
||||
@@ -242,18 +279,17 @@ class MSVCCompiler(CCompiler):
|
||||
if plat_name is None:
|
||||
plat_name = get_platform()
|
||||
# sanity check for platforms to prevent obscure errors later.
|
||||
if plat_name not in PLAT_TO_VCVARS:
|
||||
if plat_name not in _vcvars_names:
|
||||
raise DistutilsPlatformError(
|
||||
f"--plat-name must be one of {tuple(PLAT_TO_VCVARS)}"
|
||||
f"--plat-name must be one of {tuple(_vcvars_names)}"
|
||||
)
|
||||
|
||||
# Get the vcvarsall.bat spec for the requested platform.
|
||||
plat_spec = PLAT_TO_VCVARS[plat_name]
|
||||
plat_spec = _get_vcvars_spec(get_host_platform(), plat_name)
|
||||
|
||||
vc_env = _get_vc_env(plat_spec)
|
||||
if not vc_env:
|
||||
raise DistutilsPlatformError(
|
||||
"Unable to find a compatible " "Visual Studio installation."
|
||||
"Unable to find a compatible Visual Studio installation."
|
||||
)
|
||||
self._configure(vc_env)
|
||||
|
||||
@@ -334,7 +370,7 @@ class MSVCCompiler(CCompiler):
|
||||
output_dir=None,
|
||||
macros=None,
|
||||
include_dirs=None,
|
||||
debug=0,
|
||||
debug=False,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
depends=None,
|
||||
@@ -430,7 +466,7 @@ class MSVCCompiler(CCompiler):
|
||||
return objects
|
||||
|
||||
def create_static_lib(
|
||||
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
|
||||
self, objects, output_libname, output_dir=None, debug=False, target_lang=None
|
||||
):
|
||||
if not self.initialized:
|
||||
self.initialize()
|
||||
@@ -459,7 +495,7 @@ class MSVCCompiler(CCompiler):
|
||||
library_dirs=None,
|
||||
runtime_library_dirs=None,
|
||||
export_symbols=None,
|
||||
debug=0,
|
||||
debug=False,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
build_temp=None,
|
||||
@@ -558,7 +594,7 @@ class MSVCCompiler(CCompiler):
|
||||
def library_option(self, lib):
|
||||
return self.library_filename(lib)
|
||||
|
||||
def find_library_file(self, dirs, lib, debug=0):
|
||||
def find_library_file(self, dirs, lib, debug=False):
|
||||
# Prefer a debugging library if found (and requested), but deal
|
||||
# with it if we don't have one.
|
||||
if debug:
|
||||
|
||||
@@ -4,8 +4,6 @@ Utility functions for creating archive files (tarballs, zip files,
|
||||
that sort of thing)."""
|
||||
|
||||
import os
|
||||
from warnings import warn
|
||||
import sys
|
||||
|
||||
try:
|
||||
import zipfile
|
||||
@@ -13,10 +11,10 @@ except ImportError:
|
||||
zipfile = None
|
||||
|
||||
|
||||
from ._log import log
|
||||
from .dir_util import mkpath
|
||||
from .errors import DistutilsExecError
|
||||
from .spawn import spawn
|
||||
from .dir_util import mkpath
|
||||
from ._log import log
|
||||
|
||||
try:
|
||||
from pwd import getpwnam
|
||||
@@ -56,13 +54,18 @@ def _get_uid(name):
|
||||
|
||||
|
||||
def make_tarball(
|
||||
base_name, base_dir, compress="gzip", verbose=0, dry_run=0, owner=None, group=None
|
||||
base_name,
|
||||
base_dir,
|
||||
compress="gzip",
|
||||
verbose=False,
|
||||
dry_run=False,
|
||||
owner=None,
|
||||
group=None,
|
||||
):
|
||||
"""Create a (possibly compressed) tar file from all the files under
|
||||
'base_dir'.
|
||||
|
||||
'compress' must be "gzip" (the default), "bzip2", "xz", "compress", or
|
||||
None. ("compress" will be deprecated in Python 3.2)
|
||||
'compress' must be "gzip" (the default), "bzip2", "xz", or None.
|
||||
|
||||
'owner' and 'group' can be used to define an owner and a group for the
|
||||
archive that is being built. If not provided, the current owner and group
|
||||
@@ -78,20 +81,17 @@ def make_tarball(
|
||||
'bzip2': 'bz2',
|
||||
'xz': 'xz',
|
||||
None: '',
|
||||
'compress': '',
|
||||
}
|
||||
compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'xz': '.xz', 'compress': '.Z'}
|
||||
compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'xz': '.xz'}
|
||||
|
||||
# flags for compression program, each element of list will be an argument
|
||||
if compress is not None and compress not in compress_ext.keys():
|
||||
raise ValueError(
|
||||
"bad value for 'compress': must be None, 'gzip', 'bzip2', "
|
||||
"'xz' or 'compress'"
|
||||
"bad value for 'compress': must be None, 'gzip', 'bzip2', 'xz'"
|
||||
)
|
||||
|
||||
archive_name = base_name + '.tar'
|
||||
if compress != 'compress':
|
||||
archive_name += compress_ext.get(compress, '')
|
||||
archive_name += compress_ext.get(compress, '')
|
||||
|
||||
mkpath(os.path.dirname(archive_name), dry_run=dry_run)
|
||||
|
||||
@@ -113,28 +113,16 @@ def make_tarball(
|
||||
return tarinfo
|
||||
|
||||
if not dry_run:
|
||||
tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
|
||||
tar = tarfile.open(archive_name, f'w|{tar_compression[compress]}')
|
||||
try:
|
||||
tar.add(base_dir, filter=_set_uid_gid)
|
||||
finally:
|
||||
tar.close()
|
||||
|
||||
# compression using `compress`
|
||||
if compress == 'compress':
|
||||
warn("'compress' is deprecated.", DeprecationWarning)
|
||||
# the option varies depending on the platform
|
||||
compressed_name = archive_name + compress_ext[compress]
|
||||
if sys.platform == 'win32':
|
||||
cmd = [compress, archive_name, compressed_name]
|
||||
else:
|
||||
cmd = [compress, '-f', archive_name]
|
||||
spawn(cmd, dry_run=dry_run)
|
||||
return compressed_name
|
||||
|
||||
return archive_name
|
||||
|
||||
|
||||
def make_zipfile(base_name, base_dir, verbose=0, dry_run=0): # noqa: C901
|
||||
def make_zipfile(base_name, base_dir, verbose=False, dry_run=False): # noqa: C901
|
||||
"""Create a zip file from all the files under 'base_dir'.
|
||||
|
||||
The output zip file will be named 'base_name' + ".zip". Uses either the
|
||||
@@ -160,12 +148,9 @@ def make_zipfile(base_name, base_dir, verbose=0, dry_run=0): # noqa: C901
|
||||
# XXX really should distinguish between "couldn't find
|
||||
# external 'zip' command" and "zip failed".
|
||||
raise DistutilsExecError(
|
||||
(
|
||||
"unable to create zip file '%s': "
|
||||
"could neither import the 'zipfile' module nor "
|
||||
"find a standalone zip utility"
|
||||
)
|
||||
% zip_filename
|
||||
f"unable to create zip file '{zip_filename}': "
|
||||
"could neither import the 'zipfile' module nor "
|
||||
"find a standalone zip utility"
|
||||
)
|
||||
|
||||
else:
|
||||
@@ -224,8 +209,8 @@ def make_archive(
|
||||
format,
|
||||
root_dir=None,
|
||||
base_dir=None,
|
||||
verbose=0,
|
||||
dry_run=0,
|
||||
verbose=False,
|
||||
dry_run=False,
|
||||
owner=None,
|
||||
group=None,
|
||||
):
|
||||
@@ -260,11 +245,10 @@ def make_archive(
|
||||
try:
|
||||
format_info = ARCHIVE_FORMATS[format]
|
||||
except KeyError:
|
||||
raise ValueError("unknown archive format '%s'" % format)
|
||||
raise ValueError(f"unknown archive format '{format}'")
|
||||
|
||||
func = format_info[0]
|
||||
for arg, val in format_info[1]:
|
||||
kwargs[arg] = val
|
||||
kwargs.update(format_info[1])
|
||||
|
||||
if format != 'zip':
|
||||
kwargs['owner'] = owner
|
||||
|
||||
@@ -1,401 +0,0 @@
|
||||
"""distutils.bcppcompiler
|
||||
|
||||
Contains BorlandCCompiler, an implementation of the abstract CCompiler class
|
||||
for the Borland C++ compiler.
|
||||
"""
|
||||
|
||||
# This implementation by Lyle Johnson, based on the original msvccompiler.py
|
||||
# module and using the directions originally published by Gordon Williams.
|
||||
|
||||
# XXX looks like there's a LOT of overlap between these two classes:
|
||||
# someone should sit down and factor out the common code as
|
||||
# WindowsCCompiler! --GPW
|
||||
|
||||
|
||||
import os
|
||||
import warnings
|
||||
|
||||
from .errors import (
|
||||
DistutilsExecError,
|
||||
CompileError,
|
||||
LibError,
|
||||
LinkError,
|
||||
UnknownFileError,
|
||||
)
|
||||
from .ccompiler import CCompiler, gen_preprocess_options
|
||||
from .file_util import write_file
|
||||
from .dep_util import newer
|
||||
from ._log import log
|
||||
|
||||
|
||||
warnings.warn(
|
||||
"bcppcompiler is deprecated and slated to be removed "
|
||||
"in the future. Please discontinue use or file an issue "
|
||||
"with pypa/distutils describing your use case.",
|
||||
DeprecationWarning,
|
||||
)
|
||||
|
||||
|
||||
class BCPPCompiler(CCompiler):
|
||||
"""Concrete class that implements an interface to the Borland C/C++
|
||||
compiler, as defined by the CCompiler abstract class.
|
||||
"""
|
||||
|
||||
compiler_type = 'bcpp'
|
||||
|
||||
# Just set this so CCompiler's constructor doesn't barf. We currently
|
||||
# don't use the 'set_executables()' bureaucracy provided by CCompiler,
|
||||
# as it really isn't necessary for this sort of single-compiler class.
|
||||
# Would be nice to have a consistent interface with UnixCCompiler,
|
||||
# though, so it's worth thinking about.
|
||||
executables = {}
|
||||
|
||||
# Private class data (need to distinguish C from C++ source for compiler)
|
||||
_c_extensions = ['.c']
|
||||
_cpp_extensions = ['.cc', '.cpp', '.cxx']
|
||||
|
||||
# Needed for the filename generation methods provided by the
|
||||
# base class, CCompiler.
|
||||
src_extensions = _c_extensions + _cpp_extensions
|
||||
obj_extension = '.obj'
|
||||
static_lib_extension = '.lib'
|
||||
shared_lib_extension = '.dll'
|
||||
static_lib_format = shared_lib_format = '%s%s'
|
||||
exe_extension = '.exe'
|
||||
|
||||
def __init__(self, verbose=0, dry_run=0, force=0):
|
||||
super().__init__(verbose, dry_run, force)
|
||||
|
||||
# These executables are assumed to all be in the path.
|
||||
# Borland doesn't seem to use any special registry settings to
|
||||
# indicate their installation locations.
|
||||
|
||||
self.cc = "bcc32.exe"
|
||||
self.linker = "ilink32.exe"
|
||||
self.lib = "tlib.exe"
|
||||
|
||||
self.preprocess_options = None
|
||||
self.compile_options = ['/tWM', '/O2', '/q', '/g0']
|
||||
self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0']
|
||||
|
||||
self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x']
|
||||
self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x']
|
||||
self.ldflags_static = []
|
||||
self.ldflags_exe = ['/Gn', '/q', '/x']
|
||||
self.ldflags_exe_debug = ['/Gn', '/q', '/x', '/r']
|
||||
|
||||
# -- Worker methods ------------------------------------------------
|
||||
|
||||
def compile( # noqa: C901
|
||||
self,
|
||||
sources,
|
||||
output_dir=None,
|
||||
macros=None,
|
||||
include_dirs=None,
|
||||
debug=0,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
depends=None,
|
||||
):
|
||||
macros, objects, extra_postargs, pp_opts, build = self._setup_compile(
|
||||
output_dir, macros, include_dirs, sources, depends, extra_postargs
|
||||
)
|
||||
compile_opts = extra_preargs or []
|
||||
compile_opts.append('-c')
|
||||
if debug:
|
||||
compile_opts.extend(self.compile_options_debug)
|
||||
else:
|
||||
compile_opts.extend(self.compile_options)
|
||||
|
||||
for obj in objects:
|
||||
try:
|
||||
src, ext = build[obj]
|
||||
except KeyError:
|
||||
continue
|
||||
# XXX why do the normpath here?
|
||||
src = os.path.normpath(src)
|
||||
obj = os.path.normpath(obj)
|
||||
# XXX _setup_compile() did a mkpath() too but before the normpath.
|
||||
# Is it possible to skip the normpath?
|
||||
self.mkpath(os.path.dirname(obj))
|
||||
|
||||
if ext == '.res':
|
||||
# This is already a binary file -- skip it.
|
||||
continue # the 'for' loop
|
||||
if ext == '.rc':
|
||||
# This needs to be compiled to a .res file -- do it now.
|
||||
try:
|
||||
self.spawn(["brcc32", "-fo", obj, src])
|
||||
except DistutilsExecError as msg:
|
||||
raise CompileError(msg)
|
||||
continue # the 'for' loop
|
||||
|
||||
# The next two are both for the real compiler.
|
||||
if ext in self._c_extensions:
|
||||
input_opt = ""
|
||||
elif ext in self._cpp_extensions:
|
||||
input_opt = "-P"
|
||||
else:
|
||||
# Unknown file type -- no extra options. The compiler
|
||||
# will probably fail, but let it just in case this is a
|
||||
# file the compiler recognizes even if we don't.
|
||||
input_opt = ""
|
||||
|
||||
output_opt = "-o" + obj
|
||||
|
||||
# Compiler command line syntax is: "bcc32 [options] file(s)".
|
||||
# Note that the source file names must appear at the end of
|
||||
# the command line.
|
||||
try:
|
||||
self.spawn(
|
||||
[self.cc]
|
||||
+ compile_opts
|
||||
+ pp_opts
|
||||
+ [input_opt, output_opt]
|
||||
+ extra_postargs
|
||||
+ [src]
|
||||
)
|
||||
except DistutilsExecError as msg:
|
||||
raise CompileError(msg)
|
||||
|
||||
return objects
|
||||
|
||||
# compile ()
|
||||
|
||||
def create_static_lib(
|
||||
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
|
||||
):
|
||||
(objects, output_dir) = self._fix_object_args(objects, output_dir)
|
||||
output_filename = self.library_filename(output_libname, output_dir=output_dir)
|
||||
|
||||
if self._need_link(objects, output_filename):
|
||||
lib_args = [output_filename, '/u'] + objects
|
||||
if debug:
|
||||
pass # XXX what goes here?
|
||||
try:
|
||||
self.spawn([self.lib] + lib_args)
|
||||
except DistutilsExecError as msg:
|
||||
raise LibError(msg)
|
||||
else:
|
||||
log.debug("skipping %s (up-to-date)", output_filename)
|
||||
|
||||
# create_static_lib ()
|
||||
|
||||
def link( # noqa: C901
|
||||
self,
|
||||
target_desc,
|
||||
objects,
|
||||
output_filename,
|
||||
output_dir=None,
|
||||
libraries=None,
|
||||
library_dirs=None,
|
||||
runtime_library_dirs=None,
|
||||
export_symbols=None,
|
||||
debug=0,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
build_temp=None,
|
||||
target_lang=None,
|
||||
):
|
||||
# XXX this ignores 'build_temp'! should follow the lead of
|
||||
# msvccompiler.py
|
||||
|
||||
(objects, output_dir) = self._fix_object_args(objects, output_dir)
|
||||
(libraries, library_dirs, runtime_library_dirs) = self._fix_lib_args(
|
||||
libraries, library_dirs, runtime_library_dirs
|
||||
)
|
||||
|
||||
if runtime_library_dirs:
|
||||
log.warning(
|
||||
"I don't know what to do with 'runtime_library_dirs': %s",
|
||||
str(runtime_library_dirs),
|
||||
)
|
||||
|
||||
if output_dir is not None:
|
||||
output_filename = os.path.join(output_dir, output_filename)
|
||||
|
||||
if self._need_link(objects, output_filename):
|
||||
# Figure out linker args based on type of target.
|
||||
if target_desc == CCompiler.EXECUTABLE:
|
||||
startup_obj = 'c0w32'
|
||||
if debug:
|
||||
ld_args = self.ldflags_exe_debug[:]
|
||||
else:
|
||||
ld_args = self.ldflags_exe[:]
|
||||
else:
|
||||
startup_obj = 'c0d32'
|
||||
if debug:
|
||||
ld_args = self.ldflags_shared_debug[:]
|
||||
else:
|
||||
ld_args = self.ldflags_shared[:]
|
||||
|
||||
# Create a temporary exports file for use by the linker
|
||||
if export_symbols is None:
|
||||
def_file = ''
|
||||
else:
|
||||
head, tail = os.path.split(output_filename)
|
||||
modname, ext = os.path.splitext(tail)
|
||||
temp_dir = os.path.dirname(objects[0]) # preserve tree structure
|
||||
def_file = os.path.join(temp_dir, '%s.def' % modname)
|
||||
contents = ['EXPORTS']
|
||||
for sym in export_symbols or []:
|
||||
contents.append(' {}=_{}'.format(sym, sym))
|
||||
self.execute(write_file, (def_file, contents), "writing %s" % def_file)
|
||||
|
||||
# Borland C++ has problems with '/' in paths
|
||||
objects2 = map(os.path.normpath, objects)
|
||||
# split objects in .obj and .res files
|
||||
# Borland C++ needs them at different positions in the command line
|
||||
objects = [startup_obj]
|
||||
resources = []
|
||||
for file in objects2:
|
||||
(base, ext) = os.path.splitext(os.path.normcase(file))
|
||||
if ext == '.res':
|
||||
resources.append(file)
|
||||
else:
|
||||
objects.append(file)
|
||||
|
||||
for ell in library_dirs:
|
||||
ld_args.append("/L%s" % os.path.normpath(ell))
|
||||
ld_args.append("/L.") # we sometimes use relative paths
|
||||
|
||||
# list of object files
|
||||
ld_args.extend(objects)
|
||||
|
||||
# XXX the command-line syntax for Borland C++ is a bit wonky;
|
||||
# certain filenames are jammed together in one big string, but
|
||||
# comma-delimited. This doesn't mesh too well with the
|
||||
# Unix-centric attitude (with a DOS/Windows quoting hack) of
|
||||
# 'spawn()', so constructing the argument list is a bit
|
||||
# awkward. Note that doing the obvious thing and jamming all
|
||||
# the filenames and commas into one argument would be wrong,
|
||||
# because 'spawn()' would quote any filenames with spaces in
|
||||
# them. Arghghh!. Apparently it works fine as coded...
|
||||
|
||||
# name of dll/exe file
|
||||
ld_args.extend([',', output_filename])
|
||||
# no map file and start libraries
|
||||
ld_args.append(',,')
|
||||
|
||||
for lib in libraries:
|
||||
# see if we find it and if there is a bcpp specific lib
|
||||
# (xxx_bcpp.lib)
|
||||
libfile = self.find_library_file(library_dirs, lib, debug)
|
||||
if libfile is None:
|
||||
ld_args.append(lib)
|
||||
# probably a BCPP internal library -- don't warn
|
||||
else:
|
||||
# full name which prefers bcpp_xxx.lib over xxx.lib
|
||||
ld_args.append(libfile)
|
||||
|
||||
# some default libraries
|
||||
ld_args.extend(('import32', 'cw32mt'))
|
||||
|
||||
# def file for export symbols
|
||||
ld_args.extend([',', def_file])
|
||||
# add resource files
|
||||
ld_args.append(',')
|
||||
ld_args.extend(resources)
|
||||
|
||||
if extra_preargs:
|
||||
ld_args[:0] = extra_preargs
|
||||
if extra_postargs:
|
||||
ld_args.extend(extra_postargs)
|
||||
|
||||
self.mkpath(os.path.dirname(output_filename))
|
||||
try:
|
||||
self.spawn([self.linker] + ld_args)
|
||||
except DistutilsExecError as msg:
|
||||
raise LinkError(msg)
|
||||
|
||||
else:
|
||||
log.debug("skipping %s (up-to-date)", output_filename)
|
||||
|
||||
# link ()
|
||||
|
||||
# -- Miscellaneous methods -----------------------------------------
|
||||
|
||||
def find_library_file(self, dirs, lib, debug=0):
|
||||
# List of effective library names to try, in order of preference:
|
||||
# xxx_bcpp.lib is better than xxx.lib
|
||||
# and xxx_d.lib is better than xxx.lib if debug is set
|
||||
#
|
||||
# The "_bcpp" suffix is to handle a Python installation for people
|
||||
# with multiple compilers (primarily Distutils hackers, I suspect
|
||||
# ;-). The idea is they'd have one static library for each
|
||||
# compiler they care about, since (almost?) every Windows compiler
|
||||
# seems to have a different format for static libraries.
|
||||
if debug:
|
||||
dlib = lib + "_d"
|
||||
try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib)
|
||||
else:
|
||||
try_names = (lib + "_bcpp", lib)
|
||||
|
||||
for dir in dirs:
|
||||
for name in try_names:
|
||||
libfile = os.path.join(dir, self.library_filename(name))
|
||||
if os.path.exists(libfile):
|
||||
return libfile
|
||||
else:
|
||||
# Oops, didn't find it in *any* of 'dirs'
|
||||
return None
|
||||
|
||||
# overwrite the one from CCompiler to support rc and res-files
|
||||
def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
|
||||
if output_dir is None:
|
||||
output_dir = ''
|
||||
obj_names = []
|
||||
for src_name in source_filenames:
|
||||
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
|
||||
(base, ext) = os.path.splitext(os.path.normcase(src_name))
|
||||
if ext not in (self.src_extensions + ['.rc', '.res']):
|
||||
raise UnknownFileError(
|
||||
"unknown file type '{}' (from '{}')".format(ext, src_name)
|
||||
)
|
||||
if strip_dir:
|
||||
base = os.path.basename(base)
|
||||
if ext == '.res':
|
||||
# these can go unchanged
|
||||
obj_names.append(os.path.join(output_dir, base + ext))
|
||||
elif ext == '.rc':
|
||||
# these need to be compiled to .res-files
|
||||
obj_names.append(os.path.join(output_dir, base + '.res'))
|
||||
else:
|
||||
obj_names.append(os.path.join(output_dir, base + self.obj_extension))
|
||||
return obj_names
|
||||
|
||||
# object_filenames ()
|
||||
|
||||
def preprocess(
|
||||
self,
|
||||
source,
|
||||
output_file=None,
|
||||
macros=None,
|
||||
include_dirs=None,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
):
|
||||
(_, macros, include_dirs) = self._fix_compile_args(None, macros, include_dirs)
|
||||
pp_opts = gen_preprocess_options(macros, include_dirs)
|
||||
pp_args = ['cpp32.exe'] + pp_opts
|
||||
if output_file is not None:
|
||||
pp_args.append('-o' + output_file)
|
||||
if extra_preargs:
|
||||
pp_args[:0] = extra_preargs
|
||||
if extra_postargs:
|
||||
pp_args.extend(extra_postargs)
|
||||
pp_args.append(source)
|
||||
|
||||
# We need to preprocess: either we're being forced to, or the
|
||||
# source file is newer than the target (or the target doesn't
|
||||
# exist).
|
||||
if self.force or output_file is None or newer(source, output_file):
|
||||
if output_file:
|
||||
self.mkpath(os.path.dirname(output_file))
|
||||
try:
|
||||
self.spawn(pp_args)
|
||||
except DistutilsExecError as msg:
|
||||
print(msg)
|
||||
raise CompileError(msg)
|
||||
|
||||
# preprocess()
|
||||
@@ -3,24 +3,27 @@
|
||||
Contains CCompiler, an abstract base class that defines the interface
|
||||
for the Distutils compiler abstraction model."""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import types
|
||||
import warnings
|
||||
|
||||
from more_itertools import always_iterable
|
||||
|
||||
from ._log import log
|
||||
from ._modified import newer_group
|
||||
from .dir_util import mkpath
|
||||
from .errors import (
|
||||
CompileError,
|
||||
DistutilsModuleError,
|
||||
DistutilsPlatformError,
|
||||
LinkError,
|
||||
UnknownFileError,
|
||||
DistutilsPlatformError,
|
||||
DistutilsModuleError,
|
||||
)
|
||||
from .spawn import spawn
|
||||
from .file_util import move_file
|
||||
from .dir_util import mkpath
|
||||
from .dep_util import newer_group
|
||||
from .util import split_quoted, execute
|
||||
from ._log import log
|
||||
from .spawn import spawn
|
||||
from .util import execute, is_mingw, split_quoted
|
||||
|
||||
|
||||
class CCompiler:
|
||||
@@ -103,7 +106,7 @@ class CCompiler:
|
||||
library dirs specific to this compiler class
|
||||
"""
|
||||
|
||||
def __init__(self, verbose=0, dry_run=0, force=0):
|
||||
def __init__(self, verbose=False, dry_run=False, force=False):
|
||||
self.dry_run = dry_run
|
||||
self.force = force
|
||||
self.verbose = verbose
|
||||
@@ -168,8 +171,7 @@ class CCompiler:
|
||||
for key in kwargs:
|
||||
if key not in self.executables:
|
||||
raise ValueError(
|
||||
"unknown executable '%s' for class %s"
|
||||
% (key, self.__class__.__name__)
|
||||
f"unknown executable '{key}' for class {self.__class__.__name__}"
|
||||
)
|
||||
self.set_executable(key, kwargs[key])
|
||||
|
||||
@@ -188,24 +190,28 @@ class CCompiler:
|
||||
return None
|
||||
|
||||
def _check_macro_definitions(self, definitions):
|
||||
"""Ensures that every element of 'definitions' is a valid macro
|
||||
definition, ie. either (name,value) 2-tuple or a (name,) tuple. Do
|
||||
nothing if all definitions are OK, raise TypeError otherwise.
|
||||
"""
|
||||
"""Ensure that every element of 'definitions' is valid."""
|
||||
for defn in definitions:
|
||||
if not (
|
||||
isinstance(defn, tuple)
|
||||
and (
|
||||
len(defn) in (1, 2)
|
||||
and (isinstance(defn[1], str) or defn[1] is None)
|
||||
)
|
||||
and isinstance(defn[0], str)
|
||||
):
|
||||
raise TypeError(
|
||||
("invalid macro definition '%s': " % defn)
|
||||
+ "must be tuple (string,), (string, string), or "
|
||||
+ "(string, None)"
|
||||
)
|
||||
self._check_macro_definition(*defn)
|
||||
|
||||
def _check_macro_definition(self, defn):
|
||||
"""
|
||||
Raise a TypeError if defn is not valid.
|
||||
|
||||
A valid definition is either a (name, value) 2-tuple or a (name,) tuple.
|
||||
"""
|
||||
if not isinstance(defn, tuple) or not self._is_valid_macro(*defn):
|
||||
raise TypeError(
|
||||
f"invalid macro definition '{defn}': "
|
||||
"must be tuple (string,), (string, string), or (string, None)"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _is_valid_macro(name, value=None):
|
||||
"""
|
||||
A valid macro is a ``name : str`` and a ``value : str | None``.
|
||||
"""
|
||||
return isinstance(name, str) and isinstance(value, (str, types.NoneType))
|
||||
|
||||
# -- Bookkeeping methods -------------------------------------------
|
||||
|
||||
@@ -342,7 +348,7 @@ class CCompiler:
|
||||
extra = []
|
||||
|
||||
# Get the list of expected output (object) files
|
||||
objects = self.object_filenames(sources, strip_dir=0, output_dir=outdir)
|
||||
objects = self.object_filenames(sources, strip_dir=False, output_dir=outdir)
|
||||
assert len(objects) == len(sources)
|
||||
|
||||
pp_opts = gen_preprocess_options(macros, incdirs)
|
||||
@@ -382,7 +388,7 @@ class CCompiler:
|
||||
raise TypeError("'output_dir' must be a string or None")
|
||||
|
||||
if macros is None:
|
||||
macros = self.macros
|
||||
macros = list(self.macros)
|
||||
elif isinstance(macros, list):
|
||||
macros = macros + (self.macros or [])
|
||||
else:
|
||||
@@ -441,14 +447,14 @@ class CCompiler:
|
||||
fixed versions of all arguments.
|
||||
"""
|
||||
if libraries is None:
|
||||
libraries = self.libraries
|
||||
libraries = list(self.libraries)
|
||||
elif isinstance(libraries, (list, tuple)):
|
||||
libraries = list(libraries) + (self.libraries or [])
|
||||
else:
|
||||
raise TypeError("'libraries' (if supplied) must be a list of strings")
|
||||
|
||||
if library_dirs is None:
|
||||
library_dirs = self.library_dirs
|
||||
library_dirs = list(self.library_dirs)
|
||||
elif isinstance(library_dirs, (list, tuple)):
|
||||
library_dirs = list(library_dirs) + (self.library_dirs or [])
|
||||
else:
|
||||
@@ -458,14 +464,14 @@ class CCompiler:
|
||||
library_dirs += self.__class__.library_dirs
|
||||
|
||||
if runtime_library_dirs is None:
|
||||
runtime_library_dirs = self.runtime_library_dirs
|
||||
runtime_library_dirs = list(self.runtime_library_dirs)
|
||||
elif isinstance(runtime_library_dirs, (list, tuple)):
|
||||
runtime_library_dirs = list(runtime_library_dirs) + (
|
||||
self.runtime_library_dirs or []
|
||||
)
|
||||
else:
|
||||
raise TypeError(
|
||||
"'runtime_library_dirs' (if supplied) " "must be a list of strings"
|
||||
"'runtime_library_dirs' (if supplied) must be a list of strings"
|
||||
)
|
||||
|
||||
return (libraries, library_dirs, runtime_library_dirs)
|
||||
@@ -532,7 +538,7 @@ class CCompiler:
|
||||
output_dir=None,
|
||||
macros=None,
|
||||
include_dirs=None,
|
||||
debug=0,
|
||||
debug=False,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
depends=None,
|
||||
@@ -609,7 +615,7 @@ class CCompiler:
|
||||
pass
|
||||
|
||||
def create_static_lib(
|
||||
self, objects, output_libname, output_dir=None, debug=0, target_lang=None
|
||||
self, objects, output_libname, output_dir=None, debug=False, target_lang=None
|
||||
):
|
||||
"""Link a bunch of stuff together to create a static library file.
|
||||
The "bunch of stuff" consists of the list of object files supplied
|
||||
@@ -650,7 +656,7 @@ class CCompiler:
|
||||
library_dirs=None,
|
||||
runtime_library_dirs=None,
|
||||
export_symbols=None,
|
||||
debug=0,
|
||||
debug=False,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
build_temp=None,
|
||||
@@ -712,7 +718,7 @@ class CCompiler:
|
||||
library_dirs=None,
|
||||
runtime_library_dirs=None,
|
||||
export_symbols=None,
|
||||
debug=0,
|
||||
debug=False,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
build_temp=None,
|
||||
@@ -743,7 +749,7 @@ class CCompiler:
|
||||
library_dirs=None,
|
||||
runtime_library_dirs=None,
|
||||
export_symbols=None,
|
||||
debug=0,
|
||||
debug=False,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
build_temp=None,
|
||||
@@ -773,7 +779,7 @@ class CCompiler:
|
||||
libraries=None,
|
||||
library_dirs=None,
|
||||
runtime_library_dirs=None,
|
||||
debug=0,
|
||||
debug=False,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
target_lang=None,
|
||||
@@ -857,10 +863,9 @@ class CCompiler:
|
||||
if library_dirs is None:
|
||||
library_dirs = []
|
||||
fd, fname = tempfile.mkstemp(".c", funcname, text=True)
|
||||
f = os.fdopen(fd, "w")
|
||||
try:
|
||||
with os.fdopen(fd, "w", encoding='utf-8') as f:
|
||||
for incl in includes:
|
||||
f.write("""#include "%s"\n""" % incl)
|
||||
f.write(f"""#include "{incl}"\n""")
|
||||
if not includes:
|
||||
# Use "char func(void);" as the prototype to follow
|
||||
# what autoconf does. This prototype does not match
|
||||
@@ -870,25 +875,22 @@ class CCompiler:
|
||||
# know the exact argument types, and the has_function
|
||||
# interface does not provide that level of information.
|
||||
f.write(
|
||||
"""\
|
||||
f"""\
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char %s(void);
|
||||
char {funcname}(void);
|
||||
"""
|
||||
% funcname
|
||||
)
|
||||
f.write(
|
||||
"""\
|
||||
int main (int argc, char **argv) {
|
||||
%s();
|
||||
f"""\
|
||||
int main (int argc, char **argv) {{
|
||||
{funcname}();
|
||||
return 0;
|
||||
}
|
||||
}}
|
||||
"""
|
||||
% funcname
|
||||
)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
try:
|
||||
objects = self.compile([fname], include_dirs=include_dirs)
|
||||
except CompileError:
|
||||
@@ -911,7 +913,7 @@ int main (int argc, char **argv) {
|
||||
os.remove(fn)
|
||||
return True
|
||||
|
||||
def find_library_file(self, dirs, lib, debug=0):
|
||||
def find_library_file(self, dirs, lib, debug=False):
|
||||
"""Search the specified list of directories for a static or shared
|
||||
library file 'lib' and return the full path to that file. If
|
||||
'debug' true, look for a debugging version (if that makes sense on
|
||||
@@ -954,7 +956,7 @@ int main (int argc, char **argv) {
|
||||
# * exe_extension -
|
||||
# extension for executable files, eg. '' or '.exe'
|
||||
|
||||
def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
|
||||
def object_filenames(self, source_filenames, strip_dir=False, output_dir=''):
|
||||
if output_dir is None:
|
||||
output_dir = ''
|
||||
return list(
|
||||
@@ -972,9 +974,7 @@ int main (int argc, char **argv) {
|
||||
try:
|
||||
new_ext = self.out_extensions[ext]
|
||||
except LookupError:
|
||||
raise UnknownFileError(
|
||||
"unknown file type '{}' (from '{}')".format(ext, src_name)
|
||||
)
|
||||
raise UnknownFileError(f"unknown file type '{ext}' (from '{src_name}')")
|
||||
if strip_dir:
|
||||
base = os.path.basename(base)
|
||||
return os.path.join(output_dir, base + new_ext)
|
||||
@@ -991,20 +991,24 @@ int main (int argc, char **argv) {
|
||||
# If abs, chop off leading /
|
||||
return no_drive[os.path.isabs(no_drive) :]
|
||||
|
||||
def shared_object_filename(self, basename, strip_dir=0, output_dir=''):
|
||||
def shared_object_filename(self, basename, strip_dir=False, output_dir=''):
|
||||
assert output_dir is not None
|
||||
if strip_dir:
|
||||
basename = os.path.basename(basename)
|
||||
return os.path.join(output_dir, basename + self.shared_lib_extension)
|
||||
|
||||
def executable_filename(self, basename, strip_dir=0, output_dir=''):
|
||||
def executable_filename(self, basename, strip_dir=False, output_dir=''):
|
||||
assert output_dir is not None
|
||||
if strip_dir:
|
||||
basename = os.path.basename(basename)
|
||||
return os.path.join(output_dir, basename + (self.exe_extension or ''))
|
||||
|
||||
def library_filename(
|
||||
self, libname, lib_type='static', strip_dir=0, output_dir='' # or 'shared'
|
||||
self,
|
||||
libname,
|
||||
lib_type='static',
|
||||
strip_dir=False,
|
||||
output_dir='', # or 'shared'
|
||||
):
|
||||
assert output_dir is not None
|
||||
expected = '"static", "shared", "dylib", "xcode_stub"'
|
||||
@@ -1032,7 +1036,7 @@ int main (int argc, char **argv) {
|
||||
print(msg)
|
||||
|
||||
def warn(self, msg):
|
||||
sys.stderr.write("warning: %s\n" % msg)
|
||||
sys.stderr.write(f"warning: {msg}\n")
|
||||
|
||||
def execute(self, func, args, msg=None, level=1):
|
||||
execute(func, args, msg, self.dry_run)
|
||||
@@ -1056,6 +1060,7 @@ _default_compilers = (
|
||||
# on a cygwin built python we can use gcc like an ordinary UNIXish
|
||||
# compiler
|
||||
('cygwin.*', 'unix'),
|
||||
('zos', 'zos'),
|
||||
# OS name mappings
|
||||
('posix', 'unix'),
|
||||
('nt', 'msvc'),
|
||||
@@ -1076,6 +1081,10 @@ def get_default_compiler(osname=None, platform=None):
|
||||
osname = os.name
|
||||
if platform is None:
|
||||
platform = sys.platform
|
||||
# Mingw is a special case where sys.platform is 'win32' but we
|
||||
# want to use the 'mingw32' compiler, so check it first
|
||||
if is_mingw():
|
||||
return 'mingw32'
|
||||
for pattern, compiler in _default_compilers:
|
||||
if (
|
||||
re.match(pattern, platform) is not None
|
||||
@@ -1103,6 +1112,7 @@ compiler_class = {
|
||||
"Mingw32 port of GNU C Compiler for Win32",
|
||||
),
|
||||
'bcpp': ('bcppcompiler', 'BCPPCompiler', "Borland C++ Compiler"),
|
||||
'zos': ('zosccompiler', 'zOSCCompiler', 'IBM XL C/C++ Compilers'),
|
||||
}
|
||||
|
||||
|
||||
@@ -1115,15 +1125,15 @@ def show_compilers():
|
||||
# commands that use it.
|
||||
from distutils.fancy_getopt import FancyGetopt
|
||||
|
||||
compilers = []
|
||||
for compiler in compiler_class.keys():
|
||||
compilers.append(("compiler=" + compiler, None, compiler_class[compiler][2]))
|
||||
compilers.sort()
|
||||
compilers = sorted(
|
||||
("compiler=" + compiler, None, compiler_class[compiler][2])
|
||||
for compiler in compiler_class.keys()
|
||||
)
|
||||
pretty_printer = FancyGetopt(compilers)
|
||||
pretty_printer.print_help("List of available compilers:")
|
||||
|
||||
|
||||
def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
|
||||
def new_compiler(plat=None, compiler=None, verbose=False, dry_run=False, force=False):
|
||||
"""Generate an instance of some CCompiler subclass for the supplied
|
||||
platform/compiler combination. 'plat' defaults to 'os.name'
|
||||
(eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler
|
||||
@@ -1143,9 +1153,9 @@ def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
|
||||
|
||||
(module_name, class_name, long_description) = compiler_class[compiler]
|
||||
except KeyError:
|
||||
msg = "don't know how to compile C/C++ code on platform '%s'" % plat
|
||||
msg = f"don't know how to compile C/C++ code on platform '{plat}'"
|
||||
if compiler is not None:
|
||||
msg = msg + " with '%s' compiler" % compiler
|
||||
msg = msg + f" with '{compiler}' compiler"
|
||||
raise DistutilsPlatformError(msg)
|
||||
|
||||
try:
|
||||
@@ -1155,12 +1165,12 @@ def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0):
|
||||
klass = vars(module)[class_name]
|
||||
except ImportError:
|
||||
raise DistutilsModuleError(
|
||||
"can't compile C/C++ code: unable to load module '%s'" % module_name
|
||||
f"can't compile C/C++ code: unable to load module '{module_name}'"
|
||||
)
|
||||
except KeyError:
|
||||
raise DistutilsModuleError(
|
||||
"can't compile C/C++ code: unable to find class '%s' "
|
||||
"in module '%s'" % (class_name, module_name)
|
||||
f"can't compile C/C++ code: unable to find class '{class_name}' "
|
||||
f"in module '{module_name}'"
|
||||
)
|
||||
|
||||
# XXX The None is necessary to preserve backwards compatibility
|
||||
@@ -1194,23 +1204,22 @@ def gen_preprocess_options(macros, include_dirs):
|
||||
for macro in macros:
|
||||
if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2):
|
||||
raise TypeError(
|
||||
"bad macro definition '%s': "
|
||||
"each element of 'macros' list must be a 1- or 2-tuple" % macro
|
||||
f"bad macro definition '{macro}': "
|
||||
"each element of 'macros' list must be a 1- or 2-tuple"
|
||||
)
|
||||
|
||||
if len(macro) == 1: # undefine this macro
|
||||
pp_opts.append("-U%s" % macro[0])
|
||||
pp_opts.append(f"-U{macro[0]}")
|
||||
elif len(macro) == 2:
|
||||
if macro[1] is None: # define with no explicit value
|
||||
pp_opts.append("-D%s" % macro[0])
|
||||
pp_opts.append(f"-D{macro[0]}")
|
||||
else:
|
||||
# XXX *don't* need to be clever about quoting the
|
||||
# macro value here, because we're going to avoid the
|
||||
# shell at all costs when we spawn the command!
|
||||
pp_opts.append("-D%s=%s" % macro)
|
||||
pp_opts.append("-D{}={}".format(*macro))
|
||||
|
||||
for dir in include_dirs:
|
||||
pp_opts.append("-I%s" % dir)
|
||||
pp_opts.extend(f"-I{dir}" for dir in include_dirs)
|
||||
return pp_opts
|
||||
|
||||
|
||||
@@ -1221,17 +1230,10 @@ def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
|
||||
directories. Returns a list of command-line options suitable for use
|
||||
with some compiler (depending on the two format strings passed in).
|
||||
"""
|
||||
lib_opts = []
|
||||
|
||||
for dir in library_dirs:
|
||||
lib_opts.append(compiler.library_dir_option(dir))
|
||||
lib_opts = [compiler.library_dir_option(dir) for dir in library_dirs]
|
||||
|
||||
for dir in runtime_library_dirs:
|
||||
opt = compiler.runtime_library_dir_option(dir)
|
||||
if isinstance(opt, list):
|
||||
lib_opts = lib_opts + opt
|
||||
else:
|
||||
lib_opts.append(opt)
|
||||
lib_opts.extend(always_iterable(compiler.runtime_library_dir_option(dir)))
|
||||
|
||||
# XXX it's important that we *not* remove redundant library mentions!
|
||||
# sometimes you really do have to say "-lfoo -lbar -lfoo" in order to
|
||||
@@ -1247,7 +1249,7 @@ def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries):
|
||||
lib_opts.append(lib_file)
|
||||
else:
|
||||
compiler.warn(
|
||||
"no library file corresponding to " "'%s' found (skipping)" % lib
|
||||
f"no library file corresponding to '{lib}' found (skipping)"
|
||||
)
|
||||
else:
|
||||
lib_opts.append(compiler.library_option(lib))
|
||||
|
||||
@@ -4,14 +4,14 @@ Provides the Command class, the base class for the command classes
|
||||
in the distutils.command package.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from .errors import DistutilsOptionError
|
||||
from . import util, dir_util, file_util, archive_util, dep_util
|
||||
from . import _modified, archive_util, dir_util, file_util, util
|
||||
from ._log import log
|
||||
from .errors import DistutilsOptionError
|
||||
|
||||
|
||||
class Command:
|
||||
@@ -87,13 +87,13 @@ class Command:
|
||||
|
||||
# The 'help' flag is just used for command-line parsing, so
|
||||
# none of that complicated bureaucracy is needed.
|
||||
self.help = 0
|
||||
self.help = False
|
||||
|
||||
# 'finalized' records whether or not 'finalize_options()' has been
|
||||
# called. 'finalize_options()' itself should not pay attention to
|
||||
# this flag: it is the business of 'ensure_finalized()', which
|
||||
# always calls 'finalize_options()', to respect/update it.
|
||||
self.finalized = 0
|
||||
self.finalized = False
|
||||
|
||||
# XXX A more explicit way to customize dry_run would be better.
|
||||
def __getattr__(self, attr):
|
||||
@@ -109,7 +109,7 @@ class Command:
|
||||
def ensure_finalized(self):
|
||||
if not self.finalized:
|
||||
self.finalize_options()
|
||||
self.finalized = 1
|
||||
self.finalized = True
|
||||
|
||||
# Subclasses must define:
|
||||
# initialize_options()
|
||||
@@ -135,7 +135,7 @@ class Command:
|
||||
This method must be implemented by all command classes.
|
||||
"""
|
||||
raise RuntimeError(
|
||||
"abstract method -- subclass %s must override" % self.__class__
|
||||
f"abstract method -- subclass {self.__class__} must override"
|
||||
)
|
||||
|
||||
def finalize_options(self):
|
||||
@@ -150,14 +150,14 @@ class Command:
|
||||
This method must be implemented by all command classes.
|
||||
"""
|
||||
raise RuntimeError(
|
||||
"abstract method -- subclass %s must override" % self.__class__
|
||||
f"abstract method -- subclass {self.__class__} must override"
|
||||
)
|
||||
|
||||
def dump_options(self, header=None, indent=""):
|
||||
from distutils.fancy_getopt import longopt_xlate
|
||||
|
||||
if header is None:
|
||||
header = "command options for '%s':" % self.get_command_name()
|
||||
header = f"command options for '{self.get_command_name()}':"
|
||||
self.announce(indent + header, level=logging.INFO)
|
||||
indent = indent + " "
|
||||
for option, _, _ in self.user_options:
|
||||
@@ -165,7 +165,7 @@ class Command:
|
||||
if option[-1] == "=":
|
||||
option = option[:-1]
|
||||
value = getattr(self, option)
|
||||
self.announce(indent + "{} = {}".format(option, value), level=logging.INFO)
|
||||
self.announce(indent + f"{option} = {value}", level=logging.INFO)
|
||||
|
||||
def run(self):
|
||||
"""A command's raison d'etre: carry out the action it exists to
|
||||
@@ -178,7 +178,7 @@ class Command:
|
||||
This method must be implemented by all command classes.
|
||||
"""
|
||||
raise RuntimeError(
|
||||
"abstract method -- subclass %s must override" % self.__class__
|
||||
f"abstract method -- subclass {self.__class__} must override"
|
||||
)
|
||||
|
||||
def announce(self, msg, level=logging.DEBUG):
|
||||
@@ -213,9 +213,7 @@ class Command:
|
||||
setattr(self, option, default)
|
||||
return default
|
||||
elif not isinstance(val, str):
|
||||
raise DistutilsOptionError(
|
||||
"'{}' must be a {} (got `{}`)".format(option, what, val)
|
||||
)
|
||||
raise DistutilsOptionError(f"'{option}' must be a {what} (got `{val}`)")
|
||||
return val
|
||||
|
||||
def ensure_string(self, option, default=None):
|
||||
@@ -242,7 +240,7 @@ class Command:
|
||||
ok = False
|
||||
if not ok:
|
||||
raise DistutilsOptionError(
|
||||
"'{}' must be a list of strings (got {!r})".format(option, val)
|
||||
f"'{option}' must be a list of strings (got {val!r})"
|
||||
)
|
||||
|
||||
def _ensure_tested_string(self, option, tester, what, error_fmt, default=None):
|
||||
@@ -295,7 +293,7 @@ class Command:
|
||||
if getattr(self, dst_option) is None:
|
||||
setattr(self, dst_option, getattr(src_cmd_obj, src_option))
|
||||
|
||||
def get_finalized_command(self, command, create=1):
|
||||
def get_finalized_command(self, command, create=True):
|
||||
"""Wrapper around Distribution's 'get_command_obj()' method: find
|
||||
(create if necessary and 'create' is true) the command object for
|
||||
'command', call its 'ensure_finalized()' method, and return the
|
||||
@@ -307,7 +305,7 @@ class Command:
|
||||
|
||||
# XXX rename to 'get_reinitialized_command()'? (should do the
|
||||
# same in dist.py, if so)
|
||||
def reinitialize_command(self, command, reinit_subcommands=0):
|
||||
def reinitialize_command(self, command, reinit_subcommands=False):
|
||||
return self.distribution.reinitialize_command(command, reinit_subcommands)
|
||||
|
||||
def run_command(self, command):
|
||||
@@ -342,7 +340,13 @@ class Command:
|
||||
dir_util.mkpath(name, mode, dry_run=self.dry_run)
|
||||
|
||||
def copy_file(
|
||||
self, infile, outfile, preserve_mode=1, preserve_times=1, link=None, level=1
|
||||
self,
|
||||
infile,
|
||||
outfile,
|
||||
preserve_mode=True,
|
||||
preserve_times=True,
|
||||
link=None,
|
||||
level=1,
|
||||
):
|
||||
"""Copy a file respecting verbose, dry-run and force flags. (The
|
||||
former two default to whatever is in the Distribution object, and
|
||||
@@ -361,9 +365,9 @@ class Command:
|
||||
self,
|
||||
infile,
|
||||
outfile,
|
||||
preserve_mode=1,
|
||||
preserve_times=1,
|
||||
preserve_symlinks=0,
|
||||
preserve_mode=True,
|
||||
preserve_times=True,
|
||||
preserve_symlinks=False,
|
||||
level=1,
|
||||
):
|
||||
"""Copy an entire directory tree respecting verbose, dry-run,
|
||||
@@ -383,7 +387,7 @@ class Command:
|
||||
"""Move a file respecting dry-run flag."""
|
||||
return file_util.move_file(src, dst, dry_run=self.dry_run)
|
||||
|
||||
def spawn(self, cmd, search_path=1, level=1):
|
||||
def spawn(self, cmd, search_path=True, level=1):
|
||||
"""Spawn an external command respecting dry-run flag."""
|
||||
from distutils.spawn import spawn
|
||||
|
||||
@@ -414,7 +418,7 @@ class Command:
|
||||
timestamp checks.
|
||||
"""
|
||||
if skip_msg is None:
|
||||
skip_msg = "skipping %s (inputs unchanged)" % outfile
|
||||
skip_msg = f"skipping {outfile} (inputs unchanged)"
|
||||
|
||||
# Allow 'infiles' to be a single string
|
||||
if isinstance(infiles, str):
|
||||
@@ -428,7 +432,7 @@ class Command:
|
||||
# If 'outfile' must be regenerated (either because it doesn't
|
||||
# exist, is out-of-date, or the 'force' flag is true) then
|
||||
# perform the action that presumably regenerates it
|
||||
if self.force or dep_util.newer_group(infiles, outfile):
|
||||
if self.force or _modified.newer_group(infiles, outfile):
|
||||
self.execute(func, args, exec_msg, level)
|
||||
# Otherwise, print the "skip" message
|
||||
else:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Package containing implementation of all the standard Distutils
|
||||
commands."""
|
||||
|
||||
__all__ = [ # noqa: F822
|
||||
__all__ = [
|
||||
'build',
|
||||
'build_py',
|
||||
'build_ext',
|
||||
@@ -16,10 +16,8 @@ __all__ = [ # noqa: F822
|
||||
'install_scripts',
|
||||
'install_data',
|
||||
'sdist',
|
||||
'register',
|
||||
'bdist',
|
||||
'bdist_dumb',
|
||||
'bdist_rpm',
|
||||
'check',
|
||||
'upload',
|
||||
]
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,15 +2,14 @@
|
||||
Backward compatibility for homebrew builds on macOS.
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import functools
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import sysconfig
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
@functools.lru_cache
|
||||
def enabled():
|
||||
"""
|
||||
Only enabled for Python 3.9 framework homebrew builds
|
||||
@@ -38,7 +37,7 @@ schemes = dict(
|
||||
)
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
@functools.lru_cache
|
||||
def vars():
|
||||
if not enabled():
|
||||
return {}
|
||||
|
||||
@@ -7,7 +7,7 @@ import os
|
||||
import warnings
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsPlatformError, DistutilsOptionError
|
||||
from ..errors import DistutilsOptionError, DistutilsPlatformError
|
||||
from ..util import get_platform
|
||||
|
||||
|
||||
@@ -15,9 +15,10 @@ def show_formats():
|
||||
"""Print list of available formats (arguments to "--format" option)."""
|
||||
from ..fancy_getopt import FancyGetopt
|
||||
|
||||
formats = []
|
||||
for format in bdist.format_commands:
|
||||
formats.append(("formats=" + format, None, bdist.format_commands[format][1]))
|
||||
formats = [
|
||||
("formats=" + format, None, bdist.format_commands[format][1])
|
||||
for format in bdist.format_commands
|
||||
]
|
||||
pretty_printer = FancyGetopt(formats)
|
||||
pretty_printer.print_help("List of available distribution formats:")
|
||||
|
||||
@@ -41,24 +42,24 @@ class bdist(Command):
|
||||
'plat-name=',
|
||||
'p',
|
||||
"platform name to embed in generated filenames "
|
||||
"(default: %s)" % get_platform(),
|
||||
f"[default: {get_platform()}]",
|
||||
),
|
||||
('formats=', None, "formats for distribution (comma-separated list)"),
|
||||
(
|
||||
'dist-dir=',
|
||||
'd',
|
||||
"directory to put final built distributions in " "[default: dist]",
|
||||
"directory to put final built distributions in [default: dist]",
|
||||
),
|
||||
('skip-build', None, "skip rebuilding everything (for testing/debugging)"),
|
||||
(
|
||||
'owner=',
|
||||
'u',
|
||||
"Owner name used when creating a tar file" " [default: current user]",
|
||||
"Owner name used when creating a tar file [default: current user]",
|
||||
),
|
||||
(
|
||||
'group=',
|
||||
'g',
|
||||
"Group name used when creating a tar file" " [default: current group]",
|
||||
"Group name used when creating a tar file [default: current group]",
|
||||
),
|
||||
]
|
||||
|
||||
@@ -76,17 +77,15 @@ class bdist(Command):
|
||||
default_format = {'posix': 'gztar', 'nt': 'zip'}
|
||||
|
||||
# Define commands in preferred order for the --help-formats option
|
||||
format_commands = ListCompat(
|
||||
{
|
||||
'rpm': ('bdist_rpm', "RPM distribution"),
|
||||
'gztar': ('bdist_dumb', "gzip'ed tar file"),
|
||||
'bztar': ('bdist_dumb', "bzip2'ed tar file"),
|
||||
'xztar': ('bdist_dumb', "xz'ed tar file"),
|
||||
'ztar': ('bdist_dumb', "compressed tar file"),
|
||||
'tar': ('bdist_dumb', "tar file"),
|
||||
'zip': ('bdist_dumb', "ZIP file"),
|
||||
}
|
||||
)
|
||||
format_commands = ListCompat({
|
||||
'rpm': ('bdist_rpm', "RPM distribution"),
|
||||
'gztar': ('bdist_dumb', "gzip'ed tar file"),
|
||||
'bztar': ('bdist_dumb', "bzip2'ed tar file"),
|
||||
'xztar': ('bdist_dumb', "xz'ed tar file"),
|
||||
'ztar': ('bdist_dumb', "compressed tar file"),
|
||||
'tar': ('bdist_dumb', "tar file"),
|
||||
'zip': ('bdist_dumb', "ZIP file"),
|
||||
})
|
||||
|
||||
# for compatibility until consumers only reference format_commands
|
||||
format_command = format_commands
|
||||
@@ -96,7 +95,7 @@ class bdist(Command):
|
||||
self.plat_name = None
|
||||
self.formats = None
|
||||
self.dist_dir = None
|
||||
self.skip_build = 0
|
||||
self.skip_build = False
|
||||
self.group = None
|
||||
self.owner = None
|
||||
|
||||
@@ -122,7 +121,7 @@ class bdist(Command):
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to create built distributions "
|
||||
"on platform %s" % os.name
|
||||
f"on platform {os.name}"
|
||||
)
|
||||
|
||||
if self.dist_dir is None:
|
||||
@@ -135,7 +134,7 @@ class bdist(Command):
|
||||
try:
|
||||
commands.append(self.format_commands[format][0])
|
||||
except KeyError:
|
||||
raise DistutilsOptionError("invalid format '%s'" % format)
|
||||
raise DistutilsOptionError(f"invalid format '{format}'")
|
||||
|
||||
# Reinitialize and run each command.
|
||||
for i in range(len(self.formats)):
|
||||
@@ -152,5 +151,5 @@ class bdist(Command):
|
||||
# If we're going to need to run this command again, tell it to
|
||||
# keep its temporary files around so subsequent runs go faster.
|
||||
if cmd_name in commands[i + 1 :]:
|
||||
sub_cmd.keep_temp = 1
|
||||
sub_cmd.keep_temp = True
|
||||
self.run_command(cmd_name)
|
||||
|
||||
@@ -5,12 +5,13 @@ distribution -- i.e., just an archive to be unpacked under $prefix or
|
||||
$exec_prefix)."""
|
||||
|
||||
import os
|
||||
from distutils._log import log
|
||||
|
||||
from ..core import Command
|
||||
from ..util import get_platform
|
||||
from ..dir_util import remove_tree, ensure_relative
|
||||
from ..dir_util import ensure_relative, remove_tree
|
||||
from ..errors import DistutilsPlatformError
|
||||
from ..sysconfig import get_python_version
|
||||
from distutils._log import log
|
||||
from ..util import get_platform
|
||||
|
||||
|
||||
class bdist_dumb(Command):
|
||||
@@ -22,35 +23,34 @@ class bdist_dumb(Command):
|
||||
'plat-name=',
|
||||
'p',
|
||||
"platform name to embed in generated filenames "
|
||||
"(default: %s)" % get_platform(),
|
||||
f"[default: {get_platform()}]",
|
||||
),
|
||||
(
|
||||
'format=',
|
||||
'f',
|
||||
"archive format to create (tar, gztar, bztar, xztar, " "ztar, zip)",
|
||||
"archive format to create (tar, gztar, bztar, xztar, ztar, zip)",
|
||||
),
|
||||
(
|
||||
'keep-temp',
|
||||
'k',
|
||||
"keep the pseudo-installation tree around after "
|
||||
+ "creating the distribution archive",
|
||||
"keep the pseudo-installation tree around after creating the distribution archive",
|
||||
),
|
||||
('dist-dir=', 'd', "directory to put final built distributions in"),
|
||||
('skip-build', None, "skip rebuilding everything (for testing/debugging)"),
|
||||
(
|
||||
'relative',
|
||||
None,
|
||||
"build the archive using relative paths " "(default: false)",
|
||||
"build the archive using relative paths [default: false]",
|
||||
),
|
||||
(
|
||||
'owner=',
|
||||
'u',
|
||||
"Owner name used when creating a tar file" " [default: current user]",
|
||||
"Owner name used when creating a tar file [default: current user]",
|
||||
),
|
||||
(
|
||||
'group=',
|
||||
'g',
|
||||
"Group name used when creating a tar file" " [default: current group]",
|
||||
"Group name used when creating a tar file [default: current group]",
|
||||
),
|
||||
]
|
||||
|
||||
@@ -62,10 +62,10 @@ class bdist_dumb(Command):
|
||||
self.bdist_dir = None
|
||||
self.plat_name = None
|
||||
self.format = None
|
||||
self.keep_temp = 0
|
||||
self.keep_temp = False
|
||||
self.dist_dir = None
|
||||
self.skip_build = None
|
||||
self.relative = 0
|
||||
self.relative = False
|
||||
self.owner = None
|
||||
self.group = None
|
||||
|
||||
@@ -80,7 +80,7 @@ class bdist_dumb(Command):
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to create dumb built distributions "
|
||||
"on platform %s" % os.name
|
||||
f"on platform {os.name}"
|
||||
)
|
||||
|
||||
self.set_undefined_options(
|
||||
@@ -94,19 +94,17 @@ class bdist_dumb(Command):
|
||||
if not self.skip_build:
|
||||
self.run_command('build')
|
||||
|
||||
install = self.reinitialize_command('install', reinit_subcommands=1)
|
||||
install = self.reinitialize_command('install', reinit_subcommands=True)
|
||||
install.root = self.bdist_dir
|
||||
install.skip_build = self.skip_build
|
||||
install.warn_dir = 0
|
||||
install.warn_dir = False
|
||||
|
||||
log.info("installing to %s", self.bdist_dir)
|
||||
self.run_command('install')
|
||||
|
||||
# And make an archive relative to the root of the
|
||||
# pseudo-installation tree.
|
||||
archive_basename = "{}.{}".format(
|
||||
self.distribution.get_fullname(), self.plat_name
|
||||
)
|
||||
archive_basename = f"{self.distribution.get_fullname()}.{self.plat_name}"
|
||||
|
||||
pseudoinstall_root = os.path.join(self.dist_dir, archive_basename)
|
||||
if not self.relative:
|
||||
@@ -117,8 +115,7 @@ class bdist_dumb(Command):
|
||||
):
|
||||
raise DistutilsPlatformError(
|
||||
"can't make a dumb built distribution where "
|
||||
"base and platbase are different (%s, %s)"
|
||||
% (repr(install.install_base), repr(install.install_platbase))
|
||||
f"base and platbase are different ({install.install_base!r}, {install.install_platbase!r})"
|
||||
)
|
||||
else:
|
||||
archive_root = os.path.join(
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
Implements the Distutils 'bdist_rpm' command (create RPM source and binary
|
||||
distributions)."""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
from distutils._log import log
|
||||
|
||||
from ..core import Command
|
||||
from ..debug import DEBUG
|
||||
from ..file_util import write_file
|
||||
from ..errors import (
|
||||
DistutilsExecError,
|
||||
DistutilsFileError,
|
||||
DistutilsOptionError,
|
||||
DistutilsPlatformError,
|
||||
DistutilsFileError,
|
||||
DistutilsExecError,
|
||||
)
|
||||
from ..file_util import write_file
|
||||
from ..sysconfig import get_python_version
|
||||
from distutils._log import log
|
||||
|
||||
|
||||
class bdist_rpm(Command):
|
||||
@@ -34,13 +34,13 @@ class bdist_rpm(Command):
|
||||
(
|
||||
'dist-dir=',
|
||||
'd',
|
||||
"directory to put final RPM files in " "(and .spec files if --spec-only)",
|
||||
"directory to put final RPM files in (and .spec files if --spec-only)",
|
||||
),
|
||||
(
|
||||
'python=',
|
||||
None,
|
||||
"path to Python interpreter to hard-code in the .spec file "
|
||||
"(default: \"python\")",
|
||||
"[default: \"python\"]",
|
||||
),
|
||||
(
|
||||
'fix-python',
|
||||
@@ -75,7 +75,7 @@ class bdist_rpm(Command):
|
||||
(
|
||||
'packager=',
|
||||
None,
|
||||
"RPM packager (eg. \"Jane Doe <jane@example.net>\") " "[default: vendor]",
|
||||
"RPM packager (eg. \"Jane Doe <jane@example.net>\") [default: vendor]",
|
||||
),
|
||||
('doc-files=', None, "list of documentation files (space or comma-separated)"),
|
||||
('changelog=', None, "RPM changelog"),
|
||||
@@ -187,13 +187,13 @@ class bdist_rpm(Command):
|
||||
self.build_requires = None
|
||||
self.obsoletes = None
|
||||
|
||||
self.keep_temp = 0
|
||||
self.use_rpm_opt_flags = 1
|
||||
self.rpm3_mode = 1
|
||||
self.no_autoreq = 0
|
||||
self.keep_temp = False
|
||||
self.use_rpm_opt_flags = True
|
||||
self.rpm3_mode = True
|
||||
self.no_autoreq = False
|
||||
|
||||
self.force_arch = None
|
||||
self.quiet = 0
|
||||
self.quiet = False
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('bdist', ('bdist_base', 'bdist_base'))
|
||||
@@ -214,7 +214,7 @@ class bdist_rpm(Command):
|
||||
|
||||
if os.name != 'posix':
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to create RPM " "distributions on platform %s" % os.name
|
||||
f"don't know how to create RPM distributions on platform {os.name}"
|
||||
)
|
||||
if self.binary_only and self.source_only:
|
||||
raise DistutilsOptionError(
|
||||
@@ -223,7 +223,7 @@ class bdist_rpm(Command):
|
||||
|
||||
# don't pass CFLAGS to pure python distributions
|
||||
if not self.distribution.has_ext_modules():
|
||||
self.use_rpm_opt_flags = 0
|
||||
self.use_rpm_opt_flags = False
|
||||
|
||||
self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
|
||||
self.finalize_package_data()
|
||||
@@ -232,8 +232,7 @@ class bdist_rpm(Command):
|
||||
self.ensure_string('group', "Development/Libraries")
|
||||
self.ensure_string(
|
||||
'vendor',
|
||||
"%s <%s>"
|
||||
% (self.distribution.get_contact(), self.distribution.get_contact_email()),
|
||||
f"{self.distribution.get_contact()} <{self.distribution.get_contact_email()}>",
|
||||
)
|
||||
self.ensure_string('packager')
|
||||
self.ensure_string_list('doc_files')
|
||||
@@ -296,9 +295,9 @@ class bdist_rpm(Command):
|
||||
|
||||
# Spec file goes into 'dist_dir' if '--spec-only specified',
|
||||
# build/rpm.<plat> otherwise.
|
||||
spec_path = os.path.join(spec_dir, "%s.spec" % self.distribution.get_name())
|
||||
spec_path = os.path.join(spec_dir, f"{self.distribution.get_name()}.spec")
|
||||
self.execute(
|
||||
write_file, (spec_path, self._make_spec_file()), "writing '%s'" % spec_path
|
||||
write_file, (spec_path, self._make_spec_file()), f"writing '{spec_path}'"
|
||||
)
|
||||
|
||||
if self.spec_only: # stop if requested
|
||||
@@ -323,7 +322,7 @@ class bdist_rpm(Command):
|
||||
if os.path.exists(self.icon):
|
||||
self.copy_file(self.icon, source_dir)
|
||||
else:
|
||||
raise DistutilsFileError("icon file '%s' does not exist" % self.icon)
|
||||
raise DistutilsFileError(f"icon file '{self.icon}' does not exist")
|
||||
|
||||
# build package
|
||||
log.info("building RPMs")
|
||||
@@ -335,9 +334,9 @@ class bdist_rpm(Command):
|
||||
rpm_cmd.append('-bb')
|
||||
else:
|
||||
rpm_cmd.append('-ba')
|
||||
rpm_cmd.extend(['--define', '__python %s' % self.python])
|
||||
rpm_cmd.extend(['--define', f'__python {self.python}'])
|
||||
if self.rpm3_mode:
|
||||
rpm_cmd.extend(['--define', '_topdir %s' % os.path.abspath(self.rpm_base)])
|
||||
rpm_cmd.extend(['--define', f'_topdir {os.path.abspath(self.rpm_base)}'])
|
||||
if not self.keep_temp:
|
||||
rpm_cmd.append('--clean')
|
||||
|
||||
@@ -352,11 +351,7 @@ class bdist_rpm(Command):
|
||||
nvr_string = "%{name}-%{version}-%{release}"
|
||||
src_rpm = nvr_string + ".src.rpm"
|
||||
non_src_rpm = "%{arch}/" + nvr_string + ".%{arch}.rpm"
|
||||
q_cmd = r"rpm -q --qf '{} {}\n' --specfile '{}'".format(
|
||||
src_rpm,
|
||||
non_src_rpm,
|
||||
spec_path,
|
||||
)
|
||||
q_cmd = rf"rpm -q --qf '{src_rpm} {non_src_rpm}\n' --specfile '{spec_path}'"
|
||||
|
||||
out = os.popen(q_cmd)
|
||||
try:
|
||||
@@ -375,7 +370,7 @@ class bdist_rpm(Command):
|
||||
|
||||
status = out.close()
|
||||
if status:
|
||||
raise DistutilsExecError("Failed to execute: %s" % repr(q_cmd))
|
||||
raise DistutilsExecError(f"Failed to execute: {q_cmd!r}")
|
||||
|
||||
finally:
|
||||
out.close()
|
||||
@@ -401,9 +396,11 @@ class bdist_rpm(Command):
|
||||
if os.path.exists(rpm):
|
||||
self.move_file(rpm, self.dist_dir)
|
||||
filename = os.path.join(self.dist_dir, os.path.basename(rpm))
|
||||
self.distribution.dist_files.append(
|
||||
('bdist_rpm', pyversion, filename)
|
||||
)
|
||||
self.distribution.dist_files.append((
|
||||
'bdist_rpm',
|
||||
pyversion,
|
||||
filename,
|
||||
))
|
||||
|
||||
def _dist_path(self, path):
|
||||
return os.path.join(self.dist_dir, os.path.basename(path))
|
||||
@@ -428,14 +425,14 @@ class bdist_rpm(Command):
|
||||
# Generate a potential replacement value for __os_install_post (whilst
|
||||
# normalizing the whitespace to simplify the test for whether the
|
||||
# invocation of brp-python-bytecompile passes in __python):
|
||||
vendor_hook = '\n'.join(
|
||||
[' %s \\' % line.strip() for line in vendor_hook.splitlines()]
|
||||
)
|
||||
vendor_hook = '\n'.join([
|
||||
f' {line.strip()} \\' for line in vendor_hook.splitlines()
|
||||
])
|
||||
problem = "brp-python-bytecompile \\\n"
|
||||
fixed = "brp-python-bytecompile %{__python} \\\n"
|
||||
fixed_hook = vendor_hook.replace(problem, fixed)
|
||||
if fixed_hook != vendor_hook:
|
||||
spec_file.append('# Workaround for http://bugs.python.org/issue14443')
|
||||
spec_file.append('# Workaround for https://bugs.python.org/issue14443')
|
||||
spec_file.append('%define __os_install_post ' + fixed_hook + '\n')
|
||||
|
||||
# put locale summaries into spec file
|
||||
@@ -445,13 +442,11 @@ class bdist_rpm(Command):
|
||||
# spec_file.append('Summary(%s): %s' % (locale,
|
||||
# self.summaries[locale]))
|
||||
|
||||
spec_file.extend(
|
||||
[
|
||||
'Name: %{name}',
|
||||
'Version: %{version}',
|
||||
'Release: %{release}',
|
||||
]
|
||||
)
|
||||
spec_file.extend([
|
||||
'Name: %{name}',
|
||||
'Version: %{version}',
|
||||
'Release: %{release}',
|
||||
])
|
||||
|
||||
# XXX yuck! this filename is available from the "sdist" command,
|
||||
# but only after it has run: and we create the spec file before
|
||||
@@ -461,21 +456,19 @@ class bdist_rpm(Command):
|
||||
else:
|
||||
spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz')
|
||||
|
||||
spec_file.extend(
|
||||
[
|
||||
'License: ' + (self.distribution.get_license() or "UNKNOWN"),
|
||||
'Group: ' + self.group,
|
||||
'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot',
|
||||
'Prefix: %{_prefix}',
|
||||
]
|
||||
)
|
||||
spec_file.extend([
|
||||
'License: ' + (self.distribution.get_license() or "UNKNOWN"),
|
||||
'Group: ' + self.group,
|
||||
'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot',
|
||||
'Prefix: %{_prefix}',
|
||||
])
|
||||
|
||||
if not self.force_arch:
|
||||
# noarch if no extension modules
|
||||
if not self.distribution.has_ext_modules():
|
||||
spec_file.append('BuildArch: noarch')
|
||||
else:
|
||||
spec_file.append('BuildArch: %s' % self.force_arch)
|
||||
spec_file.append(f'BuildArch: {self.force_arch}')
|
||||
|
||||
for field in (
|
||||
'Vendor',
|
||||
@@ -489,7 +482,7 @@ class bdist_rpm(Command):
|
||||
if isinstance(val, list):
|
||||
spec_file.append('{}: {}'.format(field, ' '.join(val)))
|
||||
elif val is not None:
|
||||
spec_file.append('{}: {}'.format(field, val))
|
||||
spec_file.append(f'{field}: {val}')
|
||||
|
||||
if self.distribution.get_url():
|
||||
spec_file.append('Url: ' + self.distribution.get_url())
|
||||
@@ -506,13 +499,11 @@ class bdist_rpm(Command):
|
||||
if self.no_autoreq:
|
||||
spec_file.append('AutoReq: 0')
|
||||
|
||||
spec_file.extend(
|
||||
[
|
||||
'',
|
||||
'%description',
|
||||
self.distribution.get_long_description() or "",
|
||||
]
|
||||
)
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%description',
|
||||
self.distribution.get_long_description() or "",
|
||||
])
|
||||
|
||||
# put locale descriptions into spec file
|
||||
# XXX again, suppressed because config file syntax doesn't
|
||||
@@ -526,8 +517,8 @@ class bdist_rpm(Command):
|
||||
|
||||
# rpm scripts
|
||||
# figure out default build script
|
||||
def_setup_call = "{} {}".format(self.python, os.path.basename(sys.argv[0]))
|
||||
def_build = "%s build" % def_setup_call
|
||||
def_setup_call = f"{self.python} {os.path.basename(sys.argv[0])}"
|
||||
def_build = f"{def_setup_call} build"
|
||||
if self.use_rpm_opt_flags:
|
||||
def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build
|
||||
|
||||
@@ -537,9 +528,7 @@ class bdist_rpm(Command):
|
||||
# that we open and interpolate into the spec file, but the defaults
|
||||
# are just text that we drop in as-is. Hmmm.
|
||||
|
||||
install_cmd = (
|
||||
'%s install -O1 --root=$RPM_BUILD_ROOT ' '--record=INSTALLED_FILES'
|
||||
) % def_setup_call
|
||||
install_cmd = f'{def_setup_call} install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES'
|
||||
|
||||
script_options = [
|
||||
('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"),
|
||||
@@ -558,12 +547,10 @@ class bdist_rpm(Command):
|
||||
# use 'default' as contents of script
|
||||
val = getattr(self, attr)
|
||||
if val or default:
|
||||
spec_file.extend(
|
||||
[
|
||||
'',
|
||||
'%' + rpm_opt,
|
||||
]
|
||||
)
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%' + rpm_opt,
|
||||
])
|
||||
if val:
|
||||
with open(val) as f:
|
||||
spec_file.extend(f.read().split('\n'))
|
||||
@@ -571,24 +558,20 @@ class bdist_rpm(Command):
|
||||
spec_file.append(default)
|
||||
|
||||
# files section
|
||||
spec_file.extend(
|
||||
[
|
||||
'',
|
||||
'%files -f INSTALLED_FILES',
|
||||
'%defattr(-,root,root)',
|
||||
]
|
||||
)
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%files -f INSTALLED_FILES',
|
||||
'%defattr(-,root,root)',
|
||||
])
|
||||
|
||||
if self.doc_files:
|
||||
spec_file.append('%doc ' + ' '.join(self.doc_files))
|
||||
|
||||
if self.changelog:
|
||||
spec_file.extend(
|
||||
[
|
||||
'',
|
||||
'%changelog',
|
||||
]
|
||||
)
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%changelog',
|
||||
])
|
||||
spec_file.extend(self.changelog)
|
||||
|
||||
return spec_file
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
Implements the Distutils 'build' command."""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import sys
|
||||
import sysconfig
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsOptionError
|
||||
from ..util import get_platform
|
||||
@@ -25,16 +27,14 @@ class build(Command):
|
||||
(
|
||||
'build-lib=',
|
||||
None,
|
||||
"build directory for all distribution (defaults to either "
|
||||
+ "build-purelib or build-platlib",
|
||||
"build directory for all distribution (defaults to either build-purelib or build-platlib",
|
||||
),
|
||||
('build-scripts=', None, "build directory for scripts"),
|
||||
('build-temp=', 't', "temporary build directory"),
|
||||
(
|
||||
'plat-name=',
|
||||
'p',
|
||||
"platform name to build for, if supported "
|
||||
"(default: %s)" % get_platform(),
|
||||
f"platform name to build for, if supported [default: {get_platform()}]",
|
||||
),
|
||||
('compiler=', 'c', "specify the compiler type"),
|
||||
('parallel=', 'j', "number of parallel build jobs"),
|
||||
@@ -61,7 +61,7 @@ class build(Command):
|
||||
self.compiler = None
|
||||
self.plat_name = None
|
||||
self.debug = None
|
||||
self.force = 0
|
||||
self.force = False
|
||||
self.executable = None
|
||||
self.parallel = None
|
||||
|
||||
@@ -78,7 +78,11 @@ class build(Command):
|
||||
"using './configure --help' on your platform)"
|
||||
)
|
||||
|
||||
plat_specifier = ".{}-{}".format(self.plat_name, sys.implementation.cache_tag)
|
||||
plat_specifier = f".{self.plat_name}-{sys.implementation.cache_tag}"
|
||||
|
||||
# Python 3.13+ with --disable-gil shouldn't share build directories
|
||||
if sysconfig.get_config_var('Py_GIL_DISABLED'):
|
||||
plat_specifier += 't'
|
||||
|
||||
# Make it so Python 2.x and Python 2.x with --with-pydebug don't
|
||||
# share the same build directories. Doing so confuses the build
|
||||
|
||||
@@ -15,10 +15,11 @@ module."""
|
||||
# cut 'n paste. Sigh.
|
||||
|
||||
import os
|
||||
from distutils._log import log
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsSetupError
|
||||
from ..sysconfig import customize_compiler
|
||||
from distutils._log import log
|
||||
|
||||
|
||||
def show_compilers():
|
||||
@@ -56,7 +57,7 @@ class build_clib(Command):
|
||||
self.define = None
|
||||
self.undef = None
|
||||
self.debug = None
|
||||
self.force = 0
|
||||
self.force = False
|
||||
self.compiler = None
|
||||
|
||||
def finalize_options(self):
|
||||
@@ -137,8 +138,8 @@ class build_clib(Command):
|
||||
|
||||
if '/' in name or (os.sep != '/' and os.sep in name):
|
||||
raise DistutilsSetupError(
|
||||
"bad library name '%s': "
|
||||
"may not contain directory separators" % lib[0]
|
||||
f"bad library name '{lib[0]}': "
|
||||
"may not contain directory separators"
|
||||
)
|
||||
|
||||
if not isinstance(build_info, dict):
|
||||
@@ -154,7 +155,7 @@ class build_clib(Command):
|
||||
return None
|
||||
|
||||
lib_names = []
|
||||
for lib_name, build_info in self.libraries:
|
||||
for lib_name, _build_info in self.libraries:
|
||||
lib_names.append(lib_name)
|
||||
return lib_names
|
||||
|
||||
@@ -165,9 +166,9 @@ class build_clib(Command):
|
||||
sources = build_info.get('sources')
|
||||
if sources is None or not isinstance(sources, (list, tuple)):
|
||||
raise DistutilsSetupError(
|
||||
"in 'libraries' option (library '%s'), "
|
||||
f"in 'libraries' option (library '{lib_name}'), "
|
||||
"'sources' must be present and must be "
|
||||
"a list of source filenames" % lib_name
|
||||
"a list of source filenames"
|
||||
)
|
||||
|
||||
filenames.extend(sources)
|
||||
@@ -178,9 +179,9 @@ class build_clib(Command):
|
||||
sources = build_info.get('sources')
|
||||
if sources is None or not isinstance(sources, (list, tuple)):
|
||||
raise DistutilsSetupError(
|
||||
"in 'libraries' option (library '%s'), "
|
||||
f"in 'libraries' option (library '{lib_name}'), "
|
||||
"'sources' must be present and must be "
|
||||
"a list of source filenames" % lib_name
|
||||
"a list of source filenames"
|
||||
)
|
||||
sources = list(sources)
|
||||
|
||||
|
||||
@@ -8,24 +8,22 @@ import contextlib
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from distutils._log import log
|
||||
from site import USER_BASE
|
||||
|
||||
from .._modified import newer_group
|
||||
from ..core import Command
|
||||
from ..errors import (
|
||||
DistutilsOptionError,
|
||||
DistutilsSetupError,
|
||||
CCompilerError,
|
||||
DistutilsError,
|
||||
CompileError,
|
||||
DistutilsError,
|
||||
DistutilsOptionError,
|
||||
DistutilsPlatformError,
|
||||
DistutilsSetupError,
|
||||
)
|
||||
from ..sysconfig import customize_compiler, get_python_version
|
||||
from ..sysconfig import get_config_h_filename
|
||||
from ..dep_util import newer_group
|
||||
from ..extension import Extension
|
||||
from ..util import get_platform
|
||||
from distutils._log import log
|
||||
from . import py37compat
|
||||
|
||||
from site import USER_BASE
|
||||
from ..sysconfig import customize_compiler, get_config_h_filename, get_python_version
|
||||
from ..util import get_platform, is_mingw
|
||||
|
||||
# An extension name is just a dot-separated list of Python NAMEs (ie.
|
||||
# the same as a fully-qualified module name).
|
||||
@@ -59,7 +57,7 @@ class build_ext(Command):
|
||||
# takes care of both command-line and client options
|
||||
# in between initialize_options() and finalize_options())
|
||||
|
||||
sep_by = " (separated by '%s')" % os.pathsep
|
||||
sep_by = f" (separated by '{os.pathsep}')"
|
||||
user_options = [
|
||||
('build-lib=', 'b', "directory for compiled extension modules"),
|
||||
('build-temp=', 't', "directory for temporary files (build by-products)"),
|
||||
@@ -67,13 +65,13 @@ class build_ext(Command):
|
||||
'plat-name=',
|
||||
'p',
|
||||
"platform name to cross-compile for, if supported "
|
||||
"(default: %s)" % get_platform(),
|
||||
f"[default: {get_platform()}]",
|
||||
),
|
||||
(
|
||||
'inplace',
|
||||
'i',
|
||||
"ignore build-lib and put compiled extensions into the source "
|
||||
+ "directory alongside your pure Python modules",
|
||||
"directory alongside your pure Python modules",
|
||||
),
|
||||
(
|
||||
'include-dirs=',
|
||||
@@ -111,7 +109,7 @@ class build_ext(Command):
|
||||
self.build_lib = None
|
||||
self.plat_name = None
|
||||
self.build_temp = None
|
||||
self.inplace = 0
|
||||
self.inplace = False
|
||||
self.package = None
|
||||
|
||||
self.include_dirs = None
|
||||
@@ -130,6 +128,31 @@ class build_ext(Command):
|
||||
self.user = None
|
||||
self.parallel = None
|
||||
|
||||
@staticmethod
|
||||
def _python_lib_dir(sysconfig):
|
||||
"""
|
||||
Resolve Python's library directory for building extensions
|
||||
that rely on a shared Python library.
|
||||
|
||||
See python/cpython#44264 and python/cpython#48686
|
||||
"""
|
||||
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
|
||||
return
|
||||
|
||||
if sysconfig.python_build:
|
||||
yield '.'
|
||||
return
|
||||
|
||||
if sys.platform == 'zos':
|
||||
# On z/OS, a user is not required to install Python to
|
||||
# a predetermined path, but can use Python portably
|
||||
installed_dir = sysconfig.get_config_var('base')
|
||||
lib_dir = sysconfig.get_config_var('platlibdir')
|
||||
yield os.path.join(installed_dir, lib_dir)
|
||||
else:
|
||||
# building third party extensions
|
||||
yield sysconfig.get_config_var('LIBDIR')
|
||||
|
||||
def finalize_options(self): # noqa: C901
|
||||
from distutils import sysconfig
|
||||
|
||||
@@ -152,7 +175,7 @@ class build_ext(Command):
|
||||
# Make sure Python's include directories (for Python.h, pyconfig.h,
|
||||
# etc.) are in the include search path.
|
||||
py_include = sysconfig.get_python_inc()
|
||||
plat_py_include = sysconfig.get_python_inc(plat_specific=1)
|
||||
plat_py_include = sysconfig.get_python_inc(plat_specific=True)
|
||||
if self.include_dirs is None:
|
||||
self.include_dirs = self.distribution.include_dirs or []
|
||||
if isinstance(self.include_dirs, str):
|
||||
@@ -189,7 +212,7 @@ class build_ext(Command):
|
||||
# for extensions under windows use different directories
|
||||
# for Release and Debug builds.
|
||||
# also Python's library directory must be appended to library_dirs
|
||||
if os.name == 'nt':
|
||||
if os.name == 'nt' and not is_mingw():
|
||||
# the 'libs' directory is for binary installs - we assume that
|
||||
# must be the *native* platform. But we don't really support
|
||||
# cross-compiling via a binary install anyway, so we let it go.
|
||||
@@ -231,16 +254,7 @@ class build_ext(Command):
|
||||
# building python standard extensions
|
||||
self.library_dirs.append('.')
|
||||
|
||||
# For building extensions with a shared Python library,
|
||||
# Python's library directory must be appended to library_dirs
|
||||
# See Issues: #1600860, #4366
|
||||
if sysconfig.get_config_var('Py_ENABLE_SHARED'):
|
||||
if not sysconfig.python_build:
|
||||
# building third party extensions
|
||||
self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
|
||||
else:
|
||||
# building python standard extensions
|
||||
self.library_dirs.append('.')
|
||||
self.library_dirs.extend(self._python_lib_dir(sysconfig))
|
||||
|
||||
# The argument parsing will result in self.define being a string, but
|
||||
# it has to be a list of 2-tuples. All the preprocessor symbols
|
||||
@@ -412,9 +426,7 @@ class build_ext(Command):
|
||||
# Medium-easy stuff: same syntax/semantics, different names.
|
||||
ext.runtime_library_dirs = build_info.get('rpath')
|
||||
if 'def_file' in build_info:
|
||||
log.warning(
|
||||
"'def_file' element of build info dict " "no longer supported"
|
||||
)
|
||||
log.warning("'def_file' element of build info dict no longer supported")
|
||||
|
||||
# Non-trivial stuff: 'macros' split into 'define_macros'
|
||||
# and 'undef_macros'.
|
||||
@@ -453,10 +465,7 @@ class build_ext(Command):
|
||||
# And build the list of output (built) filenames. Note that this
|
||||
# ignores the 'inplace' flag, and assumes everything goes in the
|
||||
# "build" tree.
|
||||
outputs = []
|
||||
for ext in self.extensions:
|
||||
outputs.append(self.get_ext_fullpath(ext.name))
|
||||
return outputs
|
||||
return [self.get_ext_fullpath(ext.name) for ext in self.extensions]
|
||||
|
||||
def build_extensions(self):
|
||||
# First, sanity-check the 'extensions' list
|
||||
@@ -499,15 +508,15 @@ class build_ext(Command):
|
||||
except (CCompilerError, DistutilsError, CompileError) as e:
|
||||
if not ext.optional:
|
||||
raise
|
||||
self.warn('building extension "{}" failed: {}'.format(ext.name, e))
|
||||
self.warn(f'building extension "{ext.name}" failed: {e}')
|
||||
|
||||
def build_extension(self, ext):
|
||||
sources = ext.sources
|
||||
if sources is None or not isinstance(sources, (list, tuple)):
|
||||
raise DistutilsSetupError(
|
||||
"in 'ext_modules' option (extension '%s'), "
|
||||
f"in 'ext_modules' option (extension '{ext.name}'), "
|
||||
"'sources' must be present and must be "
|
||||
"a list of source filenames" % ext.name
|
||||
"a list of source filenames"
|
||||
)
|
||||
# sort to make the resulting .so file build reproducible
|
||||
sources = sorted(sources)
|
||||
@@ -629,8 +638,7 @@ class build_ext(Command):
|
||||
|
||||
# Do not override commandline arguments
|
||||
if not self.swig_opts:
|
||||
for o in extension.swig_opts:
|
||||
swig_cmd.append(o)
|
||||
swig_cmd.extend(extension.swig_opts)
|
||||
|
||||
for source in swig_sources:
|
||||
target = swig_targets[source]
|
||||
@@ -651,7 +659,7 @@ class build_ext(Command):
|
||||
# Windows (or so I presume!). If we find it there, great;
|
||||
# if not, act like Unix and assume it's in the PATH.
|
||||
for vers in ("1.3", "1.2", "1.1"):
|
||||
fn = os.path.join("c:\\swig%s" % vers, "swig.exe")
|
||||
fn = os.path.join(f"c:\\swig{vers}", "swig.exe")
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
else:
|
||||
@@ -659,7 +667,7 @@ class build_ext(Command):
|
||||
else:
|
||||
raise DistutilsPlatformError(
|
||||
"I don't know how to find (much less run) SWIG "
|
||||
"on platform '%s'" % os.name
|
||||
f"on platform '{os.name}'"
|
||||
)
|
||||
|
||||
# -- Name generators -----------------------------------------------
|
||||
@@ -742,7 +750,7 @@ class build_ext(Command):
|
||||
# pyconfig.h that MSVC groks. The other Windows compilers all seem
|
||||
# to need it mentioned explicitly, though, so that's what we do.
|
||||
# Append '_d' to the python import library on debug builds.
|
||||
if sys.platform == "win32":
|
||||
if sys.platform == "win32" and not is_mingw():
|
||||
from .._msvccompiler import MSVCCompiler
|
||||
|
||||
if not isinstance(self.compiler, MSVCCompiler):
|
||||
@@ -772,7 +780,7 @@ class build_ext(Command):
|
||||
# A native build on an Android device or on Cygwin
|
||||
if hasattr(sys, 'getandroidapilevel'):
|
||||
link_libpython = True
|
||||
elif sys.platform == 'cygwin':
|
||||
elif sys.platform == 'cygwin' or is_mingw():
|
||||
link_libpython = True
|
||||
elif '_PYTHON_HOST_PLATFORM' in os.environ:
|
||||
# We are cross-compiling for one of the relevant platforms
|
||||
@@ -785,4 +793,4 @@ class build_ext(Command):
|
||||
ldversion = get_config_var('LDVERSION')
|
||||
return ext.libraries + ['python' + ldversion]
|
||||
|
||||
return ext.libraries + py37compat.pythonlib()
|
||||
return ext.libraries
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
Implements the Distutils 'build_py' command."""
|
||||
|
||||
import os
|
||||
import importlib.util
|
||||
import sys
|
||||
import glob
|
||||
import importlib.util
|
||||
import os
|
||||
import sys
|
||||
from distutils._log import log
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsOptionError, DistutilsFileError
|
||||
from ..errors import DistutilsFileError, DistutilsOptionError
|
||||
from ..util import convert_path
|
||||
from distutils._log import log
|
||||
|
||||
|
||||
class build_py(Command):
|
||||
@@ -38,7 +38,7 @@ class build_py(Command):
|
||||
self.package = None
|
||||
self.package_data = None
|
||||
self.package_dir = None
|
||||
self.compile = 0
|
||||
self.compile = False
|
||||
self.optimize = 0
|
||||
self.force = None
|
||||
|
||||
@@ -95,7 +95,7 @@ class build_py(Command):
|
||||
self.build_packages()
|
||||
self.build_package_data()
|
||||
|
||||
self.byte_compile(self.get_outputs(include_bytecode=0))
|
||||
self.byte_compile(self.get_outputs(include_bytecode=False))
|
||||
|
||||
def get_data_files(self):
|
||||
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
|
||||
@@ -129,14 +129,14 @@ class build_py(Command):
|
||||
os.path.join(glob.escape(src_dir), convert_path(pattern))
|
||||
)
|
||||
# Files that match more than one pattern are only added once
|
||||
files.extend(
|
||||
[fn for fn in filelist if fn not in files and os.path.isfile(fn)]
|
||||
)
|
||||
files.extend([
|
||||
fn for fn in filelist if fn not in files and os.path.isfile(fn)
|
||||
])
|
||||
return files
|
||||
|
||||
def build_package_data(self):
|
||||
"""Copy data files into build directory"""
|
||||
for package, src_dir, build_dir, filenames in self.data_files:
|
||||
for _package, src_dir, build_dir, filenames in self.data_files:
|
||||
for filename in filenames:
|
||||
target = os.path.join(build_dir, filename)
|
||||
self.mkpath(os.path.dirname(target))
|
||||
@@ -191,12 +191,12 @@ class build_py(Command):
|
||||
if package_dir != "":
|
||||
if not os.path.exists(package_dir):
|
||||
raise DistutilsFileError(
|
||||
"package directory '%s' does not exist" % package_dir
|
||||
f"package directory '{package_dir}' does not exist"
|
||||
)
|
||||
if not os.path.isdir(package_dir):
|
||||
raise DistutilsFileError(
|
||||
"supposed package directory '%s' exists, "
|
||||
"but is not a directory" % package_dir
|
||||
f"supposed package directory '{package_dir}' exists, "
|
||||
"but is not a directory"
|
||||
)
|
||||
|
||||
# Directories without __init__.py are namespace packages (PEP 420).
|
||||
@@ -228,7 +228,7 @@ class build_py(Command):
|
||||
module = os.path.splitext(os.path.basename(f))[0]
|
||||
modules.append((package, module, f))
|
||||
else:
|
||||
self.debug_print("excluding %s" % setup_script)
|
||||
self.debug_print(f"excluding {setup_script}")
|
||||
return modules
|
||||
|
||||
def find_modules(self):
|
||||
@@ -264,7 +264,7 @@ class build_py(Command):
|
||||
(package_dir, checked) = packages[package]
|
||||
except KeyError:
|
||||
package_dir = self.get_package_dir(package)
|
||||
checked = 0
|
||||
checked = False
|
||||
|
||||
if not checked:
|
||||
init_py = self.check_package(package, package_dir)
|
||||
@@ -306,10 +306,10 @@ class build_py(Command):
|
||||
outfile_path = [build_dir] + list(package) + [module + ".py"]
|
||||
return os.path.join(*outfile_path)
|
||||
|
||||
def get_outputs(self, include_bytecode=1):
|
||||
def get_outputs(self, include_bytecode=True):
|
||||
modules = self.find_all_modules()
|
||||
outputs = []
|
||||
for package, module, module_file in modules:
|
||||
for package, module, _module_file in modules:
|
||||
package = package.split('.')
|
||||
filename = self.get_module_outfile(self.build_lib, package, module)
|
||||
outputs.append(filename)
|
||||
@@ -347,7 +347,7 @@ class build_py(Command):
|
||||
outfile = self.get_module_outfile(self.build_lib, package, module)
|
||||
dir = os.path.dirname(outfile)
|
||||
self.mkpath(dir)
|
||||
return self.copy_file(module_file, outfile, preserve_mode=0)
|
||||
return self.copy_file(module_file, outfile, preserve_mode=False)
|
||||
|
||||
def build_modules(self):
|
||||
modules = self.find_modules()
|
||||
|
||||
@@ -4,13 +4,14 @@ Implements the Distutils 'build_scripts' command."""
|
||||
|
||||
import os
|
||||
import re
|
||||
from stat import ST_MODE
|
||||
from distutils import sysconfig
|
||||
from ..core import Command
|
||||
from ..dep_util import newer
|
||||
from ..util import convert_path
|
||||
from distutils._log import log
|
||||
import tokenize
|
||||
from distutils import sysconfig
|
||||
from distutils._log import log
|
||||
from stat import ST_MODE
|
||||
|
||||
from .._modified import newer
|
||||
from ..core import Command
|
||||
from ..util import convert_path
|
||||
|
||||
shebang_pattern = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
|
||||
"""
|
||||
@@ -95,7 +96,7 @@ class build_scripts(Command):
|
||||
else:
|
||||
first_line = f.readline()
|
||||
if not first_line:
|
||||
self.warn("%s is an empty file (skipping)" % script)
|
||||
self.warn(f"{script} is an empty file (skipping)")
|
||||
return
|
||||
|
||||
shebang_match = shebang_pattern.match(first_line)
|
||||
@@ -109,8 +110,7 @@ class build_scripts(Command):
|
||||
else:
|
||||
executable = os.path.join(
|
||||
sysconfig.get_config_var("BINDIR"),
|
||||
"python%s%s"
|
||||
% (
|
||||
"python{}{}".format(
|
||||
sysconfig.get_config_var("VERSION"),
|
||||
sysconfig.get_config_var("EXE"),
|
||||
),
|
||||
@@ -156,9 +156,7 @@ class build_scripts(Command):
|
||||
try:
|
||||
shebang.encode('utf-8')
|
||||
except UnicodeEncodeError:
|
||||
raise ValueError(
|
||||
"The shebang ({!r}) is not encodable " "to utf-8".format(shebang)
|
||||
)
|
||||
raise ValueError(f"The shebang ({shebang!r}) is not encodable to utf-8")
|
||||
|
||||
# If the script is encoded to a custom encoding (use a
|
||||
# #coding:xxx cookie), the shebang has to be encodable to
|
||||
@@ -167,6 +165,6 @@ class build_scripts(Command):
|
||||
shebang.encode(encoding)
|
||||
except UnicodeEncodeError:
|
||||
raise ValueError(
|
||||
"The shebang ({!r}) is not encodable "
|
||||
"to the script encoding ({})".format(shebang, encoding)
|
||||
f"The shebang ({shebang!r}) is not encodable "
|
||||
f"to the script encoding ({encoding})"
|
||||
)
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
|
||||
Implements the Distutils 'check' command.
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsSetupError
|
||||
|
||||
with contextlib.suppress(ImportError):
|
||||
import docutils.utils
|
||||
import docutils.parsers.rst
|
||||
import docutils.frontend
|
||||
import docutils.nodes
|
||||
import docutils.parsers.rst
|
||||
import docutils.utils
|
||||
|
||||
class SilentReporter(docutils.utils.Reporter):
|
||||
def __init__(
|
||||
@@ -20,7 +21,7 @@ with contextlib.suppress(ImportError):
|
||||
report_level,
|
||||
halt_level,
|
||||
stream=None,
|
||||
debug=0,
|
||||
debug=False,
|
||||
encoding='ascii',
|
||||
error_handler='replace',
|
||||
):
|
||||
@@ -32,7 +33,7 @@ with contextlib.suppress(ImportError):
|
||||
def system_message(self, level, message, *children, **kwargs):
|
||||
self.messages.append((level, message, children, kwargs))
|
||||
return docutils.nodes.system_message(
|
||||
message, level=level, type=self.levels[level], *children, **kwargs
|
||||
message, *children, level=level, type=self.levels[level], **kwargs
|
||||
)
|
||||
|
||||
|
||||
@@ -57,9 +58,9 @@ class check(Command):
|
||||
|
||||
def initialize_options(self):
|
||||
"""Sets default values for options."""
|
||||
self.restructuredtext = 0
|
||||
self.restructuredtext = False
|
||||
self.metadata = 1
|
||||
self.strict = 0
|
||||
self.strict = False
|
||||
self._warnings = 0
|
||||
|
||||
def finalize_options(self):
|
||||
@@ -99,13 +100,12 @@ class check(Command):
|
||||
"""
|
||||
metadata = self.distribution.metadata
|
||||
|
||||
missing = []
|
||||
for attr in 'name', 'version':
|
||||
if not getattr(metadata, attr, None):
|
||||
missing.append(attr)
|
||||
missing = [
|
||||
attr for attr in ('name', 'version') if not getattr(metadata, attr, None)
|
||||
]
|
||||
|
||||
if missing:
|
||||
self.warn("missing required meta-data: %s" % ', '.join(missing))
|
||||
self.warn("missing required meta-data: {}".format(', '.join(missing)))
|
||||
|
||||
def check_restructuredtext(self):
|
||||
"""Checks if the long string fields are reST-compliant."""
|
||||
@@ -115,7 +115,7 @@ class check(Command):
|
||||
if line is None:
|
||||
warning = warning[1]
|
||||
else:
|
||||
warning = '{} (line {})'.format(warning[1], line)
|
||||
warning = f'{warning[1]} (line {line})'
|
||||
self.warn(warning)
|
||||
|
||||
def _check_rst_data(self, data):
|
||||
@@ -144,8 +144,11 @@ class check(Command):
|
||||
try:
|
||||
parser.parse(data, document)
|
||||
except AttributeError as e:
|
||||
reporter.messages.append(
|
||||
(-1, 'Could not finish the parsing: %s.' % e, '', {})
|
||||
)
|
||||
reporter.messages.append((
|
||||
-1,
|
||||
f'Could not finish the parsing: {e}.',
|
||||
'',
|
||||
{},
|
||||
))
|
||||
|
||||
return reporter.messages
|
||||
|
||||
@@ -5,25 +5,26 @@ Implements the Distutils 'clean' command."""
|
||||
# contributed by Bastian Kleineidam <calvin@cs.uni-sb.de>, added 2000-03-18
|
||||
|
||||
import os
|
||||
from distutils._log import log
|
||||
|
||||
from ..core import Command
|
||||
from ..dir_util import remove_tree
|
||||
from distutils._log import log
|
||||
|
||||
|
||||
class clean(Command):
|
||||
description = "clean up temporary files from 'build' command"
|
||||
user_options = [
|
||||
('build-base=', 'b', "base build directory (default: 'build.build-base')"),
|
||||
('build-base=', 'b', "base build directory [default: 'build.build-base']"),
|
||||
(
|
||||
'build-lib=',
|
||||
None,
|
||||
"build directory for all modules (default: 'build.build-lib')",
|
||||
"build directory for all modules [default: 'build.build-lib']",
|
||||
),
|
||||
('build-temp=', 't', "temporary build directory (default: 'build.build-temp')"),
|
||||
('build-temp=', 't', "temporary build directory [default: 'build.build-temp']"),
|
||||
(
|
||||
'build-scripts=',
|
||||
None,
|
||||
"build directory for scripts (default: 'build.build-scripts')",
|
||||
"build directory for scripts [default: 'build.build-scripts']",
|
||||
),
|
||||
('bdist-base=', None, "temporary directory for built distributions"),
|
||||
('all', 'a', "remove all build output, not just temporary by-products"),
|
||||
|
||||
@@ -9,13 +9,17 @@ configure-like tasks: "try to compile this C code", or "figure out where
|
||||
this header file lives".
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
from collections.abc import Sequence
|
||||
from distutils._log import log
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsExecError
|
||||
from ..sysconfig import customize_compiler
|
||||
from distutils._log import log
|
||||
|
||||
LANG_EXT = {"c": ".c", "c++": ".cxx"}
|
||||
|
||||
@@ -90,7 +94,7 @@ class config(Command):
|
||||
|
||||
if not isinstance(self.compiler, CCompiler):
|
||||
self.compiler = new_compiler(
|
||||
compiler=self.compiler, dry_run=self.dry_run, force=1
|
||||
compiler=self.compiler, dry_run=self.dry_run, force=True
|
||||
)
|
||||
customize_compiler(self.compiler)
|
||||
if self.include_dirs:
|
||||
@@ -102,10 +106,10 @@ class config(Command):
|
||||
|
||||
def _gen_temp_sourcefile(self, body, headers, lang):
|
||||
filename = "_configtest" + LANG_EXT[lang]
|
||||
with open(filename, "w") as file:
|
||||
with open(filename, "w", encoding='utf-8') as file:
|
||||
if headers:
|
||||
for header in headers:
|
||||
file.write("#include <%s>\n" % header)
|
||||
file.write(f"#include <{header}>\n")
|
||||
file.write("\n")
|
||||
file.write(body)
|
||||
if body[-1] != "\n":
|
||||
@@ -122,7 +126,7 @@ class config(Command):
|
||||
def _compile(self, body, headers, include_dirs, lang):
|
||||
src = self._gen_temp_sourcefile(body, headers, lang)
|
||||
if self.dump_source:
|
||||
dump_file(src, "compiling '%s':" % src)
|
||||
dump_file(src, f"compiling '{src}':")
|
||||
(obj,) = self.compiler.object_filenames([src])
|
||||
self.temp_files.extend([src, obj])
|
||||
self.compiler.compile([src], include_dirs=include_dirs)
|
||||
@@ -199,15 +203,8 @@ class config(Command):
|
||||
if isinstance(pattern, str):
|
||||
pattern = re.compile(pattern)
|
||||
|
||||
with open(out) as file:
|
||||
match = False
|
||||
while True:
|
||||
line = file.readline()
|
||||
if line == '':
|
||||
break
|
||||
if pattern.search(line):
|
||||
match = True
|
||||
break
|
||||
with open(out, encoding='utf-8') as file:
|
||||
match = any(pattern.search(line) for line in file)
|
||||
|
||||
self._clean()
|
||||
return match
|
||||
@@ -295,8 +292,8 @@ class config(Command):
|
||||
include_dirs=None,
|
||||
libraries=None,
|
||||
library_dirs=None,
|
||||
decl=0,
|
||||
call=0,
|
||||
decl=False,
|
||||
call=False,
|
||||
):
|
||||
"""Determine if function 'func' is available by constructing a
|
||||
source file that refers to 'func', and compiles and links it.
|
||||
@@ -314,12 +311,12 @@ class config(Command):
|
||||
self._check_compiler()
|
||||
body = []
|
||||
if decl:
|
||||
body.append("int %s ();" % func)
|
||||
body.append(f"int {func} ();")
|
||||
body.append("int main () {")
|
||||
if call:
|
||||
body.append(" %s();" % func)
|
||||
body.append(f" {func}();")
|
||||
else:
|
||||
body.append(" %s;" % func)
|
||||
body.append(f" {func};")
|
||||
body.append("}")
|
||||
body = "\n".join(body) + "\n"
|
||||
|
||||
@@ -331,7 +328,7 @@ class config(Command):
|
||||
library_dirs=None,
|
||||
headers=None,
|
||||
include_dirs=None,
|
||||
other_libraries=[],
|
||||
other_libraries: Sequence[str] = [],
|
||||
):
|
||||
"""Determine if 'library' is available to be linked against,
|
||||
without actually checking that any particular symbols are provided
|
||||
@@ -346,7 +343,7 @@ class config(Command):
|
||||
"int main (void) { }",
|
||||
headers,
|
||||
include_dirs,
|
||||
[library] + other_libraries,
|
||||
[library] + list(other_libraries),
|
||||
library_dirs,
|
||||
)
|
||||
|
||||
@@ -369,8 +366,4 @@ def dump_file(filename, head=None):
|
||||
log.info('%s', filename)
|
||||
else:
|
||||
log.info(head)
|
||||
file = open(filename)
|
||||
try:
|
||||
log.info(file.read())
|
||||
finally:
|
||||
file.close()
|
||||
log.info(pathlib.Path(filename).read_text(encoding='utf-8'))
|
||||
|
||||
@@ -2,25 +2,23 @@
|
||||
|
||||
Implements the Distutils 'install' command."""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import contextlib
|
||||
import sysconfig
|
||||
import itertools
|
||||
|
||||
import os
|
||||
import sys
|
||||
import sysconfig
|
||||
from distutils._log import log
|
||||
from site import USER_BASE, USER_SITE
|
||||
|
||||
import jaraco.collections
|
||||
|
||||
from ..core import Command
|
||||
from ..debug import DEBUG
|
||||
from ..sysconfig import get_config_vars
|
||||
from ..file_util import write_file
|
||||
from ..util import convert_path, subst_vars, change_root
|
||||
from ..util import get_platform
|
||||
from ..errors import DistutilsOptionError, DistutilsPlatformError
|
||||
from ..file_util import write_file
|
||||
from ..sysconfig import get_config_vars
|
||||
from ..util import change_root, convert_path, get_platform, subst_vars
|
||||
from . import _framework_compat as fw
|
||||
from .. import _collections
|
||||
|
||||
from site import USER_BASE
|
||||
from site import USER_SITE
|
||||
|
||||
HAS_USER_SITE = True
|
||||
|
||||
@@ -196,8 +194,7 @@ class install(Command):
|
||||
(
|
||||
'install-platbase=',
|
||||
None,
|
||||
"base installation directory for platform-specific files "
|
||||
+ "(instead of --exec-prefix or --home)",
|
||||
"base installation directory for platform-specific files (instead of --exec-prefix or --home)",
|
||||
),
|
||||
('root=', None, "install everything relative to this alternate root directory"),
|
||||
# Or, explicitly set the installation scheme
|
||||
@@ -214,8 +211,7 @@ class install(Command):
|
||||
(
|
||||
'install-lib=',
|
||||
None,
|
||||
"installation directory for all module distributions "
|
||||
+ "(overrides --install-purelib and --install-platlib)",
|
||||
"installation directory for all module distributions (overrides --install-purelib and --install-platlib)",
|
||||
),
|
||||
('install-headers=', None, "installation directory for C/C++ headers"),
|
||||
('install-scripts=', None, "installation directory for Python scripts"),
|
||||
@@ -245,9 +241,11 @@ class install(Command):
|
||||
boolean_options = ['compile', 'force', 'skip-build']
|
||||
|
||||
if HAS_USER_SITE:
|
||||
user_options.append(
|
||||
('user', None, "install in user site-package '%s'" % USER_SITE)
|
||||
)
|
||||
user_options.append((
|
||||
'user',
|
||||
None,
|
||||
f"install in user site-package '{USER_SITE}'",
|
||||
))
|
||||
boolean_options.append('user')
|
||||
|
||||
negative_opt = {'no-compile': 'compile'}
|
||||
@@ -259,7 +257,7 @@ class install(Command):
|
||||
self.prefix = None
|
||||
self.exec_prefix = None
|
||||
self.home = None
|
||||
self.user = 0
|
||||
self.user = False
|
||||
|
||||
# These select only the installation base; it's up to the user to
|
||||
# specify the installation scheme (currently, that means supplying
|
||||
@@ -294,7 +292,7 @@ class install(Command):
|
||||
# 'install_path_file' is always true unless some outsider meddles
|
||||
# with it.
|
||||
self.extra_path = None
|
||||
self.install_path_file = 1
|
||||
self.install_path_file = True
|
||||
|
||||
# 'force' forces installation, even if target files are not
|
||||
# out-of-date. 'skip_build' skips running the "build" command,
|
||||
@@ -302,9 +300,9 @@ class install(Command):
|
||||
# a user option, it's just there so the bdist_* commands can turn
|
||||
# it off) determines whether we warn about installing to a
|
||||
# directory not in sys.path.
|
||||
self.force = 0
|
||||
self.skip_build = 0
|
||||
self.warn_dir = 1
|
||||
self.force = False
|
||||
self.skip_build = False
|
||||
self.warn_dir = True
|
||||
|
||||
# These are only here as a conduit from the 'build' command to the
|
||||
# 'install_*' commands that do the real work. ('build_base' isn't
|
||||
@@ -349,8 +347,7 @@ class install(Command):
|
||||
self.install_base or self.install_platbase
|
||||
):
|
||||
raise DistutilsOptionError(
|
||||
"must supply either prefix/exec-prefix/home or "
|
||||
+ "install-base/install-platbase -- not both"
|
||||
"must supply either prefix/exec-prefix/home or install-base/install-platbase -- not both"
|
||||
)
|
||||
|
||||
if self.home and (self.prefix or self.exec_prefix):
|
||||
@@ -432,9 +429,12 @@ class install(Command):
|
||||
local_vars['userbase'] = self.install_userbase
|
||||
local_vars['usersite'] = self.install_usersite
|
||||
|
||||
self.config_vars = _collections.DictStack(
|
||||
[fw.vars(), compat_vars, sysconfig.get_config_vars(), local_vars]
|
||||
)
|
||||
self.config_vars = jaraco.collections.DictStack([
|
||||
fw.vars(),
|
||||
compat_vars,
|
||||
sysconfig.get_config_vars(),
|
||||
local_vars,
|
||||
])
|
||||
|
||||
self.expand_basedirs()
|
||||
|
||||
@@ -598,7 +598,7 @@ class install(Command):
|
||||
self.select_scheme(os.name)
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"I don't know how to install stuff on '%s'" % os.name
|
||||
f"I don't know how to install stuff on '{os.name}'"
|
||||
)
|
||||
|
||||
def select_scheme(self, name):
|
||||
@@ -620,16 +620,14 @@ class install(Command):
|
||||
|
||||
def expand_dirs(self):
|
||||
"""Calls `os.path.expanduser` on install dirs."""
|
||||
self._expand_attrs(
|
||||
[
|
||||
'install_purelib',
|
||||
'install_platlib',
|
||||
'install_lib',
|
||||
'install_headers',
|
||||
'install_scripts',
|
||||
'install_data',
|
||||
]
|
||||
)
|
||||
self._expand_attrs([
|
||||
'install_purelib',
|
||||
'install_platlib',
|
||||
'install_lib',
|
||||
'install_headers',
|
||||
'install_scripts',
|
||||
'install_data',
|
||||
])
|
||||
|
||||
def convert_paths(self, *names):
|
||||
"""Call `convert_path` over `names`."""
|
||||
@@ -683,9 +681,9 @@ class install(Command):
|
||||
if not self.user:
|
||||
return
|
||||
home = convert_path(os.path.expanduser("~"))
|
||||
for name, path in self.config_vars.items():
|
||||
for path in self.config_vars.values():
|
||||
if str(path).startswith(home) and not os.path.isdir(path):
|
||||
self.debug_print("os.makedirs('%s', 0o700)" % path)
|
||||
self.debug_print(f"os.makedirs('{path}', 0o700)")
|
||||
os.makedirs(path, 0o700)
|
||||
|
||||
# -- Command execution methods -------------------------------------
|
||||
@@ -701,7 +699,7 @@ class install(Command):
|
||||
# internally, and not to sys.path, so we don't check the platform
|
||||
# matches what we are running.
|
||||
if self.warn_dir and build_plat != get_platform():
|
||||
raise DistutilsPlatformError("Can't install when " "cross-compiling")
|
||||
raise DistutilsPlatformError("Can't install when cross-compiling")
|
||||
|
||||
# Run all sub-commands (at least those that need to be run)
|
||||
for cmd_name in self.get_sub_commands():
|
||||
@@ -720,7 +718,7 @@ class install(Command):
|
||||
self.execute(
|
||||
write_file,
|
||||
(self.record, outputs),
|
||||
"writing list of installed files to '%s'" % self.record,
|
||||
f"writing list of installed files to '{self.record}'",
|
||||
)
|
||||
|
||||
sys_path = map(os.path.normpath, sys.path)
|
||||
@@ -745,10 +743,10 @@ class install(Command):
|
||||
filename = os.path.join(self.install_libbase, self.path_file + ".pth")
|
||||
if self.install_path_file:
|
||||
self.execute(
|
||||
write_file, (filename, [self.extra_dirs]), "creating %s" % filename
|
||||
write_file, (filename, [self.extra_dirs]), f"creating {filename}"
|
||||
)
|
||||
else:
|
||||
self.warn("path file '%s' not created" % filename)
|
||||
self.warn(f"path file '{filename}' not created")
|
||||
|
||||
# -- Reporting methods ---------------------------------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,12 @@ platform-independent data files."""
|
||||
|
||||
# contributed by Bastian Kleineidam
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
import os
|
||||
from typing import Iterable
|
||||
|
||||
from ..core import Command
|
||||
from ..util import change_root, convert_path
|
||||
|
||||
@@ -18,7 +23,7 @@ class install_data(Command):
|
||||
'install-dir=',
|
||||
'd',
|
||||
"base directory for installing data files "
|
||||
"(default: installation base dir)",
|
||||
"[default: installation base dir]",
|
||||
),
|
||||
('root=', None, "install everything relative to this alternate root directory"),
|
||||
('force', 'f', "force installation (overwrite existing files)"),
|
||||
@@ -30,9 +35,9 @@ class install_data(Command):
|
||||
self.install_dir = None
|
||||
self.outfiles = []
|
||||
self.root = None
|
||||
self.force = 0
|
||||
self.force = False
|
||||
self.data_files = self.distribution.data_files
|
||||
self.warn_dir = 1
|
||||
self.warn_dir = True
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options(
|
||||
@@ -45,36 +50,42 @@ class install_data(Command):
|
||||
def run(self):
|
||||
self.mkpath(self.install_dir)
|
||||
for f in self.data_files:
|
||||
if isinstance(f, str):
|
||||
# it's a simple file, so copy it
|
||||
f = convert_path(f)
|
||||
if self.warn_dir:
|
||||
self.warn(
|
||||
"setup script did not provide a directory for "
|
||||
"'%s' -- installing right in '%s'" % (f, self.install_dir)
|
||||
)
|
||||
(out, _) = self.copy_file(f, self.install_dir)
|
||||
self.outfiles.append(out)
|
||||
else:
|
||||
# it's a tuple with path to install to and a list of files
|
||||
dir = convert_path(f[0])
|
||||
if not os.path.isabs(dir):
|
||||
dir = os.path.join(self.install_dir, dir)
|
||||
elif self.root:
|
||||
dir = change_root(self.root, dir)
|
||||
self.mkpath(dir)
|
||||
self._copy(f)
|
||||
|
||||
if f[1] == []:
|
||||
# If there are no files listed, the user must be
|
||||
# trying to create an empty directory, so add the
|
||||
# directory to the list of output files.
|
||||
self.outfiles.append(dir)
|
||||
else:
|
||||
# Copy files, adding them to the list of output files.
|
||||
for data in f[1]:
|
||||
data = convert_path(data)
|
||||
(out, _) = self.copy_file(data, dir)
|
||||
self.outfiles.append(out)
|
||||
@functools.singledispatchmethod
|
||||
def _copy(self, f: tuple[str | os.PathLike, Iterable[str | os.PathLike]]):
|
||||
# it's a tuple with path to install to and a list of files
|
||||
dir = convert_path(f[0])
|
||||
if not os.path.isabs(dir):
|
||||
dir = os.path.join(self.install_dir, dir)
|
||||
elif self.root:
|
||||
dir = change_root(self.root, dir)
|
||||
self.mkpath(dir)
|
||||
|
||||
if f[1] == []:
|
||||
# If there are no files listed, the user must be
|
||||
# trying to create an empty directory, so add the
|
||||
# directory to the list of output files.
|
||||
self.outfiles.append(dir)
|
||||
else:
|
||||
# Copy files, adding them to the list of output files.
|
||||
for data in f[1]:
|
||||
data = convert_path(data)
|
||||
(out, _) = self.copy_file(data, dir)
|
||||
self.outfiles.append(out)
|
||||
|
||||
@_copy.register(str)
|
||||
@_copy.register(os.PathLike)
|
||||
def _(self, f: str | os.PathLike):
|
||||
# it's a simple file, so copy it
|
||||
f = convert_path(f)
|
||||
if self.warn_dir:
|
||||
self.warn(
|
||||
"setup script did not provide a directory for "
|
||||
f"'{f}' -- installing right in '{self.install_dir}'"
|
||||
)
|
||||
(out, _) = self.copy_file(f, self.install_dir)
|
||||
self.outfiles.append(out)
|
||||
|
||||
def get_inputs(self):
|
||||
return self.data_files or []
|
||||
|
||||
@@ -6,12 +6,12 @@ a package's PKG-INFO metadata.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ..cmd import Command
|
||||
from .. import dir_util
|
||||
from .._log import log
|
||||
from ..cmd import Command
|
||||
|
||||
|
||||
class install_egg_info(Command):
|
||||
|
||||
@@ -19,7 +19,7 @@ class install_headers(Command):
|
||||
|
||||
def initialize_options(self):
|
||||
self.install_dir = None
|
||||
self.force = 0
|
||||
self.force = False
|
||||
self.outfiles = []
|
||||
|
||||
def finalize_options(self):
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
Implements the Distutils 'install_lib' command
|
||||
(install all Python modules)."""
|
||||
|
||||
import os
|
||||
import importlib.util
|
||||
import os
|
||||
import sys
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsOptionError
|
||||
|
||||
|
||||
# Extension for Python source files.
|
||||
PYTHON_SOURCE_EXTENSION = ".py"
|
||||
|
||||
@@ -55,7 +54,7 @@ class install_lib(Command):
|
||||
# let the 'install' command dictate our installation directory
|
||||
self.install_dir = None
|
||||
self.build_dir = None
|
||||
self.force = 0
|
||||
self.force = False
|
||||
self.compile = None
|
||||
self.optimize = None
|
||||
self.skip_build = None
|
||||
@@ -82,9 +81,9 @@ class install_lib(Command):
|
||||
if not isinstance(self.optimize, int):
|
||||
try:
|
||||
self.optimize = int(self.optimize)
|
||||
if self.optimize not in (0, 1, 2):
|
||||
raise AssertionError
|
||||
except (ValueError, AssertionError):
|
||||
except ValueError:
|
||||
pass
|
||||
if self.optimize not in (0, 1, 2):
|
||||
raise DistutilsOptionError("optimize must be 0, 1, or 2")
|
||||
|
||||
def run(self):
|
||||
@@ -115,7 +114,7 @@ class install_lib(Command):
|
||||
outfiles = self.copy_tree(self.build_dir, self.install_dir)
|
||||
else:
|
||||
self.warn(
|
||||
"'%s' does not exist -- no Python modules to install" % self.build_dir
|
||||
f"'{self.build_dir}' does not exist -- no Python modules to install"
|
||||
)
|
||||
return
|
||||
return outfiles
|
||||
@@ -162,9 +161,7 @@ class install_lib(Command):
|
||||
build_dir = getattr(build_cmd, cmd_option)
|
||||
|
||||
prefix_len = len(build_dir) + len(os.sep)
|
||||
outputs = []
|
||||
for file in build_files:
|
||||
outputs.append(os.path.join(output_dir, file[prefix_len:]))
|
||||
outputs = [os.path.join(output_dir, file[prefix_len:]) for file in build_files]
|
||||
|
||||
return outputs
|
||||
|
||||
|
||||
@@ -6,10 +6,11 @@ Python scripts."""
|
||||
# contributed by Bastian Kleineidam
|
||||
|
||||
import os
|
||||
from ..core import Command
|
||||
from distutils._log import log
|
||||
from stat import ST_MODE
|
||||
|
||||
from ..core import Command
|
||||
|
||||
|
||||
class install_scripts(Command):
|
||||
description = "install scripts (Python or otherwise)"
|
||||
@@ -25,7 +26,7 @@ class install_scripts(Command):
|
||||
|
||||
def initialize_options(self):
|
||||
self.install_dir = None
|
||||
self.force = 0
|
||||
self.force = False
|
||||
self.build_dir = None
|
||||
self.skip_build = None
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import sys
|
||||
|
||||
|
||||
def _pythonlib_compat():
|
||||
"""
|
||||
On Python 3.7 and earlier, distutils would include the Python
|
||||
library. See pypa/distutils#9.
|
||||
"""
|
||||
from distutils import sysconfig
|
||||
|
||||
if not sysconfig.get_config_var('Py_ENABLED_SHARED'):
|
||||
return
|
||||
|
||||
yield 'python{}.{}{}'.format(
|
||||
sys.hexversion >> 24,
|
||||
(sys.hexversion >> 16) & 0xFF,
|
||||
sysconfig.get_config_var('ABIFLAGS'),
|
||||
)
|
||||
|
||||
|
||||
def compose(f1, f2):
|
||||
return lambda *args, **kwargs: f1(f2(*args, **kwargs))
|
||||
|
||||
|
||||
pythonlib = (
|
||||
compose(list, _pythonlib_compat)
|
||||
if sys.version_info < (3, 8)
|
||||
and sys.platform != 'darwin'
|
||||
and sys.platform[:3] != 'aix'
|
||||
else list
|
||||
)
|
||||
@@ -1,320 +0,0 @@
|
||||
"""distutils.command.register
|
||||
|
||||
Implements the Distutils 'register' command (register with the repository).
|
||||
"""
|
||||
|
||||
# created 2002/10/21, Richard Jones
|
||||
|
||||
import getpass
|
||||
import io
|
||||
import logging
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
from warnings import warn
|
||||
|
||||
from ..core import PyPIRCCommand
|
||||
from distutils._log import log
|
||||
|
||||
|
||||
class register(PyPIRCCommand):
|
||||
description = "register the distribution with the Python package index"
|
||||
user_options = PyPIRCCommand.user_options + [
|
||||
('list-classifiers', None, 'list the valid Trove classifiers'),
|
||||
(
|
||||
'strict',
|
||||
None,
|
||||
'Will stop the registering if the meta-data are not fully compliant',
|
||||
),
|
||||
]
|
||||
boolean_options = PyPIRCCommand.boolean_options + [
|
||||
'verify',
|
||||
'list-classifiers',
|
||||
'strict',
|
||||
]
|
||||
|
||||
sub_commands = [('check', lambda self: True)]
|
||||
|
||||
def initialize_options(self):
|
||||
PyPIRCCommand.initialize_options(self)
|
||||
self.list_classifiers = 0
|
||||
self.strict = 0
|
||||
|
||||
def finalize_options(self):
|
||||
PyPIRCCommand.finalize_options(self)
|
||||
# setting options for the `check` subcommand
|
||||
check_options = {
|
||||
'strict': ('register', self.strict),
|
||||
'restructuredtext': ('register', 1),
|
||||
}
|
||||
self.distribution.command_options['check'] = check_options
|
||||
|
||||
def run(self):
|
||||
self.finalize_options()
|
||||
self._set_config()
|
||||
|
||||
# Run sub commands
|
||||
for cmd_name in self.get_sub_commands():
|
||||
self.run_command(cmd_name)
|
||||
|
||||
if self.dry_run:
|
||||
self.verify_metadata()
|
||||
elif self.list_classifiers:
|
||||
self.classifiers()
|
||||
else:
|
||||
self.send_metadata()
|
||||
|
||||
def check_metadata(self):
|
||||
"""Deprecated API."""
|
||||
warn(
|
||||
"distutils.command.register.check_metadata is deprecated; "
|
||||
"use the check command instead",
|
||||
DeprecationWarning,
|
||||
)
|
||||
check = self.distribution.get_command_obj('check')
|
||||
check.ensure_finalized()
|
||||
check.strict = self.strict
|
||||
check.restructuredtext = 1
|
||||
check.run()
|
||||
|
||||
def _set_config(self):
|
||||
'''Reads the configuration file and set attributes.'''
|
||||
config = self._read_pypirc()
|
||||
if config != {}:
|
||||
self.username = config['username']
|
||||
self.password = config['password']
|
||||
self.repository = config['repository']
|
||||
self.realm = config['realm']
|
||||
self.has_config = True
|
||||
else:
|
||||
if self.repository not in ('pypi', self.DEFAULT_REPOSITORY):
|
||||
raise ValueError('%s not found in .pypirc' % self.repository)
|
||||
if self.repository == 'pypi':
|
||||
self.repository = self.DEFAULT_REPOSITORY
|
||||
self.has_config = False
|
||||
|
||||
def classifiers(self):
|
||||
'''Fetch the list of classifiers from the server.'''
|
||||
url = self.repository + '?:action=list_classifiers'
|
||||
response = urllib.request.urlopen(url)
|
||||
log.info(self._read_pypi_response(response))
|
||||
|
||||
def verify_metadata(self):
|
||||
'''Send the metadata to the package index server to be checked.'''
|
||||
# send the info to the server and report the result
|
||||
(code, result) = self.post_to_server(self.build_post_data('verify'))
|
||||
log.info('Server response (%s): %s', code, result)
|
||||
|
||||
def send_metadata(self): # noqa: C901
|
||||
'''Send the metadata to the package index server.
|
||||
|
||||
Well, do the following:
|
||||
1. figure who the user is, and then
|
||||
2. send the data as a Basic auth'ed POST.
|
||||
|
||||
First we try to read the username/password from $HOME/.pypirc,
|
||||
which is a ConfigParser-formatted file with a section
|
||||
[distutils] containing username and password entries (both
|
||||
in clear text). Eg:
|
||||
|
||||
[distutils]
|
||||
index-servers =
|
||||
pypi
|
||||
|
||||
[pypi]
|
||||
username: fred
|
||||
password: sekrit
|
||||
|
||||
Otherwise, to figure who the user is, we offer the user three
|
||||
choices:
|
||||
|
||||
1. use existing login,
|
||||
2. register as a new user, or
|
||||
3. set the password to a random string and email the user.
|
||||
|
||||
'''
|
||||
# see if we can short-cut and get the username/password from the
|
||||
# config
|
||||
if self.has_config:
|
||||
choice = '1'
|
||||
username = self.username
|
||||
password = self.password
|
||||
else:
|
||||
choice = 'x'
|
||||
username = password = ''
|
||||
|
||||
# get the user's login info
|
||||
choices = '1 2 3 4'.split()
|
||||
while choice not in choices:
|
||||
self.announce(
|
||||
'''\
|
||||
We need to know who you are, so please choose either:
|
||||
1. use your existing login,
|
||||
2. register as a new user,
|
||||
3. have the server generate a new password for you (and email it to you), or
|
||||
4. quit
|
||||
Your selection [default 1]: ''',
|
||||
logging.INFO,
|
||||
)
|
||||
choice = input()
|
||||
if not choice:
|
||||
choice = '1'
|
||||
elif choice not in choices:
|
||||
print('Please choose one of the four options!')
|
||||
|
||||
if choice == '1':
|
||||
# get the username and password
|
||||
while not username:
|
||||
username = input('Username: ')
|
||||
while not password:
|
||||
password = getpass.getpass('Password: ')
|
||||
|
||||
# set up the authentication
|
||||
auth = urllib.request.HTTPPasswordMgr()
|
||||
host = urllib.parse.urlparse(self.repository)[1]
|
||||
auth.add_password(self.realm, host, username, password)
|
||||
# send the info to the server and report the result
|
||||
code, result = self.post_to_server(self.build_post_data('submit'), auth)
|
||||
self.announce('Server response ({}): {}'.format(code, result), logging.INFO)
|
||||
|
||||
# possibly save the login
|
||||
if code == 200:
|
||||
if self.has_config:
|
||||
# sharing the password in the distribution instance
|
||||
# so the upload command can reuse it
|
||||
self.distribution.password = password
|
||||
else:
|
||||
self.announce(
|
||||
(
|
||||
'I can store your PyPI login so future '
|
||||
'submissions will be faster.'
|
||||
),
|
||||
logging.INFO,
|
||||
)
|
||||
self.announce(
|
||||
'(the login will be stored in %s)' % self._get_rc_file(),
|
||||
logging.INFO,
|
||||
)
|
||||
choice = 'X'
|
||||
while choice.lower() not in 'yn':
|
||||
choice = input('Save your login (y/N)?')
|
||||
if not choice:
|
||||
choice = 'n'
|
||||
if choice.lower() == 'y':
|
||||
self._store_pypirc(username, password)
|
||||
|
||||
elif choice == '2':
|
||||
data = {':action': 'user'}
|
||||
data['name'] = data['password'] = data['email'] = ''
|
||||
data['confirm'] = None
|
||||
while not data['name']:
|
||||
data['name'] = input('Username: ')
|
||||
while data['password'] != data['confirm']:
|
||||
while not data['password']:
|
||||
data['password'] = getpass.getpass('Password: ')
|
||||
while not data['confirm']:
|
||||
data['confirm'] = getpass.getpass(' Confirm: ')
|
||||
if data['password'] != data['confirm']:
|
||||
data['password'] = ''
|
||||
data['confirm'] = None
|
||||
print("Password and confirm don't match!")
|
||||
while not data['email']:
|
||||
data['email'] = input(' EMail: ')
|
||||
code, result = self.post_to_server(data)
|
||||
if code != 200:
|
||||
log.info('Server response (%s): %s', code, result)
|
||||
else:
|
||||
log.info('You will receive an email shortly.')
|
||||
log.info('Follow the instructions in it to ' 'complete registration.')
|
||||
elif choice == '3':
|
||||
data = {':action': 'password_reset'}
|
||||
data['email'] = ''
|
||||
while not data['email']:
|
||||
data['email'] = input('Your email address: ')
|
||||
code, result = self.post_to_server(data)
|
||||
log.info('Server response (%s): %s', code, result)
|
||||
|
||||
def build_post_data(self, action):
|
||||
# figure the data to send - the metadata plus some additional
|
||||
# information used by the package server
|
||||
meta = self.distribution.metadata
|
||||
data = {
|
||||
':action': action,
|
||||
'metadata_version': '1.0',
|
||||
'name': meta.get_name(),
|
||||
'version': meta.get_version(),
|
||||
'summary': meta.get_description(),
|
||||
'home_page': meta.get_url(),
|
||||
'author': meta.get_contact(),
|
||||
'author_email': meta.get_contact_email(),
|
||||
'license': meta.get_licence(),
|
||||
'description': meta.get_long_description(),
|
||||
'keywords': meta.get_keywords(),
|
||||
'platform': meta.get_platforms(),
|
||||
'classifiers': meta.get_classifiers(),
|
||||
'download_url': meta.get_download_url(),
|
||||
# PEP 314
|
||||
'provides': meta.get_provides(),
|
||||
'requires': meta.get_requires(),
|
||||
'obsoletes': meta.get_obsoletes(),
|
||||
}
|
||||
if data['provides'] or data['requires'] or data['obsoletes']:
|
||||
data['metadata_version'] = '1.1'
|
||||
return data
|
||||
|
||||
def post_to_server(self, data, auth=None): # noqa: C901
|
||||
'''Post a query to the server, and return a string response.'''
|
||||
if 'name' in data:
|
||||
self.announce(
|
||||
'Registering {} to {}'.format(data['name'], self.repository),
|
||||
logging.INFO,
|
||||
)
|
||||
# Build up the MIME payload for the urllib2 POST data
|
||||
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
|
||||
sep_boundary = '\n--' + boundary
|
||||
end_boundary = sep_boundary + '--'
|
||||
body = io.StringIO()
|
||||
for key, value in data.items():
|
||||
# handle multiple entries for the same name
|
||||
if type(value) not in (type([]), type(())):
|
||||
value = [value]
|
||||
for value in value:
|
||||
value = str(value)
|
||||
body.write(sep_boundary)
|
||||
body.write('\nContent-Disposition: form-data; name="%s"' % key)
|
||||
body.write("\n\n")
|
||||
body.write(value)
|
||||
if value and value[-1] == '\r':
|
||||
body.write('\n') # write an extra newline (lurve Macs)
|
||||
body.write(end_boundary)
|
||||
body.write("\n")
|
||||
body = body.getvalue().encode("utf-8")
|
||||
|
||||
# build the Request
|
||||
headers = {
|
||||
'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8'
|
||||
% boundary,
|
||||
'Content-length': str(len(body)),
|
||||
}
|
||||
req = urllib.request.Request(self.repository, body, headers)
|
||||
|
||||
# handle HTTP and include the Basic Auth handler
|
||||
opener = urllib.request.build_opener(
|
||||
urllib.request.HTTPBasicAuthHandler(password_mgr=auth)
|
||||
)
|
||||
data = ''
|
||||
try:
|
||||
result = opener.open(req)
|
||||
except urllib.error.HTTPError as e:
|
||||
if self.show_response:
|
||||
data = e.fp.read()
|
||||
result = e.code, e.msg
|
||||
except urllib.error.URLError as e:
|
||||
result = 500, str(e)
|
||||
else:
|
||||
if self.show_response:
|
||||
data = self._read_pypi_response(result)
|
||||
result = 200, 'OK'
|
||||
if self.show_response:
|
||||
msg = '\n'.join(('-' * 75, data, '-' * 75))
|
||||
self.announce(msg, logging.INFO)
|
||||
return result
|
||||
@@ -4,31 +4,29 @@ Implements the Distutils 'sdist' command (create a source distribution)."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from distutils import archive_util, dir_util, file_util
|
||||
from distutils._log import log
|
||||
from glob import glob
|
||||
from warnings import warn
|
||||
from itertools import filterfalse
|
||||
|
||||
from ..core import Command
|
||||
from distutils import dir_util
|
||||
from distutils import file_util
|
||||
from distutils import archive_util
|
||||
from ..text_file import TextFile
|
||||
from ..filelist import FileList
|
||||
from distutils._log import log
|
||||
from ..util import convert_path
|
||||
from ..errors import DistutilsOptionError, DistutilsTemplateError
|
||||
from ..filelist import FileList
|
||||
from ..text_file import TextFile
|
||||
from ..util import convert_path
|
||||
|
||||
|
||||
def show_formats():
|
||||
"""Print all possible values for the 'formats' option (used by
|
||||
the "--help-formats" command-line option).
|
||||
"""
|
||||
from ..fancy_getopt import FancyGetopt
|
||||
from ..archive_util import ARCHIVE_FORMATS
|
||||
from ..fancy_getopt import FancyGetopt
|
||||
|
||||
formats = []
|
||||
for format in ARCHIVE_FORMATS.keys():
|
||||
formats.append(("formats=" + format, None, ARCHIVE_FORMATS[format][2]))
|
||||
formats.sort()
|
||||
formats = sorted(
|
||||
("formats=" + format, None, ARCHIVE_FORMATS[format][2])
|
||||
for format in ARCHIVE_FORMATS.keys()
|
||||
)
|
||||
FancyGetopt(formats).print_help("List of available source distribution formats:")
|
||||
|
||||
|
||||
@@ -62,7 +60,7 @@ class sdist(Command):
|
||||
(
|
||||
'manifest-only',
|
||||
'o',
|
||||
"just regenerate the manifest and then stop " "(implies --force-manifest)",
|
||||
"just regenerate the manifest and then stop (implies --force-manifest)",
|
||||
),
|
||||
(
|
||||
'force-manifest',
|
||||
@@ -79,7 +77,7 @@ class sdist(Command):
|
||||
(
|
||||
'dist-dir=',
|
||||
'd',
|
||||
"directory to put the source distribution archive(s) in " "[default: dist]",
|
||||
"directory to put the source distribution archive(s) in [default: dist]",
|
||||
),
|
||||
(
|
||||
'metadata-check',
|
||||
@@ -126,14 +124,14 @@ class sdist(Command):
|
||||
|
||||
# 'use_defaults': if true, we will include the default file set
|
||||
# in the manifest
|
||||
self.use_defaults = 1
|
||||
self.prune = 1
|
||||
self.use_defaults = True
|
||||
self.prune = True
|
||||
|
||||
self.manifest_only = 0
|
||||
self.force_manifest = 0
|
||||
self.manifest_only = False
|
||||
self.force_manifest = False
|
||||
|
||||
self.formats = ['gztar']
|
||||
self.keep_temp = 0
|
||||
self.keep_temp = False
|
||||
self.dist_dir = None
|
||||
|
||||
self.archive_files = None
|
||||
@@ -151,7 +149,7 @@ class sdist(Command):
|
||||
|
||||
bad_format = archive_util.check_archive_formats(self.formats)
|
||||
if bad_format:
|
||||
raise DistutilsOptionError("unknown archive format '%s'" % bad_format)
|
||||
raise DistutilsOptionError(f"unknown archive format '{bad_format}'")
|
||||
|
||||
if self.dist_dir is None:
|
||||
self.dist_dir = "dist"
|
||||
@@ -178,17 +176,6 @@ class sdist(Command):
|
||||
# or zipfile, or whatever.
|
||||
self.make_distribution()
|
||||
|
||||
def check_metadata(self):
|
||||
"""Deprecated API."""
|
||||
warn(
|
||||
"distutils.command.sdist.check_metadata is deprecated, \
|
||||
use the check command instead",
|
||||
PendingDeprecationWarning,
|
||||
)
|
||||
check = self.distribution.get_command_obj('check')
|
||||
check.ensure_finalized()
|
||||
check.run()
|
||||
|
||||
def get_file_list(self):
|
||||
"""Figure out the list of files to include in the source
|
||||
distribution, and put it in 'self.filelist'. This might involve
|
||||
@@ -289,7 +276,7 @@ class sdist(Command):
|
||||
if self._cs_path_exists(fn):
|
||||
self.filelist.append(fn)
|
||||
else:
|
||||
self.warn("standard file '%s' not found" % fn)
|
||||
self.warn(f"standard file '{fn}' not found")
|
||||
|
||||
def _add_defaults_optional(self):
|
||||
optional = ['tests/test*.py', 'test/test*.py', 'setup.cfg']
|
||||
@@ -309,7 +296,7 @@ class sdist(Command):
|
||||
|
||||
# getting package_data files
|
||||
# (computed in build_py.data_files by build_py.finalize_options)
|
||||
for pkg, src_dir, build_dir, filenames in build_py.data_files:
|
||||
for _pkg, src_dir, _build_dir, filenames in build_py.data_files:
|
||||
for filename in filenames:
|
||||
self.filelist.append(os.path.join(src_dir, filename))
|
||||
|
||||
@@ -354,12 +341,12 @@ class sdist(Command):
|
||||
log.info("reading manifest template '%s'", self.template)
|
||||
template = TextFile(
|
||||
self.template,
|
||||
strip_comments=1,
|
||||
skip_blanks=1,
|
||||
join_lines=1,
|
||||
lstrip_ws=1,
|
||||
rstrip_ws=1,
|
||||
collapse_join=1,
|
||||
strip_comments=True,
|
||||
skip_blanks=True,
|
||||
join_lines=True,
|
||||
lstrip_ws=True,
|
||||
rstrip_ws=True,
|
||||
collapse_join=True,
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -392,7 +379,7 @@ class sdist(Command):
|
||||
build = self.get_finalized_command('build')
|
||||
base_dir = self.distribution.get_fullname()
|
||||
|
||||
self.filelist.exclude_pattern(None, prefix=build.build_base)
|
||||
self.filelist.exclude_pattern(None, prefix=os.fspath(build.build_base))
|
||||
self.filelist.exclude_pattern(None, prefix=base_dir)
|
||||
|
||||
if sys.platform == 'win32':
|
||||
@@ -402,7 +389,7 @@ class sdist(Command):
|
||||
|
||||
vcs_dirs = ['RCS', 'CVS', r'\.svn', r'\.hg', r'\.git', r'\.bzr', '_darcs']
|
||||
vcs_ptrn = r'(^|{})({})({}).*'.format(seps, '|'.join(vcs_dirs), seps)
|
||||
self.filelist.exclude_pattern(vcs_ptrn, is_regex=1)
|
||||
self.filelist.exclude_pattern(vcs_ptrn, is_regex=True)
|
||||
|
||||
def write_manifest(self):
|
||||
"""Write the file list in 'self.filelist' (presumably as filled in
|
||||
@@ -411,8 +398,7 @@ class sdist(Command):
|
||||
"""
|
||||
if self._manifest_is_not_generated():
|
||||
log.info(
|
||||
"not writing to manually maintained "
|
||||
"manifest file '%s'" % self.manifest
|
||||
f"not writing to manually maintained manifest file '{self.manifest}'"
|
||||
)
|
||||
return
|
||||
|
||||
@@ -421,7 +407,7 @@ class sdist(Command):
|
||||
self.execute(
|
||||
file_util.write_file,
|
||||
(self.manifest, content),
|
||||
"writing manifest file '%s'" % self.manifest,
|
||||
f"writing manifest file '{self.manifest}'",
|
||||
)
|
||||
|
||||
def _manifest_is_not_generated(self):
|
||||
@@ -429,11 +415,8 @@ class sdist(Command):
|
||||
if not os.path.isfile(self.manifest):
|
||||
return False
|
||||
|
||||
fp = open(self.manifest)
|
||||
try:
|
||||
first_line = fp.readline()
|
||||
finally:
|
||||
fp.close()
|
||||
with open(self.manifest, encoding='utf-8') as fp:
|
||||
first_line = next(fp)
|
||||
return first_line != '# file GENERATED by distutils, do NOT edit\n'
|
||||
|
||||
def read_manifest(self):
|
||||
@@ -442,13 +425,11 @@ class sdist(Command):
|
||||
distribution.
|
||||
"""
|
||||
log.info("reading manifest file '%s'", self.manifest)
|
||||
with open(self.manifest) as manifest:
|
||||
for line in manifest:
|
||||
with open(self.manifest, encoding='utf-8') as lines:
|
||||
self.filelist.extend(
|
||||
# ignore comments and blank lines
|
||||
line = line.strip()
|
||||
if line.startswith('#') or not line:
|
||||
continue
|
||||
self.filelist.append(line)
|
||||
filter(None, filterfalse(is_comment, map(str.strip, lines)))
|
||||
)
|
||||
|
||||
def make_release_tree(self, base_dir, files):
|
||||
"""Create the directory tree that will become the source
|
||||
@@ -474,10 +455,10 @@ class sdist(Command):
|
||||
|
||||
if hasattr(os, 'link'): # can make hard links on this system
|
||||
link = 'hard'
|
||||
msg = "making hard links in %s..." % base_dir
|
||||
msg = f"making hard links in {base_dir}..."
|
||||
else: # nope, have to copy
|
||||
link = None
|
||||
msg = "copying files to %s..." % base_dir
|
||||
msg = f"copying files to {base_dir}..."
|
||||
|
||||
if not files:
|
||||
log.warning("no files to distribute -- empty manifest?")
|
||||
@@ -528,3 +509,7 @@ class sdist(Command):
|
||||
was run, or None if the command hasn't run yet.
|
||||
"""
|
||||
return self.archive_files
|
||||
|
||||
|
||||
def is_comment(line):
|
||||
return line.startswith('#')
|
||||
|
||||
@@ -1,206 +0,0 @@
|
||||
"""
|
||||
distutils.command.upload
|
||||
|
||||
Implements the Distutils 'upload' subcommand (upload package to a package
|
||||
index).
|
||||
"""
|
||||
|
||||
import os
|
||||
import io
|
||||
import hashlib
|
||||
import logging
|
||||
from base64 import standard_b64encode
|
||||
from urllib.request import urlopen, Request, HTTPError
|
||||
from urllib.parse import urlparse
|
||||
from ..errors import DistutilsError, DistutilsOptionError
|
||||
from ..core import PyPIRCCommand
|
||||
from ..spawn import spawn
|
||||
|
||||
|
||||
# PyPI Warehouse supports MD5, SHA256, and Blake2 (blake2-256)
|
||||
# https://bugs.python.org/issue40698
|
||||
_FILE_CONTENT_DIGESTS = {
|
||||
"md5_digest": getattr(hashlib, "md5", None),
|
||||
"sha256_digest": getattr(hashlib, "sha256", None),
|
||||
"blake2_256_digest": getattr(hashlib, "blake2b", None),
|
||||
}
|
||||
|
||||
|
||||
class upload(PyPIRCCommand):
|
||||
description = "upload binary package to PyPI"
|
||||
|
||||
user_options = PyPIRCCommand.user_options + [
|
||||
('sign', 's', 'sign files to upload using gpg'),
|
||||
('identity=', 'i', 'GPG identity used to sign files'),
|
||||
]
|
||||
|
||||
boolean_options = PyPIRCCommand.boolean_options + ['sign']
|
||||
|
||||
def initialize_options(self):
|
||||
PyPIRCCommand.initialize_options(self)
|
||||
self.username = ''
|
||||
self.password = ''
|
||||
self.show_response = 0
|
||||
self.sign = False
|
||||
self.identity = None
|
||||
|
||||
def finalize_options(self):
|
||||
PyPIRCCommand.finalize_options(self)
|
||||
if self.identity and not self.sign:
|
||||
raise DistutilsOptionError("Must use --sign for --identity to have meaning")
|
||||
config = self._read_pypirc()
|
||||
if config != {}:
|
||||
self.username = config['username']
|
||||
self.password = config['password']
|
||||
self.repository = config['repository']
|
||||
self.realm = config['realm']
|
||||
|
||||
# getting the password from the distribution
|
||||
# if previously set by the register command
|
||||
if not self.password and self.distribution.password:
|
||||
self.password = self.distribution.password
|
||||
|
||||
def run(self):
|
||||
if not self.distribution.dist_files:
|
||||
msg = (
|
||||
"Must create and upload files in one command "
|
||||
"(e.g. setup.py sdist upload)"
|
||||
)
|
||||
raise DistutilsOptionError(msg)
|
||||
for command, pyversion, filename in self.distribution.dist_files:
|
||||
self.upload_file(command, pyversion, filename)
|
||||
|
||||
def upload_file(self, command, pyversion, filename): # noqa: C901
|
||||
# Makes sure the repository URL is compliant
|
||||
schema, netloc, url, params, query, fragments = urlparse(self.repository)
|
||||
if params or query or fragments:
|
||||
raise AssertionError("Incompatible url %s" % self.repository)
|
||||
|
||||
if schema not in ('http', 'https'):
|
||||
raise AssertionError("unsupported schema " + schema)
|
||||
|
||||
# Sign if requested
|
||||
if self.sign:
|
||||
gpg_args = ["gpg", "--detach-sign", "-a", filename]
|
||||
if self.identity:
|
||||
gpg_args[2:2] = ["--local-user", self.identity]
|
||||
spawn(gpg_args, dry_run=self.dry_run)
|
||||
|
||||
# Fill in the data - send all the meta-data in case we need to
|
||||
# register a new release
|
||||
f = open(filename, 'rb')
|
||||
try:
|
||||
content = f.read()
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
meta = self.distribution.metadata
|
||||
data = {
|
||||
# action
|
||||
':action': 'file_upload',
|
||||
'protocol_version': '1',
|
||||
# identify release
|
||||
'name': meta.get_name(),
|
||||
'version': meta.get_version(),
|
||||
# file content
|
||||
'content': (os.path.basename(filename), content),
|
||||
'filetype': command,
|
||||
'pyversion': pyversion,
|
||||
# additional meta-data
|
||||
'metadata_version': '1.0',
|
||||
'summary': meta.get_description(),
|
||||
'home_page': meta.get_url(),
|
||||
'author': meta.get_contact(),
|
||||
'author_email': meta.get_contact_email(),
|
||||
'license': meta.get_licence(),
|
||||
'description': meta.get_long_description(),
|
||||
'keywords': meta.get_keywords(),
|
||||
'platform': meta.get_platforms(),
|
||||
'classifiers': meta.get_classifiers(),
|
||||
'download_url': meta.get_download_url(),
|
||||
# PEP 314
|
||||
'provides': meta.get_provides(),
|
||||
'requires': meta.get_requires(),
|
||||
'obsoletes': meta.get_obsoletes(),
|
||||
}
|
||||
|
||||
data['comment'] = ''
|
||||
|
||||
# file content digests
|
||||
for digest_name, digest_cons in _FILE_CONTENT_DIGESTS.items():
|
||||
if digest_cons is None:
|
||||
continue
|
||||
try:
|
||||
data[digest_name] = digest_cons(content).hexdigest()
|
||||
except ValueError:
|
||||
# hash digest not available or blocked by security policy
|
||||
pass
|
||||
|
||||
if self.sign:
|
||||
with open(filename + ".asc", "rb") as f:
|
||||
data['gpg_signature'] = (os.path.basename(filename) + ".asc", f.read())
|
||||
|
||||
# set up the authentication
|
||||
user_pass = (self.username + ":" + self.password).encode('ascii')
|
||||
# The exact encoding of the authentication string is debated.
|
||||
# Anyway PyPI only accepts ascii for both username or password.
|
||||
auth = "Basic " + standard_b64encode(user_pass).decode('ascii')
|
||||
|
||||
# Build up the MIME payload for the POST data
|
||||
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
|
||||
sep_boundary = b'\r\n--' + boundary.encode('ascii')
|
||||
end_boundary = sep_boundary + b'--\r\n'
|
||||
body = io.BytesIO()
|
||||
for key, value in data.items():
|
||||
title = '\r\nContent-Disposition: form-data; name="%s"' % key
|
||||
# handle multiple entries for the same name
|
||||
if not isinstance(value, list):
|
||||
value = [value]
|
||||
for value in value:
|
||||
if type(value) is tuple:
|
||||
title += '; filename="%s"' % value[0]
|
||||
value = value[1]
|
||||
else:
|
||||
value = str(value).encode('utf-8')
|
||||
body.write(sep_boundary)
|
||||
body.write(title.encode('utf-8'))
|
||||
body.write(b"\r\n\r\n")
|
||||
body.write(value)
|
||||
body.write(end_boundary)
|
||||
body = body.getvalue()
|
||||
|
||||
msg = "Submitting {} to {}".format(filename, self.repository)
|
||||
self.announce(msg, logging.INFO)
|
||||
|
||||
# build the Request
|
||||
headers = {
|
||||
'Content-type': 'multipart/form-data; boundary=%s' % boundary,
|
||||
'Content-length': str(len(body)),
|
||||
'Authorization': auth,
|
||||
}
|
||||
|
||||
request = Request(self.repository, data=body, headers=headers)
|
||||
# send the data
|
||||
try:
|
||||
result = urlopen(request)
|
||||
status = result.getcode()
|
||||
reason = result.msg
|
||||
except HTTPError as e:
|
||||
status = e.code
|
||||
reason = e.msg
|
||||
except OSError as e:
|
||||
self.announce(str(e), logging.ERROR)
|
||||
raise
|
||||
|
||||
if status == 200:
|
||||
self.announce(
|
||||
'Server response ({}): {}'.format(status, reason), logging.INFO
|
||||
)
|
||||
if self.show_response:
|
||||
text = self._read_pypi_response(result)
|
||||
msg = '\n'.join(('-' * 75, text, '-' * 75))
|
||||
self.announce(msg, logging.INFO)
|
||||
else:
|
||||
msg = 'Upload failed ({}): {}'.format(status, reason)
|
||||
self.announce(msg, logging.ERROR)
|
||||
raise DistutilsError(msg)
|
||||
15
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/__init__.py
vendored
Normal file
15
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/__init__.py
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from .py38 import removeprefix
|
||||
|
||||
|
||||
def consolidate_linker_args(args: list[str]) -> list[str] | str:
|
||||
"""
|
||||
Ensure the return value is a string for backward compatibility.
|
||||
|
||||
Retain until at least 2025-04-31. See pypa/distutils#246
|
||||
"""
|
||||
|
||||
if not all(arg.startswith('-Wl,') for arg in args):
|
||||
return args
|
||||
return '-Wl,' + ','.join(removeprefix(arg, '-Wl,') for arg in args)
|
||||
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/__pycache__/py38.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/__pycache__/py38.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/__pycache__/py39.cpython-312.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/__pycache__/py39.cpython-312.pyc
vendored
Normal file
Binary file not shown.
34
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/py38.py
vendored
Normal file
34
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/py38.py
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3, 9):
|
||||
|
||||
def removesuffix(self, suffix):
|
||||
# suffix='' should not call self[:-0].
|
||||
if suffix and self.endswith(suffix):
|
||||
return self[: -len(suffix)]
|
||||
else:
|
||||
return self[:]
|
||||
|
||||
def removeprefix(self, prefix):
|
||||
if self.startswith(prefix):
|
||||
return self[len(prefix) :]
|
||||
else:
|
||||
return self[:]
|
||||
|
||||
else:
|
||||
|
||||
def removesuffix(self, suffix):
|
||||
return self.removesuffix(suffix)
|
||||
|
||||
def removeprefix(self, prefix):
|
||||
return self.removeprefix(prefix)
|
||||
|
||||
|
||||
def aix_platform(osname, version, release):
|
||||
try:
|
||||
import _aix_support # type: ignore
|
||||
|
||||
return _aix_support.aix_platform()
|
||||
except ImportError:
|
||||
pass
|
||||
return f"{osname}-{version}.{release}"
|
||||
66
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/py39.py
vendored
Normal file
66
.CondaPkg/env/Lib/site-packages/setuptools/_distutils/compat/py39.py
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
import functools
|
||||
import itertools
|
||||
import platform
|
||||
import sys
|
||||
|
||||
|
||||
def add_ext_suffix_39(vars):
|
||||
"""
|
||||
Ensure vars contains 'EXT_SUFFIX'. pypa/distutils#130
|
||||
"""
|
||||
import _imp
|
||||
|
||||
ext_suffix = _imp.extension_suffixes()[0]
|
||||
vars.update(
|
||||
EXT_SUFFIX=ext_suffix,
|
||||
# sysconfig sets SO to match EXT_SUFFIX, so maintain
|
||||
# that expectation.
|
||||
# https://github.com/python/cpython/blob/785cc6770588de087d09e89a69110af2542be208/Lib/sysconfig.py#L671-L673
|
||||
SO=ext_suffix,
|
||||
)
|
||||
|
||||
|
||||
needs_ext_suffix = sys.version_info < (3, 10) and platform.system() == 'Windows'
|
||||
add_ext_suffix = add_ext_suffix_39 if needs_ext_suffix else lambda vars: None
|
||||
|
||||
|
||||
# from more_itertools
|
||||
class UnequalIterablesError(ValueError):
|
||||
def __init__(self, details=None):
|
||||
msg = 'Iterables have different lengths'
|
||||
if details is not None:
|
||||
msg += (': index 0 has length {}; index {} has length {}').format(*details)
|
||||
|
||||
super().__init__(msg)
|
||||
|
||||
|
||||
# from more_itertools
|
||||
def _zip_equal_generator(iterables):
|
||||
_marker = object()
|
||||
for combo in itertools.zip_longest(*iterables, fillvalue=_marker):
|
||||
for val in combo:
|
||||
if val is _marker:
|
||||
raise UnequalIterablesError()
|
||||
yield combo
|
||||
|
||||
|
||||
# from more_itertools
|
||||
def _zip_equal(*iterables):
|
||||
# Check whether the iterables are all the same size.
|
||||
try:
|
||||
first_size = len(iterables[0])
|
||||
for i, it in enumerate(iterables[1:], 1):
|
||||
size = len(it)
|
||||
if size != first_size:
|
||||
raise UnequalIterablesError(details=(first_size, i, size))
|
||||
# All sizes are equal, we can use the built-in zip.
|
||||
return zip(*iterables)
|
||||
# If any one of the iterables didn't have a length, start reading
|
||||
# them until one runs out.
|
||||
except TypeError:
|
||||
return _zip_equal_generator(iterables)
|
||||
|
||||
|
||||
zip_strict = (
|
||||
_zip_equal if sys.version_info < (3, 10) else functools.partial(zip, strict=True)
|
||||
)
|
||||
@@ -1,139 +0,0 @@
|
||||
"""distutils.pypirc
|
||||
|
||||
Provides the PyPIRCCommand class, the base class for the command classes
|
||||
that uses .pypirc in the distutils.command package.
|
||||
"""
|
||||
import os
|
||||
from configparser import RawConfigParser
|
||||
|
||||
from .cmd import Command
|
||||
|
||||
DEFAULT_PYPIRC = """\
|
||||
[distutils]
|
||||
index-servers =
|
||||
pypi
|
||||
|
||||
[pypi]
|
||||
username:%s
|
||||
password:%s
|
||||
"""
|
||||
|
||||
|
||||
class PyPIRCCommand(Command):
|
||||
"""Base command that knows how to handle the .pypirc file"""
|
||||
|
||||
DEFAULT_REPOSITORY = 'https://upload.pypi.org/legacy/'
|
||||
DEFAULT_REALM = 'pypi'
|
||||
repository = None
|
||||
realm = None
|
||||
|
||||
user_options = [
|
||||
('repository=', 'r', "url of repository [default: %s]" % DEFAULT_REPOSITORY),
|
||||
('show-response', None, 'display full response text from server'),
|
||||
]
|
||||
|
||||
boolean_options = ['show-response']
|
||||
|
||||
def _get_rc_file(self):
|
||||
"""Returns rc file path."""
|
||||
return os.path.join(os.path.expanduser('~'), '.pypirc')
|
||||
|
||||
def _store_pypirc(self, username, password):
|
||||
"""Creates a default .pypirc file."""
|
||||
rc = self._get_rc_file()
|
||||
with os.fdopen(os.open(rc, os.O_CREAT | os.O_WRONLY, 0o600), 'w') as f:
|
||||
f.write(DEFAULT_PYPIRC % (username, password))
|
||||
|
||||
def _read_pypirc(self): # noqa: C901
|
||||
"""Reads the .pypirc file."""
|
||||
rc = self._get_rc_file()
|
||||
if os.path.exists(rc):
|
||||
self.announce('Using PyPI login from %s' % rc)
|
||||
repository = self.repository or self.DEFAULT_REPOSITORY
|
||||
|
||||
config = RawConfigParser()
|
||||
config.read(rc)
|
||||
sections = config.sections()
|
||||
if 'distutils' in sections:
|
||||
# let's get the list of servers
|
||||
index_servers = config.get('distutils', 'index-servers')
|
||||
_servers = [
|
||||
server.strip()
|
||||
for server in index_servers.split('\n')
|
||||
if server.strip() != ''
|
||||
]
|
||||
if _servers == []:
|
||||
# nothing set, let's try to get the default pypi
|
||||
if 'pypi' in sections:
|
||||
_servers = ['pypi']
|
||||
else:
|
||||
# the file is not properly defined, returning
|
||||
# an empty dict
|
||||
return {}
|
||||
for server in _servers:
|
||||
current = {'server': server}
|
||||
current['username'] = config.get(server, 'username')
|
||||
|
||||
# optional params
|
||||
for key, default in (
|
||||
('repository', self.DEFAULT_REPOSITORY),
|
||||
('realm', self.DEFAULT_REALM),
|
||||
('password', None),
|
||||
):
|
||||
if config.has_option(server, key):
|
||||
current[key] = config.get(server, key)
|
||||
else:
|
||||
current[key] = default
|
||||
|
||||
# work around people having "repository" for the "pypi"
|
||||
# section of their config set to the HTTP (rather than
|
||||
# HTTPS) URL
|
||||
if server == 'pypi' and repository in (
|
||||
self.DEFAULT_REPOSITORY,
|
||||
'pypi',
|
||||
):
|
||||
current['repository'] = self.DEFAULT_REPOSITORY
|
||||
return current
|
||||
|
||||
if (
|
||||
current['server'] == repository
|
||||
or current['repository'] == repository
|
||||
):
|
||||
return current
|
||||
elif 'server-login' in sections:
|
||||
# old format
|
||||
server = 'server-login'
|
||||
if config.has_option(server, 'repository'):
|
||||
repository = config.get(server, 'repository')
|
||||
else:
|
||||
repository = self.DEFAULT_REPOSITORY
|
||||
return {
|
||||
'username': config.get(server, 'username'),
|
||||
'password': config.get(server, 'password'),
|
||||
'repository': repository,
|
||||
'server': server,
|
||||
'realm': self.DEFAULT_REALM,
|
||||
}
|
||||
|
||||
return {}
|
||||
|
||||
def _read_pypi_response(self, response):
|
||||
"""Read and decode a PyPI HTTP response."""
|
||||
import cgi
|
||||
|
||||
content_type = response.getheader('content-type', 'text/plain')
|
||||
encoding = cgi.parse_header(content_type)[1].get('charset', 'ascii')
|
||||
return response.read().decode(encoding)
|
||||
|
||||
def initialize_options(self):
|
||||
"""Initialize options."""
|
||||
self.repository = None
|
||||
self.realm = None
|
||||
self.show_response = 0
|
||||
|
||||
def finalize_options(self):
|
||||
"""Finalizes options."""
|
||||
if self.repository is None:
|
||||
self.repository = self.DEFAULT_REPOSITORY
|
||||
if self.realm is None:
|
||||
self.realm = self.DEFAULT_REALM
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user