up
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
Package containing implementation of all the standard Distutils
|
||||
commands."""
|
||||
|
||||
__all__ = [
|
||||
__all__ = [ # noqa: F822
|
||||
'build',
|
||||
'build_py',
|
||||
'build_ext',
|
||||
@@ -16,8 +16,10 @@ __all__ = [
|
||||
'install_scripts',
|
||||
'install_data',
|
||||
'sdist',
|
||||
'register',
|
||||
'bdist',
|
||||
'bdist_dumb',
|
||||
'bdist_rpm',
|
||||
'check',
|
||||
'upload',
|
||||
]
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+6
-5
@@ -2,14 +2,15 @@
|
||||
Backward compatibility for homebrew builds on macOS.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import sys
|
||||
import os
|
||||
import functools
|
||||
import subprocess
|
||||
import sysconfig
|
||||
|
||||
|
||||
@functools.lru_cache
|
||||
@functools.lru_cache()
|
||||
def enabled():
|
||||
"""
|
||||
Only enabled for Python 3.9 framework homebrew builds
|
||||
@@ -37,7 +38,7 @@ schemes = dict(
|
||||
)
|
||||
|
||||
|
||||
@functools.lru_cache
|
||||
@functools.lru_cache()
|
||||
def vars():
|
||||
if not enabled():
|
||||
return {}
|
||||
|
||||
@@ -3,49 +3,37 @@
|
||||
Implements the Distutils 'bdist' command (create a built [binary]
|
||||
distribution)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import warnings
|
||||
from collections.abc import Callable
|
||||
from typing import TYPE_CHECKING, ClassVar
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsOptionError, DistutilsPlatformError
|
||||
from ..util import get_platform
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import deprecated
|
||||
else:
|
||||
|
||||
def deprecated(message):
|
||||
return lambda fn: fn
|
||||
from distutils.core import Command
|
||||
from distutils.errors import DistutilsPlatformError, DistutilsOptionError
|
||||
from distutils.util import get_platform
|
||||
|
||||
|
||||
def show_formats():
|
||||
"""Print list of available formats (arguments to "--format" option)."""
|
||||
from ..fancy_getopt import FancyGetopt
|
||||
from distutils.fancy_getopt import FancyGetopt
|
||||
|
||||
formats = [
|
||||
("formats=" + format, None, bdist.format_commands[format][1])
|
||||
for format in bdist.format_commands
|
||||
]
|
||||
formats = []
|
||||
for format in bdist.format_commands:
|
||||
formats.append(("formats=" + format, None, bdist.format_commands[format][1]))
|
||||
pretty_printer = FancyGetopt(formats)
|
||||
pretty_printer.print_help("List of available distribution formats:")
|
||||
|
||||
|
||||
class ListCompat(dict[str, tuple[str, str]]):
|
||||
class ListCompat(dict):
|
||||
# adapter to allow for Setuptools compatibility in format_commands
|
||||
@deprecated("format_commands is now a dict. append is deprecated.")
|
||||
def append(self, item: object) -> None:
|
||||
def append(self, item):
|
||||
warnings.warn(
|
||||
"format_commands is now a dict. append is deprecated.",
|
||||
"""format_commands is now a dict. append is deprecated.""",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
|
||||
class bdist(Command):
|
||||
|
||||
description = "create a built (binary) distribution"
|
||||
|
||||
user_options = [
|
||||
@@ -54,50 +42,52 @@ class bdist(Command):
|
||||
'plat-name=',
|
||||
'p',
|
||||
"platform name to embed in generated filenames "
|
||||
f"[default: {get_platform()}]",
|
||||
"(default: %s)" % 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]",
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['skip-build']
|
||||
boolean_options = ['skip-build']
|
||||
|
||||
help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
|
||||
help_options = [
|
||||
('help-formats', None, "lists available distribution formats", show_formats),
|
||||
]
|
||||
|
||||
# The following commands do not take a format option from bdist
|
||||
no_format_option: ClassVar[tuple[str, ...]] = ('bdist_rpm',)
|
||||
no_format_option = ('bdist_rpm',)
|
||||
|
||||
# This won't do in reality: will need to distinguish RPM-ish Linux,
|
||||
# Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS.
|
||||
default_format: ClassVar[dict[str, str]] = {'posix': 'gztar', 'nt': 'zip'}
|
||||
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
|
||||
@@ -107,11 +97,11 @@ class bdist(Command):
|
||||
self.plat_name = None
|
||||
self.formats = None
|
||||
self.dist_dir = None
|
||||
self.skip_build = False
|
||||
self.skip_build = 0
|
||||
self.group = None
|
||||
self.owner = None
|
||||
|
||||
def finalize_options(self) -> None:
|
||||
def finalize_options(self):
|
||||
# have to finalize 'plat_name' before 'bdist_base'
|
||||
if self.plat_name is None:
|
||||
if self.skip_build:
|
||||
@@ -133,20 +123,20 @@ class bdist(Command):
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to create built distributions "
|
||||
f"on platform {os.name}"
|
||||
"on platform %s" % os.name
|
||||
)
|
||||
|
||||
if self.dist_dir is None:
|
||||
self.dist_dir = "dist"
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self):
|
||||
# Figure out which sub-commands we need to run.
|
||||
commands = []
|
||||
for format in self.formats:
|
||||
try:
|
||||
commands.append(self.format_commands[format][0])
|
||||
except KeyError:
|
||||
raise DistutilsOptionError(f"invalid format '{format}'")
|
||||
raise DistutilsOptionError("invalid format '%s'" % format)
|
||||
|
||||
# Reinitialize and run each command.
|
||||
for i in range(len(self.formats)):
|
||||
@@ -163,5 +153,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 = True
|
||||
sub_cmd.keep_temp = 1
|
||||
self.run_command(cmd_name)
|
||||
|
||||
+25
-22
@@ -5,17 +5,16 @@ distribution -- i.e., just an archive to be unpacked under $prefix or
|
||||
$exec_prefix)."""
|
||||
|
||||
import os
|
||||
from distutils._log import log
|
||||
from typing import ClassVar
|
||||
|
||||
from ..core import Command
|
||||
from ..dir_util import ensure_relative, remove_tree
|
||||
from ..errors import DistutilsPlatformError
|
||||
from ..sysconfig import get_python_version
|
||||
from ..util import get_platform
|
||||
from distutils.core import Command
|
||||
from distutils.util import get_platform
|
||||
from distutils.dir_util import remove_tree, ensure_relative
|
||||
from distutils.errors import DistutilsPlatformError
|
||||
from distutils.sysconfig import get_python_version
|
||||
from distutils import log
|
||||
|
||||
|
||||
class bdist_dumb(Command):
|
||||
|
||||
description = "create a \"dumb\" built distribution"
|
||||
|
||||
user_options = [
|
||||
@@ -24,38 +23,39 @@ class bdist_dumb(Command):
|
||||
'plat-name=',
|
||||
'p',
|
||||
"platform name to embed in generated filenames "
|
||||
f"[default: {get_platform()}]",
|
||||
"(default: %s)" % 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]",
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['keep-temp', 'skip-build', 'relative']
|
||||
boolean_options = ['keep-temp', 'skip-build', 'relative']
|
||||
|
||||
default_format = {'posix': 'gztar', 'nt': 'zip'}
|
||||
|
||||
@@ -63,10 +63,10 @@ class bdist_dumb(Command):
|
||||
self.bdist_dir = None
|
||||
self.plat_name = None
|
||||
self.format = None
|
||||
self.keep_temp = False
|
||||
self.keep_temp = 0
|
||||
self.dist_dir = None
|
||||
self.skip_build = None
|
||||
self.relative = False
|
||||
self.relative = 0
|
||||
self.owner = None
|
||||
self.group = None
|
||||
|
||||
@@ -81,7 +81,7 @@ class bdist_dumb(Command):
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to create dumb built distributions "
|
||||
f"on platform {os.name}"
|
||||
"on platform %s" % os.name
|
||||
)
|
||||
|
||||
self.set_undefined_options(
|
||||
@@ -95,17 +95,19 @@ class bdist_dumb(Command):
|
||||
if not self.skip_build:
|
||||
self.run_command('build')
|
||||
|
||||
install = self.reinitialize_command('install', reinit_subcommands=True)
|
||||
install = self.reinitialize_command('install', reinit_subcommands=1)
|
||||
install.root = self.bdist_dir
|
||||
install.skip_build = self.skip_build
|
||||
install.warn_dir = False
|
||||
install.warn_dir = 0
|
||||
|
||||
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 = f"{self.distribution.get_fullname()}.{self.plat_name}"
|
||||
archive_basename = "{}.{}".format(
|
||||
self.distribution.get_fullname(), self.plat_name
|
||||
)
|
||||
|
||||
pseudoinstall_root = os.path.join(self.dist_dir, archive_basename)
|
||||
if not self.relative:
|
||||
@@ -116,7 +118,8 @@ class bdist_dumb(Command):
|
||||
):
|
||||
raise DistutilsPlatformError(
|
||||
"can't make a dumb built distribution where "
|
||||
f"base and platbase are different ({install.install_base!r}, {install.install_platbase!r})"
|
||||
"base and platbase are different (%s, %s)"
|
||||
% (repr(install.install_base), repr(install.install_platbase))
|
||||
)
|
||||
else:
|
||||
archive_root = os.path.join(
|
||||
|
||||
+94
-77
@@ -3,25 +3,25 @@
|
||||
Implements the Distutils 'bdist_rpm' command (create RPM source and binary
|
||||
distributions)."""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from distutils._log import log
|
||||
from typing import ClassVar
|
||||
import os
|
||||
|
||||
from ..core import Command
|
||||
from ..debug import DEBUG
|
||||
from ..errors import (
|
||||
DistutilsExecError,
|
||||
DistutilsFileError,
|
||||
from distutils.core import Command
|
||||
from distutils.debug import DEBUG
|
||||
from distutils.file_util import write_file
|
||||
from distutils.errors import (
|
||||
DistutilsOptionError,
|
||||
DistutilsPlatformError,
|
||||
DistutilsFileError,
|
||||
DistutilsExecError,
|
||||
)
|
||||
from ..file_util import write_file
|
||||
from ..sysconfig import get_python_version
|
||||
from distutils.sysconfig import get_python_version
|
||||
from distutils import log
|
||||
|
||||
|
||||
class bdist_rpm(Command):
|
||||
|
||||
description = "create an RPM distribution"
|
||||
|
||||
user_options = [
|
||||
@@ -35,13 +35,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',
|
||||
@@ -76,7 +76,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"),
|
||||
@@ -137,7 +137,7 @@ class bdist_rpm(Command):
|
||||
('quiet', 'q', "Run the INSTALL phase of RPM building in quiet mode"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = [
|
||||
boolean_options = [
|
||||
'keep-temp',
|
||||
'use-rpm-opt-flags',
|
||||
'rpm3-mode',
|
||||
@@ -145,7 +145,7 @@ class bdist_rpm(Command):
|
||||
'quiet',
|
||||
]
|
||||
|
||||
negative_opt: ClassVar[dict[str, str]] = {
|
||||
negative_opt = {
|
||||
'no-keep-temp': 'keep-temp',
|
||||
'no-rpm-opt-flags': 'use-rpm-opt-flags',
|
||||
'rpm2-mode': 'rpm3-mode',
|
||||
@@ -188,15 +188,15 @@ class bdist_rpm(Command):
|
||||
self.build_requires = None
|
||||
self.obsoletes = None
|
||||
|
||||
self.keep_temp = False
|
||||
self.use_rpm_opt_flags = True
|
||||
self.rpm3_mode = True
|
||||
self.no_autoreq = False
|
||||
self.keep_temp = 0
|
||||
self.use_rpm_opt_flags = 1
|
||||
self.rpm3_mode = 1
|
||||
self.no_autoreq = 0
|
||||
|
||||
self.force_arch = None
|
||||
self.quiet = False
|
||||
self.quiet = 0
|
||||
|
||||
def finalize_options(self) -> None:
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('bdist', ('bdist_base', 'bdist_base'))
|
||||
if self.rpm_base is None:
|
||||
if not self.rpm3_mode:
|
||||
@@ -215,7 +215,7 @@ class bdist_rpm(Command):
|
||||
|
||||
if os.name != 'posix':
|
||||
raise DistutilsPlatformError(
|
||||
f"don't know how to create RPM distributions on platform {os.name}"
|
||||
"don't know how to create RPM " "distributions on platform %s" % os.name
|
||||
)
|
||||
if self.binary_only and self.source_only:
|
||||
raise DistutilsOptionError(
|
||||
@@ -224,16 +224,17 @@ class bdist_rpm(Command):
|
||||
|
||||
# don't pass CFLAGS to pure python distributions
|
||||
if not self.distribution.has_ext_modules():
|
||||
self.use_rpm_opt_flags = False
|
||||
self.use_rpm_opt_flags = 0
|
||||
|
||||
self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
|
||||
self.finalize_package_data()
|
||||
|
||||
def finalize_package_data(self) -> None:
|
||||
def finalize_package_data(self):
|
||||
self.ensure_string('group', "Development/Libraries")
|
||||
self.ensure_string(
|
||||
'vendor',
|
||||
f"{self.distribution.get_contact()} <{self.distribution.get_contact_email()}>",
|
||||
"%s <%s>"
|
||||
% (self.distribution.get_contact(), self.distribution.get_contact_email()),
|
||||
)
|
||||
self.ensure_string('packager')
|
||||
self.ensure_string_list('doc_files')
|
||||
@@ -275,7 +276,7 @@ class bdist_rpm(Command):
|
||||
|
||||
self.ensure_string('force_arch')
|
||||
|
||||
def run(self) -> None: # noqa: C901
|
||||
def run(self): # noqa: C901
|
||||
if DEBUG:
|
||||
print("before _get_package_data():")
|
||||
print("vendor =", self.vendor)
|
||||
@@ -296,9 +297,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, f"{self.distribution.get_name()}.spec")
|
||||
spec_path = os.path.join(spec_dir, "%s.spec" % self.distribution.get_name())
|
||||
self.execute(
|
||||
write_file, (spec_path, self._make_spec_file()), f"writing '{spec_path}'"
|
||||
write_file, (spec_path, self._make_spec_file()), "writing '%s'" % spec_path
|
||||
)
|
||||
|
||||
if self.spec_only: # stop if requested
|
||||
@@ -323,7 +324,7 @@ class bdist_rpm(Command):
|
||||
if os.path.exists(self.icon):
|
||||
self.copy_file(self.icon, source_dir)
|
||||
else:
|
||||
raise DistutilsFileError(f"icon file '{self.icon}' does not exist")
|
||||
raise DistutilsFileError("icon file '%s' does not exist" % self.icon)
|
||||
|
||||
# build package
|
||||
log.info("building RPMs")
|
||||
@@ -335,9 +336,9 @@ class bdist_rpm(Command):
|
||||
rpm_cmd.append('-bb')
|
||||
else:
|
||||
rpm_cmd.append('-ba')
|
||||
rpm_cmd.extend(['--define', f'__python {self.python}'])
|
||||
rpm_cmd.extend(['--define', '__python %s' % self.python])
|
||||
if self.rpm3_mode:
|
||||
rpm_cmd.extend(['--define', f'_topdir {os.path.abspath(self.rpm_base)}'])
|
||||
rpm_cmd.extend(['--define', '_topdir %s' % os.path.abspath(self.rpm_base)])
|
||||
if not self.keep_temp:
|
||||
rpm_cmd.append('--clean')
|
||||
|
||||
@@ -352,7 +353,11 @@ 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 = rf"rpm -q --qf '{src_rpm} {non_src_rpm}\n' --specfile '{spec_path}'"
|
||||
q_cmd = r"rpm -q --qf '{} {}\n' --specfile '{}'".format(
|
||||
src_rpm,
|
||||
non_src_rpm,
|
||||
spec_path,
|
||||
)
|
||||
|
||||
out = os.popen(q_cmd)
|
||||
try:
|
||||
@@ -371,7 +376,7 @@ class bdist_rpm(Command):
|
||||
|
||||
status = out.close()
|
||||
if status:
|
||||
raise DistutilsExecError(f"Failed to execute: {q_cmd!r}")
|
||||
raise DistutilsExecError("Failed to execute: %s" % repr(q_cmd))
|
||||
|
||||
finally:
|
||||
out.close()
|
||||
@@ -397,11 +402,9 @@ 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))
|
||||
@@ -426,14 +429,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([
|
||||
f' {line.strip()} \\' for line in vendor_hook.splitlines()
|
||||
])
|
||||
vendor_hook = '\n'.join(
|
||||
[' %s \\' % 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 https://bugs.python.org/issue14443')
|
||||
spec_file.append('# Workaround for http://bugs.python.org/issue14443')
|
||||
spec_file.append('%define __os_install_post ' + fixed_hook + '\n')
|
||||
|
||||
# put locale summaries into spec file
|
||||
@@ -443,11 +446,13 @@ 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
|
||||
@@ -457,19 +462,21 @@ 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(f'BuildArch: {self.force_arch}')
|
||||
spec_file.append('BuildArch: %s' % self.force_arch)
|
||||
|
||||
for field in (
|
||||
'Vendor',
|
||||
@@ -483,7 +490,7 @@ class bdist_rpm(Command):
|
||||
if isinstance(val, list):
|
||||
spec_file.append('{}: {}'.format(field, ' '.join(val)))
|
||||
elif val is not None:
|
||||
spec_file.append(f'{field}: {val}')
|
||||
spec_file.append('{}: {}'.format(field, val))
|
||||
|
||||
if self.distribution.get_url():
|
||||
spec_file.append('Url: ' + self.distribution.get_url())
|
||||
@@ -500,11 +507,13 @@ 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
|
||||
@@ -518,8 +527,8 @@ class bdist_rpm(Command):
|
||||
|
||||
# rpm scripts
|
||||
# figure out default build script
|
||||
def_setup_call = f"{self.python} {os.path.basename(sys.argv[0])}"
|
||||
def_build = f"{def_setup_call} build"
|
||||
def_setup_call = "{} {}".format(self.python, os.path.basename(sys.argv[0]))
|
||||
def_build = "%s build" % def_setup_call
|
||||
if self.use_rpm_opt_flags:
|
||||
def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build
|
||||
|
||||
@@ -529,7 +538,9 @@ 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 = f'{def_setup_call} install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES'
|
||||
install_cmd = (
|
||||
'%s install -O1 --root=$RPM_BUILD_ROOT ' '--record=INSTALLED_FILES'
|
||||
) % def_setup_call
|
||||
|
||||
script_options = [
|
||||
('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"),
|
||||
@@ -543,15 +554,17 @@ class bdist_rpm(Command):
|
||||
('postun', 'post_uninstall', None),
|
||||
]
|
||||
|
||||
for rpm_opt, attr, default in script_options:
|
||||
for (rpm_opt, attr, default) in script_options:
|
||||
# Insert contents of file referred to, if no file is referred to
|
||||
# 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'))
|
||||
@@ -559,20 +572,24 @@ 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,21 +2,21 @@
|
||||
|
||||
Implements the Distutils 'build' command."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
import sysconfig
|
||||
from collections.abc import Callable
|
||||
from typing import ClassVar
|
||||
import os
|
||||
from distutils.core import Command
|
||||
from distutils.errors import DistutilsOptionError
|
||||
from distutils.util import get_platform
|
||||
|
||||
from ..ccompiler import show_compilers
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsOptionError
|
||||
from ..util import get_platform
|
||||
|
||||
def show_compilers():
|
||||
from distutils.ccompiler import show_compilers
|
||||
|
||||
show_compilers()
|
||||
|
||||
|
||||
class build(Command):
|
||||
|
||||
description = "build everything needed to install"
|
||||
|
||||
user_options = [
|
||||
@@ -26,14 +26,16 @@ 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',
|
||||
f"platform name to build for, if supported [default: {get_platform()}]",
|
||||
"platform name to build for, if supported "
|
||||
"(default: %s)" % get_platform(),
|
||||
),
|
||||
('compiler=', 'c', "specify the compiler type"),
|
||||
('parallel=', 'j', "number of parallel build jobs"),
|
||||
@@ -42,9 +44,9 @@ class build(Command):
|
||||
('executable=', 'e', "specify final destination interpreter path (build.py)"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['debug', 'force']
|
||||
boolean_options = ['debug', 'force']
|
||||
|
||||
help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
|
||||
help_options = [
|
||||
('help-compiler', None, "list available compilers", show_compilers),
|
||||
]
|
||||
|
||||
@@ -60,11 +62,11 @@ class build(Command):
|
||||
self.compiler = None
|
||||
self.plat_name = None
|
||||
self.debug = None
|
||||
self.force = False
|
||||
self.force = 0
|
||||
self.executable = None
|
||||
self.parallel = None
|
||||
|
||||
def finalize_options(self) -> None: # noqa: C901
|
||||
def finalize_options(self): # noqa: C901
|
||||
if self.plat_name is None:
|
||||
self.plat_name = get_platform()
|
||||
else:
|
||||
@@ -77,11 +79,7 @@ class build(Command):
|
||||
"using './configure --help' on your platform)"
|
||||
)
|
||||
|
||||
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'
|
||||
plat_specifier = ".{}-{}".format(self.plat_name, sys.implementation.cache_tag)
|
||||
|
||||
# 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
|
||||
@@ -112,8 +110,7 @@ class build(Command):
|
||||
self.build_temp = os.path.join(self.build_base, 'temp' + plat_specifier)
|
||||
if self.build_scripts is None:
|
||||
self.build_scripts = os.path.join(
|
||||
self.build_base,
|
||||
f'scripts-{sys.version_info.major}.{sys.version_info.minor}',
|
||||
self.build_base, 'scripts-%d.%d' % sys.version_info[:2]
|
||||
)
|
||||
|
||||
if self.executable is None and sys.executable:
|
||||
@@ -125,7 +122,7 @@ class build(Command):
|
||||
except ValueError:
|
||||
raise DistutilsOptionError("parallel should be an integer")
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self):
|
||||
# Run all relevant sub-commands. This will be some subset of:
|
||||
# - build_py - pure Python modules
|
||||
# - build_clib - standalone C libraries
|
||||
|
||||
+32
-25
@@ -4,6 +4,7 @@ Implements the Distutils 'build_clib' command, to build a C/C++ library
|
||||
that is included in the module distribution and needed by an extension
|
||||
module."""
|
||||
|
||||
|
||||
# XXX this module has *lots* of code ripped-off quite transparently from
|
||||
# build_ext.py -- not surprisingly really, as the work required to build
|
||||
# a static library from a collection of C source files is not really all
|
||||
@@ -12,23 +13,25 @@ module."""
|
||||
# necessary refactoring to account for the overlap in code between the
|
||||
# two modules, mainly because a number of subtle details changed in the
|
||||
# cut 'n paste. Sigh.
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from collections.abc import Callable
|
||||
from distutils._log import log
|
||||
from typing import ClassVar
|
||||
from distutils.core import Command
|
||||
from distutils.errors import DistutilsSetupError
|
||||
from distutils.sysconfig import customize_compiler
|
||||
from distutils import log
|
||||
|
||||
from ..ccompiler import new_compiler, show_compilers
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsSetupError
|
||||
from ..sysconfig import customize_compiler
|
||||
|
||||
def show_compilers():
|
||||
from distutils.ccompiler import show_compilers
|
||||
|
||||
show_compilers()
|
||||
|
||||
|
||||
class build_clib(Command):
|
||||
|
||||
description = "build C/C++ libraries used by Python extensions"
|
||||
|
||||
user_options: ClassVar[list[tuple[str, str, str]]] = [
|
||||
user_options = [
|
||||
('build-clib=', 'b', "directory to build C/C++ libraries to"),
|
||||
('build-temp=', 't', "directory to put temporary build by-products"),
|
||||
('debug', 'g', "compile with debugging information"),
|
||||
@@ -36,9 +39,9 @@ class build_clib(Command):
|
||||
('compiler=', 'c', "specify the compiler type"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['debug', 'force']
|
||||
boolean_options = ['debug', 'force']
|
||||
|
||||
help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
|
||||
help_options = [
|
||||
('help-compiler', None, "list available compilers", show_compilers),
|
||||
]
|
||||
|
||||
@@ -54,10 +57,10 @@ class build_clib(Command):
|
||||
self.define = None
|
||||
self.undef = None
|
||||
self.debug = None
|
||||
self.force = False
|
||||
self.force = 0
|
||||
self.compiler = None
|
||||
|
||||
def finalize_options(self) -> None:
|
||||
def finalize_options(self):
|
||||
# This might be confusing: both build-clib and build-temp default
|
||||
# to build-temp as defined by the "build" command. This is because
|
||||
# I think that C libraries are really just temporary build
|
||||
@@ -84,10 +87,13 @@ class build_clib(Command):
|
||||
# XXX same as for build_ext -- what about 'self.define' and
|
||||
# 'self.undef' ?
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self):
|
||||
if not self.libraries:
|
||||
return
|
||||
|
||||
# Yech -- this is cut 'n pasted from build_ext.py!
|
||||
from distutils.ccompiler import new_compiler
|
||||
|
||||
self.compiler = new_compiler(
|
||||
compiler=self.compiler, dry_run=self.dry_run, force=self.force
|
||||
)
|
||||
@@ -97,7 +103,7 @@ class build_clib(Command):
|
||||
self.compiler.set_include_dirs(self.include_dirs)
|
||||
if self.define is not None:
|
||||
# 'define' option is a list of (name,value) tuples
|
||||
for name, value in self.define:
|
||||
for (name, value) in self.define:
|
||||
self.compiler.define_macro(name, value)
|
||||
if self.undef is not None:
|
||||
for macro in self.undef:
|
||||
@@ -105,7 +111,7 @@ class build_clib(Command):
|
||||
|
||||
self.build_libraries(self.libraries)
|
||||
|
||||
def check_library_list(self, libraries) -> None:
|
||||
def check_library_list(self, libraries):
|
||||
"""Ensure that the list of libraries is valid.
|
||||
|
||||
`library` is presumably provided as a command option 'libraries'.
|
||||
@@ -132,7 +138,8 @@ class build_clib(Command):
|
||||
|
||||
if '/' in name or (os.sep != '/' and os.sep in name):
|
||||
raise DistutilsSetupError(
|
||||
f"bad library name '{lib[0]}': may not contain directory separators"
|
||||
"bad library name '%s': "
|
||||
"may not contain directory separators" % lib[0]
|
||||
)
|
||||
|
||||
if not isinstance(build_info, dict):
|
||||
@@ -148,33 +155,33 @@ 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
|
||||
|
||||
def get_source_files(self):
|
||||
self.check_library_list(self.libraries)
|
||||
filenames = []
|
||||
for lib_name, build_info in self.libraries:
|
||||
for (lib_name, build_info) in self.libraries:
|
||||
sources = build_info.get('sources')
|
||||
if sources is None or not isinstance(sources, (list, tuple)):
|
||||
raise DistutilsSetupError(
|
||||
f"in 'libraries' option (library '{lib_name}'), "
|
||||
"in 'libraries' option (library '%s'), "
|
||||
"'sources' must be present and must be "
|
||||
"a list of source filenames"
|
||||
"a list of source filenames" % lib_name
|
||||
)
|
||||
|
||||
filenames.extend(sources)
|
||||
return filenames
|
||||
|
||||
def build_libraries(self, libraries) -> None:
|
||||
for lib_name, build_info in libraries:
|
||||
def build_libraries(self, libraries):
|
||||
for (lib_name, build_info) in libraries:
|
||||
sources = build_info.get('sources')
|
||||
if sources is None or not isinstance(sources, (list, tuple)):
|
||||
raise DistutilsSetupError(
|
||||
f"in 'libraries' option (library '{lib_name}'), "
|
||||
"in 'libraries' option (library '%s'), "
|
||||
"'sources' must be present and must be "
|
||||
"a list of source filenames"
|
||||
"a list of source filenames" % lib_name
|
||||
)
|
||||
sources = list(sources)
|
||||
|
||||
|
||||
+78
-103
@@ -4,38 +4,42 @@ Implements the Distutils 'build_ext' command, for building extension
|
||||
modules (currently limited to C extensions, should accommodate C++
|
||||
extensions ASAP)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
from distutils._log import log
|
||||
from site import USER_BASE
|
||||
from typing import ClassVar
|
||||
|
||||
from .._modified import newer_group
|
||||
from ..ccompiler import new_compiler, show_compilers
|
||||
from ..core import Command
|
||||
from ..errors import (
|
||||
CCompilerError,
|
||||
CompileError,
|
||||
DistutilsError,
|
||||
from distutils.core import Command
|
||||
from distutils.errors import (
|
||||
DistutilsOptionError,
|
||||
DistutilsPlatformError,
|
||||
DistutilsSetupError,
|
||||
CCompilerError,
|
||||
DistutilsError,
|
||||
CompileError,
|
||||
DistutilsPlatformError,
|
||||
)
|
||||
from ..extension import Extension
|
||||
from ..sysconfig import customize_compiler, get_config_h_filename, get_python_version
|
||||
from ..util import get_platform, is_freethreaded, is_mingw
|
||||
from distutils.sysconfig import customize_compiler, get_python_version
|
||||
from distutils.sysconfig import get_config_h_filename
|
||||
from distutils.dep_util import newer_group
|
||||
from distutils.extension import Extension
|
||||
from distutils.util import get_platform
|
||||
from distutils import log
|
||||
from . import py37compat
|
||||
|
||||
from site import USER_BASE
|
||||
|
||||
# An extension name is just a dot-separated list of Python NAMEs (ie.
|
||||
# the same as a fully-qualified module name).
|
||||
extension_name_re = re.compile(r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$')
|
||||
|
||||
|
||||
def show_compilers():
|
||||
from distutils.ccompiler import show_compilers
|
||||
|
||||
show_compilers()
|
||||
|
||||
|
||||
class build_ext(Command):
|
||||
|
||||
description = "build C/C++ extensions (compile/link to build directory)"
|
||||
|
||||
# XXX thoughts on how to deal with complex command-line options like
|
||||
@@ -56,7 +60,7 @@ class build_ext(Command):
|
||||
# takes care of both command-line and client options
|
||||
# in between initialize_options() and finalize_options())
|
||||
|
||||
sep_by = f" (separated by '{os.pathsep}')"
|
||||
sep_by = " (separated by '%s')" % os.pathsep
|
||||
user_options = [
|
||||
('build-lib=', 'b', "directory for compiled extension modules"),
|
||||
('build-temp=', 't', "directory for temporary files (build by-products)"),
|
||||
@@ -64,13 +68,13 @@ class build_ext(Command):
|
||||
'plat-name=',
|
||||
'p',
|
||||
"platform name to cross-compile for, if supported "
|
||||
f"[default: {get_platform()}]",
|
||||
"(default: %s)" % 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=',
|
||||
@@ -97,15 +101,9 @@ class build_ext(Command):
|
||||
('user', None, "add user include, library and rpath"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = [
|
||||
'inplace',
|
||||
'debug',
|
||||
'force',
|
||||
'swig-cpp',
|
||||
'user',
|
||||
]
|
||||
boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user']
|
||||
|
||||
help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
|
||||
help_options = [
|
||||
('help-compiler', None, "list available compilers", show_compilers),
|
||||
]
|
||||
|
||||
@@ -114,7 +112,7 @@ class build_ext(Command):
|
||||
self.build_lib = None
|
||||
self.plat_name = None
|
||||
self.build_temp = None
|
||||
self.inplace = False
|
||||
self.inplace = 0
|
||||
self.package = None
|
||||
|
||||
self.include_dirs = None
|
||||
@@ -133,32 +131,7 @@ 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) -> None: # noqa: C901
|
||||
def finalize_options(self): # noqa: C901
|
||||
from distutils import sysconfig
|
||||
|
||||
self.set_undefined_options(
|
||||
@@ -180,7 +153,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=True)
|
||||
plat_py_include = sysconfig.get_python_inc(plat_specific=1)
|
||||
if self.include_dirs is None:
|
||||
self.include_dirs = self.distribution.include_dirs or []
|
||||
if isinstance(self.include_dirs, str):
|
||||
@@ -217,7 +190,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' and not is_mingw():
|
||||
if os.name == 'nt':
|
||||
# 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.
|
||||
@@ -259,7 +232,16 @@ class build_ext(Command):
|
||||
# building python standard extensions
|
||||
self.library_dirs.append('.')
|
||||
|
||||
self.library_dirs.extend(self._python_lib_dir(sysconfig))
|
||||
# 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('.')
|
||||
|
||||
# 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
|
||||
@@ -297,7 +279,9 @@ class build_ext(Command):
|
||||
except ValueError:
|
||||
raise DistutilsOptionError("parallel should be an integer")
|
||||
|
||||
def run(self) -> None: # noqa: C901
|
||||
def run(self): # noqa: C901
|
||||
from distutils.ccompiler import new_compiler
|
||||
|
||||
# 'self.extensions', as supplied by setup.py, is a list of
|
||||
# Extension instances. See the documentation for Extension (in
|
||||
# distutils.extension) for details.
|
||||
@@ -336,12 +320,6 @@ class build_ext(Command):
|
||||
if os.name == 'nt' and self.plat_name != get_platform():
|
||||
self.compiler.initialize(self.plat_name)
|
||||
|
||||
# The official Windows free threaded Python installer doesn't set
|
||||
# Py_GIL_DISABLED because its pyconfig.h is shared with the
|
||||
# default build, so define it here (pypa/setuptools#4662).
|
||||
if os.name == 'nt' and is_freethreaded():
|
||||
self.compiler.define_macro('Py_GIL_DISABLED', '1')
|
||||
|
||||
# And make sure that any compile/link-related options (which might
|
||||
# come from the command-line or from the setup script) are set in
|
||||
# that CCompiler object -- that way, they automatically apply to
|
||||
@@ -350,7 +328,7 @@ class build_ext(Command):
|
||||
self.compiler.set_include_dirs(self.include_dirs)
|
||||
if self.define is not None:
|
||||
# 'define' option is a list of (name,value) tuples
|
||||
for name, value in self.define:
|
||||
for (name, value) in self.define:
|
||||
self.compiler.define_macro(name, value)
|
||||
if self.undef is not None:
|
||||
for macro in self.undef:
|
||||
@@ -367,7 +345,7 @@ class build_ext(Command):
|
||||
# Now actually compile and link everything.
|
||||
self.build_extensions()
|
||||
|
||||
def check_extensions_list(self, extensions) -> None: # noqa: C901
|
||||
def check_extensions_list(self, extensions): # noqa: C901
|
||||
"""Ensure that the list of extensions (presumably provided as a
|
||||
command option 'extensions') is valid, i.e. it is a list of
|
||||
Extension objects. We also support the old-style list of 2-tuples,
|
||||
@@ -395,7 +373,7 @@ class build_ext(Command):
|
||||
|
||||
ext_name, build_info = ext
|
||||
|
||||
log.warning(
|
||||
log.warn(
|
||||
"old-style (ext_name, build_info) tuple found in "
|
||||
"ext_modules for extension '%s' "
|
||||
"-- please convert to Extension instance",
|
||||
@@ -435,7 +413,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.warn("'def_file' element of build info dict " "no longer supported")
|
||||
|
||||
# Non-trivial stuff: 'macros' split into 'define_macros'
|
||||
# and 'undef_macros'.
|
||||
@@ -446,7 +424,8 @@ class build_ext(Command):
|
||||
for macro in macros:
|
||||
if not (isinstance(macro, tuple) and len(macro) in (1, 2)):
|
||||
raise DistutilsSetupError(
|
||||
"'macros' element of build info dict must be 1- or 2-tuple"
|
||||
"'macros' element of build info dict "
|
||||
"must be 1- or 2-tuple"
|
||||
)
|
||||
if len(macro) == 1:
|
||||
ext.undef_macros.append(macro[0])
|
||||
@@ -473,9 +452,12 @@ 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.
|
||||
return [self.get_ext_fullpath(ext.name) for ext in self.extensions]
|
||||
outputs = []
|
||||
for ext in self.extensions:
|
||||
outputs.append(self.get_ext_fullpath(ext.name))
|
||||
return outputs
|
||||
|
||||
def build_extensions(self) -> None:
|
||||
def build_extensions(self):
|
||||
# First, sanity-check the 'extensions' list
|
||||
self.check_extensions_list(self.extensions)
|
||||
if self.parallel:
|
||||
@@ -516,15 +498,15 @@ class build_ext(Command):
|
||||
except (CCompilerError, DistutilsError, CompileError) as e:
|
||||
if not ext.optional:
|
||||
raise
|
||||
self.warn(f'building extension "{ext.name}" failed: {e}')
|
||||
self.warn('building extension "{}" failed: {}'.format(ext.name, e))
|
||||
|
||||
def build_extension(self, ext) -> None:
|
||||
def build_extension(self, ext):
|
||||
sources = ext.sources
|
||||
if sources is None or not isinstance(sources, (list, tuple)):
|
||||
raise DistutilsSetupError(
|
||||
f"in 'ext_modules' option (extension '{ext.name}'), "
|
||||
"in 'ext_modules' option (extension '%s'), "
|
||||
"'sources' must be present and must be "
|
||||
"a list of source filenames"
|
||||
"a list of source filenames" % ext.name
|
||||
)
|
||||
# sort to make the resulting .so file build reproducible
|
||||
sources = sorted(sources)
|
||||
@@ -615,7 +597,7 @@ class build_ext(Command):
|
||||
# the temp dir.
|
||||
|
||||
if self.swig_cpp:
|
||||
log.warning("--swig-cpp is deprecated - use --swig-opts=-c++")
|
||||
log.warn("--swig-cpp is deprecated - use --swig-opts=-c++")
|
||||
|
||||
if (
|
||||
self.swig_cpp
|
||||
@@ -646,7 +628,8 @@ class build_ext(Command):
|
||||
|
||||
# Do not override commandline arguments
|
||||
if not self.swig_opts:
|
||||
swig_cmd.extend(extension.swig_opts)
|
||||
for o in extension.swig_opts:
|
||||
swig_cmd.append(o)
|
||||
|
||||
for source in swig_sources:
|
||||
target = swig_targets[source]
|
||||
@@ -667,19 +650,20 @@ 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(f"c:\\swig{vers}", "swig.exe")
|
||||
fn = os.path.join("c:\\swig%s" % vers, "swig.exe")
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
else:
|
||||
return "swig.exe"
|
||||
else:
|
||||
raise DistutilsPlatformError(
|
||||
f"I don't know how to find (much less run) SWIG on platform '{os.name}'"
|
||||
"I don't know how to find (much less run) SWIG "
|
||||
"on platform '%s'" % os.name
|
||||
)
|
||||
|
||||
# -- Name generators -----------------------------------------------
|
||||
# (extension names, filenames, whatever)
|
||||
def get_ext_fullpath(self, ext_name: str) -> str:
|
||||
def get_ext_fullpath(self, ext_name):
|
||||
"""Returns the path of the filename for a given extension.
|
||||
|
||||
The file is located in `build_lib` or directly in the package
|
||||
@@ -706,7 +690,7 @@ class build_ext(Command):
|
||||
# package_dir/filename
|
||||
return os.path.join(package_dir, filename)
|
||||
|
||||
def get_ext_fullname(self, ext_name: str) -> str:
|
||||
def get_ext_fullname(self, ext_name):
|
||||
"""Returns the fullname of a given extension name.
|
||||
|
||||
Adds the `package.` prefix"""
|
||||
@@ -715,27 +699,27 @@ class build_ext(Command):
|
||||
else:
|
||||
return self.package + '.' + ext_name
|
||||
|
||||
def get_ext_filename(self, ext_name: str) -> str:
|
||||
def get_ext_filename(self, ext_name):
|
||||
r"""Convert the name of an extension (eg. "foo.bar") into the name
|
||||
of the file from which it will be loaded (eg. "foo/bar.so", or
|
||||
"foo\bar.pyd").
|
||||
"""
|
||||
from ..sysconfig import get_config_var
|
||||
from distutils.sysconfig import get_config_var
|
||||
|
||||
ext_path = ext_name.split('.')
|
||||
ext_suffix = get_config_var('EXT_SUFFIX')
|
||||
return os.path.join(*ext_path) + ext_suffix
|
||||
|
||||
def get_export_symbols(self, ext: Extension) -> list[str]:
|
||||
def get_export_symbols(self, ext):
|
||||
"""Return the list of symbols that a shared extension has to
|
||||
export. This either uses 'ext.export_symbols' or, if it's not
|
||||
provided, "PyInit_" + module_name. Only relevant on Windows, where
|
||||
the .pyd file (DLL) must export the module "PyInit_" function.
|
||||
"""
|
||||
name = self._get_module_name_for_symbol(ext)
|
||||
name = ext.name.split('.')[-1]
|
||||
try:
|
||||
# Unicode module name support as defined in PEP-489
|
||||
# https://peps.python.org/pep-0489/#export-hook-name
|
||||
# https://www.python.org/dev/peps/pep-0489/#export-hook-name
|
||||
name.encode('ascii')
|
||||
except UnicodeEncodeError:
|
||||
suffix = 'U_' + name.encode('punycode').replace(b'-', b'_').decode('ascii')
|
||||
@@ -747,16 +731,7 @@ class build_ext(Command):
|
||||
ext.export_symbols.append(initfunc_name)
|
||||
return ext.export_symbols
|
||||
|
||||
def _get_module_name_for_symbol(self, ext):
|
||||
# Package name should be used for `__init__` modules
|
||||
# https://github.com/python/cpython/issues/80074
|
||||
# https://github.com/pypa/setuptools/issues/4826
|
||||
parts = ext.name.split(".")
|
||||
if parts[-1] == "__init__" and len(parts) >= 2:
|
||||
return parts[-2]
|
||||
return parts[-1]
|
||||
|
||||
def get_libraries(self, ext: Extension) -> list[str]: # noqa: C901
|
||||
def get_libraries(self, ext): # noqa: C901
|
||||
"""Return the list of libraries to link against when building a
|
||||
shared extension. On most platforms, this is just 'ext.libraries';
|
||||
on Windows, we add the Python library (eg. python20.dll).
|
||||
@@ -766,8 +741,8 @@ 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" and not is_mingw():
|
||||
from .._msvccompiler import MSVCCompiler
|
||||
if sys.platform == "win32":
|
||||
from distutils._msvccompiler import MSVCCompiler
|
||||
|
||||
if not isinstance(self.compiler, MSVCCompiler):
|
||||
template = "python%d%d"
|
||||
@@ -789,14 +764,14 @@ class build_ext(Command):
|
||||
# On Cygwin (and if required, other POSIX-like platforms based on
|
||||
# Windows like MinGW) it is simply necessary that all symbols in
|
||||
# shared libraries are resolved at link time.
|
||||
from ..sysconfig import get_config_var
|
||||
from distutils.sysconfig import get_config_var
|
||||
|
||||
link_libpython = False
|
||||
if get_config_var('Py_ENABLE_SHARED'):
|
||||
# A native build on an Android device or on Cygwin
|
||||
if hasattr(sys, 'getandroidapilevel'):
|
||||
link_libpython = True
|
||||
elif sys.platform == 'cygwin' or is_mingw():
|
||||
elif sys.platform == 'cygwin':
|
||||
link_libpython = True
|
||||
elif '_PYTHON_HOST_PLATFORM' in os.environ:
|
||||
# We are cross-compiling for one of the relevant platforms
|
||||
@@ -809,4 +784,4 @@ class build_ext(Command):
|
||||
ldversion = get_config_var('LDVERSION')
|
||||
return ext.libraries + ['python' + ldversion]
|
||||
|
||||
return ext.libraries
|
||||
return ext.libraries + py37compat.pythonlib()
|
||||
|
||||
+33
-33
@@ -2,19 +2,19 @@
|
||||
|
||||
Implements the Distutils 'build_py' command."""
|
||||
|
||||
import glob
|
||||
import importlib.util
|
||||
import os
|
||||
import importlib.util
|
||||
import sys
|
||||
from distutils._log import log
|
||||
from typing import ClassVar
|
||||
import glob
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsFileError, DistutilsOptionError
|
||||
from ..util import convert_path
|
||||
from distutils.core import Command
|
||||
from distutils.errors import DistutilsOptionError, DistutilsFileError
|
||||
from distutils.util import convert_path
|
||||
from distutils import log
|
||||
|
||||
|
||||
class build_py(Command):
|
||||
|
||||
description = "\"build\" pure Python modules (copy to build directory)"
|
||||
|
||||
user_options = [
|
||||
@@ -30,8 +30,8 @@ class build_py(Command):
|
||||
('force', 'f', "forcibly build everything (ignore file timestamps)"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['compile', 'force']
|
||||
negative_opt: ClassVar[dict[str, str]] = {'no-compile': 'compile'}
|
||||
boolean_options = ['compile', 'force']
|
||||
negative_opt = {'no-compile': 'compile'}
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_lib = None
|
||||
@@ -39,11 +39,11 @@ class build_py(Command):
|
||||
self.package = None
|
||||
self.package_data = None
|
||||
self.package_dir = None
|
||||
self.compile = False
|
||||
self.compile = 0
|
||||
self.optimize = 0
|
||||
self.force = None
|
||||
|
||||
def finalize_options(self) -> None:
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options(
|
||||
'build', ('build_lib', 'build_lib'), ('force', 'force')
|
||||
)
|
||||
@@ -68,7 +68,7 @@ class build_py(Command):
|
||||
except (ValueError, AssertionError):
|
||||
raise DistutilsOptionError("optimize must be 0, 1, or 2")
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self):
|
||||
# XXX copy_file by default preserves atime and mtime. IMHO this is
|
||||
# the right thing to do, but perhaps it should be an option -- in
|
||||
# particular, a site administrator might want installed files to
|
||||
@@ -96,7 +96,7 @@ class build_py(Command):
|
||||
self.build_packages()
|
||||
self.build_package_data()
|
||||
|
||||
self.byte_compile(self.get_outputs(include_bytecode=False))
|
||||
self.byte_compile(self.get_outputs(include_bytecode=0))
|
||||
|
||||
def get_data_files(self):
|
||||
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
|
||||
@@ -130,14 +130,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) -> None:
|
||||
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))
|
||||
@@ -192,12 +192,12 @@ class build_py(Command):
|
||||
if package_dir != "":
|
||||
if not os.path.exists(package_dir):
|
||||
raise DistutilsFileError(
|
||||
f"package directory '{package_dir}' does not exist"
|
||||
"package directory '%s' does not exist" % package_dir
|
||||
)
|
||||
if not os.path.isdir(package_dir):
|
||||
raise DistutilsFileError(
|
||||
f"supposed package directory '{package_dir}' exists, "
|
||||
"but is not a directory"
|
||||
"supposed package directory '%s' exists, "
|
||||
"but is not a directory" % package_dir
|
||||
)
|
||||
|
||||
# Directories without __init__.py are namespace packages (PEP 420).
|
||||
@@ -212,7 +212,7 @@ class build_py(Command):
|
||||
|
||||
def check_module(self, module, module_file):
|
||||
if not os.path.isfile(module_file):
|
||||
log.warning("file %s (for module %s) not found", module_file, module)
|
||||
log.warn("file %s (for module %s) not found", module_file, module)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -229,7 +229,7 @@ class build_py(Command):
|
||||
module = os.path.splitext(os.path.basename(f))[0]
|
||||
modules.append((package, module, f))
|
||||
else:
|
||||
self.debug_print(f"excluding {setup_script}")
|
||||
self.debug_print("excluding %s" % setup_script)
|
||||
return modules
|
||||
|
||||
def find_modules(self):
|
||||
@@ -265,7 +265,7 @@ class build_py(Command):
|
||||
(package_dir, checked) = packages[package]
|
||||
except KeyError:
|
||||
package_dir = self.get_package_dir(package)
|
||||
checked = False
|
||||
checked = 0
|
||||
|
||||
if not checked:
|
||||
init_py = self.check_package(package, package_dir)
|
||||
@@ -307,10 +307,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: bool = True) -> list[str]:
|
||||
def get_outputs(self, include_bytecode=1):
|
||||
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)
|
||||
@@ -348,18 +348,18 @@ 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=False)
|
||||
return self.copy_file(module_file, outfile, preserve_mode=0)
|
||||
|
||||
def build_modules(self) -> None:
|
||||
def build_modules(self):
|
||||
modules = self.find_modules()
|
||||
for package, module, module_file in modules:
|
||||
for (package, module, module_file) in modules:
|
||||
# Now "build" the module -- ie. copy the source file to
|
||||
# self.build_lib (the build directory for Python source).
|
||||
# (Actually, it gets copied to the directory for this package
|
||||
# under self.build_lib.)
|
||||
self.build_module(module, module_file, package)
|
||||
|
||||
def build_packages(self) -> None:
|
||||
def build_packages(self):
|
||||
for package in self.packages:
|
||||
# Get list of (package, module, module_file) tuples based on
|
||||
# scanning the package directory. 'package' is only included
|
||||
@@ -375,16 +375,16 @@ class build_py(Command):
|
||||
|
||||
# Now loop over the modules we found, "building" each one (just
|
||||
# copy it to self.build_lib).
|
||||
for package_, module, module_file in modules:
|
||||
for (package_, module, module_file) in modules:
|
||||
assert package == package_
|
||||
self.build_module(module, module_file, package)
|
||||
|
||||
def byte_compile(self, files) -> None:
|
||||
def byte_compile(self, files):
|
||||
if sys.dont_write_bytecode:
|
||||
self.warn('byte-compiling is disabled, skipping.')
|
||||
return
|
||||
|
||||
from ..util import byte_compile
|
||||
from distutils.util import byte_compile
|
||||
|
||||
prefix = self.build_lib
|
||||
if prefix[-1] != os.sep:
|
||||
|
||||
+28
-15
@@ -4,14 +4,13 @@ Implements the Distutils 'build_scripts' command."""
|
||||
|
||||
import os
|
||||
import re
|
||||
import tokenize
|
||||
from distutils._log import log
|
||||
from stat import ST_MODE
|
||||
from typing import ClassVar
|
||||
|
||||
from .._modified import newer
|
||||
from ..core import Command
|
||||
from ..util import convert_path
|
||||
from distutils import sysconfig
|
||||
from distutils.core import Command
|
||||
from distutils.dep_util import newer
|
||||
from distutils.util import convert_path
|
||||
from distutils import log
|
||||
import tokenize
|
||||
|
||||
shebang_pattern = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
|
||||
"""
|
||||
@@ -23,15 +22,16 @@ first_line_re = shebang_pattern
|
||||
|
||||
|
||||
class build_scripts(Command):
|
||||
|
||||
description = "\"build\" scripts (copy and fixup #! line)"
|
||||
|
||||
user_options: ClassVar[list[tuple[str, str, str]]] = [
|
||||
user_options = [
|
||||
('build-dir=', 'd', "directory to \"build\" (copy) to"),
|
||||
('force', 'f', "forcibly build everything (ignore file timestamps"),
|
||||
('executable=', 'e', "specify final destination interpreter path"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['force']
|
||||
boolean_options = ['force']
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_dir = None
|
||||
@@ -75,7 +75,7 @@ class build_scripts(Command):
|
||||
|
||||
return outfiles, updated_files
|
||||
|
||||
def _copy_script(self, script, outfiles, updated_files):
|
||||
def _copy_script(self, script, outfiles, updated_files): # noqa: C901
|
||||
shebang_match = None
|
||||
script = convert_path(script)
|
||||
outfile = os.path.join(self.build_dir, os.path.basename(script))
|
||||
@@ -96,7 +96,7 @@ class build_scripts(Command):
|
||||
else:
|
||||
first_line = f.readline()
|
||||
if not first_line:
|
||||
self.warn(f"{script} is an empty file (skipping)")
|
||||
self.warn("%s is an empty file (skipping)" % script)
|
||||
return
|
||||
|
||||
shebang_match = shebang_pattern.match(first_line)
|
||||
@@ -105,8 +105,19 @@ class build_scripts(Command):
|
||||
if shebang_match:
|
||||
log.info("copying and adjusting %s -> %s", script, self.build_dir)
|
||||
if not self.dry_run:
|
||||
if not sysconfig.python_build:
|
||||
executable = self.executable
|
||||
else:
|
||||
executable = os.path.join(
|
||||
sysconfig.get_config_var("BINDIR"),
|
||||
"python%s%s"
|
||||
% (
|
||||
sysconfig.get_config_var("VERSION"),
|
||||
sysconfig.get_config_var("EXE"),
|
||||
),
|
||||
)
|
||||
post_interp = shebang_match.group(1) or ''
|
||||
shebang = f"#!python{post_interp}\n"
|
||||
shebang = "#!" + executable + post_interp + "\n"
|
||||
self._validate_shebang(shebang, f.encoding)
|
||||
with open(outfile, "w", encoding=f.encoding) as outf:
|
||||
outf.write(shebang)
|
||||
@@ -146,7 +157,9 @@ class build_scripts(Command):
|
||||
try:
|
||||
shebang.encode('utf-8')
|
||||
except UnicodeEncodeError:
|
||||
raise ValueError(f"The shebang ({shebang!r}) is not encodable to utf-8")
|
||||
raise ValueError(
|
||||
"The shebang ({!r}) is not encodable " "to utf-8".format(shebang)
|
||||
)
|
||||
|
||||
# If the script is encoded to a custom encoding (use a
|
||||
# #coding:xxx cookie), the shebang has to be encodable to
|
||||
@@ -155,6 +168,6 @@ class build_scripts(Command):
|
||||
shebang.encode(encoding)
|
||||
except UnicodeEncodeError:
|
||||
raise ValueError(
|
||||
f"The shebang ({shebang!r}) is not encodable "
|
||||
f"to the script encoding ({encoding})"
|
||||
"The shebang ({!r}) is not encodable "
|
||||
"to the script encoding ({})".format(shebang, encoding)
|
||||
)
|
||||
|
||||
@@ -2,18 +2,16 @@
|
||||
|
||||
Implements the Distutils 'check' command.
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
from typing import ClassVar
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsSetupError
|
||||
from distutils.core import Command
|
||||
from distutils.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__(
|
||||
@@ -22,7 +20,7 @@ with contextlib.suppress(ImportError):
|
||||
report_level,
|
||||
halt_level,
|
||||
stream=None,
|
||||
debug=False,
|
||||
debug=0,
|
||||
encoding='ascii',
|
||||
error_handler='replace',
|
||||
):
|
||||
@@ -34,7 +32,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, *children, level=level, type=self.levels[level], **kwargs
|
||||
message, level=level, type=self.levels[level], *children, **kwargs
|
||||
)
|
||||
|
||||
|
||||
@@ -42,23 +40,26 @@ class check(Command):
|
||||
"""This command checks the meta-data of the package."""
|
||||
|
||||
description = "perform some checks on the package"
|
||||
user_options: ClassVar[list[tuple[str, str, str]]] = [
|
||||
user_options = [
|
||||
('metadata', 'm', 'Verify meta-data'),
|
||||
(
|
||||
'restructuredtext',
|
||||
'r',
|
||||
'Checks if long string meta-data syntax are reStructuredText-compliant',
|
||||
(
|
||||
'Checks if long string meta-data syntax '
|
||||
'are reStructuredText-compliant'
|
||||
),
|
||||
),
|
||||
('strict', 's', 'Will exit with an error if a check fails'),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['metadata', 'restructuredtext', 'strict']
|
||||
boolean_options = ['metadata', 'restructuredtext', 'strict']
|
||||
|
||||
def initialize_options(self):
|
||||
"""Sets default values for options."""
|
||||
self.restructuredtext = False
|
||||
self.restructuredtext = 0
|
||||
self.metadata = 1
|
||||
self.strict = False
|
||||
self.strict = 0
|
||||
self._warnings = 0
|
||||
|
||||
def finalize_options(self):
|
||||
@@ -98,12 +99,13 @@ class check(Command):
|
||||
"""
|
||||
metadata = self.distribution.metadata
|
||||
|
||||
missing = [
|
||||
attr for attr in ('name', 'version') if not getattr(metadata, attr, None)
|
||||
]
|
||||
missing = []
|
||||
for attr in 'name', 'version':
|
||||
if not getattr(metadata, attr, None):
|
||||
missing.append(attr)
|
||||
|
||||
if missing:
|
||||
self.warn("missing required meta-data: {}".format(', '.join(missing)))
|
||||
self.warn("missing required meta-data: %s" % ', '.join(missing))
|
||||
|
||||
def check_restructuredtext(self):
|
||||
"""Checks if the long string fields are reST-compliant."""
|
||||
@@ -113,7 +115,7 @@ class check(Command):
|
||||
if line is None:
|
||||
warning = warning[1]
|
||||
else:
|
||||
warning = f'{warning[1]} (line {line})'
|
||||
warning = '{} (line {})'.format(warning[1], line)
|
||||
self.warn(warning)
|
||||
|
||||
def _check_rst_data(self, data):
|
||||
@@ -141,12 +143,9 @@ class check(Command):
|
||||
document.note_source(source_path, -1)
|
||||
try:
|
||||
parser.parse(data, document)
|
||||
except (AttributeError, TypeError) as e:
|
||||
reporter.messages.append((
|
||||
-1,
|
||||
f'Could not finish the parsing: {e}.',
|
||||
'',
|
||||
{},
|
||||
))
|
||||
except AttributeError as e:
|
||||
reporter.messages.append(
|
||||
(-1, 'Could not finish the parsing: %s.' % e, '', {})
|
||||
)
|
||||
|
||||
return reporter.messages
|
||||
|
||||
@@ -5,33 +5,32 @@ 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 typing import ClassVar
|
||||
|
||||
from ..core import Command
|
||||
from ..dir_util import remove_tree
|
||||
from distutils.core import Command
|
||||
from distutils.dir_util import remove_tree
|
||||
from distutils 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"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['all']
|
||||
boolean_options = ['all']
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_base = None
|
||||
@@ -65,7 +64,7 @@ class clean(Command):
|
||||
if os.path.exists(directory):
|
||||
remove_tree(directory, dry_run=self.dry_run)
|
||||
else:
|
||||
log.warning("'%s' does not exist -- can't clean it", directory)
|
||||
log.warn("'%s' does not exist -- can't clean it", directory)
|
||||
|
||||
# just for the heck of it, try to remove the base build directory:
|
||||
# we might have emptied it right now, but if not we don't care
|
||||
|
||||
@@ -9,23 +9,19 @@ 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 ..ccompiler import CCompiler, CompileError, LinkError, new_compiler
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsExecError
|
||||
from ..sysconfig import customize_compiler
|
||||
from distutils.core import Command
|
||||
from distutils.errors import DistutilsExecError
|
||||
from distutils.sysconfig import customize_compiler
|
||||
from distutils import log
|
||||
|
||||
LANG_EXT = {"c": ".c", "c++": ".cxx"}
|
||||
|
||||
|
||||
class config(Command):
|
||||
|
||||
description = "prepare to build"
|
||||
|
||||
user_options = [
|
||||
@@ -89,9 +85,13 @@ class config(Command):
|
||||
"""Check that 'self.compiler' really is a CCompiler object;
|
||||
if not, make it one.
|
||||
"""
|
||||
# We do this late, and only on-demand, because this is an expensive
|
||||
# import.
|
||||
from distutils.ccompiler import CCompiler, new_compiler
|
||||
|
||||
if not isinstance(self.compiler, CCompiler):
|
||||
self.compiler = new_compiler(
|
||||
compiler=self.compiler, dry_run=self.dry_run, force=True
|
||||
compiler=self.compiler, dry_run=self.dry_run, force=1
|
||||
)
|
||||
customize_compiler(self.compiler)
|
||||
if self.include_dirs:
|
||||
@@ -103,10 +103,10 @@ class config(Command):
|
||||
|
||||
def _gen_temp_sourcefile(self, body, headers, lang):
|
||||
filename = "_configtest" + LANG_EXT[lang]
|
||||
with open(filename, "w", encoding='utf-8') as file:
|
||||
with open(filename, "w") as file:
|
||||
if headers:
|
||||
for header in headers:
|
||||
file.write(f"#include <{header}>\n")
|
||||
file.write("#include <%s>\n" % header)
|
||||
file.write("\n")
|
||||
file.write(body)
|
||||
if body[-1] != "\n":
|
||||
@@ -123,7 +123,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, f"compiling '{src}':")
|
||||
dump_file(src, "compiling '%s':" % src)
|
||||
(obj,) = self.compiler.object_filenames([src])
|
||||
self.temp_files.extend([src, obj])
|
||||
self.compiler.compile([src], include_dirs=include_dirs)
|
||||
@@ -174,6 +174,8 @@ class config(Command):
|
||||
preprocessor succeeded, false if there were any errors.
|
||||
('body' probably isn't of much use, but what the heck.)
|
||||
"""
|
||||
from distutils.ccompiler import CompileError
|
||||
|
||||
self._check_compiler()
|
||||
ok = True
|
||||
try:
|
||||
@@ -198,8 +200,15 @@ class config(Command):
|
||||
if isinstance(pattern, str):
|
||||
pattern = re.compile(pattern)
|
||||
|
||||
with open(out, encoding='utf-8') as file:
|
||||
match = any(pattern.search(line) for line in file)
|
||||
with open(out) as file:
|
||||
match = False
|
||||
while True:
|
||||
line = file.readline()
|
||||
if line == '':
|
||||
break
|
||||
if pattern.search(line):
|
||||
match = True
|
||||
break
|
||||
|
||||
self._clean()
|
||||
return match
|
||||
@@ -208,6 +217,8 @@ class config(Command):
|
||||
"""Try to compile a source file built from 'body' and 'headers'.
|
||||
Return true on success, false otherwise.
|
||||
"""
|
||||
from distutils.ccompiler import CompileError
|
||||
|
||||
self._check_compiler()
|
||||
try:
|
||||
self._compile(body, headers, include_dirs, lang)
|
||||
@@ -232,6 +243,8 @@ class config(Command):
|
||||
'headers', to executable form. Return true on success, false
|
||||
otherwise.
|
||||
"""
|
||||
from distutils.ccompiler import CompileError, LinkError
|
||||
|
||||
self._check_compiler()
|
||||
try:
|
||||
self._link(body, headers, include_dirs, libraries, library_dirs, lang)
|
||||
@@ -256,6 +269,8 @@ class config(Command):
|
||||
built from 'body' and 'headers'. Return true on success, false
|
||||
otherwise.
|
||||
"""
|
||||
from distutils.ccompiler import CompileError, LinkError
|
||||
|
||||
self._check_compiler()
|
||||
try:
|
||||
src, obj, exe = self._link(
|
||||
@@ -281,8 +296,8 @@ class config(Command):
|
||||
include_dirs=None,
|
||||
libraries=None,
|
||||
library_dirs=None,
|
||||
decl=False,
|
||||
call=False,
|
||||
decl=0,
|
||||
call=0,
|
||||
):
|
||||
"""Determine if function 'func' is available by constructing a
|
||||
source file that refers to 'func', and compiles and links it.
|
||||
@@ -300,12 +315,12 @@ class config(Command):
|
||||
self._check_compiler()
|
||||
body = []
|
||||
if decl:
|
||||
body.append(f"int {func} ();")
|
||||
body.append("int %s ();" % func)
|
||||
body.append("int main () {")
|
||||
if call:
|
||||
body.append(f" {func}();")
|
||||
body.append(" %s();" % func)
|
||||
else:
|
||||
body.append(f" {func};")
|
||||
body.append(" %s;" % func)
|
||||
body.append("}")
|
||||
body = "\n".join(body) + "\n"
|
||||
|
||||
@@ -317,7 +332,7 @@ class config(Command):
|
||||
library_dirs=None,
|
||||
headers=None,
|
||||
include_dirs=None,
|
||||
other_libraries: Sequence[str] = [],
|
||||
other_libraries=[],
|
||||
):
|
||||
"""Determine if 'library' is available to be linked against,
|
||||
without actually checking that any particular symbols are provided
|
||||
@@ -332,7 +347,7 @@ class config(Command):
|
||||
"int main (void) { }",
|
||||
headers,
|
||||
include_dirs,
|
||||
[library] + list(other_libraries),
|
||||
[library] + other_libraries,
|
||||
library_dirs,
|
||||
)
|
||||
|
||||
@@ -355,4 +370,8 @@ def dump_file(filename, head=None):
|
||||
log.info('%s', filename)
|
||||
else:
|
||||
log.info(head)
|
||||
log.info(pathlib.Path(filename).read_text(encoding='utf-8'))
|
||||
file = open(filename)
|
||||
try:
|
||||
log.info(file.read())
|
||||
finally:
|
||||
file.close()
|
||||
|
||||
+83
-74
@@ -2,25 +2,25 @@
|
||||
|
||||
Implements the Distutils 'install' command."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import collections
|
||||
import contextlib
|
||||
import itertools
|
||||
import os
|
||||
import sys
|
||||
import os
|
||||
import contextlib
|
||||
import sysconfig
|
||||
from distutils._log import log
|
||||
from site import USER_BASE, USER_SITE
|
||||
from typing import ClassVar
|
||||
import itertools
|
||||
|
||||
from ..core import Command
|
||||
from ..debug import DEBUG
|
||||
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 distutils import log
|
||||
from distutils.core import Command
|
||||
from distutils.debug import DEBUG
|
||||
from distutils.sysconfig import get_config_vars
|
||||
from distutils.file_util import write_file
|
||||
from distutils.util import convert_path, subst_vars, change_root
|
||||
from distutils.util import get_platform
|
||||
from distutils.errors import DistutilsOptionError, DistutilsPlatformError
|
||||
from . import _framework_compat as fw
|
||||
from .. import _collections
|
||||
|
||||
from site import USER_BASE
|
||||
from site import USER_SITE
|
||||
|
||||
HAS_USER_SITE = True
|
||||
|
||||
@@ -144,7 +144,7 @@ def _resolve_scheme(name):
|
||||
try:
|
||||
resolved = sysconfig.get_preferred_scheme(key)
|
||||
except Exception:
|
||||
resolved = fw.scheme(name)
|
||||
resolved = fw.scheme(_pypy_hack(name))
|
||||
return resolved
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ def _inject_headers(name, scheme):
|
||||
"""
|
||||
# Bypass the preferred scheme, which may not
|
||||
# have defined headers.
|
||||
fallback = _load_scheme(name)
|
||||
fallback = _load_scheme(_pypy_hack(name))
|
||||
scheme.setdefault('headers', fallback['headers'])
|
||||
return scheme
|
||||
|
||||
@@ -171,7 +171,16 @@ def _scheme_attrs(scheme):
|
||||
return {f'install_{key}': scheme[key] for key in SCHEME_KEYS}
|
||||
|
||||
|
||||
def _pypy_hack(name):
|
||||
PY37 = sys.version_info < (3, 8)
|
||||
old_pypy = hasattr(sys, 'pypy_version_info') and PY37
|
||||
prefix = not name.endswith(('_user', '_home'))
|
||||
pypy_name = 'pypy' + '_nt' * (os.name == 'nt')
|
||||
return pypy_name if old_pypy and prefix else name
|
||||
|
||||
|
||||
class install(Command):
|
||||
|
||||
description = "install everything from build directory"
|
||||
|
||||
user_options = [
|
||||
@@ -188,7 +197,8 @@ 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
|
||||
@@ -205,7 +215,8 @@ 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"),
|
||||
@@ -232,33 +243,31 @@ class install(Command):
|
||||
('record=', None, "filename in which to record list of installed files"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['compile', 'force', 'skip-build']
|
||||
boolean_options = ['compile', 'force', 'skip-build']
|
||||
|
||||
if HAS_USER_SITE:
|
||||
user_options.append((
|
||||
'user',
|
||||
None,
|
||||
f"install in user site-package '{USER_SITE}'",
|
||||
))
|
||||
user_options.append(
|
||||
('user', None, "install in user site-package '%s'" % USER_SITE)
|
||||
)
|
||||
boolean_options.append('user')
|
||||
|
||||
negative_opt: ClassVar[dict[str, str]] = {'no-compile': 'compile'}
|
||||
negative_opt = {'no-compile': 'compile'}
|
||||
|
||||
def initialize_options(self) -> None:
|
||||
def initialize_options(self):
|
||||
"""Initializes options."""
|
||||
# High-level options: these select both an installation base
|
||||
# and scheme.
|
||||
self.prefix: str | None = None
|
||||
self.exec_prefix: str | None = None
|
||||
self.home: str | None = None
|
||||
self.user = False
|
||||
self.prefix = None
|
||||
self.exec_prefix = None
|
||||
self.home = None
|
||||
self.user = 0
|
||||
|
||||
# These select only the installation base; it's up to the user to
|
||||
# specify the installation scheme (currently, that means supplying
|
||||
# the --install-{platlib,purelib,scripts,data} options).
|
||||
self.install_base = None
|
||||
self.install_platbase = None
|
||||
self.root: str | None = None
|
||||
self.root = None
|
||||
|
||||
# These options are the actual installation directories; if not
|
||||
# supplied by the user, they are filled in using the installation
|
||||
@@ -267,7 +276,7 @@ class install(Command):
|
||||
self.install_purelib = None # for pure module distributions
|
||||
self.install_platlib = None # non-pure (dists w/ extensions)
|
||||
self.install_headers = None # for C/C++ headers
|
||||
self.install_lib: str | None = None # set to either purelib or platlib
|
||||
self.install_lib = None # set to either purelib or platlib
|
||||
self.install_scripts = None
|
||||
self.install_data = None
|
||||
self.install_userbase = USER_BASE
|
||||
@@ -286,7 +295,7 @@ class install(Command):
|
||||
# 'install_path_file' is always true unless some outsider meddles
|
||||
# with it.
|
||||
self.extra_path = None
|
||||
self.install_path_file = True
|
||||
self.install_path_file = 1
|
||||
|
||||
# 'force' forces installation, even if target files are not
|
||||
# out-of-date. 'skip_build' skips running the "build" command,
|
||||
@@ -294,9 +303,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 = False
|
||||
self.skip_build = False
|
||||
self.warn_dir = True
|
||||
self.force = 0
|
||||
self.skip_build = 0
|
||||
self.warn_dir = 1
|
||||
|
||||
# These are only here as a conduit from the 'build' command to the
|
||||
# 'install_*' commands that do the real work. ('build_base' isn't
|
||||
@@ -321,7 +330,7 @@ class install(Command):
|
||||
# party Python modules on various platforms given a wide
|
||||
# array of user input is decided. Yes, it's quite complex!)
|
||||
|
||||
def finalize_options(self) -> None: # noqa: C901
|
||||
def finalize_options(self): # noqa: C901
|
||||
"""Finalizes options."""
|
||||
# This method (and its helpers, like 'finalize_unix()',
|
||||
# 'finalize_other()', and 'select_scheme()') is where the default
|
||||
@@ -341,7 +350,8 @@ 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):
|
||||
@@ -401,8 +411,8 @@ class install(Command):
|
||||
'dist_version': self.distribution.get_version(),
|
||||
'dist_fullname': self.distribution.get_fullname(),
|
||||
'py_version': py_version,
|
||||
'py_version_short': f'{sys.version_info.major}.{sys.version_info.minor}',
|
||||
'py_version_nodot': f'{sys.version_info.major}{sys.version_info.minor}',
|
||||
'py_version_short': '%d.%d' % sys.version_info[:2],
|
||||
'py_version_nodot': '%d%d' % sys.version_info[:2],
|
||||
'sys_prefix': prefix,
|
||||
'prefix': prefix,
|
||||
'sys_exec_prefix': exec_prefix,
|
||||
@@ -423,11 +433,8 @@ class install(Command):
|
||||
local_vars['userbase'] = self.install_userbase
|
||||
local_vars['usersite'] = self.install_usersite
|
||||
|
||||
self.config_vars = collections.ChainMap(
|
||||
local_vars,
|
||||
sysconfig.get_config_vars(),
|
||||
compat_vars,
|
||||
fw.vars(),
|
||||
self.config_vars = _collections.DictStack(
|
||||
[fw.vars(), compat_vars, sysconfig.get_config_vars(), local_vars]
|
||||
)
|
||||
|
||||
self.expand_basedirs()
|
||||
@@ -504,11 +511,11 @@ class install(Command):
|
||||
# Punt on doc directories for now -- after all, we're punting on
|
||||
# documentation completely!
|
||||
|
||||
def dump_dirs(self, msg) -> None:
|
||||
def dump_dirs(self, msg):
|
||||
"""Dumps the list of user options."""
|
||||
if not DEBUG:
|
||||
return
|
||||
from ..fancy_getopt import longopt_xlate
|
||||
from distutils.fancy_getopt import longopt_xlate
|
||||
|
||||
log.debug(msg + ":")
|
||||
for opt in self.user_options:
|
||||
@@ -524,7 +531,7 @@ class install(Command):
|
||||
val = getattr(self, opt_name)
|
||||
log.debug(" %s: %s", opt_name, val)
|
||||
|
||||
def finalize_unix(self) -> None:
|
||||
def finalize_unix(self):
|
||||
"""Finalizes options for posix platforms."""
|
||||
if self.install_base is not None or self.install_platbase is not None:
|
||||
incomplete_scheme = (
|
||||
@@ -573,7 +580,7 @@ class install(Command):
|
||||
self.install_platbase = self.exec_prefix
|
||||
self.select_scheme("posix_prefix")
|
||||
|
||||
def finalize_other(self) -> None:
|
||||
def finalize_other(self):
|
||||
"""Finalizes options for non-posix platforms"""
|
||||
if self.user:
|
||||
if self.install_userbase is None:
|
||||
@@ -592,50 +599,52 @@ class install(Command):
|
||||
self.select_scheme(os.name)
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
f"I don't know how to install stuff on '{os.name}'"
|
||||
"I don't know how to install stuff on '%s'" % os.name
|
||||
)
|
||||
|
||||
def select_scheme(self, name) -> None:
|
||||
def select_scheme(self, name):
|
||||
_select_scheme(self, name)
|
||||
|
||||
def _expand_attrs(self, attrs):
|
||||
for attr in attrs:
|
||||
val = getattr(self, attr)
|
||||
if val is not None:
|
||||
if os.name in ('posix', 'nt'):
|
||||
if os.name == 'posix' or os.name == 'nt':
|
||||
val = os.path.expanduser(val)
|
||||
val = subst_vars(val, self.config_vars)
|
||||
setattr(self, attr, val)
|
||||
|
||||
def expand_basedirs(self) -> None:
|
||||
def expand_basedirs(self):
|
||||
"""Calls `os.path.expanduser` on install_base, install_platbase and
|
||||
root."""
|
||||
self._expand_attrs(['install_base', 'install_platbase', 'root'])
|
||||
|
||||
def expand_dirs(self) -> None:
|
||||
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) -> None:
|
||||
def convert_paths(self, *names):
|
||||
"""Call `convert_path` over `names`."""
|
||||
for name in names:
|
||||
attr = "install_" + name
|
||||
setattr(self, attr, convert_path(getattr(self, attr)))
|
||||
|
||||
def handle_extra_path(self) -> None:
|
||||
def handle_extra_path(self):
|
||||
"""Set `path_file` and `extra_dirs` using `extra_path`."""
|
||||
if self.extra_path is None:
|
||||
self.extra_path = self.distribution.extra_path
|
||||
|
||||
if self.extra_path is not None:
|
||||
log.warning(
|
||||
log.warn(
|
||||
"Distribution option extra_path is deprecated. "
|
||||
"See issue27919 for details."
|
||||
)
|
||||
@@ -664,20 +673,20 @@ class install(Command):
|
||||
self.path_file = path_file
|
||||
self.extra_dirs = extra_dirs
|
||||
|
||||
def change_roots(self, *names) -> None:
|
||||
def change_roots(self, *names):
|
||||
"""Change the install directories pointed by name using root."""
|
||||
for name in names:
|
||||
attr = "install_" + name
|
||||
setattr(self, attr, change_root(self.root, getattr(self, attr)))
|
||||
|
||||
def create_home_path(self) -> None:
|
||||
def create_home_path(self):
|
||||
"""Create directories under ~."""
|
||||
if not self.user:
|
||||
return
|
||||
home = convert_path(os.path.expanduser("~"))
|
||||
for path in self.config_vars.values():
|
||||
for name, path in self.config_vars.items():
|
||||
if str(path).startswith(home) and not os.path.isdir(path):
|
||||
self.debug_print(f"os.makedirs('{path}', 0o700)")
|
||||
self.debug_print("os.makedirs('%s', 0o700)" % path)
|
||||
os.makedirs(path, 0o700)
|
||||
|
||||
# -- Command execution methods -------------------------------------
|
||||
@@ -693,7 +702,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():
|
||||
@@ -712,7 +721,7 @@ class install(Command):
|
||||
self.execute(
|
||||
write_file,
|
||||
(self.record, outputs),
|
||||
f"writing list of installed files to '{self.record}'",
|
||||
"writing list of installed files to '%s'" % self.record,
|
||||
)
|
||||
|
||||
sys_path = map(os.path.normpath, sys.path)
|
||||
@@ -737,10 +746,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]), f"creating {filename}"
|
||||
write_file, (filename, [self.extra_dirs]), "creating %s" % filename
|
||||
)
|
||||
else:
|
||||
self.warn(f"path file '{filename}' not created")
|
||||
self.warn("path file '%s' not created" % filename)
|
||||
|
||||
# -- Reporting methods ---------------------------------------------
|
||||
|
||||
|
||||
+38
-48
@@ -5,41 +5,37 @@ platform-independent data files."""
|
||||
|
||||
# contributed by Bastian Kleineidam
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
import os
|
||||
from collections.abc import Iterable
|
||||
from typing import ClassVar
|
||||
|
||||
from ..core import Command
|
||||
from ..util import change_root, convert_path
|
||||
from distutils.core import Command
|
||||
from distutils.util import change_root, convert_path
|
||||
|
||||
|
||||
class install_data(Command):
|
||||
|
||||
description = "install data files"
|
||||
|
||||
user_options = [
|
||||
(
|
||||
'install-dir=',
|
||||
'd',
|
||||
"base directory for installing data files [default: installation base dir]",
|
||||
"base directory for installing data files "
|
||||
"(default: installation base dir)",
|
||||
),
|
||||
('root=', None, "install everything relative to this alternate root directory"),
|
||||
('force', 'f', "force installation (overwrite existing files)"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['force']
|
||||
boolean_options = ['force']
|
||||
|
||||
def initialize_options(self):
|
||||
self.install_dir = None
|
||||
self.outfiles = []
|
||||
self.root = None
|
||||
self.force = False
|
||||
self.force = 0
|
||||
self.data_files = self.distribution.data_files
|
||||
self.warn_dir = True
|
||||
self.warn_dir = 1
|
||||
|
||||
def finalize_options(self) -> None:
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options(
|
||||
'install',
|
||||
('install_data', 'install_dir'),
|
||||
@@ -47,45 +43,39 @@ class install_data(Command):
|
||||
('force', 'force'),
|
||||
)
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self):
|
||||
self.mkpath(self.install_dir)
|
||||
for f in self.data_files:
|
||||
self._copy(f)
|
||||
|
||||
@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)
|
||||
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)
|
||||
|
||||
@_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)
|
||||
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)
|
||||
|
||||
def get_inputs(self):
|
||||
return self.data_files or []
|
||||
|
||||
+9
-9
@@ -6,20 +6,18 @@ a package's PKG-INFO metadata.
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from typing import ClassVar
|
||||
import re
|
||||
|
||||
from .. import dir_util
|
||||
from .._log import log
|
||||
from ..cmd import Command
|
||||
from distutils.cmd import Command
|
||||
from distutils import log, dir_util
|
||||
|
||||
|
||||
class install_egg_info(Command):
|
||||
"""Install an .egg-info file for the package"""
|
||||
|
||||
description = "Install package's PKG-INFO metadata as an .egg-info file"
|
||||
user_options: ClassVar[list[tuple[str, str, str]]] = [
|
||||
user_options = [
|
||||
('install-dir=', 'd', "directory to install to"),
|
||||
]
|
||||
|
||||
@@ -32,9 +30,11 @@ class install_egg_info(Command):
|
||||
Allow basename to be overridden by child class.
|
||||
Ref pypa/distutils#2.
|
||||
"""
|
||||
name = to_filename(safe_name(self.distribution.get_name()))
|
||||
version = to_filename(safe_version(self.distribution.get_version()))
|
||||
return f"{name}-{version}-py{sys.version_info.major}.{sys.version_info.minor}.egg-info"
|
||||
return "%s-%s-py%d.%d.egg-info" % (
|
||||
to_filename(safe_name(self.distribution.get_name())),
|
||||
to_filename(safe_version(self.distribution.get_version())),
|
||||
*sys.version_info[:2],
|
||||
)
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('install_lib', ('install_dir', 'install_dir'))
|
||||
|
||||
+5
-6
@@ -3,25 +3,24 @@
|
||||
Implements the Distutils 'install_headers' command, to install C/C++ header
|
||||
files to the Python include directory."""
|
||||
|
||||
from typing import ClassVar
|
||||
|
||||
from ..core import Command
|
||||
from distutils.core import Command
|
||||
|
||||
|
||||
# XXX force is never used
|
||||
class install_headers(Command):
|
||||
|
||||
description = "install C/C++ header files"
|
||||
|
||||
user_options: ClassVar[list[tuple[str, str, str]]] = [
|
||||
user_options = [
|
||||
('install-dir=', 'd', "directory to install header files to"),
|
||||
('force', 'f', "force installation (overwrite existing files)"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['force']
|
||||
boolean_options = ['force']
|
||||
|
||||
def initialize_options(self):
|
||||
self.install_dir = None
|
||||
self.force = False
|
||||
self.force = 0
|
||||
self.outfiles = []
|
||||
|
||||
def finalize_options(self):
|
||||
|
||||
+21
-21
@@ -3,21 +3,20 @@
|
||||
Implements the Distutils 'install_lib' command
|
||||
(install all Python modules)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import os
|
||||
import importlib.util
|
||||
import sys
|
||||
from typing import Any, ClassVar
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsOptionError
|
||||
from distutils.core import Command
|
||||
from distutils.errors import DistutilsOptionError
|
||||
|
||||
|
||||
# Extension for Python source files.
|
||||
PYTHON_SOURCE_EXTENSION = ".py"
|
||||
|
||||
|
||||
class install_lib(Command):
|
||||
|
||||
description = "install all Python modules (extensions and pure Python)"
|
||||
|
||||
# The byte-compilation options are a tad confusing. Here are the
|
||||
@@ -50,19 +49,19 @@ class install_lib(Command):
|
||||
('skip-build', None, "skip the build steps"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['force', 'compile', 'skip-build']
|
||||
negative_opt: ClassVar[dict[str, str]] = {'no-compile': 'compile'}
|
||||
boolean_options = ['force', 'compile', 'skip-build']
|
||||
negative_opt = {'no-compile': 'compile'}
|
||||
|
||||
def initialize_options(self):
|
||||
# let the 'install' command dictate our installation directory
|
||||
self.install_dir = None
|
||||
self.build_dir = None
|
||||
self.force = False
|
||||
self.force = 0
|
||||
self.compile = None
|
||||
self.optimize = None
|
||||
self.skip_build = None
|
||||
|
||||
def finalize_options(self) -> None:
|
||||
def finalize_options(self):
|
||||
# Get all the information we need to install pure Python modules
|
||||
# from the umbrella 'install' command -- build (source) directory,
|
||||
# install (target) directory, and whether to compile .py files.
|
||||
@@ -84,12 +83,12 @@ class install_lib(Command):
|
||||
if not isinstance(self.optimize, int):
|
||||
try:
|
||||
self.optimize = int(self.optimize)
|
||||
except ValueError:
|
||||
pass
|
||||
if self.optimize not in (0, 1, 2):
|
||||
if self.optimize not in (0, 1, 2):
|
||||
raise AssertionError
|
||||
except (ValueError, AssertionError):
|
||||
raise DistutilsOptionError("optimize must be 0, 1, or 2")
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self):
|
||||
# Make sure we have built everything we need first
|
||||
self.build()
|
||||
|
||||
@@ -105,30 +104,29 @@ class install_lib(Command):
|
||||
# -- Top-level worker functions ------------------------------------
|
||||
# (called from 'run()')
|
||||
|
||||
def build(self) -> None:
|
||||
def build(self):
|
||||
if not self.skip_build:
|
||||
if self.distribution.has_pure_modules():
|
||||
self.run_command('build_py')
|
||||
if self.distribution.has_ext_modules():
|
||||
self.run_command('build_ext')
|
||||
|
||||
# Any: https://typing.readthedocs.io/en/latest/guides/writing_stubs.html#the-any-trick
|
||||
def install(self) -> list[str] | Any:
|
||||
def install(self):
|
||||
if os.path.isdir(self.build_dir):
|
||||
outfiles = self.copy_tree(self.build_dir, self.install_dir)
|
||||
else:
|
||||
self.warn(
|
||||
f"'{self.build_dir}' does not exist -- no Python modules to install"
|
||||
"'%s' does not exist -- no Python modules to install" % self.build_dir
|
||||
)
|
||||
return
|
||||
return outfiles
|
||||
|
||||
def byte_compile(self, files) -> None:
|
||||
def byte_compile(self, files):
|
||||
if sys.dont_write_bytecode:
|
||||
self.warn('byte-compiling is disabled, skipping.')
|
||||
return
|
||||
|
||||
from ..util import byte_compile
|
||||
from distutils.util import byte_compile
|
||||
|
||||
# Get the "--root" directory supplied to the "install" command,
|
||||
# and use it as a prefix to strip off the purported filename
|
||||
@@ -165,7 +163,9 @@ class install_lib(Command):
|
||||
build_dir = getattr(build_cmd, cmd_option)
|
||||
|
||||
prefix_len = len(build_dir) + len(os.sep)
|
||||
outputs = [os.path.join(output_dir, file[prefix_len:]) for file in build_files]
|
||||
outputs = []
|
||||
for file in build_files:
|
||||
outputs.append(os.path.join(output_dir, file[prefix_len:]))
|
||||
|
||||
return outputs
|
||||
|
||||
|
||||
+7
-8
@@ -6,14 +6,13 @@ Python scripts."""
|
||||
# contributed by Bastian Kleineidam
|
||||
|
||||
import os
|
||||
from distutils._log import log
|
||||
from distutils.core import Command
|
||||
from distutils import log
|
||||
from stat import ST_MODE
|
||||
from typing import ClassVar
|
||||
|
||||
from ..core import Command
|
||||
|
||||
|
||||
class install_scripts(Command):
|
||||
|
||||
description = "install scripts (Python or otherwise)"
|
||||
|
||||
user_options = [
|
||||
@@ -23,15 +22,15 @@ class install_scripts(Command):
|
||||
('skip-build', None, "skip the build steps"),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = ['force', 'skip-build']
|
||||
boolean_options = ['force', 'skip-build']
|
||||
|
||||
def initialize_options(self):
|
||||
self.install_dir = None
|
||||
self.force = False
|
||||
self.force = 0
|
||||
self.build_dir = None
|
||||
self.skip_build = None
|
||||
|
||||
def finalize_options(self) -> None:
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('build', ('build_scripts', 'build_dir'))
|
||||
self.set_undefined_options(
|
||||
'install',
|
||||
@@ -40,7 +39,7 @@ class install_scripts(Command):
|
||||
('skip_build', 'skip_build'),
|
||||
)
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self):
|
||||
if not self.skip_build:
|
||||
self.run_command('build_scripts')
|
||||
self.outfiles = self.copy_tree(self.build_dir, self.install_dir)
|
||||
|
||||
@@ -2,42 +2,41 @@
|
||||
|
||||
Implements the Distutils 'sdist' command (create a source distribution)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
from distutils import archive_util, dir_util, file_util
|
||||
from distutils._log import log
|
||||
from glob import glob
|
||||
from itertools import filterfalse
|
||||
from typing import ClassVar
|
||||
from warnings import warn
|
||||
|
||||
from ..core import Command
|
||||
from ..errors import DistutilsOptionError, DistutilsTemplateError
|
||||
from ..filelist import FileList
|
||||
from ..text_file import TextFile
|
||||
from ..util import convert_path
|
||||
from distutils.core import Command
|
||||
from distutils import dir_util
|
||||
from distutils import file_util
|
||||
from distutils import archive_util
|
||||
from distutils.text_file import TextFile
|
||||
from distutils.filelist import FileList
|
||||
from distutils import log
|
||||
from distutils.util import convert_path
|
||||
from distutils.errors import DistutilsOptionError, DistutilsTemplateError
|
||||
|
||||
|
||||
def show_formats():
|
||||
"""Print all possible values for the 'formats' option (used by
|
||||
the "--help-formats" command-line option).
|
||||
"""
|
||||
from ..archive_util import ARCHIVE_FORMATS
|
||||
from ..fancy_getopt import FancyGetopt
|
||||
from distutils.fancy_getopt import FancyGetopt
|
||||
from distutils.archive_util import ARCHIVE_FORMATS
|
||||
|
||||
formats = sorted(
|
||||
("formats=" + format, None, ARCHIVE_FORMATS[format][2])
|
||||
for format in ARCHIVE_FORMATS.keys()
|
||||
)
|
||||
formats = []
|
||||
for format in ARCHIVE_FORMATS.keys():
|
||||
formats.append(("formats=" + format, None, ARCHIVE_FORMATS[format][2]))
|
||||
formats.sort()
|
||||
FancyGetopt(formats).print_help("List of available source distribution formats:")
|
||||
|
||||
|
||||
class sdist(Command):
|
||||
|
||||
description = "create a source distribution (tarball, zip file, etc.)"
|
||||
|
||||
def checking_metadata(self) -> bool:
|
||||
def checking_metadata(self):
|
||||
"""Callable used for the check sub-command.
|
||||
|
||||
Placed here so user_options can view it"""
|
||||
@@ -64,7 +63,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',
|
||||
@@ -81,7 +80,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',
|
||||
@@ -101,7 +100,7 @@ class sdist(Command):
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options: ClassVar[list[str]] = [
|
||||
boolean_options = [
|
||||
'use-defaults',
|
||||
'prune',
|
||||
'manifest-only',
|
||||
@@ -110,18 +109,15 @@ class sdist(Command):
|
||||
'metadata-check',
|
||||
]
|
||||
|
||||
help_options: ClassVar[list[tuple[str, str | None, str, Callable[[], object]]]] = [
|
||||
help_options = [
|
||||
('help-formats', None, "list available distribution formats", show_formats),
|
||||
]
|
||||
|
||||
negative_opt: ClassVar[dict[str, str]] = {
|
||||
'no-defaults': 'use-defaults',
|
||||
'no-prune': 'prune',
|
||||
}
|
||||
negative_opt = {'no-defaults': 'use-defaults', 'no-prune': 'prune'}
|
||||
|
||||
sub_commands = [('check', checking_metadata)]
|
||||
|
||||
READMES: ClassVar[tuple[str, ...]] = ('README', 'README.txt', 'README.rst')
|
||||
READMES = ('README', 'README.txt', 'README.rst')
|
||||
|
||||
def initialize_options(self):
|
||||
# 'template' and 'manifest' are, respectively, the names of
|
||||
@@ -131,22 +127,22 @@ class sdist(Command):
|
||||
|
||||
# 'use_defaults': if true, we will include the default file set
|
||||
# in the manifest
|
||||
self.use_defaults = True
|
||||
self.prune = True
|
||||
self.use_defaults = 1
|
||||
self.prune = 1
|
||||
|
||||
self.manifest_only = False
|
||||
self.force_manifest = False
|
||||
self.manifest_only = 0
|
||||
self.force_manifest = 0
|
||||
|
||||
self.formats = ['gztar']
|
||||
self.keep_temp = False
|
||||
self.keep_temp = 0
|
||||
self.dist_dir = None
|
||||
|
||||
self.archive_files = None
|
||||
self.metadata_check = True
|
||||
self.metadata_check = 1
|
||||
self.owner = None
|
||||
self.group = None
|
||||
|
||||
def finalize_options(self) -> None:
|
||||
def finalize_options(self):
|
||||
if self.manifest is None:
|
||||
self.manifest = "MANIFEST"
|
||||
if self.template is None:
|
||||
@@ -156,12 +152,12 @@ class sdist(Command):
|
||||
|
||||
bad_format = archive_util.check_archive_formats(self.formats)
|
||||
if bad_format:
|
||||
raise DistutilsOptionError(f"unknown archive format '{bad_format}'")
|
||||
raise DistutilsOptionError("unknown archive format '%s'" % bad_format)
|
||||
|
||||
if self.dist_dir is None:
|
||||
self.dist_dir = "dist"
|
||||
|
||||
def run(self) -> None:
|
||||
def run(self):
|
||||
# 'filelist' contains the list of files that will make up the
|
||||
# manifest
|
||||
self.filelist = FileList()
|
||||
@@ -183,7 +179,18 @@ class sdist(Command):
|
||||
# or zipfile, or whatever.
|
||||
self.make_distribution()
|
||||
|
||||
def get_file_list(self) -> None:
|
||||
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
|
||||
reading the manifest template (and writing the manifest), or just
|
||||
@@ -224,11 +231,11 @@ class sdist(Command):
|
||||
self.filelist.remove_duplicates()
|
||||
self.write_manifest()
|
||||
|
||||
def add_defaults(self) -> None:
|
||||
def add_defaults(self):
|
||||
"""Add all the default files to self.filelist:
|
||||
- README or README.txt
|
||||
- setup.py
|
||||
- tests/test*.py and test/test*.py
|
||||
- test/test*.py
|
||||
- all pure Python modules mentioned in setup script
|
||||
- all files pointed by package_data (build_py)
|
||||
- all files defined in data_files.
|
||||
@@ -283,10 +290,10 @@ class sdist(Command):
|
||||
if self._cs_path_exists(fn):
|
||||
self.filelist.append(fn)
|
||||
else:
|
||||
self.warn(f"standard file '{fn}' not found")
|
||||
self.warn("standard file '%s' not found" % fn)
|
||||
|
||||
def _add_defaults_optional(self):
|
||||
optional = ['tests/test*.py', 'test/test*.py', 'setup.cfg']
|
||||
optional = ['test/test*.py', 'setup.cfg']
|
||||
for pattern in optional:
|
||||
files = filter(os.path.isfile, glob(pattern))
|
||||
self.filelist.extend(files)
|
||||
@@ -303,7 +310,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))
|
||||
|
||||
@@ -339,7 +346,7 @@ class sdist(Command):
|
||||
build_scripts = self.get_finalized_command('build_scripts')
|
||||
self.filelist.extend(build_scripts.get_source_files())
|
||||
|
||||
def read_template(self) -> None:
|
||||
def read_template(self):
|
||||
"""Read and parse manifest template file named by self.template.
|
||||
|
||||
(usually "MANIFEST.in") The parsing and processing is done by
|
||||
@@ -348,12 +355,12 @@ class sdist(Command):
|
||||
log.info("reading manifest template '%s'", self.template)
|
||||
template = TextFile(
|
||||
self.template,
|
||||
strip_comments=True,
|
||||
skip_blanks=True,
|
||||
join_lines=True,
|
||||
lstrip_ws=True,
|
||||
rstrip_ws=True,
|
||||
collapse_join=True,
|
||||
strip_comments=1,
|
||||
skip_blanks=1,
|
||||
join_lines=1,
|
||||
lstrip_ws=1,
|
||||
rstrip_ws=1,
|
||||
collapse_join=1,
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -369,12 +376,13 @@ class sdist(Command):
|
||||
# convert_path function
|
||||
except (DistutilsTemplateError, ValueError) as msg:
|
||||
self.warn(
|
||||
f"{template.filename}, line {int(template.current_line)}: {msg}"
|
||||
"%s, line %d: %s"
|
||||
% (template.filename, template.current_line, msg)
|
||||
)
|
||||
finally:
|
||||
template.close()
|
||||
|
||||
def prune_file_list(self) -> None:
|
||||
def prune_file_list(self):
|
||||
"""Prune off branches that might slip into the file list as created
|
||||
by 'read_template()', but really don't belong there:
|
||||
* the build tree (typically "build")
|
||||
@@ -385,7 +393,7 @@ class sdist(Command):
|
||||
build = self.get_finalized_command('build')
|
||||
base_dir = self.distribution.get_fullname()
|
||||
|
||||
self.filelist.exclude_pattern(None, prefix=os.fspath(build.build_base))
|
||||
self.filelist.exclude_pattern(None, prefix=build.build_base)
|
||||
self.filelist.exclude_pattern(None, prefix=base_dir)
|
||||
|
||||
if sys.platform == 'win32':
|
||||
@@ -395,16 +403,17 @@ 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=True)
|
||||
self.filelist.exclude_pattern(vcs_ptrn, is_regex=1)
|
||||
|
||||
def write_manifest(self) -> None:
|
||||
def write_manifest(self):
|
||||
"""Write the file list in 'self.filelist' (presumably as filled in
|
||||
by 'add_defaults()' and 'read_template()') to the manifest file
|
||||
named by 'self.manifest'.
|
||||
"""
|
||||
if self._manifest_is_not_generated():
|
||||
log.info(
|
||||
f"not writing to manually maintained manifest file '{self.manifest}'"
|
||||
"not writing to manually maintained "
|
||||
"manifest file '%s'" % self.manifest
|
||||
)
|
||||
return
|
||||
|
||||
@@ -413,7 +422,7 @@ class sdist(Command):
|
||||
self.execute(
|
||||
file_util.write_file,
|
||||
(self.manifest, content),
|
||||
f"writing manifest file '{self.manifest}'",
|
||||
"writing manifest file '%s'" % self.manifest,
|
||||
)
|
||||
|
||||
def _manifest_is_not_generated(self):
|
||||
@@ -421,23 +430,28 @@ class sdist(Command):
|
||||
if not os.path.isfile(self.manifest):
|
||||
return False
|
||||
|
||||
with open(self.manifest, encoding='utf-8') as fp:
|
||||
first_line = next(fp)
|
||||
fp = open(self.manifest)
|
||||
try:
|
||||
first_line = fp.readline()
|
||||
finally:
|
||||
fp.close()
|
||||
return first_line != '# file GENERATED by distutils, do NOT edit\n'
|
||||
|
||||
def read_manifest(self) -> None:
|
||||
def read_manifest(self):
|
||||
"""Read the manifest file (named by 'self.manifest') and use it to
|
||||
fill in 'self.filelist', the list of files to include in the source
|
||||
distribution.
|
||||
"""
|
||||
log.info("reading manifest file '%s'", self.manifest)
|
||||
with open(self.manifest, encoding='utf-8') as lines:
|
||||
self.filelist.extend(
|
||||
with open(self.manifest) as manifest:
|
||||
for line in manifest:
|
||||
# ignore comments and blank lines
|
||||
filter(None, filterfalse(is_comment, map(str.strip, lines)))
|
||||
)
|
||||
line = line.strip()
|
||||
if line.startswith('#') or not line:
|
||||
continue
|
||||
self.filelist.append(line)
|
||||
|
||||
def make_release_tree(self, base_dir, files) -> None:
|
||||
def make_release_tree(self, base_dir, files):
|
||||
"""Create the directory tree that will become the source
|
||||
distribution archive. All directories implied by the filenames in
|
||||
'files' are created under 'base_dir', and then we hard link or copy
|
||||
@@ -461,25 +475,25 @@ class sdist(Command):
|
||||
|
||||
if hasattr(os, 'link'): # can make hard links on this system
|
||||
link = 'hard'
|
||||
msg = f"making hard links in {base_dir}..."
|
||||
msg = "making hard links in %s..." % base_dir
|
||||
else: # nope, have to copy
|
||||
link = None
|
||||
msg = f"copying files to {base_dir}..."
|
||||
msg = "copying files to %s..." % base_dir
|
||||
|
||||
if not files:
|
||||
log.warning("no files to distribute -- empty manifest?")
|
||||
log.warn("no files to distribute -- empty manifest?")
|
||||
else:
|
||||
log.info(msg)
|
||||
for file in files:
|
||||
if not os.path.isfile(file):
|
||||
log.warning("'%s' not a regular file -- skipping", file)
|
||||
log.warn("'%s' not a regular file -- skipping", file)
|
||||
else:
|
||||
dest = os.path.join(base_dir, file)
|
||||
self.copy_file(file, dest, link=link)
|
||||
|
||||
self.distribution.metadata.write_pkg_info(base_dir)
|
||||
|
||||
def make_distribution(self) -> None:
|
||||
def make_distribution(self):
|
||||
"""Create the source distribution(s). First, we create the release
|
||||
tree with 'make_release_tree()'; then, we create all required
|
||||
archive files (according to 'self.formats') from the release tree.
|
||||
@@ -515,7 +529,3 @@ class sdist(Command):
|
||||
was run, or None if the command hasn't run yet.
|
||||
"""
|
||||
return self.archive_files
|
||||
|
||||
|
||||
def is_comment(line: str) -> bool:
|
||||
return line.startswith('#')
|
||||
|
||||
Reference in New Issue
Block a user