mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-04-08 04:34:16 +00:00
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
parent
72ad6dc953
commit
f4cd1ba0d6
813 changed files with 66015 additions and 58839 deletions
|
|
@ -2,30 +2,32 @@
|
|||
|
||||
Package containing implementation of all the standard Distutils
|
||||
commands."""
|
||||
from __future__ import annotations
|
||||
|
||||
__all__ = ['build',
|
||||
'build_py',
|
||||
'build_ext',
|
||||
'build_clib',
|
||||
'build_scripts',
|
||||
'clean',
|
||||
'install',
|
||||
'install_lib',
|
||||
'install_headers',
|
||||
'install_scripts',
|
||||
'install_data',
|
||||
'sdist',
|
||||
'register',
|
||||
'bdist',
|
||||
'bdist_dumb',
|
||||
'bdist_rpm',
|
||||
'bdist_wininst',
|
||||
'check',
|
||||
'upload',
|
||||
# These two are reserved for future use:
|
||||
#'bdist_sdux',
|
||||
#'bdist_pkgtool',
|
||||
# Note:
|
||||
# bdist_packager is not included because it only provides
|
||||
# an abstract base class
|
||||
]
|
||||
__all__ = [
|
||||
'build',
|
||||
'build_py',
|
||||
'build_ext',
|
||||
'build_clib',
|
||||
'build_scripts',
|
||||
'clean',
|
||||
'install',
|
||||
'install_lib',
|
||||
'install_headers',
|
||||
'install_scripts',
|
||||
'install_data',
|
||||
'sdist',
|
||||
'register',
|
||||
'bdist',
|
||||
'bdist_dumb',
|
||||
'bdist_rpm',
|
||||
'bdist_wininst',
|
||||
'check',
|
||||
'upload',
|
||||
# These two are reserved for future use:
|
||||
#'bdist_sdux',
|
||||
#'bdist_pkgtool',
|
||||
# Note:
|
||||
# bdist_packager is not included because it only provides
|
||||
# an abstract base class
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
Implements the Distutils 'bdist' command (create a built [binary]
|
||||
distribution)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from distutils.core import Command
|
||||
from distutils.errors import *
|
||||
from distutils.util import get_platform
|
||||
|
|
@ -15,68 +17,93 @@ def show_formats():
|
|||
from distutils.fancy_getopt import FancyGetopt
|
||||
formats = []
|
||||
for format in bdist.format_commands:
|
||||
formats.append(("formats=" + format, None,
|
||||
bdist.format_command[format][1]))
|
||||
formats.append((
|
||||
'formats=' + format, None,
|
||||
bdist.format_command[format][1],
|
||||
))
|
||||
pretty_printer = FancyGetopt(formats)
|
||||
pretty_printer.print_help("List of available distribution formats:")
|
||||
pretty_printer.print_help('List of available distribution formats:')
|
||||
|
||||
|
||||
class bdist(Command):
|
||||
|
||||
description = "create a built (binary) distribution"
|
||||
description = 'create a built (binary) distribution'
|
||||
|
||||
user_options = [('bdist-base=', 'b',
|
||||
"temporary directory for creating built distributions"),
|
||||
('plat-name=', 'p',
|
||||
"platform name to embed in generated filenames "
|
||||
"(default: %s)" % get_platform()),
|
||||
('formats=', None,
|
||||
"formats for distribution (comma-separated list)"),
|
||||
('dist-dir=', 'd',
|
||||
"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]"),
|
||||
('group=', 'g',
|
||||
"Group name used when creating a tar file"
|
||||
" [default: current group]"),
|
||||
]
|
||||
user_options = [
|
||||
(
|
||||
'bdist-base=', 'b',
|
||||
'temporary directory for creating built distributions',
|
||||
),
|
||||
(
|
||||
'plat-name=', 'p',
|
||||
'platform name to embed in generated filenames '
|
||||
'(default: %s)' % get_platform(),
|
||||
),
|
||||
(
|
||||
'formats=', None,
|
||||
'formats for distribution (comma-separated list)',
|
||||
),
|
||||
(
|
||||
'dist-dir=', 'd',
|
||||
'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]',
|
||||
),
|
||||
(
|
||||
'group=', 'g',
|
||||
'Group name used when creating a tar file'
|
||||
' [default: current group]',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['skip-build']
|
||||
|
||||
help_options = [
|
||||
('help-formats', None,
|
||||
"lists available distribution formats", show_formats),
|
||||
]
|
||||
(
|
||||
'help-formats', None,
|
||||
'lists available distribution formats', show_formats,
|
||||
),
|
||||
]
|
||||
|
||||
# The following commands do not take a format option from bdist
|
||||
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 = {'posix': 'gztar',
|
||||
'nt': 'zip'}
|
||||
default_format = {
|
||||
'posix': 'gztar',
|
||||
'nt': 'zip',
|
||||
}
|
||||
|
||||
# Establish the preferred order (for the --help-formats option).
|
||||
format_commands = ['rpm', 'gztar', 'bztar', 'xztar', 'ztar', 'tar',
|
||||
'wininst', 'zip', 'msi']
|
||||
format_commands = [
|
||||
'rpm', 'gztar', 'bztar', 'xztar', 'ztar', 'tar',
|
||||
'wininst', 'zip', 'msi',
|
||||
]
|
||||
|
||||
# And the real information.
|
||||
format_command = {'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"),
|
||||
'wininst': ('bdist_wininst',
|
||||
"Windows executable installer"),
|
||||
'zip': ('bdist_dumb', "ZIP file"),
|
||||
'msi': ('bdist_msi', "Microsoft Installer")
|
||||
}
|
||||
|
||||
format_command = {
|
||||
'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'),
|
||||
'wininst': (
|
||||
'bdist_wininst',
|
||||
'Windows executable installer',
|
||||
),
|
||||
'zip': ('bdist_dumb', 'ZIP file'),
|
||||
'msi': ('bdist_msi', 'Microsoft Installer'),
|
||||
}
|
||||
|
||||
def initialize_options(self):
|
||||
self.bdist_base = None
|
||||
|
|
@ -100,8 +127,10 @@ class bdist(Command):
|
|||
# "build/bdist.<plat>/dumb", "build/bdist.<plat>/rpm", etc.)
|
||||
if self.bdist_base is None:
|
||||
build_base = self.get_finalized_command('build').build_base
|
||||
self.bdist_base = os.path.join(build_base,
|
||||
'bdist.' + self.plat_name)
|
||||
self.bdist_base = os.path.join(
|
||||
build_base,
|
||||
'bdist.' + self.plat_name,
|
||||
)
|
||||
|
||||
self.ensure_string_list('formats')
|
||||
if self.formats is None:
|
||||
|
|
@ -109,11 +138,12 @@ class bdist(Command):
|
|||
self.formats = [self.default_format[os.name]]
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to create built distributions "
|
||||
"on platform %s" % os.name)
|
||||
"don't know how to create built distributions "
|
||||
'on platform %s' % os.name,
|
||||
)
|
||||
|
||||
if self.dist_dir is None:
|
||||
self.dist_dir = "dist"
|
||||
self.dist_dir = 'dist'
|
||||
|
||||
def run(self):
|
||||
# Figure out which sub-commands we need to run.
|
||||
|
|
@ -138,6 +168,6 @@ 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:]:
|
||||
if cmd_name in commands[i + 1:]:
|
||||
sub_cmd.keep_temp = 1
|
||||
self.run_command(cmd_name)
|
||||
|
|
|
|||
|
|
@ -3,49 +3,72 @@
|
|||
Implements the Distutils 'bdist_dumb' command (create a "dumb" built
|
||||
distribution -- i.e., just an archive to be unpacked under $prefix or
|
||||
$exec_prefix)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import Command
|
||||
from distutils.util import get_platform
|
||||
from distutils.dir_util import remove_tree, ensure_relative
|
||||
from distutils.dir_util import ensure_relative
|
||||
from distutils.dir_util import remove_tree
|
||||
from distutils.errors import *
|
||||
from distutils.sysconfig import get_python_version
|
||||
from distutils import log
|
||||
from distutils.util import get_platform
|
||||
|
||||
|
||||
class bdist_dumb(Command):
|
||||
|
||||
description = "create a \"dumb\" built distribution"
|
||||
|
||||
user_options = [('bdist-dir=', 'd',
|
||||
"temporary directory for creating the distribution"),
|
||||
('plat-name=', 'p',
|
||||
"platform name to embed in generated filenames "
|
||||
"(default: %s)" % get_platform()),
|
||||
('format=', 'f',
|
||||
"archive format to create (tar, gztar, bztar, xztar, "
|
||||
"ztar, zip)"),
|
||||
('keep-temp', 'k',
|
||||
"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)"),
|
||||
('owner=', 'u',
|
||||
"Owner name used when creating a tar file"
|
||||
" [default: current user]"),
|
||||
('group=', 'g',
|
||||
"Group name used when creating a tar file"
|
||||
" [default: current group]"),
|
||||
]
|
||||
user_options = [
|
||||
(
|
||||
'bdist-dir=', 'd',
|
||||
'temporary directory for creating the distribution',
|
||||
),
|
||||
(
|
||||
'plat-name=', 'p',
|
||||
'platform name to embed in generated filenames '
|
||||
'(default: %s)' % get_platform(),
|
||||
),
|
||||
(
|
||||
'format=', 'f',
|
||||
'archive format to create (tar, gztar, bztar, xztar, '
|
||||
'ztar, zip)',
|
||||
),
|
||||
(
|
||||
'keep-temp', 'k',
|
||||
'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)',
|
||||
),
|
||||
(
|
||||
'owner=', 'u',
|
||||
'Owner name used when creating a tar file'
|
||||
' [default: current user]',
|
||||
),
|
||||
(
|
||||
'group=', 'g',
|
||||
'Group name used when creating a tar file'
|
||||
' [default: current group]',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['keep-temp', 'skip-build', 'relative']
|
||||
|
||||
default_format = { 'posix': 'gztar',
|
||||
'nt': 'zip' }
|
||||
default_format = {'posix': 'gztar',
|
||||
'nt': 'zip', }
|
||||
|
||||
def initialize_options(self):
|
||||
self.bdist_dir = None
|
||||
|
|
@ -68,13 +91,16 @@ class bdist_dumb(Command):
|
|||
self.format = self.default_format[os.name]
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to create dumb built distributions "
|
||||
"on platform %s" % os.name)
|
||||
"don't know how to create dumb built distributions "
|
||||
'on platform %s' % os.name,
|
||||
)
|
||||
|
||||
self.set_undefined_options('bdist',
|
||||
('dist_dir', 'dist_dir'),
|
||||
('plat_name', 'plat_name'),
|
||||
('skip_build', 'skip_build'))
|
||||
self.set_undefined_options(
|
||||
'bdist',
|
||||
('dist_dir', 'dist_dir'),
|
||||
('plat_name', 'plat_name'),
|
||||
('skip_build', 'skip_build'),
|
||||
)
|
||||
|
||||
def run(self):
|
||||
if not self.skip_build:
|
||||
|
|
@ -85,39 +111,52 @@ class bdist_dumb(Command):
|
|||
install.skip_build = self.skip_build
|
||||
install.warn_dir = 0
|
||||
|
||||
log.info("installing to %s", self.bdist_dir)
|
||||
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 = "%s.%s" % (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:
|
||||
archive_root = self.bdist_dir
|
||||
else:
|
||||
if (self.distribution.has_ext_modules() and
|
||||
(install.install_base != install.install_platbase)):
|
||||
if (
|
||||
self.distribution.has_ext_modules() and
|
||||
(install.install_base != install.install_platbase)
|
||||
):
|
||||
raise DistutilsPlatformError(
|
||||
"can't make a dumb built distribution where "
|
||||
"base and platbase are different (%s, %s)"
|
||||
% (repr(install.install_base),
|
||||
repr(install.install_platbase)))
|
||||
"can't make a dumb built distribution where "
|
||||
'base and platbase are different (%s, %s)'
|
||||
% (
|
||||
repr(install.install_base),
|
||||
repr(install.install_platbase),
|
||||
),
|
||||
)
|
||||
else:
|
||||
archive_root = os.path.join(self.bdist_dir,
|
||||
ensure_relative(install.install_base))
|
||||
archive_root = os.path.join(
|
||||
self.bdist_dir,
|
||||
ensure_relative(install.install_base),
|
||||
)
|
||||
|
||||
# Make the archive
|
||||
filename = self.make_archive(pseudoinstall_root,
|
||||
self.format, root_dir=archive_root,
|
||||
owner=self.owner, group=self.group)
|
||||
filename = self.make_archive(
|
||||
pseudoinstall_root,
|
||||
self.format, root_dir=archive_root,
|
||||
owner=self.owner, group=self.group,
|
||||
)
|
||||
if self.distribution.has_ext_modules():
|
||||
pyversion = get_python_version()
|
||||
else:
|
||||
pyversion = 'any'
|
||||
self.distribution.dist_files.append(('bdist_dumb', pyversion,
|
||||
filename))
|
||||
self.distribution.dist_files.append((
|
||||
'bdist_dumb', pyversion,
|
||||
filename,
|
||||
))
|
||||
|
||||
if not self.keep_temp:
|
||||
remove_tree(self.bdist_dir, dry_run=self.dry_run)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -2,135 +2,225 @@
|
|||
|
||||
Implements the Distutils 'bdist_rpm' command (create RPM source and binary
|
||||
distributions)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess, sys, os
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import Command
|
||||
from distutils.debug import DEBUG
|
||||
from distutils.file_util import write_file
|
||||
from distutils.errors import *
|
||||
from distutils.file_util import write_file
|
||||
from distutils.sysconfig import get_python_version
|
||||
from distutils import log
|
||||
|
||||
|
||||
class bdist_rpm(Command):
|
||||
|
||||
description = "create an RPM distribution"
|
||||
description = 'create an RPM distribution'
|
||||
|
||||
user_options = [
|
||||
('bdist-base=', None,
|
||||
"base directory for creating built distributions"),
|
||||
('rpm-base=', None,
|
||||
"base directory for creating RPMs (defaults to \"rpm\" under "
|
||||
"--bdist-base; must be specified for RPM 2)"),
|
||||
('dist-dir=', 'd',
|
||||
"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\")"),
|
||||
('fix-python', None,
|
||||
"hard-code the exact path to the current Python interpreter in "
|
||||
"the .spec file"),
|
||||
('spec-only', None,
|
||||
"only regenerate spec file"),
|
||||
('source-only', None,
|
||||
"only generate source RPM"),
|
||||
('binary-only', None,
|
||||
"only generate binary RPM"),
|
||||
('use-bzip2', None,
|
||||
"use bzip2 instead of gzip to create source distribution"),
|
||||
(
|
||||
'bdist-base=', None,
|
||||
'base directory for creating built distributions',
|
||||
),
|
||||
(
|
||||
'rpm-base=', None,
|
||||
"base directory for creating RPMs (defaults to \"rpm\" under "
|
||||
'--bdist-base; must be specified for RPM 2)',
|
||||
),
|
||||
(
|
||||
'dist-dir=', 'd',
|
||||
'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\")",
|
||||
),
|
||||
(
|
||||
'fix-python', None,
|
||||
'hard-code the exact path to the current Python interpreter in '
|
||||
'the .spec file',
|
||||
),
|
||||
(
|
||||
'spec-only', None,
|
||||
'only regenerate spec file',
|
||||
),
|
||||
(
|
||||
'source-only', None,
|
||||
'only generate source RPM',
|
||||
),
|
||||
(
|
||||
'binary-only', None,
|
||||
'only generate binary RPM',
|
||||
),
|
||||
(
|
||||
'use-bzip2', None,
|
||||
'use bzip2 instead of gzip to create source distribution',
|
||||
),
|
||||
|
||||
# More meta-data: too RPM-specific to put in the setup script,
|
||||
# but needs to go in the .spec file -- so we make these options
|
||||
# to "bdist_rpm". The idea is that packagers would put this
|
||||
# info in setup.cfg, although they are of course free to
|
||||
# supply it on the command line.
|
||||
('distribution-name=', None,
|
||||
"name of the (Linux) distribution to which this "
|
||||
"RPM applies (*not* the name of the module distribution!)"),
|
||||
('group=', None,
|
||||
"package classification [default: \"Development/Libraries\"]"),
|
||||
('release=', None,
|
||||
"RPM release number"),
|
||||
('serial=', None,
|
||||
"RPM serial number"),
|
||||
('vendor=', None,
|
||||
"RPM \"vendor\" (eg. \"Joe Blow <joe@example.com>\") "
|
||||
"[default: maintainer or author from setup script]"),
|
||||
('packager=', None,
|
||||
"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"),
|
||||
('icon=', None,
|
||||
"name of icon file"),
|
||||
('provides=', None,
|
||||
"capabilities provided by this package"),
|
||||
('requires=', None,
|
||||
"capabilities required by this package"),
|
||||
('conflicts=', None,
|
||||
"capabilities which conflict with this package"),
|
||||
('build-requires=', None,
|
||||
"capabilities required to build this package"),
|
||||
('obsoletes=', None,
|
||||
"capabilities made obsolete by this package"),
|
||||
('no-autoreq', None,
|
||||
"do not automatically calculate dependencies"),
|
||||
(
|
||||
'distribution-name=', None,
|
||||
'name of the (Linux) distribution to which this '
|
||||
'RPM applies (*not* the name of the module distribution!)',
|
||||
),
|
||||
(
|
||||
'group=', None,
|
||||
"package classification [default: \"Development/Libraries\"]",
|
||||
),
|
||||
(
|
||||
'release=', None,
|
||||
'RPM release number',
|
||||
),
|
||||
(
|
||||
'serial=', None,
|
||||
'RPM serial number',
|
||||
),
|
||||
(
|
||||
'vendor=', None,
|
||||
"RPM \"vendor\" (eg. \"Joe Blow <joe@example.com>\") "
|
||||
'[default: maintainer or author from setup script]',
|
||||
),
|
||||
(
|
||||
'packager=', None,
|
||||
"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',
|
||||
),
|
||||
(
|
||||
'icon=', None,
|
||||
'name of icon file',
|
||||
),
|
||||
(
|
||||
'provides=', None,
|
||||
'capabilities provided by this package',
|
||||
),
|
||||
(
|
||||
'requires=', None,
|
||||
'capabilities required by this package',
|
||||
),
|
||||
(
|
||||
'conflicts=', None,
|
||||
'capabilities which conflict with this package',
|
||||
),
|
||||
(
|
||||
'build-requires=', None,
|
||||
'capabilities required to build this package',
|
||||
),
|
||||
(
|
||||
'obsoletes=', None,
|
||||
'capabilities made obsolete by this package',
|
||||
),
|
||||
(
|
||||
'no-autoreq', None,
|
||||
'do not automatically calculate dependencies',
|
||||
),
|
||||
|
||||
# Actions to take when building RPM
|
||||
('keep-temp', 'k',
|
||||
"don't clean up RPM build directory"),
|
||||
('no-keep-temp', None,
|
||||
"clean up RPM build directory [default]"),
|
||||
('use-rpm-opt-flags', None,
|
||||
"compile with RPM_OPT_FLAGS when building from source RPM"),
|
||||
('no-rpm-opt-flags', None,
|
||||
"do not pass any RPM CFLAGS to compiler"),
|
||||
('rpm3-mode', None,
|
||||
"RPM 3 compatibility mode (default)"),
|
||||
('rpm2-mode', None,
|
||||
"RPM 2 compatibility mode"),
|
||||
(
|
||||
'keep-temp', 'k',
|
||||
"don't clean up RPM build directory",
|
||||
),
|
||||
(
|
||||
'no-keep-temp', None,
|
||||
'clean up RPM build directory [default]',
|
||||
),
|
||||
(
|
||||
'use-rpm-opt-flags', None,
|
||||
'compile with RPM_OPT_FLAGS when building from source RPM',
|
||||
),
|
||||
(
|
||||
'no-rpm-opt-flags', None,
|
||||
'do not pass any RPM CFLAGS to compiler',
|
||||
),
|
||||
(
|
||||
'rpm3-mode', None,
|
||||
'RPM 3 compatibility mode (default)',
|
||||
),
|
||||
(
|
||||
'rpm2-mode', None,
|
||||
'RPM 2 compatibility mode',
|
||||
),
|
||||
|
||||
# Add the hooks necessary for specifying custom scripts
|
||||
('prep-script=', None,
|
||||
"Specify a script for the PREP phase of RPM building"),
|
||||
('build-script=', None,
|
||||
"Specify a script for the BUILD phase of RPM building"),
|
||||
(
|
||||
'prep-script=', None,
|
||||
'Specify a script for the PREP phase of RPM building',
|
||||
),
|
||||
(
|
||||
'build-script=', None,
|
||||
'Specify a script for the BUILD phase of RPM building',
|
||||
),
|
||||
|
||||
('pre-install=', None,
|
||||
"Specify a script for the pre-INSTALL phase of RPM building"),
|
||||
('install-script=', None,
|
||||
"Specify a script for the INSTALL phase of RPM building"),
|
||||
('post-install=', None,
|
||||
"Specify a script for the post-INSTALL phase of RPM building"),
|
||||
(
|
||||
'pre-install=', None,
|
||||
'Specify a script for the pre-INSTALL phase of RPM building',
|
||||
),
|
||||
(
|
||||
'install-script=', None,
|
||||
'Specify a script for the INSTALL phase of RPM building',
|
||||
),
|
||||
(
|
||||
'post-install=', None,
|
||||
'Specify a script for the post-INSTALL phase of RPM building',
|
||||
),
|
||||
|
||||
('pre-uninstall=', None,
|
||||
"Specify a script for the pre-UNINSTALL phase of RPM building"),
|
||||
('post-uninstall=', None,
|
||||
"Specify a script for the post-UNINSTALL phase of RPM building"),
|
||||
(
|
||||
'pre-uninstall=', None,
|
||||
'Specify a script for the pre-UNINSTALL phase of RPM building',
|
||||
),
|
||||
(
|
||||
'post-uninstall=', None,
|
||||
'Specify a script for the post-UNINSTALL phase of RPM building',
|
||||
),
|
||||
|
||||
('clean-script=', None,
|
||||
"Specify a script for the CLEAN phase of RPM building"),
|
||||
(
|
||||
'clean-script=', None,
|
||||
'Specify a script for the CLEAN phase of RPM building',
|
||||
),
|
||||
|
||||
('verify-script=', None,
|
||||
"Specify a script for the VERIFY phase of the RPM build"),
|
||||
(
|
||||
'verify-script=', None,
|
||||
'Specify a script for the VERIFY phase of the RPM build',
|
||||
),
|
||||
|
||||
# Allow a packager to explicitly force an architecture
|
||||
('force-arch=', None,
|
||||
"Force an architecture onto the RPM build process"),
|
||||
(
|
||||
'force-arch=', None,
|
||||
'Force an architecture onto the RPM build process',
|
||||
),
|
||||
|
||||
('quiet', 'q',
|
||||
"Run the INSTALL phase of RPM building in quiet mode"),
|
||||
]
|
||||
(
|
||||
'quiet', 'q',
|
||||
'Run the INSTALL phase of RPM building in quiet mode',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['keep-temp', 'use-rpm-opt-flags', 'rpm3-mode',
|
||||
'no-autoreq', 'quiet']
|
||||
|
||||
negative_opt = {'no-keep-temp': 'keep-temp',
|
||||
'no-rpm-opt-flags': 'use-rpm-opt-flags',
|
||||
'rpm2-mode': 'rpm3-mode'}
|
||||
boolean_options = [
|
||||
'keep-temp', 'use-rpm-opt-flags', 'rpm3-mode',
|
||||
'no-autoreq', 'quiet',
|
||||
]
|
||||
|
||||
negative_opt = {
|
||||
'no-keep-temp': 'keep-temp',
|
||||
'no-rpm-opt-flags': 'use-rpm-opt-flags',
|
||||
'rpm2-mode': 'rpm3-mode',
|
||||
}
|
||||
|
||||
def initialize_options(self):
|
||||
self.bdist_base = None
|
||||
|
|
@ -182,24 +272,29 @@ class bdist_rpm(Command):
|
|||
if self.rpm_base is None:
|
||||
if not self.rpm3_mode:
|
||||
raise DistutilsOptionError(
|
||||
"you must specify --rpm-base in RPM 2 mode")
|
||||
self.rpm_base = os.path.join(self.bdist_base, "rpm")
|
||||
'you must specify --rpm-base in RPM 2 mode',
|
||||
)
|
||||
self.rpm_base = os.path.join(self.bdist_base, 'rpm')
|
||||
|
||||
if self.python is None:
|
||||
if self.fix_python:
|
||||
self.python = sys.executable
|
||||
else:
|
||||
self.python = "python3"
|
||||
self.python = 'python3'
|
||||
elif self.fix_python:
|
||||
raise DistutilsOptionError(
|
||||
"--python and --fix-python are mutually exclusive options")
|
||||
'--python and --fix-python are mutually exclusive options',
|
||||
)
|
||||
|
||||
if os.name != 'posix':
|
||||
raise DistutilsPlatformError("don't know how to create RPM "
|
||||
"distributions on platform %s" % os.name)
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to create RPM "
|
||||
'distributions on platform %s' % os.name,
|
||||
)
|
||||
if self.binary_only and self.source_only:
|
||||
raise DistutilsOptionError(
|
||||
"cannot supply both '--source-only' and '--binary-only'")
|
||||
"cannot supply both '--source-only' and '--binary-only'",
|
||||
)
|
||||
|
||||
# don't pass CFLAGS to pure python distributions
|
||||
if not self.distribution.has_ext_modules():
|
||||
|
|
@ -209,10 +304,14 @@ class bdist_rpm(Command):
|
|||
self.finalize_package_data()
|
||||
|
||||
def finalize_package_data(self):
|
||||
self.ensure_string('group', "Development/Libraries")
|
||||
self.ensure_string('vendor',
|
||||
"%s <%s>" % (self.distribution.get_contact(),
|
||||
self.distribution.get_contact_email()))
|
||||
self.ensure_string('group', 'Development/Libraries')
|
||||
self.ensure_string(
|
||||
'vendor',
|
||||
'{} <{}>'.format(
|
||||
self.distribution.get_contact(),
|
||||
self.distribution.get_contact_email(),
|
||||
),
|
||||
)
|
||||
self.ensure_string('packager')
|
||||
self.ensure_string_list('doc_files')
|
||||
if isinstance(self.doc_files, list):
|
||||
|
|
@ -220,13 +319,13 @@ class bdist_rpm(Command):
|
|||
if os.path.exists(readme) and readme not in self.doc_files:
|
||||
self.doc_files.append(readme)
|
||||
|
||||
self.ensure_string('release', "1")
|
||||
self.ensure_string('release', '1')
|
||||
self.ensure_string('serial') # should it be an int?
|
||||
|
||||
self.ensure_string('distribution_name')
|
||||
|
||||
self.ensure_string('changelog')
|
||||
# Format changelog correctly
|
||||
# Format changelog correctly
|
||||
self.changelog = self._format_changelog(self.changelog)
|
||||
|
||||
self.ensure_filename('icon')
|
||||
|
|
@ -255,11 +354,11 @@ class bdist_rpm(Command):
|
|||
|
||||
def run(self):
|
||||
if DEBUG:
|
||||
print("before _get_package_data():")
|
||||
print("vendor =", self.vendor)
|
||||
print("packager =", self.packager)
|
||||
print("doc_files =", self.doc_files)
|
||||
print("changelog =", self.changelog)
|
||||
print('before _get_package_data():')
|
||||
print('vendor =', self.vendor)
|
||||
print('packager =', self.packager)
|
||||
print('doc_files =', self.doc_files)
|
||||
print('changelog =', self.changelog)
|
||||
|
||||
# make directories
|
||||
if self.spec_only:
|
||||
|
|
@ -274,14 +373,20 @@ class bdist_rpm(Command):
|
|||
|
||||
# Spec file goes into 'dist_dir' if '--spec-only specified',
|
||||
# build/rpm.<plat> otherwise.
|
||||
spec_path = os.path.join(spec_dir,
|
||||
"%s.spec" % self.distribution.get_name())
|
||||
self.execute(write_file,
|
||||
(spec_path,
|
||||
self._make_spec_file()),
|
||||
"writing '%s'" % spec_path)
|
||||
spec_path = os.path.join(
|
||||
spec_dir,
|
||||
'%s.spec' % self.distribution.get_name(),
|
||||
)
|
||||
self.execute(
|
||||
write_file,
|
||||
(
|
||||
spec_path,
|
||||
self._make_spec_file(),
|
||||
),
|
||||
"writing '%s'" % spec_path,
|
||||
)
|
||||
|
||||
if self.spec_only: # stop if requested
|
||||
if self.spec_only: # stop if requested
|
||||
return
|
||||
|
||||
# Make a source distribution and copy to SOURCES directory with
|
||||
|
|
@ -304,13 +409,14 @@ class bdist_rpm(Command):
|
|||
self.copy_file(self.icon, source_dir)
|
||||
else:
|
||||
raise DistutilsFileError(
|
||||
"icon file '%s' does not exist" % self.icon)
|
||||
"icon file '%s' does not exist" % self.icon,
|
||||
)
|
||||
|
||||
# build package
|
||||
log.info("building RPMs")
|
||||
log.info('building RPMs')
|
||||
rpm_cmd = ['rpmbuild']
|
||||
|
||||
if self.source_only: # what kind of RPMs?
|
||||
if self.source_only: # what kind of RPMs?
|
||||
rpm_cmd.append('-bs')
|
||||
elif self.binary_only:
|
||||
rpm_cmd.append('-bb')
|
||||
|
|
@ -318,8 +424,10 @@ class bdist_rpm(Command):
|
|||
rpm_cmd.append('-ba')
|
||||
rpm_cmd.extend(['--define', '__python %s' % self.python])
|
||||
if self.rpm3_mode:
|
||||
rpm_cmd.extend(['--define',
|
||||
'_topdir %s' % 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')
|
||||
|
||||
|
|
@ -331,11 +439,12 @@ class bdist_rpm(Command):
|
|||
# file
|
||||
# Note that some of these may not be really built (if the file
|
||||
# list is empty)
|
||||
nvr_string = "%{name}-%{version}-%{release}"
|
||||
src_rpm = nvr_string + ".src.rpm"
|
||||
non_src_rpm = "%{arch}/" + nvr_string + ".%{arch}.rpm"
|
||||
q_cmd = r"rpm -q --qf '%s %s\n' --specfile '%s'" % (
|
||||
src_rpm, non_src_rpm, spec_path)
|
||||
nvr_string = '%{name}-%{version}-%{release}'
|
||||
src_rpm = nvr_string + '.src.rpm'
|
||||
non_src_rpm = '%{arch}/' + nvr_string + '.%{arch}.rpm'
|
||||
q_cmd = r"rpm -q --qf '{} {}\n' --specfile '{}'".format(
|
||||
src_rpm, non_src_rpm, spec_path,
|
||||
)
|
||||
|
||||
out = os.popen(q_cmd)
|
||||
try:
|
||||
|
|
@ -346,7 +455,7 @@ class bdist_rpm(Command):
|
|||
if not line:
|
||||
break
|
||||
l = line.strip().split()
|
||||
assert(len(l) == 2)
|
||||
assert (len(l) == 2)
|
||||
binary_rpms.append(l[1])
|
||||
# The source rpm is named after the first entry in the spec file
|
||||
if source_rpm is None:
|
||||
|
|
@ -354,7 +463,7 @@ class bdist_rpm(Command):
|
|||
|
||||
status = out.close()
|
||||
if status:
|
||||
raise DistutilsExecError("Failed to execute: %s" % repr(q_cmd))
|
||||
raise DistutilsExecError('Failed to execute: %s' % repr(q_cmd))
|
||||
|
||||
finally:
|
||||
out.close()
|
||||
|
|
@ -369,21 +478,25 @@ class bdist_rpm(Command):
|
|||
|
||||
if not self.binary_only:
|
||||
srpm = os.path.join(rpm_dir['SRPMS'], source_rpm)
|
||||
assert(os.path.exists(srpm))
|
||||
assert (os.path.exists(srpm))
|
||||
self.move_file(srpm, self.dist_dir)
|
||||
filename = os.path.join(self.dist_dir, source_rpm)
|
||||
self.distribution.dist_files.append(
|
||||
('bdist_rpm', pyversion, filename))
|
||||
('bdist_rpm', pyversion, filename),
|
||||
)
|
||||
|
||||
if not self.source_only:
|
||||
for rpm in binary_rpms:
|
||||
rpm = os.path.join(rpm_dir['RPMS'], rpm)
|
||||
if os.path.exists(rpm):
|
||||
self.move_file(rpm, self.dist_dir)
|
||||
filename = os.path.join(self.dist_dir,
|
||||
os.path.basename(rpm))
|
||||
filename = os.path.join(
|
||||
self.dist_dir,
|
||||
os.path.basename(rpm),
|
||||
)
|
||||
self.distribution.dist_files.append(
|
||||
('bdist_rpm', pyversion, filename))
|
||||
('bdist_rpm', pyversion, filename),
|
||||
)
|
||||
|
||||
def _dist_path(self, path):
|
||||
return os.path.join(self.dist_dir, os.path.basename(path))
|
||||
|
|
@ -395,12 +508,12 @@ class bdist_rpm(Command):
|
|||
# definitions and headers
|
||||
spec_file = [
|
||||
'%define name ' + self.distribution.get_name(),
|
||||
'%define version ' + self.distribution.get_version().replace('-','_'),
|
||||
'%define version ' + self.distribution.get_version().replace('-', '_'),
|
||||
'%define unmangled_version ' + self.distribution.get_version(),
|
||||
'%define release ' + self.release.replace('-','_'),
|
||||
'%define release ' + self.release.replace('-', '_'),
|
||||
'',
|
||||
'Summary: ' + self.distribution.get_description(),
|
||||
]
|
||||
]
|
||||
|
||||
# Workaround for #14443 which affects some RPM based systems such as
|
||||
# RHEL6 (and probably derivatives)
|
||||
|
|
@ -408,10 +521,12 @@ class bdist_rpm(Command):
|
|||
# Generate a potential replacement value for __os_install_post (whilst
|
||||
# normalizing the whitespace to simplify the test for whether the
|
||||
# invocation of brp-python-bytecompile passes in __python):
|
||||
vendor_hook = '\n'.join([' %s \\' % line.strip()
|
||||
for line in vendor_hook.splitlines()])
|
||||
problem = "brp-python-bytecompile \\\n"
|
||||
fixed = "brp-python-bytecompile %{__python} \\\n"
|
||||
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 http://bugs.python.org/issue14443')
|
||||
|
|
@ -427,7 +542,8 @@ class bdist_rpm(Command):
|
|||
spec_file.extend([
|
||||
'Name: %{name}',
|
||||
'Version: %{version}',
|
||||
'Release: %{release}',])
|
||||
'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
|
||||
|
|
@ -448,21 +564,21 @@ class bdist_rpm(Command):
|
|||
if not self.distribution.has_ext_modules():
|
||||
spec_file.append('BuildArch: noarch')
|
||||
else:
|
||||
spec_file.append( 'BuildArch: %s' % self.force_arch )
|
||||
spec_file.append('BuildArch: %s' % self.force_arch)
|
||||
|
||||
for field in ('Vendor',
|
||||
'Packager',
|
||||
'Provides',
|
||||
'Requires',
|
||||
'Conflicts',
|
||||
'Obsoletes',
|
||||
):
|
||||
for field in (
|
||||
'Vendor',
|
||||
'Packager',
|
||||
'Provides',
|
||||
'Requires',
|
||||
'Conflicts',
|
||||
'Obsoletes',
|
||||
):
|
||||
val = getattr(self, field.lower())
|
||||
if isinstance(val, list):
|
||||
spec_file.append('%s: %s' % (field, ' '.join(val)))
|
||||
spec_file.append('{}: {}'.format(field, ' '.join(val)))
|
||||
elif val is not None:
|
||||
spec_file.append('%s: %s' % (field, val))
|
||||
|
||||
spec_file.append('{}: {}'.format(field, val))
|
||||
|
||||
if self.distribution.get_url() != 'UNKNOWN':
|
||||
spec_file.append('Url: ' + self.distribution.get_url())
|
||||
|
|
@ -471,8 +587,10 @@ class bdist_rpm(Command):
|
|||
spec_file.append('Distribution: ' + self.distribution_name)
|
||||
|
||||
if self.build_requires:
|
||||
spec_file.append('BuildRequires: ' +
|
||||
' '.join(self.build_requires))
|
||||
spec_file.append(
|
||||
'BuildRequires: ' +
|
||||
' '.join(self.build_requires),
|
||||
)
|
||||
|
||||
if self.icon:
|
||||
spec_file.append('Icon: ' + os.path.basename(self.icon))
|
||||
|
|
@ -483,8 +601,8 @@ class bdist_rpm(Command):
|
|||
spec_file.extend([
|
||||
'',
|
||||
'%description',
|
||||
self.distribution.get_long_description()
|
||||
])
|
||||
self.distribution.get_long_description(),
|
||||
])
|
||||
|
||||
# put locale descriptions into spec file
|
||||
# XXX again, suppressed because config file syntax doesn't
|
||||
|
|
@ -498,8 +616,8 @@ class bdist_rpm(Command):
|
|||
|
||||
# rpm scripts
|
||||
# figure out default build script
|
||||
def_setup_call = "%s %s" % (self.python,os.path.basename(sys.argv[0]))
|
||||
def_build = "%s build" % def_setup_call
|
||||
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
|
||||
|
||||
|
|
@ -509,14 +627,16 @@ class bdist_rpm(Command):
|
|||
# that we open and interpolate into the spec file, but the defaults
|
||||
# are just text that we drop in as-is. Hmmm.
|
||||
|
||||
install_cmd = ('%s install -O1 --root=$RPM_BUILD_ROOT '
|
||||
'--record=INSTALLED_FILES') % def_setup_call
|
||||
install_cmd = (
|
||||
'%s install -O1 --root=$RPM_BUILD_ROOT '
|
||||
'--record=INSTALLED_FILES'
|
||||
) % def_setup_call
|
||||
|
||||
script_options = [
|
||||
('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"),
|
||||
('prep', 'prep_script', '%setup -n %{name}-%{unmangled_version}'),
|
||||
('build', 'build_script', def_build),
|
||||
('install', 'install_script', install_cmd),
|
||||
('clean', 'clean_script', "rm -rf $RPM_BUILD_ROOT"),
|
||||
('clean', 'clean_script', 'rm -rf $RPM_BUILD_ROOT'),
|
||||
('verifyscript', 'verify_script', None),
|
||||
('pre', 'pre_install', None),
|
||||
('post', 'post_install', None),
|
||||
|
|
@ -531,20 +651,20 @@ class bdist_rpm(Command):
|
|||
if val or default:
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%' + rpm_opt,])
|
||||
'%' + rpm_opt,
|
||||
])
|
||||
if val:
|
||||
with open(val) as f:
|
||||
spec_file.extend(f.read().split('\n'))
|
||||
else:
|
||||
spec_file.append(default)
|
||||
|
||||
|
||||
# files section
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%files -f INSTALLED_FILES',
|
||||
'%defattr(-,root,root)',
|
||||
])
|
||||
])
|
||||
|
||||
if self.doc_files:
|
||||
spec_file.append('%doc ' + ' '.join(self.doc_files))
|
||||
|
|
@ -552,7 +672,8 @@ class bdist_rpm(Command):
|
|||
if self.changelog:
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%changelog',])
|
||||
'%changelog',
|
||||
])
|
||||
spec_file.extend(self.changelog)
|
||||
|
||||
return spec_file
|
||||
|
|
|
|||
|
|
@ -2,69 +2,103 @@
|
|||
|
||||
Implements the Distutils 'bdist_wininst' command: create a windows installer
|
||||
exe-program."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import Command
|
||||
from distutils.util import get_platform
|
||||
from distutils.dir_util import remove_tree
|
||||
from distutils.errors import *
|
||||
from distutils.sysconfig import get_python_version
|
||||
from distutils import log
|
||||
from distutils.util import get_platform
|
||||
|
||||
|
||||
class bdist_wininst(Command):
|
||||
|
||||
description = "create an executable installer for MS Windows"
|
||||
description = 'create an executable installer for MS Windows'
|
||||
|
||||
user_options = [('bdist-dir=', None,
|
||||
"temporary directory for creating the distribution"),
|
||||
('plat-name=', 'p',
|
||||
"platform name to embed in generated filenames "
|
||||
"(default: %s)" % get_platform()),
|
||||
('keep-temp', 'k',
|
||||
"keep the pseudo-installation tree around after " +
|
||||
"creating the distribution archive"),
|
||||
('target-version=', None,
|
||||
"require a specific python version" +
|
||||
" on the target system"),
|
||||
('no-target-compile', 'c',
|
||||
"do not compile .py to .pyc on the target system"),
|
||||
('no-target-optimize', 'o',
|
||||
"do not compile .py to .pyo (optimized) "
|
||||
"on the target system"),
|
||||
('dist-dir=', 'd',
|
||||
"directory to put final built distributions in"),
|
||||
('bitmap=', 'b',
|
||||
"bitmap to use for the installer instead of python-powered logo"),
|
||||
('title=', 't',
|
||||
"title to display on the installer background instead of default"),
|
||||
('skip-build', None,
|
||||
"skip rebuilding everything (for testing/debugging)"),
|
||||
('install-script=', None,
|
||||
"basename of installation script to be run after "
|
||||
"installation or before deinstallation"),
|
||||
('pre-install-script=', None,
|
||||
"Fully qualified filename of a script to be run before "
|
||||
"any files are installed. This script need not be in the "
|
||||
"distribution"),
|
||||
('user-access-control=', None,
|
||||
"specify Vista's UAC handling - 'none'/default=no "
|
||||
"handling, 'auto'=use UAC if target Python installed for "
|
||||
"all users, 'force'=always use UAC"),
|
||||
]
|
||||
user_options = [
|
||||
(
|
||||
'bdist-dir=', None,
|
||||
'temporary directory for creating the distribution',
|
||||
),
|
||||
(
|
||||
'plat-name=', 'p',
|
||||
'platform name to embed in generated filenames '
|
||||
'(default: %s)' % get_platform(),
|
||||
),
|
||||
(
|
||||
'keep-temp', 'k',
|
||||
'keep the pseudo-installation tree around after ' +
|
||||
'creating the distribution archive',
|
||||
),
|
||||
(
|
||||
'target-version=', None,
|
||||
'require a specific python version' +
|
||||
' on the target system',
|
||||
),
|
||||
(
|
||||
'no-target-compile', 'c',
|
||||
'do not compile .py to .pyc on the target system',
|
||||
),
|
||||
(
|
||||
'no-target-optimize', 'o',
|
||||
'do not compile .py to .pyo (optimized) '
|
||||
'on the target system',
|
||||
),
|
||||
(
|
||||
'dist-dir=', 'd',
|
||||
'directory to put final built distributions in',
|
||||
),
|
||||
(
|
||||
'bitmap=', 'b',
|
||||
'bitmap to use for the installer instead of python-powered logo',
|
||||
),
|
||||
(
|
||||
'title=', 't',
|
||||
'title to display on the installer background instead of default',
|
||||
),
|
||||
(
|
||||
'skip-build', None,
|
||||
'skip rebuilding everything (for testing/debugging)',
|
||||
),
|
||||
(
|
||||
'install-script=', None,
|
||||
'basename of installation script to be run after '
|
||||
'installation or before deinstallation',
|
||||
),
|
||||
(
|
||||
'pre-install-script=', None,
|
||||
'Fully qualified filename of a script to be run before '
|
||||
'any files are installed. This script need not be in the '
|
||||
'distribution',
|
||||
),
|
||||
(
|
||||
'user-access-control=', None,
|
||||
"specify Vista's UAC handling - 'none'/default=no "
|
||||
"handling, 'auto'=use UAC if target Python installed for "
|
||||
"all users, 'force'=always use UAC",
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
|
||||
'skip-build']
|
||||
boolean_options = [
|
||||
'keep-temp', 'no-target-compile', 'no-target-optimize',
|
||||
'skip-build',
|
||||
]
|
||||
|
||||
# bpo-10945: bdist_wininst requires mbcs encoding only available on Windows
|
||||
_unsupported = (sys.platform != "win32")
|
||||
_unsupported = (sys.platform != 'win32')
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
super().__init__(*args, **kw)
|
||||
warnings.warn("bdist_wininst command is deprecated since Python 3.8, "
|
||||
"use bdist_wheel (wheel packages) instead",
|
||||
DeprecationWarning, 2)
|
||||
warnings.warn(
|
||||
'bdist_wininst command is deprecated since Python 3.8, '
|
||||
'use bdist_wheel (wheel packages) instead',
|
||||
DeprecationWarning, 2,
|
||||
)
|
||||
|
||||
def initialize_options(self):
|
||||
self.bdist_dir = None
|
||||
|
|
@ -81,7 +115,6 @@ class bdist_wininst(Command):
|
|||
self.pre_install_script = None
|
||||
self.user_access_control = None
|
||||
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('bdist', ('skip_build', 'skip_build'))
|
||||
|
||||
|
|
@ -96,20 +129,22 @@ class bdist_wininst(Command):
|
|||
self.bdist_dir = os.path.join(bdist_base, 'wininst')
|
||||
|
||||
if not self.target_version:
|
||||
self.target_version = ""
|
||||
self.target_version = ''
|
||||
|
||||
if not self.skip_build and self.distribution.has_ext_modules():
|
||||
short_version = get_python_version()
|
||||
if self.target_version and self.target_version != short_version:
|
||||
raise DistutilsOptionError(
|
||||
"target version can only be %s, or the '--skip-build'" \
|
||||
" option must be specified" % (short_version,))
|
||||
"target version can only be %s, or the '--skip-build'"
|
||||
' option must be specified' % (short_version,),
|
||||
)
|
||||
self.target_version = short_version
|
||||
|
||||
self.set_undefined_options('bdist',
|
||||
('dist_dir', 'dist_dir'),
|
||||
('plat_name', 'plat_name'),
|
||||
)
|
||||
self.set_undefined_options(
|
||||
'bdist',
|
||||
('dist_dir', 'dist_dir'),
|
||||
('plat_name', 'plat_name'),
|
||||
)
|
||||
|
||||
if self.install_script:
|
||||
for script in self.distribution.scripts:
|
||||
|
|
@ -117,16 +152,22 @@ class bdist_wininst(Command):
|
|||
break
|
||||
else:
|
||||
raise DistutilsOptionError(
|
||||
"install_script '%s' not found in scripts"
|
||||
% self.install_script)
|
||||
"install_script '%s' not found in scripts"
|
||||
% self.install_script,
|
||||
)
|
||||
|
||||
def run(self):
|
||||
if (sys.platform != "win32" and
|
||||
(self.distribution.has_ext_modules() or
|
||||
self.distribution.has_c_libraries())):
|
||||
raise DistutilsPlatformError \
|
||||
("distribution contains extensions and/or C libraries; "
|
||||
"must be compiled on a Windows 32 platform")
|
||||
if (
|
||||
sys.platform != 'win32' and
|
||||
(
|
||||
self.distribution.has_ext_modules() or
|
||||
self.distribution.has_c_libraries()
|
||||
)
|
||||
):
|
||||
raise DistutilsPlatformError(
|
||||
'distribution contains extensions and/or C libraries; '
|
||||
'must be compiled on a Windows 32 platform',
|
||||
)
|
||||
|
||||
if not self.skip_build:
|
||||
self.run_command('build')
|
||||
|
|
@ -151,12 +192,14 @@ class bdist_wininst(Command):
|
|||
# version.
|
||||
target_version = self.target_version
|
||||
if not target_version:
|
||||
assert self.skip_build, "Should have already checked this"
|
||||
assert self.skip_build, 'Should have already checked this'
|
||||
target_version = '%d.%d' % sys.version_info[:2]
|
||||
plat_specifier = ".%s-%s" % (self.plat_name, target_version)
|
||||
plat_specifier = '.{}-{}'.format(self.plat_name, target_version)
|
||||
build = self.get_finalized_command('build')
|
||||
build.build_lib = os.path.join(build.build_base,
|
||||
'lib' + plat_specifier)
|
||||
build.build_lib = os.path.join(
|
||||
build.build_base,
|
||||
'lib' + plat_specifier,
|
||||
)
|
||||
|
||||
# Use a custom scheme for the zip-file, because we have to decide
|
||||
# at installation time which scheme to use.
|
||||
|
|
@ -164,11 +207,13 @@ class bdist_wininst(Command):
|
|||
value = key.upper()
|
||||
if key == 'headers':
|
||||
value = value + '/Include/$dist_name'
|
||||
setattr(install,
|
||||
'install_' + key,
|
||||
value)
|
||||
setattr(
|
||||
install,
|
||||
'install_' + key,
|
||||
value,
|
||||
)
|
||||
|
||||
log.info("installing to %s", self.bdist_dir)
|
||||
log.info('installing to %s', self.bdist_dir)
|
||||
install.ensure_finalized()
|
||||
|
||||
# avoid warning of 'install_lib' about installing
|
||||
|
|
@ -184,16 +229,20 @@ class bdist_wininst(Command):
|
|||
from tempfile import mktemp
|
||||
archive_basename = mktemp()
|
||||
fullname = self.distribution.get_fullname()
|
||||
arcname = self.make_archive(archive_basename, "zip",
|
||||
root_dir=self.bdist_dir)
|
||||
arcname = self.make_archive(
|
||||
archive_basename, 'zip',
|
||||
root_dir=self.bdist_dir,
|
||||
)
|
||||
# create an exe containing the zip-file
|
||||
self.create_exe(arcname, fullname, self.bitmap)
|
||||
if self.distribution.has_ext_modules():
|
||||
pyversion = get_python_version()
|
||||
else:
|
||||
pyversion = 'any'
|
||||
self.distribution.dist_files.append(('bdist_wininst', pyversion,
|
||||
self.get_installer_filename(fullname)))
|
||||
self.distribution.dist_files.append((
|
||||
'bdist_wininst', pyversion,
|
||||
self.get_installer_filename(fullname),
|
||||
))
|
||||
# remove the zip-file again
|
||||
log.debug("removing temporary file '%s'", arcname)
|
||||
os.remove(arcname)
|
||||
|
|
@ -207,7 +256,7 @@ class bdist_wininst(Command):
|
|||
metadata = self.distribution.metadata
|
||||
|
||||
# Write the [metadata] section.
|
||||
lines.append("[metadata]")
|
||||
lines.append('[metadata]')
|
||||
|
||||
# 'info' will be displayed in the installer's dialog box,
|
||||
# describing the items to be installed.
|
||||
|
|
@ -215,37 +264,41 @@ class bdist_wininst(Command):
|
|||
|
||||
# Escape newline characters
|
||||
def escape(s):
|
||||
return s.replace("\n", "\\n")
|
||||
return s.replace('\n', '\\n')
|
||||
|
||||
for name in ["author", "author_email", "description", "maintainer",
|
||||
"maintainer_email", "name", "url", "version"]:
|
||||
data = getattr(metadata, name, "")
|
||||
for name in [
|
||||
'author', 'author_email', 'description', 'maintainer',
|
||||
'maintainer_email', 'name', 'url', 'version',
|
||||
]:
|
||||
data = getattr(metadata, name, '')
|
||||
if data:
|
||||
info = info + ("\n %s: %s" % \
|
||||
(name.capitalize(), escape(data)))
|
||||
lines.append("%s=%s" % (name, escape(data)))
|
||||
info = info + (
|
||||
'\n %s: %s' %
|
||||
(name.capitalize(), escape(data))
|
||||
)
|
||||
lines.append('{}={}'.format(name, escape(data)))
|
||||
|
||||
# The [setup] section contains entries controlling
|
||||
# the installer runtime.
|
||||
lines.append("\n[Setup]")
|
||||
lines.append('\n[Setup]')
|
||||
if self.install_script:
|
||||
lines.append("install_script=%s" % self.install_script)
|
||||
lines.append("info=%s" % escape(info))
|
||||
lines.append("target_compile=%d" % (not self.no_target_compile))
|
||||
lines.append("target_optimize=%d" % (not self.no_target_optimize))
|
||||
lines.append('install_script=%s' % self.install_script)
|
||||
lines.append('info=%s' % escape(info))
|
||||
lines.append('target_compile=%d' % (not self.no_target_compile))
|
||||
lines.append('target_optimize=%d' % (not self.no_target_optimize))
|
||||
if self.target_version:
|
||||
lines.append("target_version=%s" % self.target_version)
|
||||
lines.append('target_version=%s' % self.target_version)
|
||||
if self.user_access_control:
|
||||
lines.append("user_access_control=%s" % self.user_access_control)
|
||||
lines.append('user_access_control=%s' % self.user_access_control)
|
||||
|
||||
title = self.title or self.distribution.get_fullname()
|
||||
lines.append("title=%s" % escape(title))
|
||||
lines.append('title=%s' % escape(title))
|
||||
import time
|
||||
import distutils
|
||||
build_info = "Built %s with distutils-%s" % \
|
||||
build_info = 'Built %s with distutils-%s' % \
|
||||
(time.ctime(time.time()), distutils.__version__)
|
||||
lines.append("build_info=%s" % build_info)
|
||||
return "\n".join(lines)
|
||||
lines.append('build_info=%s' % build_info)
|
||||
return '\n'.join(lines)
|
||||
|
||||
def create_exe(self, arcname, fullname, bitmap=None):
|
||||
import struct
|
||||
|
|
@ -255,37 +308,39 @@ class bdist_wininst(Command):
|
|||
cfgdata = self.get_inidata()
|
||||
|
||||
installer_name = self.get_installer_filename(fullname)
|
||||
self.announce("creating %s" % installer_name)
|
||||
self.announce('creating %s' % installer_name)
|
||||
|
||||
if bitmap:
|
||||
with open(bitmap, "rb") as f:
|
||||
with open(bitmap, 'rb') as f:
|
||||
bitmapdata = f.read()
|
||||
bitmaplen = len(bitmapdata)
|
||||
else:
|
||||
bitmaplen = 0
|
||||
|
||||
with open(installer_name, "wb") as file:
|
||||
with open(installer_name, 'wb') as file:
|
||||
file.write(self.get_exe_bytes())
|
||||
if bitmap:
|
||||
file.write(bitmapdata)
|
||||
|
||||
# Convert cfgdata from unicode to ascii, mbcs encoded
|
||||
if isinstance(cfgdata, str):
|
||||
cfgdata = cfgdata.encode("mbcs")
|
||||
cfgdata = cfgdata.encode('mbcs')
|
||||
|
||||
# Append the pre-install script
|
||||
cfgdata = cfgdata + b"\0"
|
||||
cfgdata = cfgdata + b'\0'
|
||||
if self.pre_install_script:
|
||||
# We need to normalize newlines, so we open in text mode and
|
||||
# convert back to bytes. "latin-1" simply avoids any possible
|
||||
# failures.
|
||||
with open(self.pre_install_script, "r",
|
||||
encoding="latin-1") as script:
|
||||
script_data = script.read().encode("latin-1")
|
||||
cfgdata = cfgdata + script_data + b"\n\0"
|
||||
with open(
|
||||
self.pre_install_script,
|
||||
encoding='latin-1',
|
||||
) as script:
|
||||
script_data = script.read().encode('latin-1')
|
||||
cfgdata = cfgdata + script_data + b'\n\0'
|
||||
else:
|
||||
# empty pre-install script
|
||||
cfgdata = cfgdata + b"\0"
|
||||
cfgdata = cfgdata + b'\0'
|
||||
file.write(cfgdata)
|
||||
|
||||
# The 'magic number' 0x1234567B is used to make sure that the
|
||||
|
|
@ -293,13 +348,14 @@ class bdist_wininst(Command):
|
|||
# expects. If the layout changes, increment that number, make
|
||||
# the corresponding changes to the wininst.exe sources, and
|
||||
# recompile them.
|
||||
header = struct.pack("<iii",
|
||||
0x1234567B, # tag
|
||||
len(cfgdata), # length
|
||||
bitmaplen, # number of bytes in bitmap
|
||||
)
|
||||
header = struct.pack(
|
||||
'<iii',
|
||||
0x1234567B, # tag
|
||||
len(cfgdata), # length
|
||||
bitmaplen, # number of bytes in bitmap
|
||||
)
|
||||
file.write(header)
|
||||
with open(arcname, "rb") as f:
|
||||
with open(arcname, 'rb') as f:
|
||||
file.write(f.read())
|
||||
|
||||
def get_installer_filename(self, fullname):
|
||||
|
|
@ -307,12 +363,16 @@ class bdist_wininst(Command):
|
|||
if self.target_version:
|
||||
# if we create an installer for a specific python version,
|
||||
# it's better to include this in the name
|
||||
installer_name = os.path.join(self.dist_dir,
|
||||
"%s.%s-py%s.exe" %
|
||||
(fullname, self.plat_name, self.target_version))
|
||||
installer_name = os.path.join(
|
||||
self.dist_dir,
|
||||
'%s.%s-py%s.exe' %
|
||||
(fullname, self.plat_name, self.target_version),
|
||||
)
|
||||
else:
|
||||
installer_name = os.path.join(self.dist_dir,
|
||||
"%s.%s.exe" % (fullname, self.plat_name))
|
||||
installer_name = os.path.join(
|
||||
self.dist_dir,
|
||||
'{}.{}.exe'.format(fullname, self.plat_name),
|
||||
)
|
||||
return installer_name
|
||||
|
||||
def get_exe_bytes(self):
|
||||
|
|
@ -330,15 +390,15 @@ class bdist_wininst(Command):
|
|||
# use what we use
|
||||
# string compares seem wrong, but are what sysconfig.py itself uses
|
||||
if self.target_version and self.target_version < cur_version:
|
||||
if self.target_version < "2.4":
|
||||
if self.target_version < '2.4':
|
||||
bv = '6.0'
|
||||
elif self.target_version == "2.4":
|
||||
elif self.target_version == '2.4':
|
||||
bv = '7.1'
|
||||
elif self.target_version == "2.5":
|
||||
elif self.target_version == '2.5':
|
||||
bv = '8.0'
|
||||
elif self.target_version <= "3.2":
|
||||
elif self.target_version <= '3.2':
|
||||
bv = '9.0'
|
||||
elif self.target_version <= "3.4":
|
||||
elif self.target_version <= '3.4':
|
||||
bv = '10.0'
|
||||
else:
|
||||
bv = '14.0'
|
||||
|
|
@ -355,7 +415,6 @@ class bdist_wininst(Command):
|
|||
major = CRT_ASSEMBLY_VERSION.partition('.')[0]
|
||||
bv = major + '.0'
|
||||
|
||||
|
||||
# wininst-x.y.exe is in the same directory as this file
|
||||
directory = os.path.dirname(__file__)
|
||||
# we must use a wininst-x.y.exe built with the same C compiler
|
||||
|
|
@ -369,8 +428,8 @@ class bdist_wininst(Command):
|
|||
else:
|
||||
sfix = ''
|
||||
|
||||
filename = os.path.join(directory, "wininst-%s%s.exe" % (bv, sfix))
|
||||
f = open(filename, "rb")
|
||||
filename = os.path.join(directory, 'wininst-{}{}.exe'.format(bv, sfix))
|
||||
f = open(filename, 'rb')
|
||||
try:
|
||||
return f.read()
|
||||
finally:
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
"""distutils.command.build
|
||||
|
||||
Implements the Distutils 'build' command."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import sys, os
|
||||
from distutils.core import Command
|
||||
from distutils.errors import DistutilsOptionError
|
||||
from distutils.util import get_platform
|
||||
|
|
@ -15,43 +18,69 @@ def show_compilers():
|
|||
|
||||
class build(Command):
|
||||
|
||||
description = "build everything needed to install"
|
||||
description = 'build everything needed to install'
|
||||
|
||||
user_options = [
|
||||
('build-base=', 'b',
|
||||
"base directory for build library"),
|
||||
('build-purelib=', None,
|
||||
"build directory for platform-neutral distributions"),
|
||||
('build-platlib=', None,
|
||||
"build directory for platform-specific distributions"),
|
||||
('build-lib=', None,
|
||||
"build directory for all distribution (defaults to either " +
|
||||
"build-purelib or build-platlib"),
|
||||
('build-scripts=', None,
|
||||
"build directory for scripts"),
|
||||
('build-temp=', 't',
|
||||
"temporary build directory"),
|
||||
('plat-name=', 'p',
|
||||
"platform name to build for, if supported "
|
||||
"(default: %s)" % get_platform()),
|
||||
('compiler=', 'c',
|
||||
"specify the compiler type"),
|
||||
('parallel=', 'j',
|
||||
"number of parallel build jobs"),
|
||||
('debug', 'g',
|
||||
"compile extensions and libraries with debugging information"),
|
||||
('force', 'f',
|
||||
"forcibly build everything (ignore file timestamps)"),
|
||||
('executable=', 'e',
|
||||
"specify final destination interpreter path (build.py)"),
|
||||
]
|
||||
(
|
||||
'build-base=', 'b',
|
||||
'base directory for build library',
|
||||
),
|
||||
(
|
||||
'build-purelib=', None,
|
||||
'build directory for platform-neutral distributions',
|
||||
),
|
||||
(
|
||||
'build-platlib=', None,
|
||||
'build directory for platform-specific distributions',
|
||||
),
|
||||
(
|
||||
'build-lib=', None,
|
||||
'build directory for all distribution (defaults to either ' +
|
||||
'build-purelib or build-platlib',
|
||||
),
|
||||
(
|
||||
'build-scripts=', None,
|
||||
'build directory for scripts',
|
||||
),
|
||||
(
|
||||
'build-temp=', 't',
|
||||
'temporary build directory',
|
||||
),
|
||||
(
|
||||
'plat-name=', 'p',
|
||||
'platform name to build for, if supported '
|
||||
'(default: %s)' % get_platform(),
|
||||
),
|
||||
(
|
||||
'compiler=', 'c',
|
||||
'specify the compiler type',
|
||||
),
|
||||
(
|
||||
'parallel=', 'j',
|
||||
'number of parallel build jobs',
|
||||
),
|
||||
(
|
||||
'debug', 'g',
|
||||
'compile extensions and libraries with debugging information',
|
||||
),
|
||||
(
|
||||
'force', 'f',
|
||||
'forcibly build everything (ignore file timestamps)',
|
||||
),
|
||||
(
|
||||
'executable=', 'e',
|
||||
'specify final destination interpreter path (build.py)',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['debug', 'force']
|
||||
|
||||
help_options = [
|
||||
('help-compiler', None,
|
||||
"list available compilers", show_compilers),
|
||||
]
|
||||
(
|
||||
'help-compiler', None,
|
||||
'list available compilers', show_compilers,
|
||||
),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_base = 'build'
|
||||
|
|
@ -78,10 +107,11 @@ class build(Command):
|
|||
# other platforms.
|
||||
if os.name != 'nt':
|
||||
raise DistutilsOptionError(
|
||||
"--plat-name only supported on Windows (try "
|
||||
"using './configure --help' on your platform)")
|
||||
'--plat-name only supported on Windows (try '
|
||||
"using './configure --help' on your platform)",
|
||||
)
|
||||
|
||||
plat_specifier = ".%s-%d.%d" % (self.plat_name, *sys.version_info[:2])
|
||||
plat_specifier = '.%s-%d.%d' % (self.plat_name, *sys.version_info[:2])
|
||||
|
||||
# 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
|
||||
|
|
@ -95,8 +125,10 @@ class build(Command):
|
|||
if self.build_purelib is None:
|
||||
self.build_purelib = os.path.join(self.build_base, 'lib')
|
||||
if self.build_platlib is None:
|
||||
self.build_platlib = os.path.join(self.build_base,
|
||||
'lib' + plat_specifier)
|
||||
self.build_platlib = os.path.join(
|
||||
self.build_base,
|
||||
'lib' + plat_specifier,
|
||||
)
|
||||
|
||||
# 'build_lib' is the actual directory that we will use for this
|
||||
# particular module distribution -- if user didn't supply it, pick
|
||||
|
|
@ -110,11 +142,15 @@ class build(Command):
|
|||
# 'build_temp' -- temporary directory for compiler turds,
|
||||
# "build/temp.<plat>"
|
||||
if self.build_temp is None:
|
||||
self.build_temp = os.path.join(self.build_base,
|
||||
'temp' + plat_specifier)
|
||||
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,
|
||||
'scripts-%d.%d' % sys.version_info[:2])
|
||||
self.build_scripts = os.path.join(
|
||||
self.build_base,
|
||||
'scripts-%d.%d' % sys.version_info[:2],
|
||||
)
|
||||
|
||||
if self.executable is None and sys.executable:
|
||||
self.executable = os.path.normpath(sys.executable)
|
||||
|
|
@ -123,7 +159,7 @@ class build(Command):
|
|||
try:
|
||||
self.parallel = int(self.parallel)
|
||||
except ValueError:
|
||||
raise DistutilsOptionError("parallel should be an integer")
|
||||
raise DistutilsOptionError('parallel should be an integer')
|
||||
|
||||
def run(self):
|
||||
# Run all relevant sub-commands. This will be some subset of:
|
||||
|
|
@ -134,7 +170,6 @@ class build(Command):
|
|||
for cmd_name in self.get_sub_commands():
|
||||
self.run_command(cmd_name)
|
||||
|
||||
|
||||
# -- Predicates for the sub-command list ---------------------------
|
||||
|
||||
def has_pure_modules(self):
|
||||
|
|
@ -149,9 +184,9 @@ class build(Command):
|
|||
def has_scripts(self):
|
||||
return self.distribution.has_scripts()
|
||||
|
||||
|
||||
sub_commands = [('build_py', has_pure_modules),
|
||||
('build_clib', has_c_libraries),
|
||||
('build_ext', has_ext_modules),
|
||||
('build_scripts', has_scripts),
|
||||
]
|
||||
sub_commands = [
|
||||
('build_py', has_pure_modules),
|
||||
('build_clib', has_c_libraries),
|
||||
('build_ext', has_ext_modules),
|
||||
('build_scripts', has_scripts),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
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
|
||||
|
|
@ -13,12 +11,15 @@ 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 distutils import log
|
||||
from distutils.core import Command
|
||||
from distutils.errors import *
|
||||
from distutils.sysconfig import customize_compiler
|
||||
from distutils import log
|
||||
|
||||
|
||||
def show_compilers():
|
||||
from distutils.ccompiler import show_compilers
|
||||
|
|
@ -27,27 +28,39 @@ def show_compilers():
|
|||
|
||||
class build_clib(Command):
|
||||
|
||||
description = "build C/C++ libraries used by Python extensions"
|
||||
description = 'build C/C++ libraries used by Python extensions'
|
||||
|
||||
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"),
|
||||
('force', 'f',
|
||||
"forcibly build everything (ignore file timestamps)"),
|
||||
('compiler=', 'c',
|
||||
"specify the compiler type"),
|
||||
]
|
||||
(
|
||||
'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',
|
||||
),
|
||||
(
|
||||
'force', 'f',
|
||||
'forcibly build everything (ignore file timestamps)',
|
||||
),
|
||||
(
|
||||
'compiler=', 'c',
|
||||
'specify the compiler type',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['debug', 'force']
|
||||
|
||||
help_options = [
|
||||
('help-compiler', None,
|
||||
"list available compilers", show_compilers),
|
||||
]
|
||||
(
|
||||
'help-compiler', None,
|
||||
'list available compilers', show_compilers,
|
||||
),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_clib = None
|
||||
|
|
@ -64,19 +77,20 @@ class build_clib(Command):
|
|||
self.force = 0
|
||||
self.compiler = 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
|
||||
# by-products, at least from the point of view of building Python
|
||||
# extensions -- but I want to keep my options open.
|
||||
self.set_undefined_options('build',
|
||||
('build_temp', 'build_clib'),
|
||||
('build_temp', 'build_temp'),
|
||||
('compiler', 'compiler'),
|
||||
('debug', 'debug'),
|
||||
('force', 'force'))
|
||||
self.set_undefined_options(
|
||||
'build',
|
||||
('build_temp', 'build_clib'),
|
||||
('build_temp', 'build_temp'),
|
||||
('compiler', 'compiler'),
|
||||
('debug', 'debug'),
|
||||
('force', 'force'),
|
||||
)
|
||||
|
||||
self.libraries = self.distribution.libraries
|
||||
if self.libraries:
|
||||
|
|
@ -90,23 +104,24 @@ class build_clib(Command):
|
|||
# XXX same as for build_ext -- what about 'self.define' and
|
||||
# 'self.undef' ?
|
||||
|
||||
|
||||
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)
|
||||
self.compiler = new_compiler(
|
||||
compiler=self.compiler,
|
||||
dry_run=self.dry_run,
|
||||
force=self.force,
|
||||
)
|
||||
customize_compiler(self.compiler)
|
||||
|
||||
if self.include_dirs is not None:
|
||||
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:
|
||||
|
|
@ -114,7 +129,6 @@ class build_clib(Command):
|
|||
|
||||
self.build_libraries(self.libraries)
|
||||
|
||||
|
||||
def check_library_list(self, libraries):
|
||||
"""Ensure that the list of libraries is valid.
|
||||
|
||||
|
|
@ -127,29 +141,34 @@ class build_clib(Command):
|
|||
"""
|
||||
if not isinstance(libraries, list):
|
||||
raise DistutilsSetupError(
|
||||
"'libraries' option must be a list of tuples")
|
||||
"'libraries' option must be a list of tuples",
|
||||
)
|
||||
|
||||
for lib in libraries:
|
||||
if not isinstance(lib, tuple) and len(lib) != 2:
|
||||
raise DistutilsSetupError(
|
||||
"each element of 'libraries' must a 2-tuple")
|
||||
"each element of 'libraries' must a 2-tuple",
|
||||
)
|
||||
|
||||
name, build_info = lib
|
||||
|
||||
if not isinstance(name, str):
|
||||
raise DistutilsSetupError(
|
||||
"first element of each tuple in 'libraries' "
|
||||
"must be a string (the library name)")
|
||||
"first element of each tuple in 'libraries' "
|
||||
'must be a string (the library name)',
|
||||
)
|
||||
|
||||
if '/' in name or (os.sep != '/' and os.sep in name):
|
||||
raise DistutilsSetupError("bad library name '%s': "
|
||||
"may not contain directory separators" % lib[0])
|
||||
raise DistutilsSetupError(
|
||||
"bad library name '%s': "
|
||||
'may not contain directory separators' % lib[0],
|
||||
)
|
||||
|
||||
if not isinstance(build_info, dict):
|
||||
raise DistutilsSetupError(
|
||||
"second element of each tuple in 'libraries' "
|
||||
"must be a dictionary (build info)")
|
||||
|
||||
"second element of each tuple in 'libraries' "
|
||||
'must be a dictionary (build info)',
|
||||
)
|
||||
|
||||
def get_library_names(self):
|
||||
# Assume the library list is valid -- 'check_library_list()' is
|
||||
|
|
@ -162,7 +181,6 @@ class build_clib(Command):
|
|||
lib_names.append(lib_name)
|
||||
return lib_names
|
||||
|
||||
|
||||
def get_source_files(self):
|
||||
self.check_library_list(self.libraries)
|
||||
filenames = []
|
||||
|
|
@ -170,22 +188,23 @@ class build_clib(Command):
|
|||
sources = build_info.get('sources')
|
||||
if sources is None or not isinstance(sources, (list, tuple)):
|
||||
raise DistutilsSetupError(
|
||||
"in 'libraries' option (library '%s'), "
|
||||
"'sources' must be present and must be "
|
||||
"a list of source filenames" % lib_name)
|
||||
"in 'libraries' option (library '%s'), "
|
||||
"'sources' must be present and must be "
|
||||
'a list of source filenames' % lib_name,
|
||||
)
|
||||
|
||||
filenames.extend(sources)
|
||||
return filenames
|
||||
|
||||
|
||||
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(
|
||||
"in 'libraries' option (library '%s'), "
|
||||
"'sources' must be present and must be "
|
||||
"a list of source filenames" % lib_name)
|
||||
"in 'libraries' option (library '%s'), "
|
||||
"'sources' must be present and must be "
|
||||
'a list of source filenames' % lib_name,
|
||||
)
|
||||
sources = list(sources)
|
||||
|
||||
log.info("building '%s' library", lib_name)
|
||||
|
|
@ -195,15 +214,19 @@ class build_clib(Command):
|
|||
# files in a temporary build directory.)
|
||||
macros = build_info.get('macros')
|
||||
include_dirs = build_info.get('include_dirs')
|
||||
objects = self.compiler.compile(sources,
|
||||
output_dir=self.build_temp,
|
||||
macros=macros,
|
||||
include_dirs=include_dirs,
|
||||
debug=self.debug)
|
||||
objects = self.compiler.compile(
|
||||
sources,
|
||||
output_dir=self.build_temp,
|
||||
macros=macros,
|
||||
include_dirs=include_dirs,
|
||||
debug=self.debug,
|
||||
)
|
||||
|
||||
# Now "link" the object files together into a static library.
|
||||
# (On Unix at least, this isn't really linking -- it just
|
||||
# builds an archive. Whatever.)
|
||||
self.compiler.create_static_lib(objects, lib_name,
|
||||
output_dir=self.build_clib,
|
||||
debug=self.debug)
|
||||
self.compiler.create_static_lib(
|
||||
objects, lib_name,
|
||||
output_dir=self.build_clib,
|
||||
debug=self.debug,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,37 +3,39 @@
|
|||
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 distutils.core import Command
|
||||
from distutils.errors import *
|
||||
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
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import Command
|
||||
from distutils.dep_util import newer_group
|
||||
from distutils.errors import *
|
||||
from distutils.extension import Extension
|
||||
from distutils.sysconfig import customize_compiler
|
||||
from distutils.sysconfig import get_config_h_filename
|
||||
from distutils.sysconfig import get_python_version
|
||||
from distutils.util import get_platform
|
||||
|
||||
from . import py37compat
|
||||
|
||||
# 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]*)*$')
|
||||
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 ():
|
||||
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)"
|
||||
description = 'build C/C++ extensions (compile/link to build directory)'
|
||||
|
||||
# XXX thoughts on how to deal with complex command-line options like
|
||||
# these, i.e. how to make it so fancy_getopt can suck them off the
|
||||
|
|
@ -55,54 +57,94 @@ class build_ext(Command):
|
|||
|
||||
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)"),
|
||||
('plat-name=', 'p',
|
||||
"platform name to cross-compile for, if supported "
|
||||
"(default: %s)" % get_platform()),
|
||||
('inplace', 'i',
|
||||
"ignore build-lib and put compiled extensions into the source " +
|
||||
"directory alongside your pure Python modules"),
|
||||
('include-dirs=', 'I',
|
||||
"list of directories to search for header files" + sep_by),
|
||||
('define=', 'D',
|
||||
"C preprocessor macros to define"),
|
||||
('undef=', 'U',
|
||||
"C preprocessor macros to undefine"),
|
||||
('libraries=', 'l',
|
||||
"external C libraries to link with"),
|
||||
('library-dirs=', 'L',
|
||||
"directories to search for external C libraries" + sep_by),
|
||||
('rpath=', 'R',
|
||||
"directories to search for shared C libraries at runtime"),
|
||||
('link-objects=', 'O',
|
||||
"extra explicit link objects to include in the link"),
|
||||
('debug', 'g',
|
||||
"compile/link with debugging information"),
|
||||
('force', 'f',
|
||||
"forcibly build everything (ignore file timestamps)"),
|
||||
('compiler=', 'c',
|
||||
"specify the compiler type"),
|
||||
('parallel=', 'j',
|
||||
"number of parallel build jobs"),
|
||||
('swig-cpp', None,
|
||||
"make SWIG create C++ files (default is C)"),
|
||||
('swig-opts=', None,
|
||||
"list of SWIG command line options"),
|
||||
('swig=', None,
|
||||
"path to the SWIG executable"),
|
||||
('user', None,
|
||||
"add user include, library and rpath")
|
||||
]
|
||||
(
|
||||
'build-lib=', 'b',
|
||||
'directory for compiled extension modules',
|
||||
),
|
||||
(
|
||||
'build-temp=', 't',
|
||||
'directory for temporary files (build by-products)',
|
||||
),
|
||||
(
|
||||
'plat-name=', 'p',
|
||||
'platform name to cross-compile for, if supported '
|
||||
'(default: %s)' % get_platform(),
|
||||
),
|
||||
(
|
||||
'inplace', 'i',
|
||||
'ignore build-lib and put compiled extensions into the source ' +
|
||||
'directory alongside your pure Python modules',
|
||||
),
|
||||
(
|
||||
'include-dirs=', 'I',
|
||||
'list of directories to search for header files' + sep_by,
|
||||
),
|
||||
(
|
||||
'define=', 'D',
|
||||
'C preprocessor macros to define',
|
||||
),
|
||||
(
|
||||
'undef=', 'U',
|
||||
'C preprocessor macros to undefine',
|
||||
),
|
||||
(
|
||||
'libraries=', 'l',
|
||||
'external C libraries to link with',
|
||||
),
|
||||
(
|
||||
'library-dirs=', 'L',
|
||||
'directories to search for external C libraries' + sep_by,
|
||||
),
|
||||
(
|
||||
'rpath=', 'R',
|
||||
'directories to search for shared C libraries at runtime',
|
||||
),
|
||||
(
|
||||
'link-objects=', 'O',
|
||||
'extra explicit link objects to include in the link',
|
||||
),
|
||||
(
|
||||
'debug', 'g',
|
||||
'compile/link with debugging information',
|
||||
),
|
||||
(
|
||||
'force', 'f',
|
||||
'forcibly build everything (ignore file timestamps)',
|
||||
),
|
||||
(
|
||||
'compiler=', 'c',
|
||||
'specify the compiler type',
|
||||
),
|
||||
(
|
||||
'parallel=', 'j',
|
||||
'number of parallel build jobs',
|
||||
),
|
||||
(
|
||||
'swig-cpp', None,
|
||||
'make SWIG create C++ files (default is C)',
|
||||
),
|
||||
(
|
||||
'swig-opts=', None,
|
||||
'list of SWIG command line options',
|
||||
),
|
||||
(
|
||||
'swig=', None,
|
||||
'path to the SWIG executable',
|
||||
),
|
||||
(
|
||||
'user', None,
|
||||
'add user include, library and rpath',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user']
|
||||
|
||||
help_options = [
|
||||
('help-compiler', None,
|
||||
"list available compilers", show_compilers),
|
||||
]
|
||||
(
|
||||
'help-compiler', None,
|
||||
'list available compilers', show_compilers,
|
||||
),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.extensions = None
|
||||
|
|
@ -131,15 +173,16 @@ class build_ext(Command):
|
|||
def finalize_options(self):
|
||||
from distutils import sysconfig
|
||||
|
||||
self.set_undefined_options('build',
|
||||
('build_lib', 'build_lib'),
|
||||
('build_temp', 'build_temp'),
|
||||
('compiler', 'compiler'),
|
||||
('debug', 'debug'),
|
||||
('force', 'force'),
|
||||
('parallel', 'parallel'),
|
||||
('plat_name', 'plat_name'),
|
||||
)
|
||||
self.set_undefined_options(
|
||||
'build',
|
||||
('build_lib', 'build_lib'),
|
||||
('build_temp', 'build_temp'),
|
||||
('compiler', 'compiler'),
|
||||
('debug', 'debug'),
|
||||
('force', 'force'),
|
||||
('parallel', 'parallel'),
|
||||
('plat_name', 'plat_name'),
|
||||
)
|
||||
|
||||
if self.package is None:
|
||||
self.package = self.distribution.ext_package
|
||||
|
|
@ -165,7 +208,8 @@ class build_ext(Command):
|
|||
self.include_dirs.extend(py_include.split(os.path.pathsep))
|
||||
if plat_py_include != py_include:
|
||||
self.include_dirs.extend(
|
||||
plat_py_include.split(os.path.pathsep))
|
||||
plat_py_include.split(os.path.pathsep),
|
||||
)
|
||||
|
||||
self.ensure_string_list('libraries')
|
||||
self.ensure_string_list('link_objects')
|
||||
|
|
@ -195,9 +239,9 @@ class build_ext(Command):
|
|||
if sys.base_exec_prefix != sys.prefix: # Issue 16116
|
||||
self.library_dirs.append(os.path.join(sys.base_exec_prefix, 'libs'))
|
||||
if self.debug:
|
||||
self.build_temp = os.path.join(self.build_temp, "Debug")
|
||||
self.build_temp = os.path.join(self.build_temp, 'Debug')
|
||||
else:
|
||||
self.build_temp = os.path.join(self.build_temp, "Release")
|
||||
self.build_temp = os.path.join(self.build_temp, 'Release')
|
||||
|
||||
# Append the source distribution include and library directories,
|
||||
# this allows distutils on windows to work in the source tree
|
||||
|
|
@ -222,9 +266,13 @@ class build_ext(Command):
|
|||
if sys.platform[:6] == 'cygwin':
|
||||
if not sysconfig.python_build:
|
||||
# building third party extensions
|
||||
self.library_dirs.append(os.path.join(sys.prefix, "lib",
|
||||
"python" + get_python_version(),
|
||||
"config"))
|
||||
self.library_dirs.append(
|
||||
os.path.join(
|
||||
sys.prefix, 'lib',
|
||||
'python' + get_python_version(),
|
||||
'config',
|
||||
),
|
||||
)
|
||||
else:
|
||||
# building python standard extensions
|
||||
self.library_dirs.append('.')
|
||||
|
|
@ -262,8 +310,8 @@ class build_ext(Command):
|
|||
|
||||
# Finally add the user include and library directories if requested
|
||||
if self.user:
|
||||
user_include = os.path.join(USER_BASE, "include")
|
||||
user_lib = os.path.join(USER_BASE, "lib")
|
||||
user_include = os.path.join(USER_BASE, 'include')
|
||||
user_lib = os.path.join(USER_BASE, 'lib')
|
||||
if os.path.isdir(user_include):
|
||||
self.include_dirs.append(user_include)
|
||||
if os.path.isdir(user_lib):
|
||||
|
|
@ -274,7 +322,7 @@ class build_ext(Command):
|
|||
try:
|
||||
self.parallel = int(self.parallel)
|
||||
except ValueError:
|
||||
raise DistutilsOptionError("parallel should be an integer")
|
||||
raise DistutilsOptionError('parallel should be an integer')
|
||||
|
||||
def run(self):
|
||||
from distutils.ccompiler import new_compiler
|
||||
|
|
@ -304,10 +352,12 @@ class build_ext(Command):
|
|||
|
||||
# Setup the CCompiler object that we'll use to do all the
|
||||
# compiling and linking
|
||||
self.compiler = new_compiler(compiler=self.compiler,
|
||||
verbose=self.verbose,
|
||||
dry_run=self.dry_run,
|
||||
force=self.force)
|
||||
self.compiler = new_compiler(
|
||||
compiler=self.compiler,
|
||||
verbose=self.verbose,
|
||||
dry_run=self.dry_run,
|
||||
force=self.force,
|
||||
)
|
||||
customize_compiler(self.compiler)
|
||||
# If we are cross-compiling, init the compiler now (if we are not
|
||||
# cross-compiling, init would not hurt, but people may rely on
|
||||
|
|
@ -352,34 +402,42 @@ class build_ext(Command):
|
|||
"""
|
||||
if not isinstance(extensions, list):
|
||||
raise DistutilsSetupError(
|
||||
"'ext_modules' option must be a list of Extension instances")
|
||||
"'ext_modules' option must be a list of Extension instances",
|
||||
)
|
||||
|
||||
for i, ext in enumerate(extensions):
|
||||
if isinstance(ext, Extension):
|
||||
continue # OK! (assume type-checking done
|
||||
# by Extension constructor)
|
||||
# by Extension constructor)
|
||||
|
||||
if not isinstance(ext, tuple) or len(ext) != 2:
|
||||
raise DistutilsSetupError(
|
||||
"each element of 'ext_modules' option must be an "
|
||||
"Extension instance or 2-tuple")
|
||||
"each element of 'ext_modules' option must be an "
|
||||
'Extension instance or 2-tuple',
|
||||
)
|
||||
|
||||
ext_name, build_info = ext
|
||||
|
||||
log.warn("old-style (ext_name, build_info) tuple found in "
|
||||
"ext_modules for extension '%s' "
|
||||
"-- please convert to Extension instance", ext_name)
|
||||
log.warn(
|
||||
'old-style (ext_name, build_info) tuple found in '
|
||||
"ext_modules for extension '%s' "
|
||||
'-- please convert to Extension instance', ext_name,
|
||||
)
|
||||
|
||||
if not (isinstance(ext_name, str) and
|
||||
extension_name_re.match(ext_name)):
|
||||
if not (
|
||||
isinstance(ext_name, str) and
|
||||
extension_name_re.match(ext_name)
|
||||
):
|
||||
raise DistutilsSetupError(
|
||||
"first element of each tuple in 'ext_modules' "
|
||||
"must be the extension name (a string)")
|
||||
"first element of each tuple in 'ext_modules' "
|
||||
'must be the extension name (a string)',
|
||||
)
|
||||
|
||||
if not isinstance(build_info, dict):
|
||||
raise DistutilsSetupError(
|
||||
"second element of each tuple in 'ext_modules' "
|
||||
"must be a dictionary (build info)")
|
||||
"second element of each tuple in 'ext_modules' "
|
||||
'must be a dictionary (build info)',
|
||||
)
|
||||
|
||||
# OK, the (ext_name, build_info) dict is type-safe: convert it
|
||||
# to an Extension instance.
|
||||
|
|
@ -387,9 +445,11 @@ class build_ext(Command):
|
|||
|
||||
# Easy stuff: one-to-one mapping from dict elements to
|
||||
# instance attributes.
|
||||
for key in ('include_dirs', 'library_dirs', 'libraries',
|
||||
'extra_objects', 'extra_compile_args',
|
||||
'extra_link_args'):
|
||||
for key in (
|
||||
'include_dirs', 'library_dirs', 'libraries',
|
||||
'extra_objects', 'extra_compile_args',
|
||||
'extra_link_args',
|
||||
):
|
||||
val = build_info.get(key)
|
||||
if val is not None:
|
||||
setattr(ext, key, val)
|
||||
|
|
@ -397,8 +457,10 @@ 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.warn("'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'.
|
||||
|
|
@ -409,8 +471,9 @@ 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])
|
||||
elif len(macro) == 2:
|
||||
|
|
@ -463,8 +526,10 @@ class build_ext(Command):
|
|||
return
|
||||
|
||||
with ThreadPoolExecutor(max_workers=workers) as executor:
|
||||
futures = [executor.submit(self.build_extension, ext)
|
||||
for ext in self.extensions]
|
||||
futures = [
|
||||
executor.submit(self.build_extension, ext)
|
||||
for ext in self.extensions
|
||||
]
|
||||
for ext, fut in zip(self.extensions, futures):
|
||||
with self._filter_build_errors(ext):
|
||||
fut.result()
|
||||
|
|
@ -481,16 +546,19 @@ class build_ext(Command):
|
|||
except (CCompilerError, DistutilsError, CompileError) as e:
|
||||
if not ext.optional:
|
||||
raise
|
||||
self.warn('building extension "%s" failed: %s' %
|
||||
(ext.name, e))
|
||||
self.warn(
|
||||
'building extension "%s" failed: %s' %
|
||||
(ext.name, e),
|
||||
)
|
||||
|
||||
def build_extension(self, ext):
|
||||
sources = ext.sources
|
||||
if sources is None or not isinstance(sources, (list, tuple)):
|
||||
raise DistutilsSetupError(
|
||||
"in 'ext_modules' option (extension '%s'), "
|
||||
"'sources' must be present and must be "
|
||||
"a list of source filenames" % ext.name)
|
||||
"in 'ext_modules' option (extension '%s'), "
|
||||
"'sources' must be present and must be "
|
||||
'a list of source filenames' % ext.name,
|
||||
)
|
||||
# sort to make the resulting .so file build reproducible
|
||||
sources = sorted(sources)
|
||||
|
||||
|
|
@ -527,13 +595,15 @@ class build_ext(Command):
|
|||
for undef in ext.undef_macros:
|
||||
macros.append((undef,))
|
||||
|
||||
objects = self.compiler.compile(sources,
|
||||
output_dir=self.build_temp,
|
||||
macros=macros,
|
||||
include_dirs=ext.include_dirs,
|
||||
debug=self.debug,
|
||||
extra_postargs=extra_args,
|
||||
depends=ext.depends)
|
||||
objects = self.compiler.compile(
|
||||
sources,
|
||||
output_dir=self.build_temp,
|
||||
macros=macros,
|
||||
include_dirs=ext.include_dirs,
|
||||
debug=self.debug,
|
||||
extra_postargs=extra_args,
|
||||
depends=ext.depends,
|
||||
)
|
||||
|
||||
# XXX outdated variable, kept here in case third-part code
|
||||
# needs it.
|
||||
|
|
@ -558,7 +628,8 @@ class build_ext(Command):
|
|||
export_symbols=self.get_export_symbols(ext),
|
||||
debug=self.debug,
|
||||
build_temp=self.build_temp,
|
||||
target_lang=language)
|
||||
target_lang=language,
|
||||
)
|
||||
|
||||
def swig_sources(self, sources, extension):
|
||||
"""Walk the list of source files in 'sources', looking for SWIG
|
||||
|
|
@ -576,7 +647,7 @@ class build_ext(Command):
|
|||
# the temp dir.
|
||||
|
||||
if self.swig_cpp:
|
||||
log.warn("--swig-cpp is deprecated - use --swig-opts=-c++")
|
||||
log.warn('--swig-cpp is deprecated - use --swig-opts=-c++')
|
||||
|
||||
if self.swig_cpp or ('-c++' in self.swig_opts) or \
|
||||
('-c++' in extension.swig_opts):
|
||||
|
|
@ -586,7 +657,7 @@ class build_ext(Command):
|
|||
|
||||
for source in sources:
|
||||
(base, ext) = os.path.splitext(source)
|
||||
if ext == ".i": # SWIG interface file
|
||||
if ext == '.i': # SWIG interface file
|
||||
new_sources.append(base + '_wrap' + target_ext)
|
||||
swig_sources.append(source)
|
||||
swig_targets[source] = new_sources[-1]
|
||||
|
|
@ -597,10 +668,10 @@ class build_ext(Command):
|
|||
return new_sources
|
||||
|
||||
swig = self.swig or self.find_swig()
|
||||
swig_cmd = [swig, "-python"]
|
||||
swig_cmd = [swig, '-python']
|
||||
swig_cmd.extend(self.swig_opts)
|
||||
if self.swig_cpp:
|
||||
swig_cmd.append("-c++")
|
||||
swig_cmd.append('-c++')
|
||||
|
||||
# Do not override commandline arguments
|
||||
if not self.swig_opts:
|
||||
|
|
@ -609,8 +680,8 @@ class build_ext(Command):
|
|||
|
||||
for source in swig_sources:
|
||||
target = swig_targets[source]
|
||||
log.info("swigging %s to %s", source, target)
|
||||
self.spawn(swig_cmd + ["-o", target, source])
|
||||
log.info('swigging %s to %s', source, target)
|
||||
self.spawn(swig_cmd + ['-o', target, source])
|
||||
|
||||
return new_sources
|
||||
|
||||
|
|
@ -619,22 +690,23 @@ class build_ext(Command):
|
|||
just "swig" -- it should be in the PATH. Tries a bit harder on
|
||||
Windows.
|
||||
"""
|
||||
if os.name == "posix":
|
||||
return "swig"
|
||||
elif os.name == "nt":
|
||||
if os.name == 'posix':
|
||||
return 'swig'
|
||||
elif os.name == 'nt':
|
||||
# Look for SWIG in its standard installation directory on
|
||||
# Windows (or so I presume!). If we find it there, great;
|
||||
# if not, act like Unix and assume it's in the PATH.
|
||||
for vers in ("1.3", "1.2", "1.1"):
|
||||
fn = os.path.join("c:\\swig%s" % vers, "swig.exe")
|
||||
for vers in ('1.3', '1.2', '1.1'):
|
||||
fn = os.path.join('c:\\swig%s' % vers, 'swig.exe')
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
else:
|
||||
return "swig.exe"
|
||||
return 'swig.exe'
|
||||
else:
|
||||
raise DistutilsPlatformError(
|
||||
"I don't know how to find (much less run) SWIG "
|
||||
"on platform '%s'" % os.name)
|
||||
"I don't know how to find (much less run) SWIG "
|
||||
"on platform '%s'" % os.name,
|
||||
)
|
||||
|
||||
# -- Name generators -----------------------------------------------
|
||||
# (extension names, filenames, whatever)
|
||||
|
|
@ -652,7 +724,7 @@ class build_ext(Command):
|
|||
# no further work needed
|
||||
# returning :
|
||||
# build_dir/package/path/filename
|
||||
filename = os.path.join(*modpath[:-1]+[filename])
|
||||
filename = os.path.join(*modpath[:-1] + [filename])
|
||||
return os.path.join(self.build_lib, filename)
|
||||
|
||||
# the inplace option requires to find the package directory
|
||||
|
|
@ -698,9 +770,9 @@ class build_ext(Command):
|
|||
except UnicodeEncodeError:
|
||||
suffix = 'U_' + name.encode('punycode').replace(b'-', b'_').decode('ascii')
|
||||
else:
|
||||
suffix = "_" + name
|
||||
suffix = '_' + name
|
||||
|
||||
initfunc_name = "PyInit" + suffix
|
||||
initfunc_name = 'PyInit' + suffix
|
||||
if initfunc_name not in ext.export_symbols:
|
||||
ext.export_symbols.append(initfunc_name)
|
||||
return ext.export_symbols
|
||||
|
|
@ -715,14 +787,16 @@ class build_ext(Command):
|
|||
# pyconfig.h that MSVC groks. The other Windows compilers all seem
|
||||
# to need it mentioned explicitly, though, so that's what we do.
|
||||
# Append '_d' to the python import library on debug builds.
|
||||
if sys.platform == "win32":
|
||||
if sys.platform == 'win32':
|
||||
from distutils._msvccompiler import MSVCCompiler
|
||||
if not isinstance(self.compiler, MSVCCompiler):
|
||||
template = "python%d%d"
|
||||
template = 'python%d%d'
|
||||
if self.debug:
|
||||
template = template + '_d'
|
||||
pythonlib = (template %
|
||||
(sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff))
|
||||
pythonlib = (
|
||||
template %
|
||||
(sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)
|
||||
)
|
||||
# don't extend ext.libraries, it may be shared with other
|
||||
# extensions, it is a reference to the original list
|
||||
return ext.libraries + [pythonlib]
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
"""distutils.command.build_py
|
||||
|
||||
Implements the Distutils 'build_py' command."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import importlib.util
|
||||
import sys
|
||||
import glob
|
||||
import importlib.util
|
||||
import os
|
||||
import sys
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import Command
|
||||
from distutils.errors import *
|
||||
from distutils.util import convert_path
|
||||
from distutils import log
|
||||
|
||||
|
||||
class build_py (Command):
|
||||
|
||||
|
|
@ -18,16 +20,18 @@ class build_py (Command):
|
|||
|
||||
user_options = [
|
||||
('build-lib=', 'd', "directory to \"build\" (copy) to"),
|
||||
('compile', 'c', "compile .py to .pyc"),
|
||||
('compile', 'c', 'compile .py to .pyc'),
|
||||
('no-compile', None, "don't compile .py files [default]"),
|
||||
('optimize=', 'O',
|
||||
"also compile with optimization: -O1 for \"python -O\", "
|
||||
"-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
|
||||
('force', 'f', "forcibly build everything (ignore file timestamps)"),
|
||||
]
|
||||
(
|
||||
'optimize=', 'O',
|
||||
"also compile with optimization: -O1 for \"python -O\", "
|
||||
"-O2 for \"python -OO\", and -O0 to disable [default: -O0]",
|
||||
),
|
||||
('force', 'f', 'forcibly build everything (ignore file timestamps)'),
|
||||
]
|
||||
|
||||
boolean_options = ['compile', 'force']
|
||||
negative_opt = {'no-compile' : 'compile'}
|
||||
negative_opt = {'no-compile': 'compile'}
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_lib = None
|
||||
|
|
@ -40,9 +44,11 @@ class build_py (Command):
|
|||
self.force = None
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('build',
|
||||
('build_lib', 'build_lib'),
|
||||
('force', 'force'))
|
||||
self.set_undefined_options(
|
||||
'build',
|
||||
('build_lib', 'build_lib'),
|
||||
('force', 'force'),
|
||||
)
|
||||
|
||||
# Get the distribution options that are aliases for build_py
|
||||
# options -- list of packages and list of modules.
|
||||
|
|
@ -62,7 +68,7 @@ class build_py (Command):
|
|||
self.optimize = int(self.optimize)
|
||||
assert 0 <= self.optimize <= 2
|
||||
except (ValueError, AssertionError):
|
||||
raise DistutilsOptionError("optimize must be 0, 1, or 2")
|
||||
raise DistutilsOptionError('optimize must be 0, 1, or 2')
|
||||
|
||||
def run(self):
|
||||
# XXX copy_file by default preserves atime and mtime. IMHO this is
|
||||
|
|
@ -109,26 +115,30 @@ class build_py (Command):
|
|||
# Length of path to strip from found files
|
||||
plen = 0
|
||||
if src_dir:
|
||||
plen = len(src_dir)+1
|
||||
plen = len(src_dir) + 1
|
||||
|
||||
# Strip directory from globbed filenames
|
||||
filenames = [
|
||||
file[plen:] for file in self.find_data_files(package, src_dir)
|
||||
]
|
||||
]
|
||||
data.append((package, src_dir, build_dir, filenames))
|
||||
return data
|
||||
|
||||
def find_data_files(self, package, src_dir):
|
||||
"""Return filenames for package's data files in 'src_dir'"""
|
||||
globs = (self.package_data.get('', [])
|
||||
+ self.package_data.get(package, []))
|
||||
globs = (
|
||||
self.package_data.get('', []) +
|
||||
self.package_data.get(package, [])
|
||||
)
|
||||
files = []
|
||||
for pattern in globs:
|
||||
# Each pattern has to be converted to a platform-specific path
|
||||
filelist = glob.glob(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):
|
||||
|
|
@ -138,8 +148,10 @@ class build_py (Command):
|
|||
for filename in filenames:
|
||||
target = os.path.join(build_dir, filename)
|
||||
self.mkpath(os.path.dirname(target))
|
||||
self.copy_file(os.path.join(src_dir, filename), target,
|
||||
preserve_mode=False)
|
||||
self.copy_file(
|
||||
os.path.join(src_dir, filename), target,
|
||||
preserve_mode=False,
|
||||
)
|
||||
|
||||
def get_package_dir(self, package):
|
||||
"""Return the directory, relative to the top of the source
|
||||
|
|
@ -185,23 +197,29 @@ class build_py (Command):
|
|||
# assume exists. Also, os.path.exists and isdir don't know about
|
||||
# my "empty string means current dir" convention, so we have to
|
||||
# circumvent them.
|
||||
if package_dir != "":
|
||||
if package_dir != '':
|
||||
if not os.path.exists(package_dir):
|
||||
raise DistutilsFileError(
|
||||
"package directory '%s' does not exist" % package_dir)
|
||||
"package directory '%s' does not exist" % package_dir,
|
||||
)
|
||||
if not os.path.isdir(package_dir):
|
||||
raise DistutilsFileError(
|
||||
"supposed package directory '%s' exists, "
|
||||
"but is not a directory" % package_dir)
|
||||
"supposed package directory '%s' exists, "
|
||||
'but is not a directory' % package_dir,
|
||||
)
|
||||
|
||||
# Require __init__.py for all but the "root package"
|
||||
if package:
|
||||
init_py = os.path.join(package_dir, "__init__.py")
|
||||
init_py = os.path.join(package_dir, '__init__.py')
|
||||
if os.path.isfile(init_py):
|
||||
return init_py
|
||||
else:
|
||||
log.warn(("package init file '%s' not found " +
|
||||
"(or not a regular file)"), init_py)
|
||||
log.warn(
|
||||
(
|
||||
"package init file '%s' not found " +
|
||||
'(or not a regular file)'
|
||||
), init_py,
|
||||
)
|
||||
|
||||
# Either not in a package at all (__init__.py not expected), or
|
||||
# __init__.py doesn't exist -- so don't return the filename.
|
||||
|
|
@ -209,14 +227,14 @@ class build_py (Command):
|
|||
|
||||
def check_module(self, module, module_file):
|
||||
if not os.path.isfile(module_file):
|
||||
log.warn("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
|
||||
|
||||
def find_package_modules(self, package, package_dir):
|
||||
self.check_package(package, package_dir)
|
||||
module_files = glob.glob(os.path.join(glob.escape(package_dir), "*.py"))
|
||||
module_files = glob.glob(os.path.join(glob.escape(package_dir), '*.py'))
|
||||
modules = []
|
||||
setup_script = os.path.abspath(self.distribution.script_name)
|
||||
|
||||
|
|
@ -226,7 +244,7 @@ class build_py (Command):
|
|||
module = os.path.splitext(os.path.basename(f))[0]
|
||||
modules.append((package, module, f))
|
||||
else:
|
||||
self.debug_print("excluding %s" % setup_script)
|
||||
self.debug_print('excluding %s' % setup_script)
|
||||
return modules
|
||||
|
||||
def find_modules(self):
|
||||
|
|
@ -268,12 +286,12 @@ class build_py (Command):
|
|||
init_py = self.check_package(package, package_dir)
|
||||
packages[package] = (package_dir, 1)
|
||||
if init_py:
|
||||
modules.append((package, "__init__", init_py))
|
||||
modules.append((package, '__init__', init_py))
|
||||
|
||||
# XXX perhaps we should also check for just .pyc files
|
||||
# (so greedy closed-source bastards can distribute Python
|
||||
# modules too)
|
||||
module_file = os.path.join(package_dir, module_base + ".py")
|
||||
module_file = os.path.join(package_dir, module_base + '.py')
|
||||
if not self.check_module(module, module_file):
|
||||
continue
|
||||
|
||||
|
|
@ -301,7 +319,7 @@ class build_py (Command):
|
|||
return [module[-1] for module in self.find_all_modules()]
|
||||
|
||||
def get_module_outfile(self, build_dir, package, module):
|
||||
outfile_path = [build_dir] + list(package) + [module + ".py"]
|
||||
outfile_path = [build_dir] + list(package) + [module + '.py']
|
||||
return os.path.join(*outfile_path)
|
||||
|
||||
def get_outputs(self, include_bytecode=1):
|
||||
|
|
@ -313,17 +331,23 @@ class build_py (Command):
|
|||
outputs.append(filename)
|
||||
if include_bytecode:
|
||||
if self.compile:
|
||||
outputs.append(importlib.util.cache_from_source(
|
||||
filename, optimization=''))
|
||||
outputs.append(
|
||||
importlib.util.cache_from_source(
|
||||
filename, optimization='',
|
||||
),
|
||||
)
|
||||
if self.optimize > 0:
|
||||
outputs.append(importlib.util.cache_from_source(
|
||||
filename, optimization=self.optimize))
|
||||
outputs.append(
|
||||
importlib.util.cache_from_source(
|
||||
filename, optimization=self.optimize,
|
||||
),
|
||||
)
|
||||
|
||||
outputs += [
|
||||
os.path.join(build_dir, filename)
|
||||
for package, src_dir, build_dir, filenames in self.data_files
|
||||
for filename in filenames
|
||||
]
|
||||
]
|
||||
|
||||
return outputs
|
||||
|
||||
|
|
@ -332,7 +356,8 @@ class build_py (Command):
|
|||
package = package.split('.')
|
||||
elif not isinstance(package, (list, tuple)):
|
||||
raise TypeError(
|
||||
"'package' must be a string (dot-separated), list, or tuple")
|
||||
"'package' must be a string (dot-separated), list, or tuple",
|
||||
)
|
||||
|
||||
# Now put the module source file into the "build" area -- this is
|
||||
# easy, we just copy it somewhere under self.build_lib (the build
|
||||
|
|
@ -385,8 +410,12 @@ class build_py (Command):
|
|||
# method of the "install_lib" command, except for the determination
|
||||
# of the 'prefix' string. Hmmm.
|
||||
if self.compile:
|
||||
byte_compile(files, optimize=0,
|
||||
force=self.force, prefix=prefix, dry_run=self.dry_run)
|
||||
byte_compile(
|
||||
files, optimize=0,
|
||||
force=self.force, prefix=prefix, dry_run=self.dry_run,
|
||||
)
|
||||
if self.optimize > 0:
|
||||
byte_compile(files, optimize=self.optimize,
|
||||
force=self.force, prefix=prefix, dry_run=self.dry_run)
|
||||
byte_compile(
|
||||
files, optimize=self.optimize,
|
||||
force=self.force, prefix=prefix, dry_run=self.dry_run,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,32 +1,35 @@
|
|||
"""distutils.command.build_scripts
|
||||
|
||||
Implements the Distutils 'build_scripts' command."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os, re
|
||||
import os
|
||||
import re
|
||||
import tokenize
|
||||
from stat import ST_MODE
|
||||
|
||||
from distutils import log
|
||||
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
|
||||
|
||||
# check if Python is called on the first line with this expression
|
||||
first_line_re = re.compile(b'^#!.*python[0-9.]*([ \t].*)?$')
|
||||
|
||||
|
||||
class build_scripts(Command):
|
||||
|
||||
description = "\"build\" scripts (copy and fixup #! line)"
|
||||
|
||||
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"),
|
||||
]
|
||||
('force', 'f', 'forcibly build everything (ignore file timestamps'),
|
||||
('executable=', 'e', 'specify final destination interpreter path'),
|
||||
]
|
||||
|
||||
boolean_options = ['force']
|
||||
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_dir = None
|
||||
self.scripts = None
|
||||
|
|
@ -35,10 +38,12 @@ class build_scripts(Command):
|
|||
self.outfiles = None
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('build',
|
||||
('build_scripts', 'build_dir'),
|
||||
('force', 'force'),
|
||||
('executable', 'executable'))
|
||||
self.set_undefined_options(
|
||||
'build',
|
||||
('build_scripts', 'build_dir'),
|
||||
('force', 'force'),
|
||||
('executable', 'executable'),
|
||||
)
|
||||
self.scripts = self.distribution.scripts
|
||||
|
||||
def get_source_files(self):
|
||||
|
|
@ -49,7 +54,6 @@ class build_scripts(Command):
|
|||
return
|
||||
self.copy_scripts()
|
||||
|
||||
|
||||
def copy_scripts(self):
|
||||
r"""Copy each script listed in 'self.scripts'; if it's marked as a
|
||||
Python script in the Unix way (first line matches 'first_line_re',
|
||||
|
|
@ -66,14 +70,14 @@ class build_scripts(Command):
|
|||
outfiles.append(outfile)
|
||||
|
||||
if not self.force and not newer(script, outfile):
|
||||
log.debug("not copying %s (up-to-date)", script)
|
||||
log.debug('not copying %s (up-to-date)', script)
|
||||
continue
|
||||
|
||||
# Always open the file, but ignore failures in dry-run mode --
|
||||
# that way, we'll get accurate feedback if we can read the
|
||||
# script.
|
||||
try:
|
||||
f = open(script, "rb")
|
||||
f = open(script, 'rb')
|
||||
except OSError:
|
||||
if not self.dry_run:
|
||||
raise
|
||||
|
|
@ -83,7 +87,7 @@ class build_scripts(Command):
|
|||
f.seek(0)
|
||||
first_line = f.readline()
|
||||
if not first_line:
|
||||
self.warn("%s is an empty file (skipping)" % script)
|
||||
self.warn('%s is an empty file (skipping)' % script)
|
||||
continue
|
||||
|
||||
match = first_line_re.match(first_line)
|
||||
|
|
@ -92,19 +96,24 @@ class build_scripts(Command):
|
|||
post_interp = match.group(1) or b''
|
||||
|
||||
if adjust:
|
||||
log.info("copying and adjusting %s -> %s", script,
|
||||
self.build_dir)
|
||||
log.info(
|
||||
'copying and adjusting %s -> %s', script,
|
||||
self.build_dir,
|
||||
)
|
||||
updated_files.append(outfile)
|
||||
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")))
|
||||
sysconfig.get_config_var('BINDIR'),
|
||||
'python{}{}'.format(
|
||||
sysconfig.get_config_var('VERSION'),
|
||||
sysconfig.get_config_var('EXE'),
|
||||
),
|
||||
)
|
||||
executable = os.fsencode(executable)
|
||||
shebang = b"#!" + executable + post_interp + b"\n"
|
||||
shebang = b'#!' + executable + post_interp + b'\n'
|
||||
# Python parser starts to read a script using UTF-8 until
|
||||
# it gets a #coding:xxx cookie. The shebang has to be the
|
||||
# first line of a file, the #coding:xxx cookie cannot be
|
||||
|
|
@ -114,8 +123,9 @@ class build_scripts(Command):
|
|||
shebang.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
raise ValueError(
|
||||
"The shebang ({!r}) is not decodable "
|
||||
"from utf-8".format(shebang))
|
||||
'The shebang ({!r}) is not decodable '
|
||||
'from utf-8'.format(shebang),
|
||||
)
|
||||
# If the script is encoded to a custom encoding (use a
|
||||
# #coding:xxx cookie), the shebang has to be decodable from
|
||||
# the script encoding too.
|
||||
|
|
@ -123,10 +133,11 @@ class build_scripts(Command):
|
|||
shebang.decode(encoding)
|
||||
except UnicodeDecodeError:
|
||||
raise ValueError(
|
||||
"The shebang ({!r}) is not decodable "
|
||||
"from the script encoding ({})"
|
||||
.format(shebang, encoding))
|
||||
with open(outfile, "wb") as outf:
|
||||
'The shebang ({!r}) is not decodable '
|
||||
'from the script encoding ({})'
|
||||
.format(shebang, encoding),
|
||||
)
|
||||
with open(outfile, 'wb') as outf:
|
||||
outf.write(shebang)
|
||||
outf.writelines(f.readlines())
|
||||
if f:
|
||||
|
|
@ -140,13 +151,15 @@ class build_scripts(Command):
|
|||
if os.name == 'posix':
|
||||
for file in outfiles:
|
||||
if self.dry_run:
|
||||
log.info("changing mode of %s", file)
|
||||
log.info('changing mode of %s', file)
|
||||
else:
|
||||
oldmode = os.stat(file)[ST_MODE] & 0o7777
|
||||
newmode = (oldmode | 0o555) & 0o7777
|
||||
if newmode != oldmode:
|
||||
log.info("changing mode of %s from %o to %o",
|
||||
file, oldmode, newmode)
|
||||
log.info(
|
||||
'changing mode of %s from %o to %o',
|
||||
file, oldmode, newmode,
|
||||
)
|
||||
os.chmod(file, newmode)
|
||||
# XXX should we modify self.outfiles?
|
||||
return outfiles, updated_files
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
Implements the Distutils 'check' command.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from distutils.core import Command
|
||||
from distutils.errors import DistutilsSetupError
|
||||
|
||||
|
|
@ -14,17 +16,23 @@ try:
|
|||
|
||||
class SilentReporter(Reporter):
|
||||
|
||||
def __init__(self, source, report_level, halt_level, stream=None,
|
||||
debug=0, encoding='ascii', error_handler='replace'):
|
||||
def __init__(
|
||||
self, source, report_level, halt_level, stream=None,
|
||||
debug=0, encoding='ascii', error_handler='replace',
|
||||
):
|
||||
self.messages = []
|
||||
Reporter.__init__(self, source, report_level, halt_level, stream,
|
||||
debug, encoding, error_handler)
|
||||
Reporter.__init__(
|
||||
self, source, report_level, halt_level, stream,
|
||||
debug, encoding, error_handler,
|
||||
)
|
||||
|
||||
def system_message(self, level, message, *children, **kwargs):
|
||||
self.messages.append((level, message, children, kwargs))
|
||||
return nodes.system_message(message, level=level,
|
||||
type=self.levels[level],
|
||||
*children, **kwargs)
|
||||
return nodes.system_message(
|
||||
message, level=level,
|
||||
type=self.levels[level],
|
||||
*children, **kwargs,
|
||||
)
|
||||
|
||||
HAS_DOCUTILS = True
|
||||
except Exception:
|
||||
|
|
@ -32,16 +40,25 @@ except Exception:
|
|||
# indicate that docutils is not ported to Py3k.
|
||||
HAS_DOCUTILS = False
|
||||
|
||||
|
||||
class check(Command):
|
||||
"""This command checks the meta-data of the package.
|
||||
"""
|
||||
description = ("perform some checks on the package")
|
||||
user_options = [('metadata', 'm', 'Verify meta-data'),
|
||||
('restructuredtext', 'r',
|
||||
('Checks if long string meta-data syntax '
|
||||
'are reStructuredText-compliant')),
|
||||
('strict', 's',
|
||||
'Will exit with an error if a check fails')]
|
||||
description = ('perform some checks on the package')
|
||||
user_options = [
|
||||
('metadata', 'm', 'Verify meta-data'),
|
||||
(
|
||||
'restructuredtext', 'r',
|
||||
(
|
||||
'Checks if long string meta-data syntax '
|
||||
'are reStructuredText-compliant'
|
||||
),
|
||||
),
|
||||
(
|
||||
'strict', 's',
|
||||
'Will exit with an error if a check fails',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['metadata', 'restructuredtext', 'strict']
|
||||
|
||||
|
|
@ -95,19 +112,25 @@ class check(Command):
|
|||
missing.append(attr)
|
||||
|
||||
if missing:
|
||||
self.warn("missing required meta-data: %s" % ', '.join(missing))
|
||||
self.warn('missing required meta-data: %s' % ', '.join(missing))
|
||||
if metadata.author:
|
||||
if not metadata.author_email:
|
||||
self.warn("missing meta-data: if 'author' supplied, " +
|
||||
"'author_email' should be supplied too")
|
||||
self.warn(
|
||||
"missing meta-data: if 'author' supplied, " +
|
||||
"'author_email' should be supplied too",
|
||||
)
|
||||
elif metadata.maintainer:
|
||||
if not metadata.maintainer_email:
|
||||
self.warn("missing meta-data: if 'maintainer' supplied, " +
|
||||
"'maintainer_email' should be supplied too")
|
||||
self.warn(
|
||||
"missing meta-data: if 'maintainer' supplied, " +
|
||||
"'maintainer_email' should be supplied too",
|
||||
)
|
||||
else:
|
||||
self.warn("missing meta-data: either (author and author_email) " +
|
||||
"or (maintainer and maintainer_email) " +
|
||||
"should be supplied")
|
||||
self.warn(
|
||||
'missing meta-data: either (author and author_email) ' +
|
||||
'or (maintainer and maintainer_email) ' +
|
||||
'should be supplied',
|
||||
)
|
||||
|
||||
def check_restructuredtext(self):
|
||||
"""Checks if the long string fields are reST-compliant."""
|
||||
|
|
@ -117,7 +140,7 @@ class check(Command):
|
|||
if line is None:
|
||||
warning = warning[1]
|
||||
else:
|
||||
warning = '%s (line %s)' % (warning[1], line)
|
||||
warning = '{} (line {})'.format(warning[1], line)
|
||||
self.warn(warning)
|
||||
|
||||
def _check_rst_data(self, data):
|
||||
|
|
@ -129,13 +152,15 @@ class check(Command):
|
|||
settings.tab_width = 4
|
||||
settings.pep_references = None
|
||||
settings.rfc_references = None
|
||||
reporter = SilentReporter(source_path,
|
||||
settings.report_level,
|
||||
settings.halt_level,
|
||||
stream=settings.warning_stream,
|
||||
debug=settings.debug,
|
||||
encoding=settings.error_encoding,
|
||||
error_handler=settings.error_encoding_error_handler)
|
||||
reporter = SilentReporter(
|
||||
source_path,
|
||||
settings.report_level,
|
||||
settings.halt_level,
|
||||
stream=settings.warning_stream,
|
||||
debug=settings.debug,
|
||||
encoding=settings.error_encoding,
|
||||
error_handler=settings.error_encoding_error_handler,
|
||||
)
|
||||
|
||||
document = nodes.document(settings, reporter, source=source_path)
|
||||
document.note_source(source_path, -1)
|
||||
|
|
@ -143,6 +168,7 @@ class check(Command):
|
|||
parser.parse(data, document)
|
||||
except AttributeError as e:
|
||||
reporter.messages.append(
|
||||
(-1, 'Could not finish the parsing: %s.' % e, '', {}))
|
||||
(-1, 'Could not finish the parsing: %s.' % e, '', {}),
|
||||
)
|
||||
|
||||
return reporter.messages
|
||||
|
|
|
|||
|
|
@ -1,30 +1,44 @@
|
|||
"""distutils.command.clean
|
||||
|
||||
Implements the Distutils 'clean' command."""
|
||||
|
||||
# contributed by Bastian Kleineidam <calvin@cs.uni-sb.de>, added 2000-03-18
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from distutils import log
|
||||
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-lib=', None,
|
||||
"build directory for all modules (default: 'build.build-lib')"),
|
||||
('build-temp=', 't',
|
||||
"temporary build directory (default: 'build.build-temp')"),
|
||||
('build-scripts=', None,
|
||||
"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")
|
||||
(
|
||||
'build-base=', 'b',
|
||||
"base build directory (default: 'build.build-base')",
|
||||
),
|
||||
(
|
||||
'build-lib=', None,
|
||||
"build directory for all modules (default: 'build.build-lib')",
|
||||
),
|
||||
(
|
||||
'build-temp=', 't',
|
||||
"temporary build directory (default: 'build.build-temp')",
|
||||
),
|
||||
(
|
||||
'build-scripts=', None,
|
||||
"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 = ['all']
|
||||
|
|
@ -38,13 +52,17 @@ class clean(Command):
|
|||
self.all = None
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('build',
|
||||
('build_base', 'build_base'),
|
||||
('build_lib', 'build_lib'),
|
||||
('build_scripts', 'build_scripts'),
|
||||
('build_temp', 'build_temp'))
|
||||
self.set_undefined_options('bdist',
|
||||
('bdist_base', 'bdist_base'))
|
||||
self.set_undefined_options(
|
||||
'build',
|
||||
('build_base', 'build_base'),
|
||||
('build_lib', 'build_lib'),
|
||||
('build_scripts', 'build_scripts'),
|
||||
('build_temp', 'build_temp'),
|
||||
)
|
||||
self.set_undefined_options(
|
||||
'bdist',
|
||||
('bdist_base', 'bdist_base'),
|
||||
)
|
||||
|
||||
def run(self):
|
||||
# remove the build/temp.<plat> directory (unless it's already
|
||||
|
|
@ -52,19 +70,25 @@ class clean(Command):
|
|||
if os.path.exists(self.build_temp):
|
||||
remove_tree(self.build_temp, dry_run=self.dry_run)
|
||||
else:
|
||||
log.debug("'%s' does not exist -- can't clean it",
|
||||
self.build_temp)
|
||||
log.debug(
|
||||
"'%s' does not exist -- can't clean it",
|
||||
self.build_temp,
|
||||
)
|
||||
|
||||
if self.all:
|
||||
# remove build directories
|
||||
for directory in (self.build_lib,
|
||||
self.bdist_base,
|
||||
self.build_scripts):
|
||||
for directory in (
|
||||
self.build_lib,
|
||||
self.bdist_base,
|
||||
self.build_scripts,
|
||||
):
|
||||
if os.path.exists(directory):
|
||||
remove_tree(directory, dry_run=self.dry_run)
|
||||
else:
|
||||
log.warn("'%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
|
||||
|
|
|
|||
|
|
@ -8,42 +8,62 @@ list of standard commands. Also, this is a good place to put common
|
|||
configure-like tasks: "try to compile this C code", or "figure out where
|
||||
this header file lives".
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os, re
|
||||
import os
|
||||
import re
|
||||
|
||||
from distutils import log
|
||||
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"}
|
||||
LANG_EXT = {'c': '.c', 'c++': '.cxx'}
|
||||
|
||||
|
||||
class config(Command):
|
||||
|
||||
description = "prepare to build"
|
||||
description = 'prepare to build'
|
||||
|
||||
user_options = [
|
||||
('compiler=', None,
|
||||
"specify the compiler type"),
|
||||
('cc=', None,
|
||||
"specify the compiler executable"),
|
||||
('include-dirs=', 'I',
|
||||
"list of directories to search for header files"),
|
||||
('define=', 'D',
|
||||
"C preprocessor macros to define"),
|
||||
('undef=', 'U',
|
||||
"C preprocessor macros to undefine"),
|
||||
('libraries=', 'l',
|
||||
"external C libraries to link with"),
|
||||
('library-dirs=', 'L',
|
||||
"directories to search for external C libraries"),
|
||||
|
||||
('noisy', None,
|
||||
"show every action (compile, link, run, ...) taken"),
|
||||
('dump-source', None,
|
||||
"dump generated source files before attempting to compile them"),
|
||||
]
|
||||
(
|
||||
'compiler=', None,
|
||||
'specify the compiler type',
|
||||
),
|
||||
(
|
||||
'cc=', None,
|
||||
'specify the compiler executable',
|
||||
),
|
||||
(
|
||||
'include-dirs=', 'I',
|
||||
'list of directories to search for header files',
|
||||
),
|
||||
(
|
||||
'define=', 'D',
|
||||
'C preprocessor macros to define',
|
||||
),
|
||||
(
|
||||
'undef=', 'U',
|
||||
'C preprocessor macros to undefine',
|
||||
),
|
||||
(
|
||||
'libraries=', 'l',
|
||||
'external C libraries to link with',
|
||||
),
|
||||
(
|
||||
'library-dirs=', 'L',
|
||||
'directories to search for external C libraries',
|
||||
),
|
||||
|
||||
(
|
||||
'noisy', None,
|
||||
'show every action (compile, link, run, ...) taken',
|
||||
),
|
||||
(
|
||||
'dump-source', None,
|
||||
'dump generated source files before attempting to compile them',
|
||||
),
|
||||
]
|
||||
|
||||
# The three standard command methods: since the "config" command
|
||||
# does nothing by default, these are empty.
|
||||
|
|
@ -94,8 +114,10 @@ class config(Command):
|
|||
# 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=1)
|
||||
self.compiler = new_compiler(
|
||||
compiler=self.compiler,
|
||||
dry_run=self.dry_run, force=1,
|
||||
)
|
||||
customize_compiler(self.compiler)
|
||||
if self.include_dirs:
|
||||
self.compiler.set_include_dirs(self.include_dirs)
|
||||
|
|
@ -105,20 +127,20 @@ class config(Command):
|
|||
self.compiler.set_library_dirs(self.library_dirs)
|
||||
|
||||
def _gen_temp_sourcefile(self, body, headers, lang):
|
||||
filename = "_configtest" + LANG_EXT[lang]
|
||||
with open(filename, "w") as file:
|
||||
filename = '_configtest' + LANG_EXT[lang]
|
||||
with open(filename, 'w') as file:
|
||||
if headers:
|
||||
for header in headers:
|
||||
file.write("#include <%s>\n" % header)
|
||||
file.write("\n")
|
||||
file.write('#include <%s>\n' % header)
|
||||
file.write('\n')
|
||||
file.write(body)
|
||||
if body[-1] != "\n":
|
||||
file.write("\n")
|
||||
if body[-1] != '\n':
|
||||
file.write('\n')
|
||||
return filename
|
||||
|
||||
def _preprocess(self, body, headers, include_dirs, lang):
|
||||
src = self._gen_temp_sourcefile(body, headers, lang)
|
||||
out = "_configtest.i"
|
||||
out = '_configtest.i'
|
||||
self.temp_files.extend([src, out])
|
||||
self.compiler.preprocess(src, out, include_dirs=include_dirs)
|
||||
return (src, out)
|
||||
|
|
@ -132,14 +154,18 @@ class config(Command):
|
|||
self.compiler.compile([src], include_dirs=include_dirs)
|
||||
return (src, obj)
|
||||
|
||||
def _link(self, body, headers, include_dirs, libraries, library_dirs,
|
||||
lang):
|
||||
def _link(
|
||||
self, body, headers, include_dirs, libraries, library_dirs,
|
||||
lang,
|
||||
):
|
||||
(src, obj) = self._compile(body, headers, include_dirs, lang)
|
||||
prog = os.path.splitext(os.path.basename(src))[0]
|
||||
self.compiler.link_executable([obj], prog,
|
||||
libraries=libraries,
|
||||
library_dirs=library_dirs,
|
||||
target_lang=lang)
|
||||
self.compiler.link_executable(
|
||||
[obj], prog,
|
||||
libraries=libraries,
|
||||
library_dirs=library_dirs,
|
||||
target_lang=lang,
|
||||
)
|
||||
|
||||
if self.compiler.exe_extension is not None:
|
||||
prog = prog + self.compiler.exe_extension
|
||||
|
|
@ -151,14 +177,13 @@ class config(Command):
|
|||
if not filenames:
|
||||
filenames = self.temp_files
|
||||
self.temp_files = []
|
||||
log.info("removing: %s", ' '.join(filenames))
|
||||
log.info('removing: %s', ' '.join(filenames))
|
||||
for filename in filenames:
|
||||
try:
|
||||
os.remove(filename)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
# XXX these ignore the dry-run flag: what to do, what to do? even if
|
||||
# you want a dry-run build, you still need some sort of configuration
|
||||
# info. My inclination is to make it up to the real config command to
|
||||
|
|
@ -169,7 +194,7 @@ class config(Command):
|
|||
|
||||
# XXX need access to the header search path and maybe default macros.
|
||||
|
||||
def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"):
|
||||
def try_cpp(self, body=None, headers=None, include_dirs=None, lang='c'):
|
||||
"""Construct a source file from 'body' (a string containing lines
|
||||
of C/C++ code) and 'headers' (a list of header files to include)
|
||||
and run it through the preprocessor. Return true if the
|
||||
|
|
@ -187,8 +212,10 @@ class config(Command):
|
|||
self._clean()
|
||||
return ok
|
||||
|
||||
def search_cpp(self, pattern, body=None, headers=None, include_dirs=None,
|
||||
lang="c"):
|
||||
def search_cpp(
|
||||
self, pattern, body=None, headers=None, include_dirs=None,
|
||||
lang='c',
|
||||
):
|
||||
"""Construct a source file (just like 'try_cpp()'), run it through
|
||||
the preprocessor, and return true if any line of the output matches
|
||||
'pattern'. 'pattern' should either be a compiled regex object or a
|
||||
|
|
@ -215,7 +242,7 @@ class config(Command):
|
|||
self._clean()
|
||||
return match
|
||||
|
||||
def try_compile(self, body, headers=None, include_dirs=None, lang="c"):
|
||||
def try_compile(self, body, headers=None, include_dirs=None, lang='c'):
|
||||
"""Try to compile a source file built from 'body' and 'headers'.
|
||||
Return true on success, false otherwise.
|
||||
"""
|
||||
|
|
@ -227,12 +254,14 @@ class config(Command):
|
|||
except CompileError:
|
||||
ok = False
|
||||
|
||||
log.info(ok and "success!" or "failure.")
|
||||
log.info(ok and 'success!' or 'failure.')
|
||||
self._clean()
|
||||
return ok
|
||||
|
||||
def try_link(self, body, headers=None, include_dirs=None, libraries=None,
|
||||
library_dirs=None, lang="c"):
|
||||
def try_link(
|
||||
self, body, headers=None, include_dirs=None, libraries=None,
|
||||
library_dirs=None, lang='c',
|
||||
):
|
||||
"""Try to compile and link a source file, built from 'body' and
|
||||
'headers', to executable form. Return true on success, false
|
||||
otherwise.
|
||||
|
|
@ -240,18 +269,22 @@ class config(Command):
|
|||
from distutils.ccompiler import CompileError, LinkError
|
||||
self._check_compiler()
|
||||
try:
|
||||
self._link(body, headers, include_dirs,
|
||||
libraries, library_dirs, lang)
|
||||
self._link(
|
||||
body, headers, include_dirs,
|
||||
libraries, library_dirs, lang,
|
||||
)
|
||||
ok = True
|
||||
except (CompileError, LinkError):
|
||||
ok = False
|
||||
|
||||
log.info(ok and "success!" or "failure.")
|
||||
log.info(ok and 'success!' or 'failure.')
|
||||
self._clean()
|
||||
return ok
|
||||
|
||||
def try_run(self, body, headers=None, include_dirs=None, libraries=None,
|
||||
library_dirs=None, lang="c"):
|
||||
def try_run(
|
||||
self, body, headers=None, include_dirs=None, libraries=None,
|
||||
library_dirs=None, lang='c',
|
||||
):
|
||||
"""Try to compile, link to an executable, and run a program
|
||||
built from 'body' and 'headers'. Return true on success, false
|
||||
otherwise.
|
||||
|
|
@ -259,24 +292,27 @@ class config(Command):
|
|||
from distutils.ccompiler import CompileError, LinkError
|
||||
self._check_compiler()
|
||||
try:
|
||||
src, obj, exe = self._link(body, headers, include_dirs,
|
||||
libraries, library_dirs, lang)
|
||||
src, obj, exe = self._link(
|
||||
body, headers, include_dirs,
|
||||
libraries, library_dirs, lang,
|
||||
)
|
||||
self.spawn([exe])
|
||||
ok = True
|
||||
except (CompileError, LinkError, DistutilsExecError):
|
||||
ok = False
|
||||
|
||||
log.info(ok and "success!" or "failure.")
|
||||
log.info(ok and 'success!' or 'failure.')
|
||||
self._clean()
|
||||
return ok
|
||||
|
||||
|
||||
# -- High-level methods --------------------------------------------
|
||||
# (these are the ones that are actually likely to be useful
|
||||
# when implementing a real-world config command!)
|
||||
|
||||
def check_func(self, func, headers=None, include_dirs=None,
|
||||
libraries=None, library_dirs=None, decl=0, call=0):
|
||||
def check_func(
|
||||
self, func, headers=None, include_dirs=None,
|
||||
libraries=None, library_dirs=None, decl=0, call=0,
|
||||
):
|
||||
"""Determine if function 'func' is available by constructing a
|
||||
source file that refers to 'func', and compiles and links it.
|
||||
If everything succeeds, returns true; otherwise returns false.
|
||||
|
|
@ -293,20 +329,24 @@ class config(Command):
|
|||
self._check_compiler()
|
||||
body = []
|
||||
if decl:
|
||||
body.append("int %s ();" % func)
|
||||
body.append("int main () {")
|
||||
body.append('int %s ();' % func)
|
||||
body.append('int main () {')
|
||||
if call:
|
||||
body.append(" %s();" % func)
|
||||
body.append(' %s();' % func)
|
||||
else:
|
||||
body.append(" %s;" % func)
|
||||
body.append("}")
|
||||
body = "\n".join(body) + "\n"
|
||||
body.append(' %s;' % func)
|
||||
body.append('}')
|
||||
body = '\n'.join(body) + '\n'
|
||||
|
||||
return self.try_link(body, headers, include_dirs,
|
||||
libraries, library_dirs)
|
||||
return self.try_link(
|
||||
body, headers, include_dirs,
|
||||
libraries, library_dirs,
|
||||
)
|
||||
|
||||
def check_lib(self, library, library_dirs=None, headers=None,
|
||||
include_dirs=None, other_libraries=[]):
|
||||
def check_lib(
|
||||
self, library, library_dirs=None, headers=None,
|
||||
include_dirs=None, other_libraries=[],
|
||||
):
|
||||
"""Determine if 'library' is available to be linked against,
|
||||
without actually checking that any particular symbols are provided
|
||||
by it. 'headers' will be used in constructing the source file to
|
||||
|
|
@ -316,17 +356,24 @@ class config(Command):
|
|||
has symbols that depend on other libraries.
|
||||
"""
|
||||
self._check_compiler()
|
||||
return self.try_link("int main (void) { }", headers, include_dirs,
|
||||
[library] + other_libraries, library_dirs)
|
||||
return self.try_link(
|
||||
'int main (void) { }', headers, include_dirs,
|
||||
[library] + other_libraries, library_dirs,
|
||||
)
|
||||
|
||||
def check_header(self, header, include_dirs=None, library_dirs=None,
|
||||
lang="c"):
|
||||
def check_header(
|
||||
self, header, include_dirs=None, library_dirs=None,
|
||||
lang='c',
|
||||
):
|
||||
"""Determine if the system header file named by 'header_file'
|
||||
exists and can be found by the preprocessor; return true if so,
|
||||
false otherwise.
|
||||
"""
|
||||
return self.try_cpp(body="/* No body */", headers=[header],
|
||||
include_dirs=include_dirs)
|
||||
return self.try_cpp(
|
||||
body='/* No body */', headers=[header],
|
||||
include_dirs=include_dirs,
|
||||
)
|
||||
|
||||
|
||||
def dump_file(filename, head=None):
|
||||
"""Dumps a file content into log.info.
|
||||
|
|
|
|||
|
|
@ -1,22 +1,24 @@
|
|||
"""distutils.command.install
|
||||
|
||||
Implements the Distutils 'install' command."""
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import os
|
||||
import sys
|
||||
from site import USER_BASE
|
||||
from site import USER_SITE
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import Command
|
||||
from distutils.debug import DEBUG
|
||||
from distutils.sysconfig import get_config_vars
|
||||
from distutils.errors import DistutilsOptionError
|
||||
from distutils.errors import DistutilsPlatformError
|
||||
from distutils.file_util import write_file
|
||||
from distutils.util import convert_path, subst_vars, change_root
|
||||
from distutils.sysconfig import get_config_vars
|
||||
from distutils.util import change_root
|
||||
from distutils.util import convert_path
|
||||
from distutils.util import get_platform
|
||||
from distutils.errors import DistutilsOptionError
|
||||
|
||||
from site import USER_BASE
|
||||
from site import USER_SITE
|
||||
from distutils.util import subst_vars
|
||||
HAS_USER_SITE = True
|
||||
|
||||
WINDOWS_SCHEME = {
|
||||
|
|
@ -24,7 +26,7 @@ WINDOWS_SCHEME = {
|
|||
'platlib': '$base/Lib/site-packages',
|
||||
'headers': '$base/Include/$dist_name',
|
||||
'scripts': '$base/Scripts',
|
||||
'data' : '$base',
|
||||
'data': '$base',
|
||||
}
|
||||
|
||||
INSTALL_SCHEMES = {
|
||||
|
|
@ -33,31 +35,31 @@ INSTALL_SCHEMES = {
|
|||
'platlib': '$platbase/$platlibdir/python$py_version_short/site-packages',
|
||||
'headers': '$base/include/python$py_version_short$abiflags/$dist_name',
|
||||
'scripts': '$base/bin',
|
||||
'data' : '$base',
|
||||
},
|
||||
'data': '$base',
|
||||
},
|
||||
'unix_home': {
|
||||
'purelib': '$base/lib/python',
|
||||
'platlib': '$base/$platlibdir/python',
|
||||
'headers': '$base/include/python/$dist_name',
|
||||
'scripts': '$base/bin',
|
||||
'data' : '$base',
|
||||
},
|
||||
'data': '$base',
|
||||
},
|
||||
'nt': WINDOWS_SCHEME,
|
||||
'pypy': {
|
||||
'purelib': '$base/site-packages',
|
||||
'platlib': '$base/site-packages',
|
||||
'headers': '$base/include/$dist_name',
|
||||
'scripts': '$base/bin',
|
||||
'data' : '$base',
|
||||
},
|
||||
'data': '$base',
|
||||
},
|
||||
'pypy_nt': {
|
||||
'purelib': '$base/site-packages',
|
||||
'platlib': '$base/site-packages',
|
||||
'headers': '$base/include/$dist_name',
|
||||
'scripts': '$base/Scripts',
|
||||
'data' : '$base',
|
||||
},
|
||||
}
|
||||
'data': '$base',
|
||||
},
|
||||
}
|
||||
|
||||
# user site schemes
|
||||
if HAS_USER_SITE:
|
||||
|
|
@ -66,8 +68,8 @@ if HAS_USER_SITE:
|
|||
'platlib': '$usersite',
|
||||
'headers': '$userbase/Python$py_version_nodot/Include/$dist_name',
|
||||
'scripts': '$userbase/Python$py_version_nodot/Scripts',
|
||||
'data' : '$userbase',
|
||||
}
|
||||
'data': '$userbase',
|
||||
}
|
||||
|
||||
INSTALL_SCHEMES['unix_user'] = {
|
||||
'purelib': '$usersite',
|
||||
|
|
@ -75,8 +77,8 @@ if HAS_USER_SITE:
|
|||
'headers':
|
||||
'$userbase/include/python$py_version_short$abiflags/$dist_name',
|
||||
'scripts': '$userbase/bin',
|
||||
'data' : '$userbase',
|
||||
}
|
||||
'data': '$userbase',
|
||||
}
|
||||
|
||||
# The keys to an installation scheme; if any new types of files are to be
|
||||
# installed, be sure to add an entry to every installation scheme above,
|
||||
|
|
@ -86,56 +88,86 @@ SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data')
|
|||
|
||||
class install(Command):
|
||||
|
||||
description = "install everything from build directory"
|
||||
description = 'install everything from build directory'
|
||||
|
||||
user_options = [
|
||||
# Select installation scheme and set base director(y|ies)
|
||||
('prefix=', None,
|
||||
"installation prefix"),
|
||||
('exec-prefix=', None,
|
||||
"(Unix only) prefix for platform-specific files"),
|
||||
('home=', None,
|
||||
"(Unix only) home directory to install under"),
|
||||
(
|
||||
'prefix=', None,
|
||||
'installation prefix',
|
||||
),
|
||||
(
|
||||
'exec-prefix=', None,
|
||||
'(Unix only) prefix for platform-specific files',
|
||||
),
|
||||
(
|
||||
'home=', None,
|
||||
'(Unix only) home directory to install under',
|
||||
),
|
||||
|
||||
# Or, just set the base director(y|ies)
|
||||
('install-base=', None,
|
||||
"base installation directory (instead of --prefix or --home)"),
|
||||
('install-platbase=', None,
|
||||
"base installation directory for platform-specific files " +
|
||||
"(instead of --exec-prefix or --home)"),
|
||||
('root=', None,
|
||||
"install everything relative to this alternate root directory"),
|
||||
(
|
||||
'install-base=', None,
|
||||
'base installation directory (instead of --prefix or --home)',
|
||||
),
|
||||
(
|
||||
'install-platbase=', None,
|
||||
'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
|
||||
('install-purelib=', None,
|
||||
"installation directory for pure Python module distributions"),
|
||||
('install-platlib=', None,
|
||||
"installation directory for non-pure module distributions"),
|
||||
('install-lib=', None,
|
||||
"installation directory for all module distributions " +
|
||||
"(overrides --install-purelib and --install-platlib)"),
|
||||
(
|
||||
'install-purelib=', None,
|
||||
'installation directory for pure Python module distributions',
|
||||
),
|
||||
(
|
||||
'install-platlib=', None,
|
||||
'installation directory for non-pure module distributions',
|
||||
),
|
||||
(
|
||||
'install-lib=', None,
|
||||
'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"),
|
||||
('install-data=', None,
|
||||
"installation directory for data files"),
|
||||
(
|
||||
'install-headers=', None,
|
||||
'installation directory for C/C++ headers',
|
||||
),
|
||||
(
|
||||
'install-scripts=', None,
|
||||
'installation directory for Python scripts',
|
||||
),
|
||||
(
|
||||
'install-data=', None,
|
||||
'installation directory for data files',
|
||||
),
|
||||
|
||||
# Byte-compilation options -- see install_lib.py for details, as
|
||||
# these are duplicated from there (but only install_lib does
|
||||
# anything with them).
|
||||
('compile', 'c', "compile .py to .pyc [default]"),
|
||||
('compile', 'c', 'compile .py to .pyc [default]'),
|
||||
('no-compile', None, "don't compile .py files"),
|
||||
('optimize=', 'O',
|
||||
"also compile with optimization: -O1 for \"python -O\", "
|
||||
"-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
|
||||
(
|
||||
'optimize=', 'O',
|
||||
"also compile with optimization: -O1 for \"python -O\", "
|
||||
"-O2 for \"python -OO\", and -O0 to disable [default: -O0]",
|
||||
),
|
||||
|
||||
# Miscellaneous control options
|
||||
('force', 'f',
|
||||
"force installation (overwrite any existing files)"),
|
||||
('skip-build', None,
|
||||
"skip rebuilding everything (for testing/debugging)"),
|
||||
(
|
||||
'force', 'f',
|
||||
'force installation (overwrite any existing files)',
|
||||
),
|
||||
(
|
||||
'skip-build', None,
|
||||
'skip rebuilding everything (for testing/debugging)',
|
||||
),
|
||||
|
||||
# Where to install documentation (eventually!)
|
||||
#('doc-format=', None, "format of documentation to generate"),
|
||||
|
|
@ -143,19 +175,22 @@ class install(Command):
|
|||
#('install-html=', None, "directory for HTML documentation"),
|
||||
#('install-info=', None, "directory for GNU info files"),
|
||||
|
||||
('record=', None,
|
||||
"filename in which to record list of installed files"),
|
||||
]
|
||||
(
|
||||
'record=', None,
|
||||
'filename in which to record list of installed files',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['compile', 'force', 'skip-build']
|
||||
|
||||
if HAS_USER_SITE:
|
||||
user_options.append(('user', None,
|
||||
"install in user site-package '%s'" % USER_SITE))
|
||||
user_options.append((
|
||||
'user', None,
|
||||
"install in user site-package '%s'" % USER_SITE,
|
||||
))
|
||||
boolean_options.append('user')
|
||||
|
||||
negative_opt = {'no-compile' : 'compile'}
|
||||
|
||||
negative_opt = {'no-compile': 'compile'}
|
||||
|
||||
def initialize_options(self):
|
||||
"""Initializes options."""
|
||||
|
|
@ -228,7 +263,6 @@ class install(Command):
|
|||
|
||||
self.record = None
|
||||
|
||||
|
||||
# -- Option finalizing methods -------------------------------------
|
||||
# (This is rather more involved than for most commands,
|
||||
# because this is where the policy for installing third-
|
||||
|
|
@ -252,24 +286,30 @@ class install(Command):
|
|||
# that's wrong on any platform.
|
||||
|
||||
if ((self.prefix or self.exec_prefix or self.home) and
|
||||
(self.install_base or self.install_platbase)):
|
||||
(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):
|
||||
raise DistutilsOptionError(
|
||||
"must supply either home or prefix/exec-prefix -- not both")
|
||||
'must supply either home or prefix/exec-prefix -- not both',
|
||||
)
|
||||
|
||||
if self.user and (self.prefix or self.exec_prefix or self.home or
|
||||
self.install_base or self.install_platbase):
|
||||
raise DistutilsOptionError("can't combine user with prefix, "
|
||||
"exec_prefix/home, or install_(plat)base")
|
||||
if self.user and (
|
||||
self.prefix or self.exec_prefix or self.home or
|
||||
self.install_base or self.install_platbase
|
||||
):
|
||||
raise DistutilsOptionError(
|
||||
"can't combine user with prefix, "
|
||||
'exec_prefix/home, or install_(plat)base',
|
||||
)
|
||||
|
||||
# Next, stuff that's wrong (or dubious) only on certain platforms.
|
||||
if os.name != "posix":
|
||||
if os.name != 'posix':
|
||||
if self.exec_prefix:
|
||||
self.warn("exec-prefix option ignored on this platform")
|
||||
self.warn('exec-prefix option ignored on this platform')
|
||||
self.exec_prefix = None
|
||||
|
||||
# Now the interesting logic -- so interesting that we farm it out
|
||||
|
|
@ -280,14 +320,14 @@ class install(Command):
|
|||
# install_{purelib,platlib,lib,scripts,data,...}, and the
|
||||
# INSTALL_SCHEME dictionary above. Phew!
|
||||
|
||||
self.dump_dirs("pre-finalize_{unix,other}")
|
||||
self.dump_dirs('pre-finalize_{unix,other}')
|
||||
|
||||
if os.name == 'posix':
|
||||
self.finalize_unix()
|
||||
else:
|
||||
self.finalize_other()
|
||||
|
||||
self.dump_dirs("post-finalize_{unix,other}()")
|
||||
self.dump_dirs('post-finalize_{unix,other}()')
|
||||
|
||||
# Expand configuration variables, tilde, etc. in self.install_base
|
||||
# and self.install_platbase -- that way, we can use $base or
|
||||
|
|
@ -301,19 +341,20 @@ class install(Command):
|
|||
except AttributeError:
|
||||
# sys.abiflags may not be defined on all platforms.
|
||||
abiflags = ''
|
||||
self.config_vars = {'dist_name': self.distribution.get_name(),
|
||||
'dist_version': self.distribution.get_version(),
|
||||
'dist_fullname': self.distribution.get_fullname(),
|
||||
'py_version': py_version,
|
||||
'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,
|
||||
'exec_prefix': exec_prefix,
|
||||
'abiflags': abiflags,
|
||||
'platlibdir': getattr(sys, 'platlibdir', 'lib'),
|
||||
}
|
||||
self.config_vars = {
|
||||
'dist_name': self.distribution.get_name(),
|
||||
'dist_version': self.distribution.get_version(),
|
||||
'dist_fullname': self.distribution.get_fullname(),
|
||||
'py_version': py_version,
|
||||
'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,
|
||||
'exec_prefix': exec_prefix,
|
||||
'abiflags': abiflags,
|
||||
'platlibdir': getattr(sys, 'platlibdir', 'lib'),
|
||||
}
|
||||
|
||||
if HAS_USER_SITE:
|
||||
self.config_vars['userbase'] = self.install_userbase
|
||||
|
|
@ -321,7 +362,7 @@ class install(Command):
|
|||
|
||||
self.expand_basedirs()
|
||||
|
||||
self.dump_dirs("post-expand_basedirs()")
|
||||
self.dump_dirs('post-expand_basedirs()')
|
||||
|
||||
# Now define config vars for the base directories so we can expand
|
||||
# everything else.
|
||||
|
|
@ -330,14 +371,14 @@ class install(Command):
|
|||
|
||||
if DEBUG:
|
||||
from pprint import pprint
|
||||
print("config vars:")
|
||||
print('config vars:')
|
||||
pprint(self.config_vars)
|
||||
|
||||
# Expand "~" and configuration variables in the installation
|
||||
# directories.
|
||||
self.expand_dirs()
|
||||
|
||||
self.dump_dirs("post-expand_dirs()")
|
||||
self.dump_dirs('post-expand_dirs()')
|
||||
|
||||
# Create directories in the home dir:
|
||||
if self.user:
|
||||
|
|
@ -348,17 +389,18 @@ class install(Command):
|
|||
# module distribution is pure or not. Of course, if the user
|
||||
# already specified install_lib, use their selection.
|
||||
if self.install_lib is None:
|
||||
if self.distribution.has_ext_modules(): # has extensions: non-pure
|
||||
if self.distribution.has_ext_modules(): # has extensions: non-pure
|
||||
self.install_lib = self.install_platlib
|
||||
else:
|
||||
self.install_lib = self.install_purelib
|
||||
|
||||
|
||||
# Convert directories from Unix /-separated syntax to the local
|
||||
# convention.
|
||||
self.convert_paths('lib', 'purelib', 'platlib',
|
||||
'scripts', 'data', 'headers',
|
||||
'userbase', 'usersite')
|
||||
self.convert_paths(
|
||||
'lib', 'purelib', 'platlib',
|
||||
'scripts', 'data', 'headers',
|
||||
'userbase', 'usersite',
|
||||
)
|
||||
|
||||
# Deprecated
|
||||
# Well, we're not actually fully completely finalized yet: we still
|
||||
|
|
@ -366,21 +408,25 @@ class install(Command):
|
|||
# non-packagized module distributions (hello, Numerical Python!) to
|
||||
# get their own directories.
|
||||
self.handle_extra_path()
|
||||
self.install_libbase = self.install_lib # needed for .pth file
|
||||
self.install_libbase = self.install_lib # needed for .pth file
|
||||
self.install_lib = os.path.join(self.install_lib, self.extra_dirs)
|
||||
|
||||
# If a new root directory was supplied, make all the installation
|
||||
# dirs relative to it.
|
||||
if self.root is not None:
|
||||
self.change_roots('libbase', 'lib', 'purelib', 'platlib',
|
||||
'scripts', 'data', 'headers')
|
||||
self.change_roots(
|
||||
'libbase', 'lib', 'purelib', 'platlib',
|
||||
'scripts', 'data', 'headers',
|
||||
)
|
||||
|
||||
self.dump_dirs("after prepending root")
|
||||
self.dump_dirs('after prepending root')
|
||||
|
||||
# Find out the build directories, ie. where to install from.
|
||||
self.set_undefined_options('build',
|
||||
('build_base', 'build_base'),
|
||||
('build_lib', 'build_lib'))
|
||||
self.set_undefined_options(
|
||||
'build',
|
||||
('build_base', 'build_base'),
|
||||
('build_lib', 'build_lib'),
|
||||
)
|
||||
|
||||
# Punt on doc directories for now -- after all, we're punting on
|
||||
# documentation completely!
|
||||
|
|
@ -390,10 +436,10 @@ class install(Command):
|
|||
if not DEBUG:
|
||||
return
|
||||
from distutils.fancy_getopt import longopt_xlate
|
||||
log.debug(msg + ":")
|
||||
log.debug(msg + ':')
|
||||
for opt in self.user_options:
|
||||
opt_name = opt[0]
|
||||
if opt_name[-1] == "=":
|
||||
if opt_name[-1] == '=':
|
||||
opt_name = opt_name[0:-1]
|
||||
if opt_name in self.negative_opt:
|
||||
opt_name = self.negative_opt[opt_name]
|
||||
|
|
@ -402,36 +448,43 @@ class install(Command):
|
|||
else:
|
||||
opt_name = opt_name.translate(longopt_xlate)
|
||||
val = getattr(self, opt_name)
|
||||
log.debug(" %s: %s", opt_name, val)
|
||||
log.debug(' %s: %s', opt_name, val)
|
||||
|
||||
def finalize_unix(self):
|
||||
"""Finalizes options for posix platforms."""
|
||||
if self.install_base is not None or self.install_platbase is not None:
|
||||
if ((self.install_lib is None and
|
||||
self.install_purelib is None and
|
||||
self.install_platlib is None) or
|
||||
if (
|
||||
(
|
||||
self.install_lib is None and
|
||||
self.install_purelib is None and
|
||||
self.install_platlib is None
|
||||
) or
|
||||
self.install_headers is None or
|
||||
self.install_scripts is None or
|
||||
self.install_data is None):
|
||||
self.install_data is None
|
||||
):
|
||||
raise DistutilsOptionError(
|
||||
"install-base or install-platbase supplied, but "
|
||||
"installation scheme is incomplete")
|
||||
'install-base or install-platbase supplied, but '
|
||||
'installation scheme is incomplete',
|
||||
)
|
||||
return
|
||||
|
||||
if self.user:
|
||||
if self.install_userbase is None:
|
||||
raise DistutilsPlatformError(
|
||||
"User base directory is not specified")
|
||||
'User base directory is not specified',
|
||||
)
|
||||
self.install_base = self.install_platbase = self.install_userbase
|
||||
self.select_scheme("unix_user")
|
||||
self.select_scheme('unix_user')
|
||||
elif self.home is not None:
|
||||
self.install_base = self.install_platbase = self.home
|
||||
self.select_scheme("unix_home")
|
||||
self.select_scheme('unix_home')
|
||||
else:
|
||||
if self.prefix is None:
|
||||
if self.exec_prefix is not None:
|
||||
raise DistutilsOptionError(
|
||||
"must not supply exec-prefix without prefix")
|
||||
'must not supply exec-prefix without prefix',
|
||||
)
|
||||
|
||||
self.prefix = os.path.normpath(sys.prefix)
|
||||
self.exec_prefix = os.path.normpath(sys.exec_prefix)
|
||||
|
|
@ -442,19 +495,20 @@ class install(Command):
|
|||
|
||||
self.install_base = self.prefix
|
||||
self.install_platbase = self.exec_prefix
|
||||
self.select_scheme("unix_prefix")
|
||||
self.select_scheme('unix_prefix')
|
||||
|
||||
def finalize_other(self):
|
||||
"""Finalizes options for non-posix platforms"""
|
||||
if self.user:
|
||||
if self.install_userbase is None:
|
||||
raise DistutilsPlatformError(
|
||||
"User base directory is not specified")
|
||||
'User base directory is not specified',
|
||||
)
|
||||
self.install_base = self.install_platbase = self.install_userbase
|
||||
self.select_scheme(os.name + "_user")
|
||||
self.select_scheme(os.name + '_user')
|
||||
elif self.home is not None:
|
||||
self.install_base = self.install_platbase = self.home
|
||||
self.select_scheme("unix_home")
|
||||
self.select_scheme('unix_home')
|
||||
else:
|
||||
if self.prefix is None:
|
||||
self.prefix = os.path.normpath(sys.prefix)
|
||||
|
|
@ -464,14 +518,17 @@ class install(Command):
|
|||
self.select_scheme(os.name)
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"I don't know how to install stuff on '%s'" % os.name)
|
||||
"I don't know how to install stuff on '%s'" % os.name,
|
||||
)
|
||||
|
||||
def select_scheme(self, name):
|
||||
"""Sets the install directories by applying the install schemes."""
|
||||
# it's the caller's problem if they supply a bad name!
|
||||
if (hasattr(sys, 'pypy_version_info') and
|
||||
sys.version_info < (3, 8) and
|
||||
not name.endswith(('_user', '_home'))):
|
||||
if (
|
||||
hasattr(sys, 'pypy_version_info') and
|
||||
sys.version_info < (3, 8) and
|
||||
not name.endswith(('_user', '_home'))
|
||||
):
|
||||
if os.name == 'nt':
|
||||
name = 'pypy_nt'
|
||||
else:
|
||||
|
|
@ -498,14 +555,16 @@ class install(Command):
|
|||
|
||||
def expand_dirs(self):
|
||||
"""Calls `os.path.expanduser` on install dirs."""
|
||||
self._expand_attrs(['install_purelib', 'install_platlib',
|
||||
'install_lib', 'install_headers',
|
||||
'install_scripts', 'install_data',])
|
||||
self._expand_attrs([
|
||||
'install_purelib', 'install_platlib',
|
||||
'install_lib', 'install_headers',
|
||||
'install_scripts', 'install_data',
|
||||
])
|
||||
|
||||
def convert_paths(self, *names):
|
||||
"""Call `convert_path` over `names`."""
|
||||
for name in names:
|
||||
attr = "install_" + name
|
||||
attr = 'install_' + name
|
||||
setattr(self, attr, convert_path(getattr(self, attr)))
|
||||
|
||||
def handle_extra_path(self):
|
||||
|
|
@ -515,8 +574,8 @@ class install(Command):
|
|||
|
||||
if self.extra_path is not None:
|
||||
log.warn(
|
||||
"Distribution option extra_path is deprecated. "
|
||||
"See issue27919 for details."
|
||||
'Distribution option extra_path is deprecated. '
|
||||
'See issue27919 for details.',
|
||||
)
|
||||
if isinstance(self.extra_path, str):
|
||||
self.extra_path = self.extra_path.split(',')
|
||||
|
|
@ -527,8 +586,9 @@ class install(Command):
|
|||
path_file, extra_dirs = self.extra_path
|
||||
else:
|
||||
raise DistutilsOptionError(
|
||||
"'extra_path' option must be a list, tuple, or "
|
||||
"comma-separated string with 1 or 2 elements")
|
||||
"'extra_path' option must be a list, tuple, or "
|
||||
'comma-separated string with 1 or 2 elements',
|
||||
)
|
||||
|
||||
# convert to local form in case Unix notation used (as it
|
||||
# should be in setup scripts)
|
||||
|
|
@ -545,14 +605,14 @@ class install(Command):
|
|||
def change_roots(self, *names):
|
||||
"""Change the install directories pointed by name using root."""
|
||||
for name in names:
|
||||
attr = "install_" + name
|
||||
attr = 'install_' + name
|
||||
setattr(self, attr, change_root(self.root, getattr(self, attr)))
|
||||
|
||||
def create_home_path(self):
|
||||
"""Create directories under ~."""
|
||||
if not self.user:
|
||||
return
|
||||
home = convert_path(os.path.expanduser("~"))
|
||||
home = convert_path(os.path.expanduser('~'))
|
||||
for name, path in self.config_vars.items():
|
||||
if path.startswith(home) and not os.path.isdir(path):
|
||||
self.debug_print("os.makedirs('%s', 0o700)" % path)
|
||||
|
|
@ -571,8 +631,10 @@ 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():
|
||||
|
|
@ -588,34 +650,45 @@ class install(Command):
|
|||
root_len = len(self.root)
|
||||
for counter in range(len(outputs)):
|
||||
outputs[counter] = outputs[counter][root_len:]
|
||||
self.execute(write_file,
|
||||
(self.record, outputs),
|
||||
"writing list of installed files to '%s'" %
|
||||
self.record)
|
||||
self.execute(
|
||||
write_file,
|
||||
(self.record, outputs),
|
||||
"writing list of installed files to '%s'" %
|
||||
self.record,
|
||||
)
|
||||
|
||||
sys_path = map(os.path.normpath, sys.path)
|
||||
sys_path = map(os.path.normcase, sys_path)
|
||||
install_lib = os.path.normcase(os.path.normpath(self.install_lib))
|
||||
if (self.warn_dir and
|
||||
if (
|
||||
self.warn_dir and
|
||||
not (self.path_file and self.install_path_file) and
|
||||
install_lib not in sys_path):
|
||||
log.debug(("modules installed to '%s', which is not in "
|
||||
"Python's module search path (sys.path) -- "
|
||||
"you'll have to change the search path yourself"),
|
||||
self.install_lib)
|
||||
install_lib not in sys_path
|
||||
):
|
||||
log.debug(
|
||||
(
|
||||
"modules installed to '%s', which is not in "
|
||||
"Python's module search path (sys.path) -- "
|
||||
"you'll have to change the search path yourself"
|
||||
),
|
||||
self.install_lib,
|
||||
)
|
||||
|
||||
def create_path_file(self):
|
||||
"""Creates the .pth file"""
|
||||
filename = os.path.join(self.install_libbase,
|
||||
self.path_file + ".pth")
|
||||
filename = os.path.join(
|
||||
self.install_libbase,
|
||||
self.path_file + '.pth',
|
||||
)
|
||||
if self.install_path_file:
|
||||
self.execute(write_file,
|
||||
(filename, [self.extra_dirs]),
|
||||
"creating %s" % filename)
|
||||
self.execute(
|
||||
write_file,
|
||||
(filename, [self.extra_dirs]),
|
||||
'creating %s' % filename,
|
||||
)
|
||||
else:
|
||||
self.warn("path file '%s' not created" % filename)
|
||||
|
||||
|
||||
# -- Reporting methods ---------------------------------------------
|
||||
|
||||
def get_outputs(self):
|
||||
|
|
@ -630,8 +703,12 @@ class install(Command):
|
|||
outputs.append(filename)
|
||||
|
||||
if self.path_file and self.install_path_file:
|
||||
outputs.append(os.path.join(self.install_libbase,
|
||||
self.path_file + ".pth"))
|
||||
outputs.append(
|
||||
os.path.join(
|
||||
self.install_libbase,
|
||||
self.path_file + '.pth',
|
||||
),
|
||||
)
|
||||
|
||||
return outputs
|
||||
|
||||
|
|
@ -650,8 +727,10 @@ class install(Command):
|
|||
def has_lib(self):
|
||||
"""Returns true if the current distribution has any Python
|
||||
modules to install."""
|
||||
return (self.distribution.has_pure_modules() or
|
||||
self.distribution.has_ext_modules())
|
||||
return (
|
||||
self.distribution.has_pure_modules() or
|
||||
self.distribution.has_ext_modules()
|
||||
)
|
||||
|
||||
def has_headers(self):
|
||||
"""Returns true if the current distribution has any headers to
|
||||
|
|
@ -670,9 +749,10 @@ class install(Command):
|
|||
|
||||
# 'sub_commands': a list of commands this command might have to run to
|
||||
# get its work done. See cmd.py for more info.
|
||||
sub_commands = [('install_lib', has_lib),
|
||||
('install_headers', has_headers),
|
||||
('install_scripts', has_scripts),
|
||||
('install_data', has_data),
|
||||
('install_egg_info', lambda self:True),
|
||||
]
|
||||
sub_commands = [
|
||||
('install_lib', has_lib),
|
||||
('install_headers', has_headers),
|
||||
('install_scripts', has_scripts),
|
||||
('install_data', has_data),
|
||||
('install_egg_info', lambda self: True),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,25 +2,32 @@
|
|||
|
||||
Implements the Distutils 'install_data' command, for installing
|
||||
platform-independent data files."""
|
||||
|
||||
# contributed by Bastian Kleineidam
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from distutils.core import Command
|
||||
from distutils.util import change_root, convert_path
|
||||
from distutils.util import change_root
|
||||
from distutils.util import convert_path
|
||||
|
||||
|
||||
class install_data(Command):
|
||||
|
||||
description = "install data files"
|
||||
description = 'install data files'
|
||||
|
||||
user_options = [
|
||||
('install-dir=', 'd',
|
||||
"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)"),
|
||||
]
|
||||
(
|
||||
'install-dir=', 'd',
|
||||
'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 = ['force']
|
||||
|
||||
|
|
@ -33,11 +40,12 @@ class install_data(Command):
|
|||
self.warn_dir = 1
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('install',
|
||||
('install_data', 'install_dir'),
|
||||
('root', 'root'),
|
||||
('force', 'force'),
|
||||
)
|
||||
self.set_undefined_options(
|
||||
'install',
|
||||
('install_data', 'install_dir'),
|
||||
('root', 'root'),
|
||||
('force', 'force'),
|
||||
)
|
||||
|
||||
def run(self):
|
||||
self.mkpath(self.install_dir)
|
||||
|
|
@ -46,9 +54,11 @@ class install_data(Command):
|
|||
# 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))
|
||||
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:
|
||||
|
|
|
|||
|
|
@ -2,29 +2,34 @@
|
|||
|
||||
Implements the Distutils 'install_egg_info' command, for installing
|
||||
a package's PKG-INFO metadata."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from distutils import dir_util
|
||||
from distutils import log
|
||||
from distutils.cmd import Command
|
||||
from distutils import log, dir_util
|
||||
import os, sys, re
|
||||
|
||||
|
||||
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 = [
|
||||
('install-dir=', 'd', "directory to install to"),
|
||||
('install-dir=', 'd', 'directory to install to'),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.install_dir = None
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('install_lib',('install_dir','install_dir'))
|
||||
basename = "%s-%s-py%d.%d.egg-info" % (
|
||||
self.set_undefined_options('install_lib', ('install_dir', 'install_dir'))
|
||||
basename = '%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]
|
||||
*sys.version_info[:2],
|
||||
)
|
||||
self.target = os.path.join(self.install_dir, basename)
|
||||
self.outputs = [self.target]
|
||||
|
|
@ -34,11 +39,13 @@ class install_egg_info(Command):
|
|||
if os.path.isdir(target) and not os.path.islink(target):
|
||||
dir_util.remove_tree(target, dry_run=self.dry_run)
|
||||
elif os.path.exists(target):
|
||||
self.execute(os.unlink,(self.target,),"Removing "+target)
|
||||
self.execute(os.unlink, (self.target,), 'Removing ' + target)
|
||||
elif not os.path.isdir(self.install_dir):
|
||||
self.execute(os.makedirs, (self.install_dir,),
|
||||
"Creating "+self.install_dir)
|
||||
log.info("Writing %s", target)
|
||||
self.execute(
|
||||
os.makedirs, (self.install_dir,),
|
||||
'Creating ' + self.install_dir,
|
||||
)
|
||||
log.info('Writing %s', target)
|
||||
if not self.dry_run:
|
||||
with open(target, 'w', encoding='UTF-8') as f:
|
||||
self.distribution.metadata.write_pkg_file(f)
|
||||
|
|
@ -65,7 +72,7 @@ def safe_version(version):
|
|||
Spaces become dots, and all other non-alphanumeric characters become
|
||||
dashes, with runs of multiple dashes condensed to a single dash.
|
||||
"""
|
||||
version = version.replace(' ','.')
|
||||
version = version.replace(' ', '.')
|
||||
return re.sub('[^A-Za-z0-9.]+', '-', version)
|
||||
|
||||
|
||||
|
|
@ -74,4 +81,4 @@ def to_filename(name):
|
|||
|
||||
Any '-' characters are currently replaced with '_'.
|
||||
"""
|
||||
return name.replace('-','_')
|
||||
return name.replace('-', '_')
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
Implements the Distutils 'install_headers' command, to install C/C++ header
|
||||
files to the Python include directory."""
|
||||
from __future__ import annotations
|
||||
|
||||
from distutils.core import Command
|
||||
|
||||
|
|
@ -9,13 +10,18 @@ from distutils.core import Command
|
|||
# XXX force is never used
|
||||
class install_headers(Command):
|
||||
|
||||
description = "install C/C++ header files"
|
||||
description = 'install C/C++ header files'
|
||||
|
||||
user_options = [('install-dir=', 'd',
|
||||
"directory to install header files to"),
|
||||
('force', 'f',
|
||||
"force installation (overwrite existing files)"),
|
||||
]
|
||||
user_options = [
|
||||
(
|
||||
'install-dir=', 'd',
|
||||
'directory to install header files to',
|
||||
),
|
||||
(
|
||||
'force', 'f',
|
||||
'force installation (overwrite existing files)',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['force']
|
||||
|
||||
|
|
@ -25,10 +31,11 @@ class install_headers(Command):
|
|||
self.outfiles = []
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('install',
|
||||
('install_headers', 'install_dir'),
|
||||
('force', 'force'))
|
||||
|
||||
self.set_undefined_options(
|
||||
'install',
|
||||
('install_headers', 'install_dir'),
|
||||
('force', 'force'),
|
||||
)
|
||||
|
||||
def run(self):
|
||||
headers = self.distribution.headers
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
Implements the Distutils 'install_lib' command
|
||||
(install all Python modules)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import importlib.util
|
||||
import os
|
||||
import sys
|
||||
|
||||
from distutils.core import Command
|
||||
|
|
@ -12,11 +13,12 @@ from distutils.errors import DistutilsOptionError
|
|||
|
||||
|
||||
# Extension for Python source files.
|
||||
PYTHON_SOURCE_EXTENSION = ".py"
|
||||
PYTHON_SOURCE_EXTENSION = '.py'
|
||||
|
||||
|
||||
class install_lib(Command):
|
||||
|
||||
description = "install all Python modules (extensions and pure Python)"
|
||||
description = 'install all Python modules (extensions and pure Python)'
|
||||
|
||||
# The byte-compilation options are a tad confusing. Here are the
|
||||
# possible scenarios:
|
||||
|
|
@ -34,19 +36,21 @@ class install_lib(Command):
|
|||
# optimization to use.
|
||||
|
||||
user_options = [
|
||||
('install-dir=', 'd', "directory to install to"),
|
||||
('build-dir=','b', "build directory (where to install from)"),
|
||||
('force', 'f', "force installation (overwrite existing files)"),
|
||||
('compile', 'c', "compile .py to .pyc [default]"),
|
||||
('install-dir=', 'd', 'directory to install to'),
|
||||
('build-dir=', 'b', 'build directory (where to install from)'),
|
||||
('force', 'f', 'force installation (overwrite existing files)'),
|
||||
('compile', 'c', 'compile .py to .pyc [default]'),
|
||||
('no-compile', None, "don't compile .py files"),
|
||||
('optimize=', 'O',
|
||||
"also compile with optimization: -O1 for \"python -O\", "
|
||||
"-O2 for \"python -OO\", and -O0 to disable [default: -O0]"),
|
||||
('skip-build', None, "skip the build steps"),
|
||||
]
|
||||
(
|
||||
'optimize=', 'O',
|
||||
"also compile with optimization: -O1 for \"python -O\", "
|
||||
"-O2 for \"python -OO\", and -O0 to disable [default: -O0]",
|
||||
),
|
||||
('skip-build', None, 'skip the build steps'),
|
||||
]
|
||||
|
||||
boolean_options = ['force', 'compile', 'skip-build']
|
||||
negative_opt = {'no-compile' : 'compile'}
|
||||
negative_opt = {'no-compile': 'compile'}
|
||||
|
||||
def initialize_options(self):
|
||||
# let the 'install' command dictate our installation directory
|
||||
|
|
@ -61,14 +65,15 @@ class install_lib(Command):
|
|||
# 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.
|
||||
self.set_undefined_options('install',
|
||||
('build_lib', 'build_dir'),
|
||||
('install_lib', 'install_dir'),
|
||||
('force', 'force'),
|
||||
('compile', 'compile'),
|
||||
('optimize', 'optimize'),
|
||||
('skip_build', 'skip_build'),
|
||||
)
|
||||
self.set_undefined_options(
|
||||
'install',
|
||||
('build_lib', 'build_dir'),
|
||||
('install_lib', 'install_dir'),
|
||||
('force', 'force'),
|
||||
('compile', 'compile'),
|
||||
('optimize', 'optimize'),
|
||||
('skip_build', 'skip_build'),
|
||||
)
|
||||
|
||||
if self.compile is None:
|
||||
self.compile = True
|
||||
|
|
@ -81,7 +86,7 @@ class install_lib(Command):
|
|||
if self.optimize not in (0, 1, 2):
|
||||
raise AssertionError
|
||||
except (ValueError, AssertionError):
|
||||
raise DistutilsOptionError("optimize must be 0, 1, or 2")
|
||||
raise DistutilsOptionError('optimize must be 0, 1, or 2')
|
||||
|
||||
def run(self):
|
||||
# Make sure we have built everything we need first
|
||||
|
|
@ -110,8 +115,10 @@ class install_lib(Command):
|
|||
if os.path.isdir(self.build_dir):
|
||||
outfiles = self.copy_tree(self.build_dir, self.install_dir)
|
||||
else:
|
||||
self.warn("'%s' does not exist -- no Python modules to install" %
|
||||
self.build_dir)
|
||||
self.warn(
|
||||
"'%s' does not exist -- no Python modules to install" %
|
||||
self.build_dir,
|
||||
)
|
||||
return
|
||||
return outfiles
|
||||
|
||||
|
|
@ -129,14 +136,17 @@ class install_lib(Command):
|
|||
install_root = self.get_finalized_command('install').root
|
||||
|
||||
if self.compile:
|
||||
byte_compile(files, optimize=0,
|
||||
force=self.force, prefix=install_root,
|
||||
dry_run=self.dry_run)
|
||||
byte_compile(
|
||||
files, optimize=0,
|
||||
force=self.force, prefix=install_root,
|
||||
dry_run=self.dry_run,
|
||||
)
|
||||
if self.optimize > 0:
|
||||
byte_compile(files, optimize=self.optimize,
|
||||
force=self.force, prefix=install_root,
|
||||
verbose=self.verbose, dry_run=self.dry_run)
|
||||
|
||||
byte_compile(
|
||||
files, optimize=self.optimize,
|
||||
force=self.force, prefix=install_root,
|
||||
verbose=self.verbose, dry_run=self.dry_run,
|
||||
)
|
||||
|
||||
# -- Utility methods -----------------------------------------------
|
||||
|
||||
|
|
@ -165,15 +175,20 @@ class install_lib(Command):
|
|||
if ext != PYTHON_SOURCE_EXTENSION:
|
||||
continue
|
||||
if self.compile:
|
||||
bytecode_files.append(importlib.util.cache_from_source(
|
||||
py_file, optimization=''))
|
||||
bytecode_files.append(
|
||||
importlib.util.cache_from_source(
|
||||
py_file, optimization='',
|
||||
),
|
||||
)
|
||||
if self.optimize > 0:
|
||||
bytecode_files.append(importlib.util.cache_from_source(
|
||||
py_file, optimization=self.optimize))
|
||||
bytecode_files.append(
|
||||
importlib.util.cache_from_source(
|
||||
py_file, optimization=self.optimize,
|
||||
),
|
||||
)
|
||||
|
||||
return bytecode_files
|
||||
|
||||
|
||||
# -- External interface --------------------------------------------
|
||||
# (called by outsiders)
|
||||
|
||||
|
|
@ -183,18 +198,22 @@ class install_lib(Command):
|
|||
modules have actually been built yet.
|
||||
"""
|
||||
pure_outputs = \
|
||||
self._mutate_outputs(self.distribution.has_pure_modules(),
|
||||
'build_py', 'build_lib',
|
||||
self.install_dir)
|
||||
self._mutate_outputs(
|
||||
self.distribution.has_pure_modules(),
|
||||
'build_py', 'build_lib',
|
||||
self.install_dir,
|
||||
)
|
||||
if self.compile:
|
||||
bytecode_outputs = self._bytecode_filenames(pure_outputs)
|
||||
else:
|
||||
bytecode_outputs = []
|
||||
|
||||
ext_outputs = \
|
||||
self._mutate_outputs(self.distribution.has_ext_modules(),
|
||||
'build_ext', 'build_lib',
|
||||
self.install_dir)
|
||||
self._mutate_outputs(
|
||||
self.distribution.has_ext_modules(),
|
||||
'build_ext', 'build_lib',
|
||||
self.install_dir,
|
||||
)
|
||||
|
||||
return pure_outputs + bytecode_outputs + ext_outputs
|
||||
|
||||
|
|
|
|||
|
|
@ -2,24 +2,25 @@
|
|||
|
||||
Implements the Distutils 'install_scripts' command, for installing
|
||||
Python scripts."""
|
||||
|
||||
# contributed by Bastian Kleineidam
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from distutils.core import Command
|
||||
from distutils import log
|
||||
from stat import ST_MODE
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import Command
|
||||
|
||||
|
||||
class install_scripts(Command):
|
||||
|
||||
description = "install scripts (Python or otherwise)"
|
||||
description = 'install scripts (Python or otherwise)'
|
||||
|
||||
user_options = [
|
||||
('install-dir=', 'd', "directory to install scripts to"),
|
||||
('build-dir=','b', "build directory (where to install from)"),
|
||||
('force', 'f', "force installation (overwrite existing files)"),
|
||||
('skip-build', None, "skip the build steps"),
|
||||
('install-dir=', 'd', 'directory to install scripts to'),
|
||||
('build-dir=', 'b', 'build directory (where to install from)'),
|
||||
('force', 'f', 'force installation (overwrite existing files)'),
|
||||
('skip-build', None, 'skip the build steps'),
|
||||
]
|
||||
|
||||
boolean_options = ['force', 'skip-build']
|
||||
|
|
@ -32,11 +33,12 @@ class install_scripts(Command):
|
|||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('build', ('build_scripts', 'build_dir'))
|
||||
self.set_undefined_options('install',
|
||||
('install_scripts', 'install_dir'),
|
||||
('force', 'force'),
|
||||
('skip_build', 'skip_build'),
|
||||
)
|
||||
self.set_undefined_options(
|
||||
'install',
|
||||
('install_scripts', 'install_dir'),
|
||||
('force', 'force'),
|
||||
('skip_build', 'skip_build'),
|
||||
)
|
||||
|
||||
def run(self):
|
||||
if not self.skip_build:
|
||||
|
|
@ -47,10 +49,10 @@ class install_scripts(Command):
|
|||
# all the scripts we just installed.
|
||||
for file in self.get_outputs():
|
||||
if self.dry_run:
|
||||
log.info("changing mode of %s", file)
|
||||
log.info('changing mode of %s', file)
|
||||
else:
|
||||
mode = ((os.stat(file)[ST_MODE]) | 0o555) & 0o7777
|
||||
log.info("changing mode of %s to %o", file, mode)
|
||||
log.info('changing mode of %s to %o', file, mode)
|
||||
os.chmod(file, mode)
|
||||
|
||||
def get_inputs(self):
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
|
|
@ -23,8 +25,8 @@ def compose(f1, f2):
|
|||
|
||||
pythonlib = (
|
||||
compose(list, _pythonlib_compat)
|
||||
if sys.version_info < (3, 8)
|
||||
and sys.platform != 'darwin'
|
||||
and sys.platform[:3] != 'aix'
|
||||
if sys.version_info < (3, 8) and
|
||||
sys.platform != 'darwin' and
|
||||
sys.platform[:3] != 'aix'
|
||||
else list
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,29 +2,36 @@
|
|||
|
||||
Implements the Distutils 'register' command (register with the repository).
|
||||
"""
|
||||
|
||||
# created 2002/10/21, Richard Jones
|
||||
from __future__ import annotations
|
||||
|
||||
import getpass
|
||||
import io
|
||||
import urllib.parse, urllib.request
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
from warnings import warn
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import PyPIRCCommand
|
||||
from distutils.errors import *
|
||||
from distutils import log
|
||||
|
||||
|
||||
class register(PyPIRCCommand):
|
||||
|
||||
description = ("register the distribution with the Python package index")
|
||||
description = ('register the distribution with the Python package index')
|
||||
user_options = PyPIRCCommand.user_options + [
|
||||
('list-classifiers', None,
|
||||
'list the valid Trove classifiers'),
|
||||
('strict', None ,
|
||||
'Will stop the registering if the meta-data are not fully compliant')
|
||||
]
|
||||
(
|
||||
'list-classifiers', None,
|
||||
'list the valid Trove classifiers',
|
||||
),
|
||||
(
|
||||
'strict', None,
|
||||
'Will stop the registering if the meta-data are not fully compliant',
|
||||
),
|
||||
]
|
||||
boolean_options = PyPIRCCommand.boolean_options + [
|
||||
'verify', 'list-classifiers', 'strict']
|
||||
'verify', 'list-classifiers', 'strict',
|
||||
]
|
||||
|
||||
sub_commands = [('check', lambda self: True)]
|
||||
|
||||
|
|
@ -36,8 +43,10 @@ class register(PyPIRCCommand):
|
|||
def finalize_options(self):
|
||||
PyPIRCCommand.finalize_options(self)
|
||||
# setting options for the `check` subcommand
|
||||
check_options = {'strict': ('register', self.strict),
|
||||
'restructuredtext': ('register', 1)}
|
||||
check_options = {
|
||||
'strict': ('register', self.strict),
|
||||
'restructuredtext': ('register', 1),
|
||||
}
|
||||
self.distribution.command_options['check'] = check_options
|
||||
|
||||
def run(self):
|
||||
|
|
@ -57,8 +66,10 @@ class register(PyPIRCCommand):
|
|||
|
||||
def check_metadata(self):
|
||||
"""Deprecated API."""
|
||||
warn("distutils.command.register.check_metadata is deprecated, \
|
||||
use the check command instead", PendingDeprecationWarning)
|
||||
warn(
|
||||
'distutils.command.register.check_metadata is deprecated, \
|
||||
use the check command instead', PendingDeprecationWarning,
|
||||
)
|
||||
check = self.distribution.get_command_obj('check')
|
||||
check.ensure_finalized()
|
||||
check.strict = self.strict
|
||||
|
|
@ -85,7 +96,7 @@ class register(PyPIRCCommand):
|
|||
def classifiers(self):
|
||||
''' Fetch the list of classifiers from the server.
|
||||
'''
|
||||
url = self.repository+'?:action=list_classifiers'
|
||||
url = self.repository + '?:action=list_classifiers'
|
||||
response = urllib.request.urlopen(url)
|
||||
log.info(self._read_pypi_response(response))
|
||||
|
||||
|
|
@ -137,13 +148,15 @@ class register(PyPIRCCommand):
|
|||
# get the user's login info
|
||||
choices = '1 2 3 4'.split()
|
||||
while choice not in choices:
|
||||
self.announce('''\
|
||||
self.announce(
|
||||
'''\
|
||||
We need to know who you are, so please choose either:
|
||||
1. use your existing login,
|
||||
2. register as a new user,
|
||||
3. have the server generate a new password for you (and email it to you), or
|
||||
4. quit
|
||||
Your selection [default 1]: ''', log.INFO)
|
||||
Your selection [default 1]: ''', log.INFO,
|
||||
)
|
||||
choice = input()
|
||||
if not choice:
|
||||
choice = '1'
|
||||
|
|
@ -162,10 +175,14 @@ Your selection [default 1]: ''', log.INFO)
|
|||
host = urllib.parse.urlparse(self.repository)[1]
|
||||
auth.add_password(self.realm, host, username, password)
|
||||
# send the info to the server and report the result
|
||||
code, result = self.post_to_server(self.build_post_data('submit'),
|
||||
auth)
|
||||
self.announce('Server response (%s): %s' % (code, result),
|
||||
log.INFO)
|
||||
code, result = self.post_to_server(
|
||||
self.build_post_data('submit'),
|
||||
auth,
|
||||
)
|
||||
self.announce(
|
||||
'Server response ({}): {}'.format(code, result),
|
||||
log.INFO,
|
||||
)
|
||||
|
||||
# possibly save the login
|
||||
if code == 200:
|
||||
|
|
@ -174,10 +191,16 @@ Your selection [default 1]: ''', log.INFO)
|
|||
# so the upload command can reuse it
|
||||
self.distribution.password = password
|
||||
else:
|
||||
self.announce(('I can store your PyPI login so future '
|
||||
'submissions will be faster.'), log.INFO)
|
||||
self.announce('(the login will be stored in %s)' % \
|
||||
self._get_rc_file(), log.INFO)
|
||||
self.announce(
|
||||
(
|
||||
'I can store your PyPI login so future '
|
||||
'submissions will be faster.'
|
||||
), log.INFO,
|
||||
)
|
||||
self.announce(
|
||||
'(the login will be stored in %s)' %
|
||||
self._get_rc_file(), log.INFO,
|
||||
)
|
||||
choice = 'X'
|
||||
while choice.lower() not in 'yn':
|
||||
choice = input('Save your login (y/N)?')
|
||||
|
|
@ -208,8 +231,10 @@ Your selection [default 1]: ''', log.INFO)
|
|||
log.info('Server response (%s): %s', code, result)
|
||||
else:
|
||||
log.info('You will receive an email shortly.')
|
||||
log.info(('Follow the instructions in it to '
|
||||
'complete registration.'))
|
||||
log.info(
|
||||
'Follow the instructions in it to '
|
||||
'complete registration.'
|
||||
)
|
||||
elif choice == '3':
|
||||
data = {':action': 'password_reset'}
|
||||
data['email'] = ''
|
||||
|
|
@ -224,7 +249,7 @@ Your selection [default 1]: ''', log.INFO)
|
|||
meta = self.distribution.metadata
|
||||
data = {
|
||||
':action': action,
|
||||
'metadata_version' : '1.0',
|
||||
'metadata_version': '1.0',
|
||||
'name': meta.get_name(),
|
||||
'version': meta.get_version(),
|
||||
'summary': meta.get_description(),
|
||||
|
|
@ -250,9 +275,13 @@ Your selection [default 1]: ''', log.INFO)
|
|||
''' Post a query to the server, and return a string response.
|
||||
'''
|
||||
if 'name' in data:
|
||||
self.announce('Registering %s to %s' % (data['name'],
|
||||
self.repository),
|
||||
log.INFO)
|
||||
self.announce(
|
||||
'Registering {} to {}'.format(
|
||||
data['name'],
|
||||
self.repository,
|
||||
),
|
||||
log.INFO,
|
||||
)
|
||||
# Build up the MIME payload for the urllib2 POST data
|
||||
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
|
||||
sep_boundary = '\n--' + boundary
|
||||
|
|
@ -260,30 +289,30 @@ Your selection [default 1]: ''', log.INFO)
|
|||
body = io.StringIO()
|
||||
for key, value in data.items():
|
||||
# handle multiple entries for the same name
|
||||
if type(value) not in (type([]), type( () )):
|
||||
if type(value) not in (type([]), type(())):
|
||||
value = [value]
|
||||
for value in value:
|
||||
value = str(value)
|
||||
body.write(sep_boundary)
|
||||
body.write('\nContent-Disposition: form-data; name="%s"'%key)
|
||||
body.write("\n\n")
|
||||
body.write('\nContent-Disposition: form-data; name="%s"' % key)
|
||||
body.write('\n\n')
|
||||
body.write(value)
|
||||
if value and value[-1] == '\r':
|
||||
body.write('\n') # write an extra newline (lurve Macs)
|
||||
body.write(end_boundary)
|
||||
body.write("\n")
|
||||
body = body.getvalue().encode("utf-8")
|
||||
body.write('\n')
|
||||
body = body.getvalue().encode('utf-8')
|
||||
|
||||
# build the Request
|
||||
headers = {
|
||||
'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8'%boundary,
|
||||
'Content-length': str(len(body))
|
||||
'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8' % boundary,
|
||||
'Content-length': str(len(body)),
|
||||
}
|
||||
req = urllib.request.Request(self.repository, body, headers)
|
||||
|
||||
# handle HTTP and include the Basic Auth handler
|
||||
opener = urllib.request.build_opener(
|
||||
urllib.request.HTTPBasicAuthHandler(password_mgr=auth)
|
||||
urllib.request.HTTPBasicAuthHandler(password_mgr=auth),
|
||||
)
|
||||
data = ''
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
"""distutils.command.sdist
|
||||
|
||||
Implements the Distutils 'sdist' command (create a source distribution)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from glob import glob
|
||||
from warnings import warn
|
||||
|
||||
from distutils.core import Command
|
||||
from distutils import archive_util
|
||||
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.core import Command
|
||||
from distutils.errors import DistutilsOptionError
|
||||
from distutils.errors import DistutilsTemplateError
|
||||
from distutils.filelist import FileList
|
||||
from distutils.text_file import TextFile
|
||||
from distutils.util import convert_path
|
||||
from distutils.errors import DistutilsTemplateError, DistutilsOptionError
|
||||
|
||||
|
||||
def show_formats():
|
||||
|
|
@ -26,16 +28,19 @@ def show_formats():
|
|||
from distutils.archive_util import ARCHIVE_FORMATS
|
||||
formats = []
|
||||
for format in ARCHIVE_FORMATS.keys():
|
||||
formats.append(("formats=" + format, None,
|
||||
ARCHIVE_FORMATS[format][2]))
|
||||
formats.append((
|
||||
'formats=' + format, None,
|
||||
ARCHIVE_FORMATS[format][2],
|
||||
))
|
||||
formats.sort()
|
||||
FancyGetopt(formats).print_help(
|
||||
"List of available source distribution formats:")
|
||||
'List of available source distribution formats:',
|
||||
)
|
||||
|
||||
|
||||
class sdist(Command):
|
||||
|
||||
description = "create a source distribution (tarball, zip file, etc.)"
|
||||
description = 'create a source distribution (tarball, zip file, etc.)'
|
||||
|
||||
def checking_metadata(self):
|
||||
"""Callable used for the check sub-command.
|
||||
|
|
@ -44,55 +49,88 @@ class sdist(Command):
|
|||
return self.metadata_check
|
||||
|
||||
user_options = [
|
||||
('template=', 't',
|
||||
"name of manifest template file [default: MANIFEST.in]"),
|
||||
('manifest=', 'm',
|
||||
"name of manifest file [default: MANIFEST]"),
|
||||
('use-defaults', None,
|
||||
"include the default file set in the manifest "
|
||||
"[default; disable with --no-defaults]"),
|
||||
('no-defaults', None,
|
||||
"don't include the default file set"),
|
||||
('prune', None,
|
||||
"specifically exclude files/directories that should not be "
|
||||
"distributed (build tree, RCS/CVS dirs, etc.) "
|
||||
"[default; disable with --no-prune]"),
|
||||
('no-prune', None,
|
||||
"don't automatically exclude anything"),
|
||||
('manifest-only', 'o',
|
||||
"just regenerate the manifest and then stop "
|
||||
"(implies --force-manifest)"),
|
||||
('force-manifest', 'f',
|
||||
"forcibly regenerate the manifest and carry on as usual. "
|
||||
"Deprecated: now the manifest is always regenerated."),
|
||||
('formats=', None,
|
||||
"formats for source distribution (comma-separated list)"),
|
||||
('keep-temp', 'k',
|
||||
"keep the distribution tree around after creating " +
|
||||
"archive file(s)"),
|
||||
('dist-dir=', 'd',
|
||||
"directory to put the source distribution archive(s) in "
|
||||
"[default: dist]"),
|
||||
('metadata-check', None,
|
||||
"Ensure that all required elements of meta-data "
|
||||
"are supplied. Warn if any missing. [default]"),
|
||||
('owner=', 'u',
|
||||
"Owner name used when creating a tar file [default: current user]"),
|
||||
('group=', 'g',
|
||||
"Group name used when creating a tar file [default: current group]"),
|
||||
]
|
||||
(
|
||||
'template=', 't',
|
||||
'name of manifest template file [default: MANIFEST.in]',
|
||||
),
|
||||
(
|
||||
'manifest=', 'm',
|
||||
'name of manifest file [default: MANIFEST]',
|
||||
),
|
||||
(
|
||||
'use-defaults', None,
|
||||
'include the default file set in the manifest '
|
||||
'[default; disable with --no-defaults]',
|
||||
),
|
||||
(
|
||||
'no-defaults', None,
|
||||
"don't include the default file set",
|
||||
),
|
||||
(
|
||||
'prune', None,
|
||||
'specifically exclude files/directories that should not be '
|
||||
'distributed (build tree, RCS/CVS dirs, etc.) '
|
||||
'[default; disable with --no-prune]',
|
||||
),
|
||||
(
|
||||
'no-prune', None,
|
||||
"don't automatically exclude anything",
|
||||
),
|
||||
(
|
||||
'manifest-only', 'o',
|
||||
'just regenerate the manifest and then stop '
|
||||
'(implies --force-manifest)',
|
||||
),
|
||||
(
|
||||
'force-manifest', 'f',
|
||||
'forcibly regenerate the manifest and carry on as usual. '
|
||||
'Deprecated: now the manifest is always regenerated.',
|
||||
),
|
||||
(
|
||||
'formats=', None,
|
||||
'formats for source distribution (comma-separated list)',
|
||||
),
|
||||
(
|
||||
'keep-temp', 'k',
|
||||
'keep the distribution tree around after creating ' +
|
||||
'archive file(s)',
|
||||
),
|
||||
(
|
||||
'dist-dir=', 'd',
|
||||
'directory to put the source distribution archive(s) in '
|
||||
'[default: dist]',
|
||||
),
|
||||
(
|
||||
'metadata-check', None,
|
||||
'Ensure that all required elements of meta-data '
|
||||
'are supplied. Warn if any missing. [default]',
|
||||
),
|
||||
(
|
||||
'owner=', 'u',
|
||||
'Owner name used when creating a tar file [default: current user]',
|
||||
),
|
||||
(
|
||||
'group=', 'g',
|
||||
'Group name used when creating a tar file [default: current group]',
|
||||
),
|
||||
]
|
||||
|
||||
boolean_options = ['use-defaults', 'prune',
|
||||
'manifest-only', 'force-manifest',
|
||||
'keep-temp', 'metadata-check']
|
||||
boolean_options = [
|
||||
'use-defaults', 'prune',
|
||||
'manifest-only', 'force-manifest',
|
||||
'keep-temp', 'metadata-check',
|
||||
]
|
||||
|
||||
help_options = [
|
||||
('help-formats', None,
|
||||
"list available distribution formats", show_formats),
|
||||
]
|
||||
(
|
||||
'help-formats', None,
|
||||
'list available distribution formats', show_formats,
|
||||
),
|
||||
]
|
||||
|
||||
negative_opt = {'no-defaults': 'use-defaults',
|
||||
'no-prune': 'prune' }
|
||||
negative_opt = {
|
||||
'no-defaults': 'use-defaults',
|
||||
'no-prune': 'prune', }
|
||||
|
||||
sub_commands = [('check', checking_metadata)]
|
||||
|
||||
|
|
@ -123,19 +161,20 @@ class sdist(Command):
|
|||
|
||||
def finalize_options(self):
|
||||
if self.manifest is None:
|
||||
self.manifest = "MANIFEST"
|
||||
self.manifest = 'MANIFEST'
|
||||
if self.template is None:
|
||||
self.template = "MANIFEST.in"
|
||||
self.template = 'MANIFEST.in'
|
||||
|
||||
self.ensure_string_list('formats')
|
||||
|
||||
bad_format = archive_util.check_archive_formats(self.formats)
|
||||
if bad_format:
|
||||
raise DistutilsOptionError(
|
||||
"unknown archive format '%s'" % bad_format)
|
||||
"unknown archive format '%s'" % bad_format,
|
||||
)
|
||||
|
||||
if self.dist_dir is None:
|
||||
self.dist_dir = "dist"
|
||||
self.dist_dir = 'dist'
|
||||
|
||||
def run(self):
|
||||
# 'filelist' contains the list of files that will make up the
|
||||
|
|
@ -161,8 +200,10 @@ class sdist(Command):
|
|||
|
||||
def check_metadata(self):
|
||||
"""Deprecated API."""
|
||||
warn("distutils.command.sdist.check_metadata is deprecated, \
|
||||
use the check command instead", PendingDeprecationWarning)
|
||||
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()
|
||||
|
|
@ -189,9 +230,13 @@ class sdist(Command):
|
|||
return
|
||||
|
||||
if not template_exists:
|
||||
self.warn(("manifest template '%s' does not exist " +
|
||||
"(using default file list)") %
|
||||
self.template)
|
||||
self.warn(
|
||||
(
|
||||
"manifest template '%s' does not exist " +
|
||||
'(using default file list)'
|
||||
) %
|
||||
self.template,
|
||||
)
|
||||
self.filelist.findall()
|
||||
|
||||
if self.use_defaults:
|
||||
|
|
@ -259,8 +304,10 @@ class sdist(Command):
|
|||
break
|
||||
|
||||
if not got_it:
|
||||
self.warn("standard file not found: should have one of " +
|
||||
', '.join(alts))
|
||||
self.warn(
|
||||
'standard file not found: should have one of ' +
|
||||
', '.join(alts),
|
||||
)
|
||||
else:
|
||||
if self._cs_path_exists(fn):
|
||||
self.filelist.append(fn)
|
||||
|
|
@ -328,9 +375,11 @@ class sdist(Command):
|
|||
'self.filelist', which updates itself accordingly.
|
||||
"""
|
||||
log.info("reading manifest template '%s'", self.template)
|
||||
template = TextFile(self.template, strip_comments=1, skip_blanks=1,
|
||||
join_lines=1, lstrip_ws=1, rstrip_ws=1,
|
||||
collapse_join=1)
|
||||
template = TextFile(
|
||||
self.template, strip_comments=1, skip_blanks=1,
|
||||
join_lines=1, lstrip_ws=1, rstrip_ws=1,
|
||||
collapse_join=1,
|
||||
)
|
||||
|
||||
try:
|
||||
while True:
|
||||
|
|
@ -344,9 +393,13 @@ class sdist(Command):
|
|||
# malformed lines, or a ValueError from the lower-level
|
||||
# convert_path function
|
||||
except (DistutilsTemplateError, ValueError) as msg:
|
||||
self.warn("%s, line %d: %s" % (template.filename,
|
||||
template.current_line,
|
||||
msg))
|
||||
self.warn(
|
||||
'%s, line %d: %s' % (
|
||||
template.filename,
|
||||
template.current_line,
|
||||
msg,
|
||||
),
|
||||
)
|
||||
finally:
|
||||
template.close()
|
||||
|
||||
|
|
@ -369,9 +422,11 @@ class sdist(Command):
|
|||
else:
|
||||
seps = '/'
|
||||
|
||||
vcs_dirs = ['RCS', 'CVS', r'\.svn', r'\.hg', r'\.git', r'\.bzr',
|
||||
'_darcs']
|
||||
vcs_ptrn = r'(^|%s)(%s)(%s).*' % (seps, '|'.join(vcs_dirs), seps)
|
||||
vcs_dirs = [
|
||||
'RCS', 'CVS', r'\.svn', r'\.hg', r'\.git', r'\.bzr',
|
||||
'_darcs',
|
||||
]
|
||||
vcs_ptrn = r'(^|{})({})({}).*'.format(seps, '|'.join(vcs_dirs), seps)
|
||||
self.filelist.exclude_pattern(vcs_ptrn, is_regex=1)
|
||||
|
||||
def write_manifest(self):
|
||||
|
|
@ -380,14 +435,18 @@ class sdist(Command):
|
|||
named by 'self.manifest'.
|
||||
"""
|
||||
if self._manifest_is_not_generated():
|
||||
log.info("not writing to manually maintained "
|
||||
"manifest file '%s'" % self.manifest)
|
||||
log.info(
|
||||
'not writing to manually maintained '
|
||||
"manifest file '%s'" % self.manifest,
|
||||
)
|
||||
return
|
||||
|
||||
content = self.filelist.files[:]
|
||||
content.insert(0, '# file GENERATED by distutils, do NOT edit')
|
||||
self.execute(file_util.write_file, (self.manifest, content),
|
||||
"writing manifest file '%s'" % self.manifest)
|
||||
self.execute(
|
||||
file_util.write_file, (self.manifest, content),
|
||||
"writing manifest file '%s'" % self.manifest,
|
||||
)
|
||||
|
||||
def _manifest_is_not_generated(self):
|
||||
# check for special comment used in 3.1.3 and higher
|
||||
|
|
@ -439,13 +498,13 @@ class sdist(Command):
|
|||
|
||||
if hasattr(os, 'link'): # can make hard links on this system
|
||||
link = 'hard'
|
||||
msg = "making hard links in %s..." % base_dir
|
||||
msg = 'making hard links in %s...' % base_dir
|
||||
else: # nope, have to copy
|
||||
link = None
|
||||
msg = "copying files to %s..." % base_dir
|
||||
msg = 'copying files to %s...' % base_dir
|
||||
|
||||
if not files:
|
||||
log.warn("no files to distribute -- empty manifest?")
|
||||
log.warn('no files to distribute -- empty manifest?')
|
||||
else:
|
||||
log.info(msg)
|
||||
for file in files:
|
||||
|
|
@ -477,8 +536,10 @@ class sdist(Command):
|
|||
self.formats.append(self.formats.pop(self.formats.index('tar')))
|
||||
|
||||
for fmt in self.formats:
|
||||
file = self.make_archive(base_name, fmt, base_dir=base_dir,
|
||||
owner=self.owner, group=self.group)
|
||||
file = self.make_archive(
|
||||
base_name, fmt, base_dir=base_dir,
|
||||
owner=self.owner, group=self.group,
|
||||
)
|
||||
archive_files.append(file)
|
||||
self.distribution.dist_files.append(('sdist', '', file))
|
||||
|
||||
|
|
|
|||
|
|
@ -4,37 +4,44 @@ distutils.command.upload
|
|||
Implements the Distutils 'upload' subcommand (upload package to a package
|
||||
index).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import io
|
||||
import hashlib
|
||||
import io
|
||||
import os
|
||||
from base64 import standard_b64encode
|
||||
from urllib.request import urlopen, Request, HTTPError
|
||||
from urllib.parse import urlparse
|
||||
from distutils.errors import DistutilsError, DistutilsOptionError
|
||||
from distutils.core import PyPIRCCommand
|
||||
from distutils.spawn import spawn
|
||||
from urllib.request import HTTPError
|
||||
from urllib.request import Request
|
||||
from urllib.request import urlopen
|
||||
|
||||
from distutils import log
|
||||
from distutils.core import PyPIRCCommand
|
||||
from distutils.errors import DistutilsError
|
||||
from distutils.errors import DistutilsOptionError
|
||||
from distutils.spawn import spawn
|
||||
|
||||
|
||||
# PyPI Warehouse supports MD5, SHA256, and Blake2 (blake2-256)
|
||||
# https://bugs.python.org/issue40698
|
||||
_FILE_CONTENT_DIGESTS = {
|
||||
"md5_digest": getattr(hashlib, "md5", None),
|
||||
"sha256_digest": getattr(hashlib, "sha256", None),
|
||||
"blake2_256_digest": getattr(hashlib, "blake2b", None),
|
||||
'md5_digest': getattr(hashlib, 'md5', None),
|
||||
'sha256_digest': getattr(hashlib, 'sha256', None),
|
||||
'blake2_256_digest': getattr(hashlib, 'blake2b', None),
|
||||
}
|
||||
|
||||
|
||||
class upload(PyPIRCCommand):
|
||||
|
||||
description = "upload binary package to PyPI"
|
||||
description = 'upload binary package to PyPI'
|
||||
|
||||
user_options = PyPIRCCommand.user_options + [
|
||||
('sign', 's',
|
||||
'sign files to upload using gpg'),
|
||||
(
|
||||
'sign', 's',
|
||||
'sign files to upload using gpg',
|
||||
),
|
||||
('identity=', 'i', 'GPG identity used to sign files'),
|
||||
]
|
||||
]
|
||||
|
||||
boolean_options = PyPIRCCommand.boolean_options + ['sign']
|
||||
|
||||
|
|
@ -50,7 +57,7 @@ class upload(PyPIRCCommand):
|
|||
PyPIRCCommand.finalize_options(self)
|
||||
if self.identity and not self.sign:
|
||||
raise DistutilsOptionError(
|
||||
"Must use --sign for --identity to have meaning"
|
||||
'Must use --sign for --identity to have meaning',
|
||||
)
|
||||
config = self._read_pypirc()
|
||||
if config != {}:
|
||||
|
|
@ -66,8 +73,10 @@ class upload(PyPIRCCommand):
|
|||
|
||||
def run(self):
|
||||
if not self.distribution.dist_files:
|
||||
msg = ("Must create and upload files in one command "
|
||||
"(e.g. setup.py sdist upload)")
|
||||
msg = (
|
||||
'Must create and upload files in one command '
|
||||
'(e.g. setup.py sdist upload)'
|
||||
)
|
||||
raise DistutilsOptionError(msg)
|
||||
for command, pyversion, filename in self.distribution.dist_files:
|
||||
self.upload_file(command, pyversion, filename)
|
||||
|
|
@ -77,22 +86,24 @@ class upload(PyPIRCCommand):
|
|||
schema, netloc, url, params, query, fragments = \
|
||||
urlparse(self.repository)
|
||||
if params or query or fragments:
|
||||
raise AssertionError("Incompatible url %s" % self.repository)
|
||||
raise AssertionError('Incompatible url %s' % self.repository)
|
||||
|
||||
if schema not in ('http', 'https'):
|
||||
raise AssertionError("unsupported schema " + schema)
|
||||
raise AssertionError('unsupported schema ' + schema)
|
||||
|
||||
# Sign if requested
|
||||
if self.sign:
|
||||
gpg_args = ["gpg", "--detach-sign", "-a", filename]
|
||||
gpg_args = ['gpg', '--detach-sign', '-a', filename]
|
||||
if self.identity:
|
||||
gpg_args[2:2] = ["--local-user", self.identity]
|
||||
spawn(gpg_args,
|
||||
dry_run=self.dry_run)
|
||||
gpg_args[2:2] = ['--local-user', self.identity]
|
||||
spawn(
|
||||
gpg_args,
|
||||
dry_run=self.dry_run,
|
||||
)
|
||||
|
||||
# Fill in the data - send all the meta-data in case we need to
|
||||
# register a new release
|
||||
f = open(filename,'rb')
|
||||
f = open(filename, 'rb')
|
||||
try:
|
||||
content = f.read()
|
||||
finally:
|
||||
|
|
@ -109,7 +120,7 @@ class upload(PyPIRCCommand):
|
|||
'version': meta.get_version(),
|
||||
|
||||
# file content
|
||||
'content': (os.path.basename(filename),content),
|
||||
'content': (os.path.basename(filename), content),
|
||||
'filetype': command,
|
||||
'pyversion': pyversion,
|
||||
|
||||
|
|
@ -129,7 +140,7 @@ class upload(PyPIRCCommand):
|
|||
'provides': meta.get_provides(),
|
||||
'requires': meta.get_requires(),
|
||||
'obsoletes': meta.get_obsoletes(),
|
||||
}
|
||||
}
|
||||
|
||||
data['comment'] = ''
|
||||
|
||||
|
|
@ -144,15 +155,17 @@ class upload(PyPIRCCommand):
|
|||
pass
|
||||
|
||||
if self.sign:
|
||||
with open(filename + ".asc", "rb") as f:
|
||||
data['gpg_signature'] = (os.path.basename(filename) + ".asc",
|
||||
f.read())
|
||||
with open(filename + '.asc', 'rb') as f:
|
||||
data['gpg_signature'] = (
|
||||
os.path.basename(filename) + '.asc',
|
||||
f.read(),
|
||||
)
|
||||
|
||||
# set up the authentication
|
||||
user_pass = (self.username + ":" + self.password).encode('ascii')
|
||||
user_pass = (self.username + ':' + self.password).encode('ascii')
|
||||
# The exact encoding of the authentication string is debated.
|
||||
# Anyway PyPI only accepts ascii for both username or password.
|
||||
auth = "Basic " + standard_b64encode(user_pass).decode('ascii')
|
||||
auth = 'Basic ' + standard_b64encode(user_pass).decode('ascii')
|
||||
|
||||
# Build up the MIME payload for the POST data
|
||||
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
|
||||
|
|
@ -172,12 +185,12 @@ class upload(PyPIRCCommand):
|
|||
value = str(value).encode('utf-8')
|
||||
body.write(sep_boundary)
|
||||
body.write(title.encode('utf-8'))
|
||||
body.write(b"\r\n\r\n")
|
||||
body.write(b'\r\n\r\n')
|
||||
body.write(value)
|
||||
body.write(end_boundary)
|
||||
body = body.getvalue()
|
||||
|
||||
msg = "Submitting %s to %s" % (filename, self.repository)
|
||||
msg = 'Submitting {} to {}'.format(filename, self.repository)
|
||||
self.announce(msg, log.INFO)
|
||||
|
||||
# build the Request
|
||||
|
|
@ -187,8 +200,10 @@ class upload(PyPIRCCommand):
|
|||
'Authorization': auth,
|
||||
}
|
||||
|
||||
request = Request(self.repository, data=body,
|
||||
headers=headers)
|
||||
request = Request(
|
||||
self.repository, data=body,
|
||||
headers=headers,
|
||||
)
|
||||
# send the data
|
||||
try:
|
||||
result = urlopen(request)
|
||||
|
|
@ -202,13 +217,15 @@ class upload(PyPIRCCommand):
|
|||
raise
|
||||
|
||||
if status == 200:
|
||||
self.announce('Server response (%s): %s' % (status, reason),
|
||||
log.INFO)
|
||||
self.announce(
|
||||
'Server response ({}): {}'.format(status, reason),
|
||||
log.INFO,
|
||||
)
|
||||
if self.show_response:
|
||||
text = self._read_pypi_response(result)
|
||||
msg = '\n'.join(('-' * 75, text, '-' * 75))
|
||||
self.announce(msg, log.INFO)
|
||||
else:
|
||||
msg = 'Upload failed (%s): %s' % (status, reason)
|
||||
msg = 'Upload failed ({}): {}'.format(status, reason)
|
||||
self.announce(msg, log.ERROR)
|
||||
raise DistutilsError(msg)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue