help
This commit is contained in:
parent
f9a2e68c8b
commit
95d0201681
1552 changed files with 367539 additions and 2 deletions
253
env/Lib/site-packages/setuptools/__init__.py
vendored
Normal file
253
env/Lib/site-packages/setuptools/__init__.py
vendored
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
"""Extensions to the 'distutils' for large or complex distributions"""
|
||||
|
||||
import os
|
||||
import functools
|
||||
|
||||
# Disabled for now due to: #2228, #2230
|
||||
import setuptools.distutils_patch # noqa: F401
|
||||
|
||||
import distutils.core
|
||||
import distutils.filelist
|
||||
import re
|
||||
from distutils.errors import DistutilsOptionError
|
||||
from distutils.util import convert_path
|
||||
from fnmatch import fnmatchcase
|
||||
|
||||
from ._deprecation_warning import SetuptoolsDeprecationWarning
|
||||
|
||||
from setuptools.extern.six import PY3, string_types
|
||||
from setuptools.extern.six.moves import filter, map
|
||||
|
||||
import setuptools.version
|
||||
from setuptools.extension import Extension
|
||||
from setuptools.dist import Distribution
|
||||
from setuptools.depends import Require
|
||||
from . import monkey
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
__all__ = [
|
||||
'setup', 'Distribution', 'Command', 'Extension', 'Require',
|
||||
'SetuptoolsDeprecationWarning',
|
||||
'find_packages'
|
||||
]
|
||||
|
||||
if PY3:
|
||||
__all__.append('find_namespace_packages')
|
||||
|
||||
__version__ = setuptools.version.__version__
|
||||
|
||||
bootstrap_install_from = None
|
||||
|
||||
# If we run 2to3 on .py files, should we also convert docstrings?
|
||||
# Default: yes; assume that we can detect doctests reliably
|
||||
run_2to3_on_doctests = True
|
||||
# Standard package names for fixer packages
|
||||
lib2to3_fixer_packages = ['lib2to3.fixes']
|
||||
|
||||
|
||||
class PackageFinder:
|
||||
"""
|
||||
Generate a list of all Python packages found within a directory
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def find(cls, where='.', exclude=(), include=('*',)):
|
||||
"""Return a list all Python packages found within directory 'where'
|
||||
|
||||
'where' is the root directory which will be searched for packages. It
|
||||
should be supplied as a "cross-platform" (i.e. URL-style) path; it will
|
||||
be converted to the appropriate local path syntax.
|
||||
|
||||
'exclude' is a sequence of package names to exclude; '*' can be used
|
||||
as a wildcard in the names, such that 'foo.*' will exclude all
|
||||
subpackages of 'foo' (but not 'foo' itself).
|
||||
|
||||
'include' is a sequence of package names to include. If it's
|
||||
specified, only the named packages will be included. If it's not
|
||||
specified, all found packages will be included. 'include' can contain
|
||||
shell style wildcard patterns just like 'exclude'.
|
||||
"""
|
||||
|
||||
return list(cls._find_packages_iter(
|
||||
convert_path(where),
|
||||
cls._build_filter('ez_setup', '*__pycache__', *exclude),
|
||||
cls._build_filter(*include)))
|
||||
|
||||
@classmethod
|
||||
def _find_packages_iter(cls, where, exclude, include):
|
||||
"""
|
||||
All the packages found in 'where' that pass the 'include' filter, but
|
||||
not the 'exclude' filter.
|
||||
"""
|
||||
for root, dirs, files in os.walk(where, followlinks=True):
|
||||
# Copy dirs to iterate over it, then empty dirs.
|
||||
all_dirs = dirs[:]
|
||||
dirs[:] = []
|
||||
|
||||
for dir in all_dirs:
|
||||
full_path = os.path.join(root, dir)
|
||||
rel_path = os.path.relpath(full_path, where)
|
||||
package = rel_path.replace(os.path.sep, '.')
|
||||
|
||||
# Skip directory trees that are not valid packages
|
||||
if ('.' in dir or not cls._looks_like_package(full_path)):
|
||||
continue
|
||||
|
||||
# Should this package be included?
|
||||
if include(package) and not exclude(package):
|
||||
yield package
|
||||
|
||||
# Keep searching subdirectories, as there may be more packages
|
||||
# down there, even if the parent was excluded.
|
||||
dirs.append(dir)
|
||||
|
||||
@staticmethod
|
||||
def _looks_like_package(path):
|
||||
"""Does a directory look like a package?"""
|
||||
return os.path.isfile(os.path.join(path, '__init__.py'))
|
||||
|
||||
@staticmethod
|
||||
def _build_filter(*patterns):
|
||||
"""
|
||||
Given a list of patterns, return a callable that will be true only if
|
||||
the input matches at least one of the patterns.
|
||||
"""
|
||||
return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns)
|
||||
|
||||
|
||||
class PEP420PackageFinder(PackageFinder):
|
||||
@staticmethod
|
||||
def _looks_like_package(path):
|
||||
return True
|
||||
|
||||
|
||||
find_packages = PackageFinder.find
|
||||
|
||||
if PY3:
|
||||
find_namespace_packages = PEP420PackageFinder.find
|
||||
|
||||
|
||||
def _install_setup_requires(attrs):
|
||||
# Note: do not use `setuptools.Distribution` directly, as
|
||||
# our PEP 517 backend patch `distutils.core.Distribution`.
|
||||
class MinimalDistribution(distutils.core.Distribution):
|
||||
"""
|
||||
A minimal version of a distribution for supporting the
|
||||
fetch_build_eggs interface.
|
||||
"""
|
||||
def __init__(self, attrs):
|
||||
_incl = 'dependency_links', 'setup_requires'
|
||||
filtered = {
|
||||
k: attrs[k]
|
||||
for k in set(_incl) & set(attrs)
|
||||
}
|
||||
distutils.core.Distribution.__init__(self, filtered)
|
||||
|
||||
def finalize_options(self):
|
||||
"""
|
||||
Disable finalize_options to avoid building the working set.
|
||||
Ref #2158.
|
||||
"""
|
||||
|
||||
dist = MinimalDistribution(attrs)
|
||||
|
||||
# Honor setup.cfg's options.
|
||||
dist.parse_config_files(ignore_option_errors=True)
|
||||
if dist.setup_requires:
|
||||
dist.fetch_build_eggs(dist.setup_requires)
|
||||
|
||||
|
||||
def setup(**attrs):
|
||||
# Make sure we have any requirements needed to interpret 'attrs'.
|
||||
_install_setup_requires(attrs)
|
||||
return distutils.core.setup(**attrs)
|
||||
|
||||
|
||||
setup.__doc__ = distutils.core.setup.__doc__
|
||||
|
||||
|
||||
_Command = monkey.get_unpatched(distutils.core.Command)
|
||||
|
||||
|
||||
class Command(_Command):
|
||||
__doc__ = _Command.__doc__
|
||||
|
||||
command_consumes_arguments = False
|
||||
|
||||
def __init__(self, dist, **kw):
|
||||
"""
|
||||
Construct the command for dist, updating
|
||||
vars(self) with any keyword parameters.
|
||||
"""
|
||||
_Command.__init__(self, dist)
|
||||
vars(self).update(kw)
|
||||
|
||||
def _ensure_stringlike(self, option, what, default=None):
|
||||
val = getattr(self, option)
|
||||
if val is None:
|
||||
setattr(self, option, default)
|
||||
return default
|
||||
elif not isinstance(val, string_types):
|
||||
raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
|
||||
% (option, what, val))
|
||||
return val
|
||||
|
||||
def ensure_string_list(self, option):
|
||||
r"""Ensure that 'option' is a list of strings. If 'option' is
|
||||
currently a string, we split it either on /,\s*/ or /\s+/, so
|
||||
"foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
|
||||
["foo", "bar", "baz"].
|
||||
"""
|
||||
val = getattr(self, option)
|
||||
if val is None:
|
||||
return
|
||||
elif isinstance(val, string_types):
|
||||
setattr(self, option, re.split(r',\s*|\s+', val))
|
||||
else:
|
||||
if isinstance(val, list):
|
||||
ok = all(isinstance(v, string_types) for v in val)
|
||||
else:
|
||||
ok = False
|
||||
if not ok:
|
||||
raise DistutilsOptionError(
|
||||
"'%s' must be a list of strings (got %r)"
|
||||
% (option, val))
|
||||
|
||||
def reinitialize_command(self, command, reinit_subcommands=0, **kw):
|
||||
cmd = _Command.reinitialize_command(self, command, reinit_subcommands)
|
||||
vars(cmd).update(kw)
|
||||
return cmd
|
||||
|
||||
|
||||
def _find_all_simple(path):
|
||||
"""
|
||||
Find all files under 'path'
|
||||
"""
|
||||
results = (
|
||||
os.path.join(base, file)
|
||||
for base, dirs, files in os.walk(path, followlinks=True)
|
||||
for file in files
|
||||
)
|
||||
return filter(os.path.isfile, results)
|
||||
|
||||
|
||||
def findall(dir=os.curdir):
|
||||
"""
|
||||
Find all files under 'dir' and return the list of full filenames.
|
||||
Unless dir is '.', return full filenames with dir prepended.
|
||||
"""
|
||||
files = _find_all_simple(dir)
|
||||
if dir == os.curdir:
|
||||
make_rel = functools.partial(os.path.relpath, start=dir)
|
||||
files = map(make_rel, files)
|
||||
return list(files)
|
||||
|
||||
|
||||
class sic(str):
|
||||
"""Treat this string as-is (https://en.wikipedia.org/wiki/Sic)"""
|
||||
|
||||
|
||||
# Apply monkey patches
|
||||
monkey.patch_all()
|
||||
BIN
env/Lib/site-packages/setuptools/__pycache__/__init__.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/__init__.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/_imp.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/_imp.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/archive_util.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/archive_util.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/build_meta.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/build_meta.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/config.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/config.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/dep_util.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/dep_util.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/depends.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/depends.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/dist.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/dist.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/distutils_patch.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/distutils_patch.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/errors.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/errors.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/extension.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/extension.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/glob.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/glob.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/installer.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/installer.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/launch.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/launch.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/lib2to3_ex.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/lib2to3_ex.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/monkey.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/monkey.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/msvc.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/msvc.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/namespaces.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/namespaces.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/package_index.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/package_index.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/py27compat.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/py27compat.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/py31compat.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/py31compat.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/py33compat.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/py33compat.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/py34compat.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/py34compat.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/sandbox.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/sandbox.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/ssl_support.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/ssl_support.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/unicode_utils.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/unicode_utils.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/version.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/version.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/wheel.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/wheel.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/__pycache__/windows_support.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/__pycache__/windows_support.cpython-39.pyc
vendored
Normal file
Binary file not shown.
7
env/Lib/site-packages/setuptools/_deprecation_warning.py
vendored
Normal file
7
env/Lib/site-packages/setuptools/_deprecation_warning.py
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
class SetuptoolsDeprecationWarning(Warning):
|
||||
"""
|
||||
Base class for warning deprecations in ``setuptools``
|
||||
|
||||
This class is not derived from ``DeprecationWarning``, and as such is
|
||||
visible by default.
|
||||
"""
|
||||
15
env/Lib/site-packages/setuptools/_distutils/__init__.py
vendored
Normal file
15
env/Lib/site-packages/setuptools/_distutils/__init__.py
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
"""distutils
|
||||
|
||||
The main package for the Python Module Distribution Utilities. Normally
|
||||
used from a setup script as
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
setup (...)
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
__version__ = sys.version[:sys.version.index(' ')]
|
||||
|
||||
local = True
|
||||
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/bcppcompiler.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/bcppcompiler.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/config.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/config.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/core.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/core.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/debug.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/debug.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/dist.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/dist.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/errors.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/errors.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/extension.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/extension.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/log.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/log.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/msvc9compiler.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/msvc9compiler.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/util.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/util.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/version.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/version.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-39.pyc
vendored
Normal file
Binary file not shown.
537
env/Lib/site-packages/setuptools/_distutils/_msvccompiler.py
vendored
Normal file
537
env/Lib/site-packages/setuptools/_distutils/_msvccompiler.py
vendored
Normal file
|
|
@ -0,0 +1,537 @@
|
|||
"""distutils._msvccompiler
|
||||
|
||||
Contains MSVCCompiler, an implementation of the abstract CCompiler class
|
||||
for Microsoft Visual Studio 2015.
|
||||
|
||||
The module is compatible with VS 2015 and later. You can find legacy support
|
||||
for older versions in distutils.msvc9compiler and distutils.msvccompiler.
|
||||
"""
|
||||
|
||||
# Written by Perry Stoll
|
||||
# hacked by Robin Becker and Thomas Heller to do a better job of
|
||||
# finding DevStudio (through the registry)
|
||||
# ported to VS 2005 and VS 2008 by Christian Heimes
|
||||
# ported to VS 2015 by Steve Dower
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import contextlib
|
||||
with contextlib.suppress(ImportError):
|
||||
import winreg
|
||||
|
||||
from distutils.errors import DistutilsExecError, DistutilsPlatformError, \
|
||||
CompileError, LibError, LinkError
|
||||
from distutils.ccompiler import CCompiler, gen_lib_options
|
||||
from distutils import log
|
||||
from distutils.util import get_platform
|
||||
|
||||
from itertools import count
|
||||
|
||||
def _find_vc2015():
|
||||
try:
|
||||
key = winreg.OpenKeyEx(
|
||||
winreg.HKEY_LOCAL_MACHINE,
|
||||
r"Software\Microsoft\VisualStudio\SxS\VC7",
|
||||
access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY
|
||||
)
|
||||
except OSError:
|
||||
log.debug("Visual C++ is not registered")
|
||||
return None, None
|
||||
|
||||
best_version = 0
|
||||
best_dir = None
|
||||
with key:
|
||||
for i in count():
|
||||
try:
|
||||
v, vc_dir, vt = winreg.EnumValue(key, i)
|
||||
except OSError:
|
||||
break
|
||||
if v and vt == winreg.REG_SZ and os.path.isdir(vc_dir):
|
||||
try:
|
||||
version = int(float(v))
|
||||
except (ValueError, TypeError):
|
||||
continue
|
||||
if version >= 14 and version > best_version:
|
||||
best_version, best_dir = version, vc_dir
|
||||
return best_version, best_dir
|
||||
|
||||
def _find_vc2017():
|
||||
"""Returns "15, path" based on the result of invoking vswhere.exe
|
||||
If no install is found, returns "None, None"
|
||||
|
||||
The version is returned to avoid unnecessarily changing the function
|
||||
result. It may be ignored when the path is not None.
|
||||
|
||||
If vswhere.exe is not available, by definition, VS 2017 is not
|
||||
installed.
|
||||
"""
|
||||
root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles")
|
||||
if not root:
|
||||
return None, None
|
||||
|
||||
try:
|
||||
path = subprocess.check_output([
|
||||
os.path.join(root, "Microsoft Visual Studio", "Installer", "vswhere.exe"),
|
||||
"-latest",
|
||||
"-prerelease",
|
||||
"-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
|
||||
"-property", "installationPath",
|
||||
"-products", "*",
|
||||
], encoding="mbcs", errors="strict").strip()
|
||||
except (subprocess.CalledProcessError, OSError, UnicodeDecodeError):
|
||||
return None, None
|
||||
|
||||
path = os.path.join(path, "VC", "Auxiliary", "Build")
|
||||
if os.path.isdir(path):
|
||||
return 15, path
|
||||
|
||||
return None, None
|
||||
|
||||
PLAT_SPEC_TO_RUNTIME = {
|
||||
'x86' : 'x86',
|
||||
'x86_amd64' : 'x64',
|
||||
'x86_arm' : 'arm',
|
||||
'x86_arm64' : 'arm64'
|
||||
}
|
||||
|
||||
def _find_vcvarsall(plat_spec):
|
||||
# bpo-38597: Removed vcruntime return value
|
||||
_, best_dir = _find_vc2017()
|
||||
|
||||
if not best_dir:
|
||||
best_version, best_dir = _find_vc2015()
|
||||
|
||||
if not best_dir:
|
||||
log.debug("No suitable Visual C++ version found")
|
||||
return None, None
|
||||
|
||||
vcvarsall = os.path.join(best_dir, "vcvarsall.bat")
|
||||
if not os.path.isfile(vcvarsall):
|
||||
log.debug("%s cannot be found", vcvarsall)
|
||||
return None, None
|
||||
|
||||
return vcvarsall, None
|
||||
|
||||
def _get_vc_env(plat_spec):
|
||||
if os.getenv("DISTUTILS_USE_SDK"):
|
||||
return {
|
||||
key.lower(): value
|
||||
for key, value in os.environ.items()
|
||||
}
|
||||
|
||||
vcvarsall, _ = _find_vcvarsall(plat_spec)
|
||||
if not vcvarsall:
|
||||
raise DistutilsPlatformError("Unable to find vcvarsall.bat")
|
||||
|
||||
try:
|
||||
out = subprocess.check_output(
|
||||
'cmd /u /c "{}" {} && set'.format(vcvarsall, plat_spec),
|
||||
stderr=subprocess.STDOUT,
|
||||
).decode('utf-16le', errors='replace')
|
||||
except subprocess.CalledProcessError as exc:
|
||||
log.error(exc.output)
|
||||
raise DistutilsPlatformError("Error executing {}"
|
||||
.format(exc.cmd))
|
||||
|
||||
env = {
|
||||
key.lower(): value
|
||||
for key, _, value in
|
||||
(line.partition('=') for line in out.splitlines())
|
||||
if key and value
|
||||
}
|
||||
|
||||
return env
|
||||
|
||||
def _find_exe(exe, paths=None):
|
||||
"""Return path to an MSVC executable program.
|
||||
|
||||
Tries to find the program in several places: first, one of the
|
||||
MSVC program search paths from the registry; next, the directories
|
||||
in the PATH environment variable. If any of those work, return an
|
||||
absolute path that is known to exist. If none of them work, just
|
||||
return the original program name, 'exe'.
|
||||
"""
|
||||
if not paths:
|
||||
paths = os.getenv('path').split(os.pathsep)
|
||||
for p in paths:
|
||||
fn = os.path.join(os.path.abspath(p), exe)
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
return exe
|
||||
|
||||
# A map keyed by get_platform() return values to values accepted by
|
||||
# 'vcvarsall.bat'. Always cross-compile from x86 to work with the
|
||||
# lighter-weight MSVC installs that do not include native 64-bit tools.
|
||||
PLAT_TO_VCVARS = {
|
||||
'win32' : 'x86',
|
||||
'win-amd64' : 'x86_amd64',
|
||||
'win-arm32' : 'x86_arm',
|
||||
'win-arm64' : 'x86_arm64'
|
||||
}
|
||||
|
||||
class MSVCCompiler(CCompiler) :
|
||||
"""Concrete class that implements an interface to Microsoft Visual C++,
|
||||
as defined by the CCompiler abstract class."""
|
||||
|
||||
compiler_type = 'msvc'
|
||||
|
||||
# Just set this so CCompiler's constructor doesn't barf. We currently
|
||||
# don't use the 'set_executables()' bureaucracy provided by CCompiler,
|
||||
# as it really isn't necessary for this sort of single-compiler class.
|
||||
# Would be nice to have a consistent interface with UnixCCompiler,
|
||||
# though, so it's worth thinking about.
|
||||
executables = {}
|
||||
|
||||
# Private class data (need to distinguish C from C++ source for compiler)
|
||||
_c_extensions = ['.c']
|
||||
_cpp_extensions = ['.cc', '.cpp', '.cxx']
|
||||
_rc_extensions = ['.rc']
|
||||
_mc_extensions = ['.mc']
|
||||
|
||||
# Needed for the filename generation methods provided by the
|
||||
# base class, CCompiler.
|
||||
src_extensions = (_c_extensions + _cpp_extensions +
|
||||
_rc_extensions + _mc_extensions)
|
||||
res_extension = '.res'
|
||||
obj_extension = '.obj'
|
||||
static_lib_extension = '.lib'
|
||||
shared_lib_extension = '.dll'
|
||||
static_lib_format = shared_lib_format = '%s%s'
|
||||
exe_extension = '.exe'
|
||||
|
||||
|
||||
def __init__(self, verbose=0, dry_run=0, force=0):
|
||||
CCompiler.__init__ (self, verbose, dry_run, force)
|
||||
# target platform (.plat_name is consistent with 'bdist')
|
||||
self.plat_name = None
|
||||
self.initialized = False
|
||||
|
||||
def initialize(self, plat_name=None):
|
||||
# multi-init means we would need to check platform same each time...
|
||||
assert not self.initialized, "don't init multiple times"
|
||||
if plat_name is None:
|
||||
plat_name = get_platform()
|
||||
# sanity check for platforms to prevent obscure errors later.
|
||||
if plat_name not in PLAT_TO_VCVARS:
|
||||
raise DistutilsPlatformError("--plat-name must be one of {}"
|
||||
.format(tuple(PLAT_TO_VCVARS)))
|
||||
|
||||
# Get the vcvarsall.bat spec for the requested platform.
|
||||
plat_spec = PLAT_TO_VCVARS[plat_name]
|
||||
|
||||
vc_env = _get_vc_env(plat_spec)
|
||||
if not vc_env:
|
||||
raise DistutilsPlatformError("Unable to find a compatible "
|
||||
"Visual Studio installation.")
|
||||
|
||||
self._paths = vc_env.get('path', '')
|
||||
paths = self._paths.split(os.pathsep)
|
||||
self.cc = _find_exe("cl.exe", paths)
|
||||
self.linker = _find_exe("link.exe", paths)
|
||||
self.lib = _find_exe("lib.exe", paths)
|
||||
self.rc = _find_exe("rc.exe", paths) # resource compiler
|
||||
self.mc = _find_exe("mc.exe", paths) # message compiler
|
||||
self.mt = _find_exe("mt.exe", paths) # message compiler
|
||||
|
||||
for dir in vc_env.get('include', '').split(os.pathsep):
|
||||
if dir:
|
||||
self.add_include_dir(dir.rstrip(os.sep))
|
||||
|
||||
for dir in vc_env.get('lib', '').split(os.pathsep):
|
||||
if dir:
|
||||
self.add_library_dir(dir.rstrip(os.sep))
|
||||
|
||||
self.preprocess_options = None
|
||||
# bpo-38597: Always compile with dynamic linking
|
||||
# Future releases of Python 3.x will include all past
|
||||
# versions of vcruntime*.dll for compatibility.
|
||||
self.compile_options = [
|
||||
'/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG', '/MD'
|
||||
]
|
||||
|
||||
self.compile_options_debug = [
|
||||
'/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG'
|
||||
]
|
||||
|
||||
ldflags = [
|
||||
'/nologo', '/INCREMENTAL:NO', '/LTCG'
|
||||
]
|
||||
|
||||
ldflags_debug = [
|
||||
'/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL'
|
||||
]
|
||||
|
||||
self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1']
|
||||
self.ldflags_exe_debug = [*ldflags_debug, '/MANIFEST:EMBED,ID=1']
|
||||
self.ldflags_shared = [*ldflags, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO']
|
||||
self.ldflags_shared_debug = [*ldflags_debug, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO']
|
||||
self.ldflags_static = [*ldflags]
|
||||
self.ldflags_static_debug = [*ldflags_debug]
|
||||
|
||||
self._ldflags = {
|
||||
(CCompiler.EXECUTABLE, None): self.ldflags_exe,
|
||||
(CCompiler.EXECUTABLE, False): self.ldflags_exe,
|
||||
(CCompiler.EXECUTABLE, True): self.ldflags_exe_debug,
|
||||
(CCompiler.SHARED_OBJECT, None): self.ldflags_shared,
|
||||
(CCompiler.SHARED_OBJECT, False): self.ldflags_shared,
|
||||
(CCompiler.SHARED_OBJECT, True): self.ldflags_shared_debug,
|
||||
(CCompiler.SHARED_LIBRARY, None): self.ldflags_static,
|
||||
(CCompiler.SHARED_LIBRARY, False): self.ldflags_static,
|
||||
(CCompiler.SHARED_LIBRARY, True): self.ldflags_static_debug,
|
||||
}
|
||||
|
||||
self.initialized = True
|
||||
|
||||
# -- Worker methods ------------------------------------------------
|
||||
|
||||
def object_filenames(self,
|
||||
source_filenames,
|
||||
strip_dir=0,
|
||||
output_dir=''):
|
||||
ext_map = {
|
||||
**{ext: self.obj_extension for ext in self.src_extensions},
|
||||
**{ext: self.res_extension for ext in self._rc_extensions + self._mc_extensions},
|
||||
}
|
||||
|
||||
output_dir = output_dir or ''
|
||||
|
||||
def make_out_path(p):
|
||||
base, ext = os.path.splitext(p)
|
||||
if strip_dir:
|
||||
base = os.path.basename(base)
|
||||
else:
|
||||
_, base = os.path.splitdrive(base)
|
||||
if base.startswith((os.path.sep, os.path.altsep)):
|
||||
base = base[1:]
|
||||
try:
|
||||
# XXX: This may produce absurdly long paths. We should check
|
||||
# the length of the result and trim base until we fit within
|
||||
# 260 characters.
|
||||
return os.path.join(output_dir, base + ext_map[ext])
|
||||
except LookupError:
|
||||
# Better to raise an exception instead of silently continuing
|
||||
# and later complain about sources and targets having
|
||||
# different lengths
|
||||
raise CompileError("Don't know how to compile {}".format(p))
|
||||
|
||||
return list(map(make_out_path, source_filenames))
|
||||
|
||||
|
||||
def compile(self, sources,
|
||||
output_dir=None, macros=None, include_dirs=None, debug=0,
|
||||
extra_preargs=None, extra_postargs=None, depends=None):
|
||||
|
||||
if not self.initialized:
|
||||
self.initialize()
|
||||
compile_info = self._setup_compile(output_dir, macros, include_dirs,
|
||||
sources, depends, extra_postargs)
|
||||
macros, objects, extra_postargs, pp_opts, build = compile_info
|
||||
|
||||
compile_opts = extra_preargs or []
|
||||
compile_opts.append('/c')
|
||||
if debug:
|
||||
compile_opts.extend(self.compile_options_debug)
|
||||
else:
|
||||
compile_opts.extend(self.compile_options)
|
||||
|
||||
|
||||
add_cpp_opts = False
|
||||
|
||||
for obj in objects:
|
||||
try:
|
||||
src, ext = build[obj]
|
||||
except KeyError:
|
||||
continue
|
||||
if debug:
|
||||
# pass the full pathname to MSVC in debug mode,
|
||||
# this allows the debugger to find the source file
|
||||
# without asking the user to browse for it
|
||||
src = os.path.abspath(src)
|
||||
|
||||
if ext in self._c_extensions:
|
||||
input_opt = "/Tc" + src
|
||||
elif ext in self._cpp_extensions:
|
||||
input_opt = "/Tp" + src
|
||||
add_cpp_opts = True
|
||||
elif ext in self._rc_extensions:
|
||||
# compile .RC to .RES file
|
||||
input_opt = src
|
||||
output_opt = "/fo" + obj
|
||||
try:
|
||||
self.spawn([self.rc] + pp_opts + [output_opt, input_opt])
|
||||
except DistutilsExecError as msg:
|
||||
raise CompileError(msg)
|
||||
continue
|
||||
elif ext in self._mc_extensions:
|
||||
# Compile .MC to .RC file to .RES file.
|
||||
# * '-h dir' specifies the directory for the
|
||||
# generated include file
|
||||
# * '-r dir' specifies the target directory of the
|
||||
# generated RC file and the binary message resource
|
||||
# it includes
|
||||
#
|
||||
# For now (since there are no options to change this),
|
||||
# we use the source-directory for the include file and
|
||||
# the build directory for the RC file and message
|
||||
# resources. This works at least for win32all.
|
||||
h_dir = os.path.dirname(src)
|
||||
rc_dir = os.path.dirname(obj)
|
||||
try:
|
||||
# first compile .MC to .RC and .H file
|
||||
self.spawn([self.mc, '-h', h_dir, '-r', rc_dir, src])
|
||||
base, _ = os.path.splitext(os.path.basename (src))
|
||||
rc_file = os.path.join(rc_dir, base + '.rc')
|
||||
# then compile .RC to .RES file
|
||||
self.spawn([self.rc, "/fo" + obj, rc_file])
|
||||
|
||||
except DistutilsExecError as msg:
|
||||
raise CompileError(msg)
|
||||
continue
|
||||
else:
|
||||
# how to handle this file?
|
||||
raise CompileError("Don't know how to compile {} to {}"
|
||||
.format(src, obj))
|
||||
|
||||
args = [self.cc] + compile_opts + pp_opts
|
||||
if add_cpp_opts:
|
||||
args.append('/EHsc')
|
||||
args.append(input_opt)
|
||||
args.append("/Fo" + obj)
|
||||
args.extend(extra_postargs)
|
||||
|
||||
try:
|
||||
self.spawn(args)
|
||||
except DistutilsExecError as msg:
|
||||
raise CompileError(msg)
|
||||
|
||||
return objects
|
||||
|
||||
|
||||
def create_static_lib(self,
|
||||
objects,
|
||||
output_libname,
|
||||
output_dir=None,
|
||||
debug=0,
|
||||
target_lang=None):
|
||||
|
||||
if not self.initialized:
|
||||
self.initialize()
|
||||
objects, output_dir = self._fix_object_args(objects, output_dir)
|
||||
output_filename = self.library_filename(output_libname,
|
||||
output_dir=output_dir)
|
||||
|
||||
if self._need_link(objects, output_filename):
|
||||
lib_args = objects + ['/OUT:' + output_filename]
|
||||
if debug:
|
||||
pass # XXX what goes here?
|
||||
try:
|
||||
log.debug('Executing "%s" %s', self.lib, ' '.join(lib_args))
|
||||
self.spawn([self.lib] + lib_args)
|
||||
except DistutilsExecError as msg:
|
||||
raise LibError(msg)
|
||||
else:
|
||||
log.debug("skipping %s (up-to-date)", output_filename)
|
||||
|
||||
|
||||
def link(self,
|
||||
target_desc,
|
||||
objects,
|
||||
output_filename,
|
||||
output_dir=None,
|
||||
libraries=None,
|
||||
library_dirs=None,
|
||||
runtime_library_dirs=None,
|
||||
export_symbols=None,
|
||||
debug=0,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
build_temp=None,
|
||||
target_lang=None):
|
||||
|
||||
if not self.initialized:
|
||||
self.initialize()
|
||||
objects, output_dir = self._fix_object_args(objects, output_dir)
|
||||
fixed_args = self._fix_lib_args(libraries, library_dirs,
|
||||
runtime_library_dirs)
|
||||
libraries, library_dirs, runtime_library_dirs = fixed_args
|
||||
|
||||
if runtime_library_dirs:
|
||||
self.warn("I don't know what to do with 'runtime_library_dirs': "
|
||||
+ str(runtime_library_dirs))
|
||||
|
||||
lib_opts = gen_lib_options(self,
|
||||
library_dirs, runtime_library_dirs,
|
||||
libraries)
|
||||
if output_dir is not None:
|
||||
output_filename = os.path.join(output_dir, output_filename)
|
||||
|
||||
if self._need_link(objects, output_filename):
|
||||
ldflags = self._ldflags[target_desc, debug]
|
||||
|
||||
export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])]
|
||||
|
||||
ld_args = (ldflags + lib_opts + export_opts +
|
||||
objects + ['/OUT:' + output_filename])
|
||||
|
||||
# The MSVC linker generates .lib and .exp files, which cannot be
|
||||
# suppressed by any linker switches. The .lib files may even be
|
||||
# needed! Make sure they are generated in the temporary build
|
||||
# directory. Since they have different names for debug and release
|
||||
# builds, they can go into the same directory.
|
||||
build_temp = os.path.dirname(objects[0])
|
||||
if export_symbols is not None:
|
||||
(dll_name, dll_ext) = os.path.splitext(
|
||||
os.path.basename(output_filename))
|
||||
implib_file = os.path.join(
|
||||
build_temp,
|
||||
self.library_filename(dll_name))
|
||||
ld_args.append ('/IMPLIB:' + implib_file)
|
||||
|
||||
if extra_preargs:
|
||||
ld_args[:0] = extra_preargs
|
||||
if extra_postargs:
|
||||
ld_args.extend(extra_postargs)
|
||||
|
||||
output_dir = os.path.dirname(os.path.abspath(output_filename))
|
||||
self.mkpath(output_dir)
|
||||
try:
|
||||
log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args))
|
||||
self.spawn([self.linker] + ld_args)
|
||||
except DistutilsExecError as msg:
|
||||
raise LinkError(msg)
|
||||
else:
|
||||
log.debug("skipping %s (up-to-date)", output_filename)
|
||||
|
||||
def spawn(self, cmd):
|
||||
env = dict(os.environ, PATH=self._paths)
|
||||
return super().spawn(cmd, env=env)
|
||||
|
||||
# -- Miscellaneous methods -----------------------------------------
|
||||
# These are all used by the 'gen_lib_options() function, in
|
||||
# ccompiler.py.
|
||||
|
||||
def library_dir_option(self, dir):
|
||||
return "/LIBPATH:" + dir
|
||||
|
||||
def runtime_library_dir_option(self, dir):
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to set runtime library search path for MSVC")
|
||||
|
||||
def library_option(self, lib):
|
||||
return self.library_filename(lib)
|
||||
|
||||
def find_library_file(self, dirs, lib, debug=0):
|
||||
# Prefer a debugging library if found (and requested), but deal
|
||||
# with it if we don't have one.
|
||||
if debug:
|
||||
try_names = [lib + "_d", lib]
|
||||
else:
|
||||
try_names = [lib]
|
||||
for dir in dirs:
|
||||
for name in try_names:
|
||||
libfile = os.path.join(dir, self.library_filename(name))
|
||||
if os.path.isfile(libfile):
|
||||
return libfile
|
||||
else:
|
||||
# Oops, didn't find it in *any* of 'dirs'
|
||||
return None
|
||||
256
env/Lib/site-packages/setuptools/_distutils/archive_util.py
vendored
Normal file
256
env/Lib/site-packages/setuptools/_distutils/archive_util.py
vendored
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
"""distutils.archive_util
|
||||
|
||||
Utility functions for creating archive files (tarballs, zip files,
|
||||
that sort of thing)."""
|
||||
|
||||
import os
|
||||
from warnings import warn
|
||||
import sys
|
||||
|
||||
try:
|
||||
import zipfile
|
||||
except ImportError:
|
||||
zipfile = None
|
||||
|
||||
|
||||
from distutils.errors import DistutilsExecError
|
||||
from distutils.spawn import spawn
|
||||
from distutils.dir_util import mkpath
|
||||
from distutils import log
|
||||
|
||||
try:
|
||||
from pwd import getpwnam
|
||||
except ImportError:
|
||||
getpwnam = None
|
||||
|
||||
try:
|
||||
from grp import getgrnam
|
||||
except ImportError:
|
||||
getgrnam = None
|
||||
|
||||
def _get_gid(name):
|
||||
"""Returns a gid, given a group name."""
|
||||
if getgrnam is None or name is None:
|
||||
return None
|
||||
try:
|
||||
result = getgrnam(name)
|
||||
except KeyError:
|
||||
result = None
|
||||
if result is not None:
|
||||
return result[2]
|
||||
return None
|
||||
|
||||
def _get_uid(name):
|
||||
"""Returns an uid, given a user name."""
|
||||
if getpwnam is None or name is None:
|
||||
return None
|
||||
try:
|
||||
result = getpwnam(name)
|
||||
except KeyError:
|
||||
result = None
|
||||
if result is not None:
|
||||
return result[2]
|
||||
return None
|
||||
|
||||
def make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
|
||||
owner=None, group=None):
|
||||
"""Create a (possibly compressed) tar file from all the files under
|
||||
'base_dir'.
|
||||
|
||||
'compress' must be "gzip" (the default), "bzip2", "xz", "compress", or
|
||||
None. ("compress" will be deprecated in Python 3.2)
|
||||
|
||||
'owner' and 'group' can be used to define an owner and a group for the
|
||||
archive that is being built. If not provided, the current owner and group
|
||||
will be used.
|
||||
|
||||
The output tar file will be named 'base_dir' + ".tar", possibly plus
|
||||
the appropriate compression extension (".gz", ".bz2", ".xz" or ".Z").
|
||||
|
||||
Returns the output filename.
|
||||
"""
|
||||
tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', 'xz': 'xz', None: '',
|
||||
'compress': ''}
|
||||
compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'xz': '.xz',
|
||||
'compress': '.Z'}
|
||||
|
||||
# flags for compression program, each element of list will be an argument
|
||||
if compress is not None and compress not in compress_ext.keys():
|
||||
raise ValueError(
|
||||
"bad value for 'compress': must be None, 'gzip', 'bzip2', "
|
||||
"'xz' or 'compress'")
|
||||
|
||||
archive_name = base_name + '.tar'
|
||||
if compress != 'compress':
|
||||
archive_name += compress_ext.get(compress, '')
|
||||
|
||||
mkpath(os.path.dirname(archive_name), dry_run=dry_run)
|
||||
|
||||
# creating the tarball
|
||||
import tarfile # late import so Python build itself doesn't break
|
||||
|
||||
log.info('Creating tar archive')
|
||||
|
||||
uid = _get_uid(owner)
|
||||
gid = _get_gid(group)
|
||||
|
||||
def _set_uid_gid(tarinfo):
|
||||
if gid is not None:
|
||||
tarinfo.gid = gid
|
||||
tarinfo.gname = group
|
||||
if uid is not None:
|
||||
tarinfo.uid = uid
|
||||
tarinfo.uname = owner
|
||||
return tarinfo
|
||||
|
||||
if not dry_run:
|
||||
tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
|
||||
try:
|
||||
tar.add(base_dir, filter=_set_uid_gid)
|
||||
finally:
|
||||
tar.close()
|
||||
|
||||
# compression using `compress`
|
||||
if compress == 'compress':
|
||||
warn("'compress' will be deprecated.", PendingDeprecationWarning)
|
||||
# the option varies depending on the platform
|
||||
compressed_name = archive_name + compress_ext[compress]
|
||||
if sys.platform == 'win32':
|
||||
cmd = [compress, archive_name, compressed_name]
|
||||
else:
|
||||
cmd = [compress, '-f', archive_name]
|
||||
spawn(cmd, dry_run=dry_run)
|
||||
return compressed_name
|
||||
|
||||
return archive_name
|
||||
|
||||
def make_zipfile(base_name, base_dir, verbose=0, dry_run=0):
|
||||
"""Create a zip file from all the files under 'base_dir'.
|
||||
|
||||
The output zip file will be named 'base_name' + ".zip". Uses either the
|
||||
"zipfile" Python module (if available) or the InfoZIP "zip" utility
|
||||
(if installed and found on the default search path). If neither tool is
|
||||
available, raises DistutilsExecError. Returns the name of the output zip
|
||||
file.
|
||||
"""
|
||||
zip_filename = base_name + ".zip"
|
||||
mkpath(os.path.dirname(zip_filename), dry_run=dry_run)
|
||||
|
||||
# If zipfile module is not available, try spawning an external
|
||||
# 'zip' command.
|
||||
if zipfile is None:
|
||||
if verbose:
|
||||
zipoptions = "-r"
|
||||
else:
|
||||
zipoptions = "-rq"
|
||||
|
||||
try:
|
||||
spawn(["zip", zipoptions, zip_filename, base_dir],
|
||||
dry_run=dry_run)
|
||||
except DistutilsExecError:
|
||||
# XXX really should distinguish between "couldn't find
|
||||
# external 'zip' command" and "zip failed".
|
||||
raise DistutilsExecError(("unable to create zip file '%s': "
|
||||
"could neither import the 'zipfile' module nor "
|
||||
"find a standalone zip utility") % zip_filename)
|
||||
|
||||
else:
|
||||
log.info("creating '%s' and adding '%s' to it",
|
||||
zip_filename, base_dir)
|
||||
|
||||
if not dry_run:
|
||||
try:
|
||||
zip = zipfile.ZipFile(zip_filename, "w",
|
||||
compression=zipfile.ZIP_DEFLATED)
|
||||
except RuntimeError:
|
||||
zip = zipfile.ZipFile(zip_filename, "w",
|
||||
compression=zipfile.ZIP_STORED)
|
||||
|
||||
with zip:
|
||||
if base_dir != os.curdir:
|
||||
path = os.path.normpath(os.path.join(base_dir, ''))
|
||||
zip.write(path, path)
|
||||
log.info("adding '%s'", path)
|
||||
for dirpath, dirnames, filenames in os.walk(base_dir):
|
||||
for name in dirnames:
|
||||
path = os.path.normpath(os.path.join(dirpath, name, ''))
|
||||
zip.write(path, path)
|
||||
log.info("adding '%s'", path)
|
||||
for name in filenames:
|
||||
path = os.path.normpath(os.path.join(dirpath, name))
|
||||
if os.path.isfile(path):
|
||||
zip.write(path, path)
|
||||
log.info("adding '%s'", path)
|
||||
|
||||
return zip_filename
|
||||
|
||||
ARCHIVE_FORMATS = {
|
||||
'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
|
||||
'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
|
||||
'xztar': (make_tarball, [('compress', 'xz')], "xz'ed tar-file"),
|
||||
'ztar': (make_tarball, [('compress', 'compress')], "compressed tar file"),
|
||||
'tar': (make_tarball, [('compress', None)], "uncompressed tar file"),
|
||||
'zip': (make_zipfile, [],"ZIP file")
|
||||
}
|
||||
|
||||
def check_archive_formats(formats):
|
||||
"""Returns the first format from the 'format' list that is unknown.
|
||||
|
||||
If all formats are known, returns None
|
||||
"""
|
||||
for format in formats:
|
||||
if format not in ARCHIVE_FORMATS:
|
||||
return format
|
||||
return None
|
||||
|
||||
def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
|
||||
dry_run=0, owner=None, group=None):
|
||||
"""Create an archive file (eg. zip or tar).
|
||||
|
||||
'base_name' is the name of the file to create, minus any format-specific
|
||||
extension; 'format' is the archive format: one of "zip", "tar", "gztar",
|
||||
"bztar", "xztar", or "ztar".
|
||||
|
||||
'root_dir' is a directory that will be the root directory of the
|
||||
archive; ie. we typically chdir into 'root_dir' before creating the
|
||||
archive. 'base_dir' is the directory where we start archiving from;
|
||||
ie. 'base_dir' will be the common prefix of all files and
|
||||
directories in the archive. 'root_dir' and 'base_dir' both default
|
||||
to the current directory. Returns the name of the archive file.
|
||||
|
||||
'owner' and 'group' are used when creating a tar archive. By default,
|
||||
uses the current owner and group.
|
||||
"""
|
||||
save_cwd = os.getcwd()
|
||||
if root_dir is not None:
|
||||
log.debug("changing into '%s'", root_dir)
|
||||
base_name = os.path.abspath(base_name)
|
||||
if not dry_run:
|
||||
os.chdir(root_dir)
|
||||
|
||||
if base_dir is None:
|
||||
base_dir = os.curdir
|
||||
|
||||
kwargs = {'dry_run': dry_run}
|
||||
|
||||
try:
|
||||
format_info = ARCHIVE_FORMATS[format]
|
||||
except KeyError:
|
||||
raise ValueError("unknown archive format '%s'" % format)
|
||||
|
||||
func = format_info[0]
|
||||
for arg, val in format_info[1]:
|
||||
kwargs[arg] = val
|
||||
|
||||
if format != 'zip':
|
||||
kwargs['owner'] = owner
|
||||
kwargs['group'] = group
|
||||
|
||||
try:
|
||||
filename = func(base_name, base_dir, **kwargs)
|
||||
finally:
|
||||
if root_dir is not None:
|
||||
log.debug("changing back to '%s'", save_cwd)
|
||||
os.chdir(save_cwd)
|
||||
|
||||
return filename
|
||||
393
env/Lib/site-packages/setuptools/_distutils/bcppcompiler.py
vendored
Normal file
393
env/Lib/site-packages/setuptools/_distutils/bcppcompiler.py
vendored
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
"""distutils.bcppcompiler
|
||||
|
||||
Contains BorlandCCompiler, an implementation of the abstract CCompiler class
|
||||
for the Borland C++ compiler.
|
||||
"""
|
||||
|
||||
# This implementation by Lyle Johnson, based on the original msvccompiler.py
|
||||
# module and using the directions originally published by Gordon Williams.
|
||||
|
||||
# XXX looks like there's a LOT of overlap between these two classes:
|
||||
# someone should sit down and factor out the common code as
|
||||
# WindowsCCompiler! --GPW
|
||||
|
||||
|
||||
import os
|
||||
from distutils.errors import \
|
||||
DistutilsExecError, \
|
||||
CompileError, LibError, LinkError, UnknownFileError
|
||||
from distutils.ccompiler import \
|
||||
CCompiler, gen_preprocess_options
|
||||
from distutils.file_util import write_file
|
||||
from distutils.dep_util import newer
|
||||
from distutils import log
|
||||
|
||||
class BCPPCompiler(CCompiler) :
|
||||
"""Concrete class that implements an interface to the Borland C/C++
|
||||
compiler, as defined by the CCompiler abstract class.
|
||||
"""
|
||||
|
||||
compiler_type = 'bcpp'
|
||||
|
||||
# Just set this so CCompiler's constructor doesn't barf. We currently
|
||||
# don't use the 'set_executables()' bureaucracy provided by CCompiler,
|
||||
# as it really isn't necessary for this sort of single-compiler class.
|
||||
# Would be nice to have a consistent interface with UnixCCompiler,
|
||||
# though, so it's worth thinking about.
|
||||
executables = {}
|
||||
|
||||
# Private class data (need to distinguish C from C++ source for compiler)
|
||||
_c_extensions = ['.c']
|
||||
_cpp_extensions = ['.cc', '.cpp', '.cxx']
|
||||
|
||||
# Needed for the filename generation methods provided by the
|
||||
# base class, CCompiler.
|
||||
src_extensions = _c_extensions + _cpp_extensions
|
||||
obj_extension = '.obj'
|
||||
static_lib_extension = '.lib'
|
||||
shared_lib_extension = '.dll'
|
||||
static_lib_format = shared_lib_format = '%s%s'
|
||||
exe_extension = '.exe'
|
||||
|
||||
|
||||
def __init__ (self,
|
||||
verbose=0,
|
||||
dry_run=0,
|
||||
force=0):
|
||||
|
||||
CCompiler.__init__ (self, verbose, dry_run, force)
|
||||
|
||||
# These executables are assumed to all be in the path.
|
||||
# Borland doesn't seem to use any special registry settings to
|
||||
# indicate their installation locations.
|
||||
|
||||
self.cc = "bcc32.exe"
|
||||
self.linker = "ilink32.exe"
|
||||
self.lib = "tlib.exe"
|
||||
|
||||
self.preprocess_options = None
|
||||
self.compile_options = ['/tWM', '/O2', '/q', '/g0']
|
||||
self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0']
|
||||
|
||||
self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x']
|
||||
self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x']
|
||||
self.ldflags_static = []
|
||||
self.ldflags_exe = ['/Gn', '/q', '/x']
|
||||
self.ldflags_exe_debug = ['/Gn', '/q', '/x','/r']
|
||||
|
||||
|
||||
# -- Worker methods ------------------------------------------------
|
||||
|
||||
def compile(self, sources,
|
||||
output_dir=None, macros=None, include_dirs=None, debug=0,
|
||||
extra_preargs=None, extra_postargs=None, depends=None):
|
||||
|
||||
macros, objects, extra_postargs, pp_opts, build = \
|
||||
self._setup_compile(output_dir, macros, include_dirs, sources,
|
||||
depends, extra_postargs)
|
||||
compile_opts = extra_preargs or []
|
||||
compile_opts.append ('-c')
|
||||
if debug:
|
||||
compile_opts.extend (self.compile_options_debug)
|
||||
else:
|
||||
compile_opts.extend (self.compile_options)
|
||||
|
||||
for obj in objects:
|
||||
try:
|
||||
src, ext = build[obj]
|
||||
except KeyError:
|
||||
continue
|
||||
# XXX why do the normpath here?
|
||||
src = os.path.normpath(src)
|
||||
obj = os.path.normpath(obj)
|
||||
# XXX _setup_compile() did a mkpath() too but before the normpath.
|
||||
# Is it possible to skip the normpath?
|
||||
self.mkpath(os.path.dirname(obj))
|
||||
|
||||
if ext == '.res':
|
||||
# This is already a binary file -- skip it.
|
||||
continue # the 'for' loop
|
||||
if ext == '.rc':
|
||||
# This needs to be compiled to a .res file -- do it now.
|
||||
try:
|
||||
self.spawn (["brcc32", "-fo", obj, src])
|
||||
except DistutilsExecError as msg:
|
||||
raise CompileError(msg)
|
||||
continue # the 'for' loop
|
||||
|
||||
# The next two are both for the real compiler.
|
||||
if ext in self._c_extensions:
|
||||
input_opt = ""
|
||||
elif ext in self._cpp_extensions:
|
||||
input_opt = "-P"
|
||||
else:
|
||||
# Unknown file type -- no extra options. The compiler
|
||||
# will probably fail, but let it just in case this is a
|
||||
# file the compiler recognizes even if we don't.
|
||||
input_opt = ""
|
||||
|
||||
output_opt = "-o" + obj
|
||||
|
||||
# Compiler command line syntax is: "bcc32 [options] file(s)".
|
||||
# Note that the source file names must appear at the end of
|
||||
# the command line.
|
||||
try:
|
||||
self.spawn ([self.cc] + compile_opts + pp_opts +
|
||||
[input_opt, output_opt] +
|
||||
extra_postargs + [src])
|
||||
except DistutilsExecError as msg:
|
||||
raise CompileError(msg)
|
||||
|
||||
return objects
|
||||
|
||||
# compile ()
|
||||
|
||||
|
||||
def create_static_lib (self,
|
||||
objects,
|
||||
output_libname,
|
||||
output_dir=None,
|
||||
debug=0,
|
||||
target_lang=None):
|
||||
|
||||
(objects, output_dir) = self._fix_object_args (objects, output_dir)
|
||||
output_filename = \
|
||||
self.library_filename (output_libname, output_dir=output_dir)
|
||||
|
||||
if self._need_link (objects, output_filename):
|
||||
lib_args = [output_filename, '/u'] + objects
|
||||
if debug:
|
||||
pass # XXX what goes here?
|
||||
try:
|
||||
self.spawn ([self.lib] + lib_args)
|
||||
except DistutilsExecError as msg:
|
||||
raise LibError(msg)
|
||||
else:
|
||||
log.debug("skipping %s (up-to-date)", output_filename)
|
||||
|
||||
# create_static_lib ()
|
||||
|
||||
|
||||
def link (self,
|
||||
target_desc,
|
||||
objects,
|
||||
output_filename,
|
||||
output_dir=None,
|
||||
libraries=None,
|
||||
library_dirs=None,
|
||||
runtime_library_dirs=None,
|
||||
export_symbols=None,
|
||||
debug=0,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
build_temp=None,
|
||||
target_lang=None):
|
||||
|
||||
# XXX this ignores 'build_temp'! should follow the lead of
|
||||
# msvccompiler.py
|
||||
|
||||
(objects, output_dir) = self._fix_object_args (objects, output_dir)
|
||||
(libraries, library_dirs, runtime_library_dirs) = \
|
||||
self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
|
||||
|
||||
if runtime_library_dirs:
|
||||
log.warn("I don't know what to do with 'runtime_library_dirs': %s",
|
||||
str(runtime_library_dirs))
|
||||
|
||||
if output_dir is not None:
|
||||
output_filename = os.path.join (output_dir, output_filename)
|
||||
|
||||
if self._need_link (objects, output_filename):
|
||||
|
||||
# Figure out linker args based on type of target.
|
||||
if target_desc == CCompiler.EXECUTABLE:
|
||||
startup_obj = 'c0w32'
|
||||
if debug:
|
||||
ld_args = self.ldflags_exe_debug[:]
|
||||
else:
|
||||
ld_args = self.ldflags_exe[:]
|
||||
else:
|
||||
startup_obj = 'c0d32'
|
||||
if debug:
|
||||
ld_args = self.ldflags_shared_debug[:]
|
||||
else:
|
||||
ld_args = self.ldflags_shared[:]
|
||||
|
||||
|
||||
# Create a temporary exports file for use by the linker
|
||||
if export_symbols is None:
|
||||
def_file = ''
|
||||
else:
|
||||
head, tail = os.path.split (output_filename)
|
||||
modname, ext = os.path.splitext (tail)
|
||||
temp_dir = os.path.dirname(objects[0]) # preserve tree structure
|
||||
def_file = os.path.join (temp_dir, '%s.def' % modname)
|
||||
contents = ['EXPORTS']
|
||||
for sym in (export_symbols or []):
|
||||
contents.append(' %s=_%s' % (sym, sym))
|
||||
self.execute(write_file, (def_file, contents),
|
||||
"writing %s" % def_file)
|
||||
|
||||
# Borland C++ has problems with '/' in paths
|
||||
objects2 = map(os.path.normpath, objects)
|
||||
# split objects in .obj and .res files
|
||||
# Borland C++ needs them at different positions in the command line
|
||||
objects = [startup_obj]
|
||||
resources = []
|
||||
for file in objects2:
|
||||
(base, ext) = os.path.splitext(os.path.normcase(file))
|
||||
if ext == '.res':
|
||||
resources.append(file)
|
||||
else:
|
||||
objects.append(file)
|
||||
|
||||
|
||||
for l in library_dirs:
|
||||
ld_args.append("/L%s" % os.path.normpath(l))
|
||||
ld_args.append("/L.") # we sometimes use relative paths
|
||||
|
||||
# list of object files
|
||||
ld_args.extend(objects)
|
||||
|
||||
# XXX the command-line syntax for Borland C++ is a bit wonky;
|
||||
# certain filenames are jammed together in one big string, but
|
||||
# comma-delimited. This doesn't mesh too well with the
|
||||
# Unix-centric attitude (with a DOS/Windows quoting hack) of
|
||||
# 'spawn()', so constructing the argument list is a bit
|
||||
# awkward. Note that doing the obvious thing and jamming all
|
||||
# the filenames and commas into one argument would be wrong,
|
||||
# because 'spawn()' would quote any filenames with spaces in
|
||||
# them. Arghghh!. Apparently it works fine as coded...
|
||||
|
||||
# name of dll/exe file
|
||||
ld_args.extend([',',output_filename])
|
||||
# no map file and start libraries
|
||||
ld_args.append(',,')
|
||||
|
||||
for lib in libraries:
|
||||
# see if we find it and if there is a bcpp specific lib
|
||||
# (xxx_bcpp.lib)
|
||||
libfile = self.find_library_file(library_dirs, lib, debug)
|
||||
if libfile is None:
|
||||
ld_args.append(lib)
|
||||
# probably a BCPP internal library -- don't warn
|
||||
else:
|
||||
# full name which prefers bcpp_xxx.lib over xxx.lib
|
||||
ld_args.append(libfile)
|
||||
|
||||
# some default libraries
|
||||
ld_args.append ('import32')
|
||||
ld_args.append ('cw32mt')
|
||||
|
||||
# def file for export symbols
|
||||
ld_args.extend([',',def_file])
|
||||
# add resource files
|
||||
ld_args.append(',')
|
||||
ld_args.extend(resources)
|
||||
|
||||
|
||||
if extra_preargs:
|
||||
ld_args[:0] = extra_preargs
|
||||
if extra_postargs:
|
||||
ld_args.extend(extra_postargs)
|
||||
|
||||
self.mkpath (os.path.dirname (output_filename))
|
||||
try:
|
||||
self.spawn ([self.linker] + ld_args)
|
||||
except DistutilsExecError as msg:
|
||||
raise LinkError(msg)
|
||||
|
||||
else:
|
||||
log.debug("skipping %s (up-to-date)", output_filename)
|
||||
|
||||
# link ()
|
||||
|
||||
# -- Miscellaneous methods -----------------------------------------
|
||||
|
||||
|
||||
def find_library_file (self, dirs, lib, debug=0):
|
||||
# List of effective library names to try, in order of preference:
|
||||
# xxx_bcpp.lib is better than xxx.lib
|
||||
# and xxx_d.lib is better than xxx.lib if debug is set
|
||||
#
|
||||
# The "_bcpp" suffix is to handle a Python installation for people
|
||||
# with multiple compilers (primarily Distutils hackers, I suspect
|
||||
# ;-). The idea is they'd have one static library for each
|
||||
# compiler they care about, since (almost?) every Windows compiler
|
||||
# seems to have a different format for static libraries.
|
||||
if debug:
|
||||
dlib = (lib + "_d")
|
||||
try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib)
|
||||
else:
|
||||
try_names = (lib + "_bcpp", lib)
|
||||
|
||||
for dir in dirs:
|
||||
for name in try_names:
|
||||
libfile = os.path.join(dir, self.library_filename(name))
|
||||
if os.path.exists(libfile):
|
||||
return libfile
|
||||
else:
|
||||
# Oops, didn't find it in *any* of 'dirs'
|
||||
return None
|
||||
|
||||
# overwrite the one from CCompiler to support rc and res-files
|
||||
def object_filenames (self,
|
||||
source_filenames,
|
||||
strip_dir=0,
|
||||
output_dir=''):
|
||||
if output_dir is None: output_dir = ''
|
||||
obj_names = []
|
||||
for src_name in source_filenames:
|
||||
# use normcase to make sure '.rc' is really '.rc' and not '.RC'
|
||||
(base, ext) = os.path.splitext (os.path.normcase(src_name))
|
||||
if ext not in (self.src_extensions + ['.rc','.res']):
|
||||
raise UnknownFileError("unknown file type '%s' (from '%s')" % \
|
||||
(ext, src_name))
|
||||
if strip_dir:
|
||||
base = os.path.basename (base)
|
||||
if ext == '.res':
|
||||
# these can go unchanged
|
||||
obj_names.append (os.path.join (output_dir, base + ext))
|
||||
elif ext == '.rc':
|
||||
# these need to be compiled to .res-files
|
||||
obj_names.append (os.path.join (output_dir, base + '.res'))
|
||||
else:
|
||||
obj_names.append (os.path.join (output_dir,
|
||||
base + self.obj_extension))
|
||||
return obj_names
|
||||
|
||||
# object_filenames ()
|
||||
|
||||
def preprocess (self,
|
||||
source,
|
||||
output_file=None,
|
||||
macros=None,
|
||||
include_dirs=None,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None):
|
||||
|
||||
(_, macros, include_dirs) = \
|
||||
self._fix_compile_args(None, macros, include_dirs)
|
||||
pp_opts = gen_preprocess_options(macros, include_dirs)
|
||||
pp_args = ['cpp32.exe'] + pp_opts
|
||||
if output_file is not None:
|
||||
pp_args.append('-o' + output_file)
|
||||
if extra_preargs:
|
||||
pp_args[:0] = extra_preargs
|
||||
if extra_postargs:
|
||||
pp_args.extend(extra_postargs)
|
||||
pp_args.append(source)
|
||||
|
||||
# We need to preprocess: either we're being forced to, or the
|
||||
# source file is newer than the target (or the target doesn't
|
||||
# exist).
|
||||
if self.force or output_file is None or newer(source, output_file):
|
||||
if output_file:
|
||||
self.mkpath(os.path.dirname(output_file))
|
||||
try:
|
||||
self.spawn(pp_args)
|
||||
except DistutilsExecError as msg:
|
||||
print(msg)
|
||||
raise CompileError(msg)
|
||||
|
||||
# preprocess()
|
||||
1116
env/Lib/site-packages/setuptools/_distutils/ccompiler.py
vendored
Normal file
1116
env/Lib/site-packages/setuptools/_distutils/ccompiler.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
403
env/Lib/site-packages/setuptools/_distutils/cmd.py
vendored
Normal file
403
env/Lib/site-packages/setuptools/_distutils/cmd.py
vendored
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
"""distutils.cmd
|
||||
|
||||
Provides the Command class, the base class for the command classes
|
||||
in the distutils.command package.
|
||||
"""
|
||||
|
||||
import sys, os, re
|
||||
from distutils.errors import DistutilsOptionError
|
||||
from distutils import util, dir_util, file_util, archive_util, dep_util
|
||||
from distutils import log
|
||||
|
||||
class Command:
|
||||
"""Abstract base class for defining command classes, the "worker bees"
|
||||
of the Distutils. A useful analogy for command classes is to think of
|
||||
them as subroutines with local variables called "options". The options
|
||||
are "declared" in 'initialize_options()' and "defined" (given their
|
||||
final values, aka "finalized") in 'finalize_options()', both of which
|
||||
must be defined by every command class. The distinction between the
|
||||
two is necessary because option values might come from the outside
|
||||
world (command line, config file, ...), and any options dependent on
|
||||
other options must be computed *after* these outside influences have
|
||||
been processed -- hence 'finalize_options()'. The "body" of the
|
||||
subroutine, where it does all its work based on the values of its
|
||||
options, is the 'run()' method, which must also be implemented by every
|
||||
command class.
|
||||
"""
|
||||
|
||||
# 'sub_commands' formalizes the notion of a "family" of commands,
|
||||
# eg. "install" as the parent with sub-commands "install_lib",
|
||||
# "install_headers", etc. The parent of a family of commands
|
||||
# defines 'sub_commands' as a class attribute; it's a list of
|
||||
# (command_name : string, predicate : unbound_method | string | None)
|
||||
# tuples, where 'predicate' is a method of the parent command that
|
||||
# determines whether the corresponding command is applicable in the
|
||||
# current situation. (Eg. we "install_headers" is only applicable if
|
||||
# we have any C header files to install.) If 'predicate' is None,
|
||||
# that command is always applicable.
|
||||
#
|
||||
# 'sub_commands' is usually defined at the *end* of a class, because
|
||||
# predicates can be unbound methods, so they must already have been
|
||||
# defined. The canonical example is the "install" command.
|
||||
sub_commands = []
|
||||
|
||||
|
||||
# -- Creation/initialization methods -------------------------------
|
||||
|
||||
def __init__(self, dist):
|
||||
"""Create and initialize a new Command object. Most importantly,
|
||||
invokes the 'initialize_options()' method, which is the real
|
||||
initializer and depends on the actual command being
|
||||
instantiated.
|
||||
"""
|
||||
# late import because of mutual dependence between these classes
|
||||
from distutils.dist import Distribution
|
||||
|
||||
if not isinstance(dist, Distribution):
|
||||
raise TypeError("dist must be a Distribution instance")
|
||||
if self.__class__ is Command:
|
||||
raise RuntimeError("Command is an abstract class")
|
||||
|
||||
self.distribution = dist
|
||||
self.initialize_options()
|
||||
|
||||
# Per-command versions of the global flags, so that the user can
|
||||
# customize Distutils' behaviour command-by-command and let some
|
||||
# commands fall back on the Distribution's behaviour. None means
|
||||
# "not defined, check self.distribution's copy", while 0 or 1 mean
|
||||
# false and true (duh). Note that this means figuring out the real
|
||||
# value of each flag is a touch complicated -- hence "self._dry_run"
|
||||
# will be handled by __getattr__, below.
|
||||
# XXX This needs to be fixed.
|
||||
self._dry_run = None
|
||||
|
||||
# verbose is largely ignored, but needs to be set for
|
||||
# backwards compatibility (I think)?
|
||||
self.verbose = dist.verbose
|
||||
|
||||
# Some commands define a 'self.force' option to ignore file
|
||||
# timestamps, but methods defined *here* assume that
|
||||
# 'self.force' exists for all commands. So define it here
|
||||
# just to be safe.
|
||||
self.force = None
|
||||
|
||||
# The 'help' flag is just used for command-line parsing, so
|
||||
# none of that complicated bureaucracy is needed.
|
||||
self.help = 0
|
||||
|
||||
# 'finalized' records whether or not 'finalize_options()' has been
|
||||
# called. 'finalize_options()' itself should not pay attention to
|
||||
# this flag: it is the business of 'ensure_finalized()', which
|
||||
# always calls 'finalize_options()', to respect/update it.
|
||||
self.finalized = 0
|
||||
|
||||
# XXX A more explicit way to customize dry_run would be better.
|
||||
def __getattr__(self, attr):
|
||||
if attr == 'dry_run':
|
||||
myval = getattr(self, "_" + attr)
|
||||
if myval is None:
|
||||
return getattr(self.distribution, attr)
|
||||
else:
|
||||
return myval
|
||||
else:
|
||||
raise AttributeError(attr)
|
||||
|
||||
def ensure_finalized(self):
|
||||
if not self.finalized:
|
||||
self.finalize_options()
|
||||
self.finalized = 1
|
||||
|
||||
# Subclasses must define:
|
||||
# initialize_options()
|
||||
# provide default values for all options; may be customized by
|
||||
# setup script, by options from config file(s), or by command-line
|
||||
# options
|
||||
# finalize_options()
|
||||
# decide on the final values for all options; this is called
|
||||
# after all possible intervention from the outside world
|
||||
# (command-line, option file, etc.) has been processed
|
||||
# run()
|
||||
# run the command: do whatever it is we're here to do,
|
||||
# controlled by the command's various option values
|
||||
|
||||
def initialize_options(self):
|
||||
"""Set default values for all the options that this command
|
||||
supports. Note that these defaults may be overridden by other
|
||||
commands, by the setup script, by config files, or by the
|
||||
command-line. Thus, this is not the place to code dependencies
|
||||
between options; generally, 'initialize_options()' implementations
|
||||
are just a bunch of "self.foo = None" assignments.
|
||||
|
||||
This method must be implemented by all command classes.
|
||||
"""
|
||||
raise RuntimeError("abstract method -- subclass %s must override"
|
||||
% self.__class__)
|
||||
|
||||
def finalize_options(self):
|
||||
"""Set final values for all the options that this command supports.
|
||||
This is always called as late as possible, ie. after any option
|
||||
assignments from the command-line or from other commands have been
|
||||
done. Thus, this is the place to code option dependencies: if
|
||||
'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as
|
||||
long as 'foo' still has the same value it was assigned in
|
||||
'initialize_options()'.
|
||||
|
||||
This method must be implemented by all command classes.
|
||||
"""
|
||||
raise RuntimeError("abstract method -- subclass %s must override"
|
||||
% self.__class__)
|
||||
|
||||
|
||||
def dump_options(self, header=None, indent=""):
|
||||
from distutils.fancy_getopt import longopt_xlate
|
||||
if header is None:
|
||||
header = "command options for '%s':" % self.get_command_name()
|
||||
self.announce(indent + header, level=log.INFO)
|
||||
indent = indent + " "
|
||||
for (option, _, _) in self.user_options:
|
||||
option = option.translate(longopt_xlate)
|
||||
if option[-1] == "=":
|
||||
option = option[:-1]
|
||||
value = getattr(self, option)
|
||||
self.announce(indent + "%s = %s" % (option, value),
|
||||
level=log.INFO)
|
||||
|
||||
def run(self):
|
||||
"""A command's raison d'etre: carry out the action it exists to
|
||||
perform, controlled by the options initialized in
|
||||
'initialize_options()', customized by other commands, the setup
|
||||
script, the command-line, and config files, and finalized in
|
||||
'finalize_options()'. All terminal output and filesystem
|
||||
interaction should be done by 'run()'.
|
||||
|
||||
This method must be implemented by all command classes.
|
||||
"""
|
||||
raise RuntimeError("abstract method -- subclass %s must override"
|
||||
% self.__class__)
|
||||
|
||||
def announce(self, msg, level=1):
|
||||
"""If the current verbosity level is of greater than or equal to
|
||||
'level' print 'msg' to stdout.
|
||||
"""
|
||||
log.log(level, msg)
|
||||
|
||||
def debug_print(self, msg):
|
||||
"""Print 'msg' to stdout if the global DEBUG (taken from the
|
||||
DISTUTILS_DEBUG environment variable) flag is true.
|
||||
"""
|
||||
from distutils.debug import DEBUG
|
||||
if DEBUG:
|
||||
print(msg)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
# -- Option validation methods -------------------------------------
|
||||
# (these are very handy in writing the 'finalize_options()' method)
|
||||
#
|
||||
# NB. the general philosophy here is to ensure that a particular option
|
||||
# value meets certain type and value constraints. If not, we try to
|
||||
# force it into conformance (eg. if we expect a list but have a string,
|
||||
# split the string on comma and/or whitespace). If we can't force the
|
||||
# option into conformance, raise DistutilsOptionError. Thus, command
|
||||
# classes need do nothing more than (eg.)
|
||||
# self.ensure_string_list('foo')
|
||||
# and they can be guaranteed that thereafter, self.foo will be
|
||||
# a list of strings.
|
||||
|
||||
def _ensure_stringlike(self, option, what, default=None):
|
||||
val = getattr(self, option)
|
||||
if val is None:
|
||||
setattr(self, option, default)
|
||||
return default
|
||||
elif not isinstance(val, str):
|
||||
raise DistutilsOptionError("'%s' must be a %s (got `%s`)"
|
||||
% (option, what, val))
|
||||
return val
|
||||
|
||||
def ensure_string(self, option, default=None):
|
||||
"""Ensure that 'option' is a string; if not defined, set it to
|
||||
'default'.
|
||||
"""
|
||||
self._ensure_stringlike(option, "string", default)
|
||||
|
||||
def ensure_string_list(self, option):
|
||||
r"""Ensure that 'option' is a list of strings. If 'option' is
|
||||
currently a string, we split it either on /,\s*/ or /\s+/, so
|
||||
"foo bar baz", "foo,bar,baz", and "foo, bar baz" all become
|
||||
["foo", "bar", "baz"].
|
||||
"""
|
||||
val = getattr(self, option)
|
||||
if val is None:
|
||||
return
|
||||
elif isinstance(val, str):
|
||||
setattr(self, option, re.split(r',\s*|\s+', val))
|
||||
else:
|
||||
if isinstance(val, list):
|
||||
ok = all(isinstance(v, str) for v in val)
|
||||
else:
|
||||
ok = False
|
||||
if not ok:
|
||||
raise DistutilsOptionError(
|
||||
"'%s' must be a list of strings (got %r)"
|
||||
% (option, val))
|
||||
|
||||
def _ensure_tested_string(self, option, tester, what, error_fmt,
|
||||
default=None):
|
||||
val = self._ensure_stringlike(option, what, default)
|
||||
if val is not None and not tester(val):
|
||||
raise DistutilsOptionError(("error in '%s' option: " + error_fmt)
|
||||
% (option, val))
|
||||
|
||||
def ensure_filename(self, option):
|
||||
"""Ensure that 'option' is the name of an existing file."""
|
||||
self._ensure_tested_string(option, os.path.isfile,
|
||||
"filename",
|
||||
"'%s' does not exist or is not a file")
|
||||
|
||||
def ensure_dirname(self, option):
|
||||
self._ensure_tested_string(option, os.path.isdir,
|
||||
"directory name",
|
||||
"'%s' does not exist or is not a directory")
|
||||
|
||||
|
||||
# -- Convenience methods for commands ------------------------------
|
||||
|
||||
def get_command_name(self):
|
||||
if hasattr(self, 'command_name'):
|
||||
return self.command_name
|
||||
else:
|
||||
return self.__class__.__name__
|
||||
|
||||
def set_undefined_options(self, src_cmd, *option_pairs):
|
||||
"""Set the values of any "undefined" options from corresponding
|
||||
option values in some other command object. "Undefined" here means
|
||||
"is None", which is the convention used to indicate that an option
|
||||
has not been changed between 'initialize_options()' and
|
||||
'finalize_options()'. Usually called from 'finalize_options()' for
|
||||
options that depend on some other command rather than another
|
||||
option of the same command. 'src_cmd' is the other command from
|
||||
which option values will be taken (a command object will be created
|
||||
for it if necessary); the remaining arguments are
|
||||
'(src_option,dst_option)' tuples which mean "take the value of
|
||||
'src_option' in the 'src_cmd' command object, and copy it to
|
||||
'dst_option' in the current command object".
|
||||
"""
|
||||
# Option_pairs: list of (src_option, dst_option) tuples
|
||||
src_cmd_obj = self.distribution.get_command_obj(src_cmd)
|
||||
src_cmd_obj.ensure_finalized()
|
||||
for (src_option, dst_option) in option_pairs:
|
||||
if getattr(self, dst_option) is None:
|
||||
setattr(self, dst_option, getattr(src_cmd_obj, src_option))
|
||||
|
||||
def get_finalized_command(self, command, create=1):
|
||||
"""Wrapper around Distribution's 'get_command_obj()' method: find
|
||||
(create if necessary and 'create' is true) the command object for
|
||||
'command', call its 'ensure_finalized()' method, and return the
|
||||
finalized command object.
|
||||
"""
|
||||
cmd_obj = self.distribution.get_command_obj(command, create)
|
||||
cmd_obj.ensure_finalized()
|
||||
return cmd_obj
|
||||
|
||||
# XXX rename to 'get_reinitialized_command()'? (should do the
|
||||
# same in dist.py, if so)
|
||||
def reinitialize_command(self, command, reinit_subcommands=0):
|
||||
return self.distribution.reinitialize_command(command,
|
||||
reinit_subcommands)
|
||||
|
||||
def run_command(self, command):
|
||||
"""Run some other command: uses the 'run_command()' method of
|
||||
Distribution, which creates and finalizes the command object if
|
||||
necessary and then invokes its 'run()' method.
|
||||
"""
|
||||
self.distribution.run_command(command)
|
||||
|
||||
def get_sub_commands(self):
|
||||
"""Determine the sub-commands that are relevant in the current
|
||||
distribution (ie., that need to be run). This is based on the
|
||||
'sub_commands' class attribute: each tuple in that list may include
|
||||
a method that we call to determine if the subcommand needs to be
|
||||
run for the current distribution. Return a list of command names.
|
||||
"""
|
||||
commands = []
|
||||
for (cmd_name, method) in self.sub_commands:
|
||||
if method is None or method(self):
|
||||
commands.append(cmd_name)
|
||||
return commands
|
||||
|
||||
|
||||
# -- External world manipulation -----------------------------------
|
||||
|
||||
def warn(self, msg):
|
||||
log.warn("warning: %s: %s\n", self.get_command_name(), msg)
|
||||
|
||||
def execute(self, func, args, msg=None, level=1):
|
||||
util.execute(func, args, msg, dry_run=self.dry_run)
|
||||
|
||||
def mkpath(self, name, mode=0o777):
|
||||
dir_util.mkpath(name, mode, dry_run=self.dry_run)
|
||||
|
||||
def copy_file(self, infile, outfile, preserve_mode=1, preserve_times=1,
|
||||
link=None, level=1):
|
||||
"""Copy a file respecting verbose, dry-run and force flags. (The
|
||||
former two default to whatever is in the Distribution object, and
|
||||
the latter defaults to false for commands that don't define it.)"""
|
||||
return file_util.copy_file(infile, outfile, preserve_mode,
|
||||
preserve_times, not self.force, link,
|
||||
dry_run=self.dry_run)
|
||||
|
||||
def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1,
|
||||
preserve_symlinks=0, level=1):
|
||||
"""Copy an entire directory tree respecting verbose, dry-run,
|
||||
and force flags.
|
||||
"""
|
||||
return dir_util.copy_tree(infile, outfile, preserve_mode,
|
||||
preserve_times, preserve_symlinks,
|
||||
not self.force, dry_run=self.dry_run)
|
||||
|
||||
def move_file (self, src, dst, level=1):
|
||||
"""Move a file respecting dry-run flag."""
|
||||
return file_util.move_file(src, dst, dry_run=self.dry_run)
|
||||
|
||||
def spawn(self, cmd, search_path=1, level=1):
|
||||
"""Spawn an external command respecting dry-run flag."""
|
||||
from distutils.spawn import spawn
|
||||
spawn(cmd, search_path, dry_run=self.dry_run)
|
||||
|
||||
def make_archive(self, base_name, format, root_dir=None, base_dir=None,
|
||||
owner=None, group=None):
|
||||
return archive_util.make_archive(base_name, format, root_dir, base_dir,
|
||||
dry_run=self.dry_run,
|
||||
owner=owner, group=group)
|
||||
|
||||
def make_file(self, infiles, outfile, func, args,
|
||||
exec_msg=None, skip_msg=None, level=1):
|
||||
"""Special case of 'execute()' for operations that process one or
|
||||
more input files and generate one output file. Works just like
|
||||
'execute()', except the operation is skipped and a different
|
||||
message printed if 'outfile' already exists and is newer than all
|
||||
files listed in 'infiles'. If the command defined 'self.force',
|
||||
and it is true, then the command is unconditionally run -- does no
|
||||
timestamp checks.
|
||||
"""
|
||||
if skip_msg is None:
|
||||
skip_msg = "skipping %s (inputs unchanged)" % outfile
|
||||
|
||||
# Allow 'infiles' to be a single string
|
||||
if isinstance(infiles, str):
|
||||
infiles = (infiles,)
|
||||
elif not isinstance(infiles, (list, tuple)):
|
||||
raise TypeError(
|
||||
"'infiles' must be a string, or a list or tuple of strings")
|
||||
|
||||
if exec_msg is None:
|
||||
exec_msg = "generating %s from %s" % (outfile, ', '.join(infiles))
|
||||
|
||||
# If 'outfile' must be regenerated (either because it doesn't
|
||||
# exist, is out-of-date, or the 'force' flag is true) then
|
||||
# perform the action that presumably regenerates it
|
||||
if self.force or dep_util.newer_group(infiles, outfile):
|
||||
self.execute(func, args, exec_msg, level)
|
||||
# Otherwise, print the "skip" message
|
||||
else:
|
||||
log.debug(skip_msg)
|
||||
31
env/Lib/site-packages/setuptools/_distutils/command/__init__.py
vendored
Normal file
31
env/Lib/site-packages/setuptools/_distutils/command/__init__.py
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
"""distutils.command
|
||||
|
||||
Package containing implementation of all the standard Distutils
|
||||
commands."""
|
||||
|
||||
__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
|
||||
]
|
||||
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_msi.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_msi.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_wininst.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_wininst.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/register.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/register.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/upload.cpython-39.pyc
vendored
Normal file
BIN
env/Lib/site-packages/setuptools/_distutils/command/__pycache__/upload.cpython-39.pyc
vendored
Normal file
Binary file not shown.
143
env/Lib/site-packages/setuptools/_distutils/command/bdist.py
vendored
Normal file
143
env/Lib/site-packages/setuptools/_distutils/command/bdist.py
vendored
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
"""distutils.command.bdist
|
||||
|
||||
Implements the Distutils 'bdist' command (create a built [binary]
|
||||
distribution)."""
|
||||
|
||||
import os
|
||||
from distutils.core import Command
|
||||
from distutils.errors import *
|
||||
from distutils.util import get_platform
|
||||
|
||||
|
||||
def show_formats():
|
||||
"""Print list of available formats (arguments to "--format" option).
|
||||
"""
|
||||
from distutils.fancy_getopt import FancyGetopt
|
||||
formats = []
|
||||
for format in bdist.format_commands:
|
||||
formats.append(("formats=" + format, None,
|
||||
bdist.format_command[format][1]))
|
||||
pretty_printer = FancyGetopt(formats)
|
||||
pretty_printer.print_help("List of available distribution formats:")
|
||||
|
||||
|
||||
class bdist(Command):
|
||||
|
||||
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]"),
|
||||
]
|
||||
|
||||
boolean_options = ['skip-build']
|
||||
|
||||
help_options = [
|
||||
('help-formats', None,
|
||||
"lists available distribution formats", show_formats),
|
||||
]
|
||||
|
||||
# The following commands do not take a format option from bdist
|
||||
no_format_option = ('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'}
|
||||
|
||||
# Establish the preferred order (for the --help-formats option).
|
||||
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")
|
||||
}
|
||||
|
||||
|
||||
def initialize_options(self):
|
||||
self.bdist_base = None
|
||||
self.plat_name = None
|
||||
self.formats = None
|
||||
self.dist_dir = None
|
||||
self.skip_build = 0
|
||||
self.group = None
|
||||
self.owner = None
|
||||
|
||||
def finalize_options(self):
|
||||
# have to finalize 'plat_name' before 'bdist_base'
|
||||
if self.plat_name is None:
|
||||
if self.skip_build:
|
||||
self.plat_name = get_platform()
|
||||
else:
|
||||
self.plat_name = self.get_finalized_command('build').plat_name
|
||||
|
||||
# 'bdist_base' -- parent of per-built-distribution-format
|
||||
# temporary directories (eg. we'll probably have
|
||||
# "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.ensure_string_list('formats')
|
||||
if self.formats is None:
|
||||
try:
|
||||
self.formats = [self.default_format[os.name]]
|
||||
except KeyError:
|
||||
raise DistutilsPlatformError(
|
||||
"don't know how to create built distributions "
|
||||
"on platform %s" % os.name)
|
||||
|
||||
if self.dist_dir is None:
|
||||
self.dist_dir = "dist"
|
||||
|
||||
def run(self):
|
||||
# Figure out which sub-commands we need to run.
|
||||
commands = []
|
||||
for format in self.formats:
|
||||
try:
|
||||
commands.append(self.format_command[format][0])
|
||||
except KeyError:
|
||||
raise DistutilsOptionError("invalid format '%s'" % format)
|
||||
|
||||
# Reinitialize and run each command.
|
||||
for i in range(len(self.formats)):
|
||||
cmd_name = commands[i]
|
||||
sub_cmd = self.reinitialize_command(cmd_name)
|
||||
if cmd_name not in self.no_format_option:
|
||||
sub_cmd.format = self.formats[i]
|
||||
|
||||
# passing the owner and group names for tar archiving
|
||||
if cmd_name == 'bdist_dumb':
|
||||
sub_cmd.owner = self.owner
|
||||
sub_cmd.group = self.group
|
||||
|
||||
# If we're going to need to run this command again, tell it to
|
||||
# keep its temporary files around so subsequent runs go faster.
|
||||
if cmd_name in commands[i+1:]:
|
||||
sub_cmd.keep_temp = 1
|
||||
self.run_command(cmd_name)
|
||||
123
env/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py
vendored
Normal file
123
env/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py
vendored
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
"""distutils.command.bdist_dumb
|
||||
|
||||
Implements the Distutils 'bdist_dumb' command (create a "dumb" built
|
||||
distribution -- i.e., just an archive to be unpacked under $prefix or
|
||||
$exec_prefix)."""
|
||||
|
||||
import os
|
||||
from distutils.core import Command
|
||||
from distutils.util import get_platform
|
||||
from distutils.dir_util import remove_tree, ensure_relative
|
||||
from distutils.errors import *
|
||||
from distutils.sysconfig import get_python_version
|
||||
from distutils import log
|
||||
|
||||
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]"),
|
||||
]
|
||||
|
||||
boolean_options = ['keep-temp', 'skip-build', 'relative']
|
||||
|
||||
default_format = { 'posix': 'gztar',
|
||||
'nt': 'zip' }
|
||||
|
||||
def initialize_options(self):
|
||||
self.bdist_dir = None
|
||||
self.plat_name = None
|
||||
self.format = None
|
||||
self.keep_temp = 0
|
||||
self.dist_dir = None
|
||||
self.skip_build = None
|
||||
self.relative = 0
|
||||
self.owner = None
|
||||
self.group = None
|
||||
|
||||
def finalize_options(self):
|
||||
if self.bdist_dir is None:
|
||||
bdist_base = self.get_finalized_command('bdist').bdist_base
|
||||
self.bdist_dir = os.path.join(bdist_base, 'dumb')
|
||||
|
||||
if self.format is None:
|
||||
try:
|
||||
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)
|
||||
|
||||
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:
|
||||
self.run_command('build')
|
||||
|
||||
install = self.reinitialize_command('install', reinit_subcommands=1)
|
||||
install.root = self.bdist_dir
|
||||
install.skip_build = self.skip_build
|
||||
install.warn_dir = 0
|
||||
|
||||
log.info("installing to %s", self.bdist_dir)
|
||||
self.run_command('install')
|
||||
|
||||
# And make an archive relative to the root of the
|
||||
# pseudo-installation tree.
|
||||
archive_basename = "%s.%s" % (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)):
|
||||
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)))
|
||||
else:
|
||||
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)
|
||||
if self.distribution.has_ext_modules():
|
||||
pyversion = get_python_version()
|
||||
else:
|
||||
pyversion = 'any'
|
||||
self.distribution.dist_files.append(('bdist_dumb', pyversion,
|
||||
filename))
|
||||
|
||||
if not self.keep_temp:
|
||||
remove_tree(self.bdist_dir, dry_run=self.dry_run)
|
||||
749
env/Lib/site-packages/setuptools/_distutils/command/bdist_msi.py
vendored
Normal file
749
env/Lib/site-packages/setuptools/_distutils/command/bdist_msi.py
vendored
Normal file
|
|
@ -0,0 +1,749 @@
|
|||
# Copyright (C) 2005, 2006 Martin von Löwis
|
||||
# Licensed to PSF under a Contributor Agreement.
|
||||
# The bdist_wininst command proper
|
||||
# based on bdist_wininst
|
||||
"""
|
||||
Implements the bdist_msi command.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from distutils.core import Command
|
||||
from distutils.dir_util import remove_tree
|
||||
from distutils.sysconfig import get_python_version
|
||||
from distutils.version import StrictVersion
|
||||
from distutils.errors import DistutilsOptionError
|
||||
from distutils.util import get_platform
|
||||
from distutils import log
|
||||
import msilib
|
||||
from msilib import schema, sequence, text
|
||||
from msilib import Directory, Feature, Dialog, add_data
|
||||
|
||||
class PyDialog(Dialog):
|
||||
"""Dialog class with a fixed layout: controls at the top, then a ruler,
|
||||
then a list of buttons: back, next, cancel. Optionally a bitmap at the
|
||||
left."""
|
||||
def __init__(self, *args, **kw):
|
||||
"""Dialog(database, name, x, y, w, h, attributes, title, first,
|
||||
default, cancel, bitmap=true)"""
|
||||
Dialog.__init__(self, *args)
|
||||
ruler = self.h - 36
|
||||
bmwidth = 152*ruler/328
|
||||
#if kw.get("bitmap", True):
|
||||
# self.bitmap("Bitmap", 0, 0, bmwidth, ruler, "PythonWin")
|
||||
self.line("BottomLine", 0, ruler, self.w, 0)
|
||||
|
||||
def title(self, title):
|
||||
"Set the title text of the dialog at the top."
|
||||
# name, x, y, w, h, flags=Visible|Enabled|Transparent|NoPrefix,
|
||||
# text, in VerdanaBold10
|
||||
self.text("Title", 15, 10, 320, 60, 0x30003,
|
||||
r"{\VerdanaBold10}%s" % title)
|
||||
|
||||
def back(self, title, next, name = "Back", active = 1):
|
||||
"""Add a back button with a given title, the tab-next button,
|
||||
its name in the Control table, possibly initially disabled.
|
||||
|
||||
Return the button, so that events can be associated"""
|
||||
if active:
|
||||
flags = 3 # Visible|Enabled
|
||||
else:
|
||||
flags = 1 # Visible
|
||||
return self.pushbutton(name, 180, self.h-27 , 56, 17, flags, title, next)
|
||||
|
||||
def cancel(self, title, next, name = "Cancel", active = 1):
|
||||
"""Add a cancel button with a given title, the tab-next button,
|
||||
its name in the Control table, possibly initially disabled.
|
||||
|
||||
Return the button, so that events can be associated"""
|
||||
if active:
|
||||
flags = 3 # Visible|Enabled
|
||||
else:
|
||||
flags = 1 # Visible
|
||||
return self.pushbutton(name, 304, self.h-27, 56, 17, flags, title, next)
|
||||
|
||||
def next(self, title, next, name = "Next", active = 1):
|
||||
"""Add a Next button with a given title, the tab-next button,
|
||||
its name in the Control table, possibly initially disabled.
|
||||
|
||||
Return the button, so that events can be associated"""
|
||||
if active:
|
||||
flags = 3 # Visible|Enabled
|
||||
else:
|
||||
flags = 1 # Visible
|
||||
return self.pushbutton(name, 236, self.h-27, 56, 17, flags, title, next)
|
||||
|
||||
def xbutton(self, name, title, next, xpos):
|
||||
"""Add a button with a given title, the tab-next button,
|
||||
its name in the Control table, giving its x position; the
|
||||
y-position is aligned with the other buttons.
|
||||
|
||||
Return the button, so that events can be associated"""
|
||||
return self.pushbutton(name, int(self.w*xpos - 28), self.h-27, 56, 17, 3, title, next)
|
||||
|
||||
class bdist_msi(Command):
|
||||
|
||||
description = "create a Microsoft Installer (.msi) binary distribution"
|
||||
|
||||
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"),
|
||||
('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"),
|
||||
]
|
||||
|
||||
boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
|
||||
'skip-build']
|
||||
|
||||
all_versions = ['2.0', '2.1', '2.2', '2.3', '2.4',
|
||||
'2.5', '2.6', '2.7', '2.8', '2.9',
|
||||
'3.0', '3.1', '3.2', '3.3', '3.4',
|
||||
'3.5', '3.6', '3.7', '3.8', '3.9']
|
||||
other_version = 'X'
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
super().__init__(*args, **kw)
|
||||
warnings.warn("bdist_msi command is deprecated since Python 3.9, "
|
||||
"use bdist_wheel (wheel packages) instead",
|
||||
DeprecationWarning, 2)
|
||||
|
||||
def initialize_options(self):
|
||||
self.bdist_dir = None
|
||||
self.plat_name = None
|
||||
self.keep_temp = 0
|
||||
self.no_target_compile = 0
|
||||
self.no_target_optimize = 0
|
||||
self.target_version = None
|
||||
self.dist_dir = None
|
||||
self.skip_build = None
|
||||
self.install_script = None
|
||||
self.pre_install_script = None
|
||||
self.versions = None
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('bdist', ('skip_build', 'skip_build'))
|
||||
|
||||
if self.bdist_dir is None:
|
||||
bdist_base = self.get_finalized_command('bdist').bdist_base
|
||||
self.bdist_dir = os.path.join(bdist_base, 'msi')
|
||||
|
||||
short_version = get_python_version()
|
||||
if (not self.target_version) and self.distribution.has_ext_modules():
|
||||
self.target_version = short_version
|
||||
|
||||
if self.target_version:
|
||||
self.versions = [self.target_version]
|
||||
if not self.skip_build and self.distribution.has_ext_modules()\
|
||||
and self.target_version != short_version:
|
||||
raise DistutilsOptionError(
|
||||
"target version can only be %s, or the '--skip-build'"
|
||||
" option must be specified" % (short_version,))
|
||||
else:
|
||||
self.versions = list(self.all_versions)
|
||||
|
||||
self.set_undefined_options('bdist',
|
||||
('dist_dir', 'dist_dir'),
|
||||
('plat_name', 'plat_name'),
|
||||
)
|
||||
|
||||
if self.pre_install_script:
|
||||
raise DistutilsOptionError(
|
||||
"the pre-install-script feature is not yet implemented")
|
||||
|
||||
if self.install_script:
|
||||
for script in self.distribution.scripts:
|
||||
if self.install_script == os.path.basename(script):
|
||||
break
|
||||
else:
|
||||
raise DistutilsOptionError(
|
||||
"install_script '%s' not found in scripts"
|
||||
% self.install_script)
|
||||
self.install_script_key = None
|
||||
|
||||
def run(self):
|
||||
if not self.skip_build:
|
||||
self.run_command('build')
|
||||
|
||||
install = self.reinitialize_command('install', reinit_subcommands=1)
|
||||
install.prefix = self.bdist_dir
|
||||
install.skip_build = self.skip_build
|
||||
install.warn_dir = 0
|
||||
|
||||
install_lib = self.reinitialize_command('install_lib')
|
||||
# we do not want to include pyc or pyo files
|
||||
install_lib.compile = 0
|
||||
install_lib.optimize = 0
|
||||
|
||||
if self.distribution.has_ext_modules():
|
||||
# If we are building an installer for a Python version other
|
||||
# than the one we are currently running, then we need to ensure
|
||||
# our build_lib reflects the other Python version rather than ours.
|
||||
# Note that for target_version!=sys.version, we must have skipped the
|
||||
# build step, so there is no issue with enforcing the build of this
|
||||
# version.
|
||||
target_version = self.target_version
|
||||
if not target_version:
|
||||
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)
|
||||
build = self.get_finalized_command('build')
|
||||
build.build_lib = os.path.join(build.build_base,
|
||||
'lib' + plat_specifier)
|
||||
|
||||
log.info("installing to %s", self.bdist_dir)
|
||||
install.ensure_finalized()
|
||||
|
||||
# avoid warning of 'install_lib' about installing
|
||||
# into a directory not in sys.path
|
||||
sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))
|
||||
|
||||
install.run()
|
||||
|
||||
del sys.path[0]
|
||||
|
||||
self.mkpath(self.dist_dir)
|
||||
fullname = self.distribution.get_fullname()
|
||||
installer_name = self.get_installer_filename(fullname)
|
||||
installer_name = os.path.abspath(installer_name)
|
||||
if os.path.exists(installer_name): os.unlink(installer_name)
|
||||
|
||||
metadata = self.distribution.metadata
|
||||
author = metadata.author
|
||||
if not author:
|
||||
author = metadata.maintainer
|
||||
if not author:
|
||||
author = "UNKNOWN"
|
||||
version = metadata.get_version()
|
||||
# ProductVersion must be strictly numeric
|
||||
# XXX need to deal with prerelease versions
|
||||
sversion = "%d.%d.%d" % StrictVersion(version).version
|
||||
# Prefix ProductName with Python x.y, so that
|
||||
# it sorts together with the other Python packages
|
||||
# in Add-Remove-Programs (APR)
|
||||
fullname = self.distribution.get_fullname()
|
||||
if self.target_version:
|
||||
product_name = "Python %s %s" % (self.target_version, fullname)
|
||||
else:
|
||||
product_name = "Python %s" % (fullname)
|
||||
self.db = msilib.init_database(installer_name, schema,
|
||||
product_name, msilib.gen_uuid(),
|
||||
sversion, author)
|
||||
msilib.add_tables(self.db, sequence)
|
||||
props = [('DistVersion', version)]
|
||||
email = metadata.author_email or metadata.maintainer_email
|
||||
if email:
|
||||
props.append(("ARPCONTACT", email))
|
||||
if metadata.url:
|
||||
props.append(("ARPURLINFOABOUT", metadata.url))
|
||||
if props:
|
||||
add_data(self.db, 'Property', props)
|
||||
|
||||
self.add_find_python()
|
||||
self.add_files()
|
||||
self.add_scripts()
|
||||
self.add_ui()
|
||||
self.db.Commit()
|
||||
|
||||
if hasattr(self.distribution, 'dist_files'):
|
||||
tup = 'bdist_msi', self.target_version or 'any', fullname
|
||||
self.distribution.dist_files.append(tup)
|
||||
|
||||
if not self.keep_temp:
|
||||
remove_tree(self.bdist_dir, dry_run=self.dry_run)
|
||||
|
||||
def add_files(self):
|
||||
db = self.db
|
||||
cab = msilib.CAB("distfiles")
|
||||
rootdir = os.path.abspath(self.bdist_dir)
|
||||
|
||||
root = Directory(db, cab, None, rootdir, "TARGETDIR", "SourceDir")
|
||||
f = Feature(db, "Python", "Python", "Everything",
|
||||
0, 1, directory="TARGETDIR")
|
||||
|
||||
items = [(f, root, '')]
|
||||
for version in self.versions + [self.other_version]:
|
||||
target = "TARGETDIR" + version
|
||||
name = default = "Python" + version
|
||||
desc = "Everything"
|
||||
if version is self.other_version:
|
||||
title = "Python from another location"
|
||||
level = 2
|
||||
else:
|
||||
title = "Python %s from registry" % version
|
||||
level = 1
|
||||
f = Feature(db, name, title, desc, 1, level, directory=target)
|
||||
dir = Directory(db, cab, root, rootdir, target, default)
|
||||
items.append((f, dir, version))
|
||||
db.Commit()
|
||||
|
||||
seen = {}
|
||||
for feature, dir, version in items:
|
||||
todo = [dir]
|
||||
while todo:
|
||||
dir = todo.pop()
|
||||
for file in os.listdir(dir.absolute):
|
||||
afile = os.path.join(dir.absolute, file)
|
||||
if os.path.isdir(afile):
|
||||
short = "%s|%s" % (dir.make_short(file), file)
|
||||
default = file + version
|
||||
newdir = Directory(db, cab, dir, file, default, short)
|
||||
todo.append(newdir)
|
||||
else:
|
||||
if not dir.component:
|
||||
dir.start_component(dir.logical, feature, 0)
|
||||
if afile not in seen:
|
||||
key = seen[afile] = dir.add_file(file)
|
||||
if file==self.install_script:
|
||||
if self.install_script_key:
|
||||
raise DistutilsOptionError(
|
||||
"Multiple files with name %s" % file)
|
||||
self.install_script_key = '[#%s]' % key
|
||||
else:
|
||||
key = seen[afile]
|
||||
add_data(self.db, "DuplicateFile",
|
||||
[(key + version, dir.component, key, None, dir.logical)])
|
||||
db.Commit()
|
||||
cab.commit(db)
|
||||
|
||||
def add_find_python(self):
|
||||
"""Adds code to the installer to compute the location of Python.
|
||||
|
||||
Properties PYTHON.MACHINE.X.Y and PYTHON.USER.X.Y will be set from the
|
||||
registry for each version of Python.
|
||||
|
||||
Properties TARGETDIRX.Y will be set from PYTHON.USER.X.Y if defined,
|
||||
else from PYTHON.MACHINE.X.Y.
|
||||
|
||||
Properties PYTHONX.Y will be set to TARGETDIRX.Y\\python.exe"""
|
||||
|
||||
start = 402
|
||||
for ver in self.versions:
|
||||
install_path = r"SOFTWARE\Python\PythonCore\%s\InstallPath" % ver
|
||||
machine_reg = "python.machine." + ver
|
||||
user_reg = "python.user." + ver
|
||||
machine_prop = "PYTHON.MACHINE." + ver
|
||||
user_prop = "PYTHON.USER." + ver
|
||||
machine_action = "PythonFromMachine" + ver
|
||||
user_action = "PythonFromUser" + ver
|
||||
exe_action = "PythonExe" + ver
|
||||
target_dir_prop = "TARGETDIR" + ver
|
||||
exe_prop = "PYTHON" + ver
|
||||
if msilib.Win64:
|
||||
# type: msidbLocatorTypeRawValue + msidbLocatorType64bit
|
||||
Type = 2+16
|
||||
else:
|
||||
Type = 2
|
||||
add_data(self.db, "RegLocator",
|
||||
[(machine_reg, 2, install_path, None, Type),
|
||||
(user_reg, 1, install_path, None, Type)])
|
||||
add_data(self.db, "AppSearch",
|
||||
[(machine_prop, machine_reg),
|
||||
(user_prop, user_reg)])
|
||||
add_data(self.db, "CustomAction",
|
||||
[(machine_action, 51+256, target_dir_prop, "[" + machine_prop + "]"),
|
||||
(user_action, 51+256, target_dir_prop, "[" + user_prop + "]"),
|
||||
(exe_action, 51+256, exe_prop, "[" + target_dir_prop + "]\\python.exe"),
|
||||
])
|
||||
add_data(self.db, "InstallExecuteSequence",
|
||||
[(machine_action, machine_prop, start),
|
||||
(user_action, user_prop, start + 1),
|
||||
(exe_action, None, start + 2),
|
||||
])
|
||||
add_data(self.db, "InstallUISequence",
|
||||
[(machine_action, machine_prop, start),
|
||||
(user_action, user_prop, start + 1),
|
||||
(exe_action, None, start + 2),
|
||||
])
|
||||
add_data(self.db, "Condition",
|
||||
[("Python" + ver, 0, "NOT TARGETDIR" + ver)])
|
||||
start += 4
|
||||
assert start < 500
|
||||
|
||||
def add_scripts(self):
|
||||
if self.install_script:
|
||||
start = 6800
|
||||
for ver in self.versions + [self.other_version]:
|
||||
install_action = "install_script." + ver
|
||||
exe_prop = "PYTHON" + ver
|
||||
add_data(self.db, "CustomAction",
|
||||
[(install_action, 50, exe_prop, self.install_script_key)])
|
||||
add_data(self.db, "InstallExecuteSequence",
|
||||
[(install_action, "&Python%s=3" % ver, start)])
|
||||
start += 1
|
||||
# XXX pre-install scripts are currently refused in finalize_options()
|
||||
# but if this feature is completed, it will also need to add
|
||||
# entries for each version as the above code does
|
||||
if self.pre_install_script:
|
||||
scriptfn = os.path.join(self.bdist_dir, "preinstall.bat")
|
||||
with open(scriptfn, "w") as f:
|
||||
# The batch file will be executed with [PYTHON], so that %1
|
||||
# is the path to the Python interpreter; %0 will be the path
|
||||
# of the batch file.
|
||||
# rem ="""
|
||||
# %1 %0
|
||||
# exit
|
||||
# """
|
||||
# <actual script>
|
||||
f.write('rem ="""\n%1 %0\nexit\n"""\n')
|
||||
with open(self.pre_install_script) as fin:
|
||||
f.write(fin.read())
|
||||
add_data(self.db, "Binary",
|
||||
[("PreInstall", msilib.Binary(scriptfn))
|
||||
])
|
||||
add_data(self.db, "CustomAction",
|
||||
[("PreInstall", 2, "PreInstall", None)
|
||||
])
|
||||
add_data(self.db, "InstallExecuteSequence",
|
||||
[("PreInstall", "NOT Installed", 450)])
|
||||
|
||||
|
||||
def add_ui(self):
|
||||
db = self.db
|
||||
x = y = 50
|
||||
w = 370
|
||||
h = 300
|
||||
title = "[ProductName] Setup"
|
||||
|
||||
# see "Dialog Style Bits"
|
||||
modal = 3 # visible | modal
|
||||
modeless = 1 # visible
|
||||
track_disk_space = 32
|
||||
|
||||
# UI customization properties
|
||||
add_data(db, "Property",
|
||||
# See "DefaultUIFont Property"
|
||||
[("DefaultUIFont", "DlgFont8"),
|
||||
# See "ErrorDialog Style Bit"
|
||||
("ErrorDialog", "ErrorDlg"),
|
||||
("Progress1", "Install"), # modified in maintenance type dlg
|
||||
("Progress2", "installs"),
|
||||
("MaintenanceForm_Action", "Repair"),
|
||||
# possible values: ALL, JUSTME
|
||||
("WhichUsers", "ALL")
|
||||
])
|
||||
|
||||
# Fonts, see "TextStyle Table"
|
||||
add_data(db, "TextStyle",
|
||||
[("DlgFont8", "Tahoma", 9, None, 0),
|
||||
("DlgFontBold8", "Tahoma", 8, None, 1), #bold
|
||||
("VerdanaBold10", "Verdana", 10, None, 1),
|
||||
("VerdanaRed9", "Verdana", 9, 255, 0),
|
||||
])
|
||||
|
||||
# UI Sequences, see "InstallUISequence Table", "Using a Sequence Table"
|
||||
# Numbers indicate sequence; see sequence.py for how these action integrate
|
||||
add_data(db, "InstallUISequence",
|
||||
[("PrepareDlg", "Not Privileged or Windows9x or Installed", 140),
|
||||
("WhichUsersDlg", "Privileged and not Windows9x and not Installed", 141),
|
||||
# In the user interface, assume all-users installation if privileged.
|
||||
("SelectFeaturesDlg", "Not Installed", 1230),
|
||||
# XXX no support for resume installations yet
|
||||
#("ResumeDlg", "Installed AND (RESUME OR Preselected)", 1240),
|
||||
("MaintenanceTypeDlg", "Installed AND NOT RESUME AND NOT Preselected", 1250),
|
||||
("ProgressDlg", None, 1280)])
|
||||
|
||||
add_data(db, 'ActionText', text.ActionText)
|
||||
add_data(db, 'UIText', text.UIText)
|
||||
#####################################################################
|
||||
# Standard dialogs: FatalError, UserExit, ExitDialog
|
||||
fatal=PyDialog(db, "FatalError", x, y, w, h, modal, title,
|
||||
"Finish", "Finish", "Finish")
|
||||
fatal.title("[ProductName] Installer ended prematurely")
|
||||
fatal.back("< Back", "Finish", active = 0)
|
||||
fatal.cancel("Cancel", "Back", active = 0)
|
||||
fatal.text("Description1", 15, 70, 320, 80, 0x30003,
|
||||
"[ProductName] setup ended prematurely because of an error. Your system has not been modified. To install this program at a later time, please run the installation again.")
|
||||
fatal.text("Description2", 15, 155, 320, 20, 0x30003,
|
||||
"Click the Finish button to exit the Installer.")
|
||||
c=fatal.next("Finish", "Cancel", name="Finish")
|
||||
c.event("EndDialog", "Exit")
|
||||
|
||||
user_exit=PyDialog(db, "UserExit", x, y, w, h, modal, title,
|
||||
"Finish", "Finish", "Finish")
|
||||
user_exit.title("[ProductName] Installer was interrupted")
|
||||
user_exit.back("< Back", "Finish", active = 0)
|
||||
user_exit.cancel("Cancel", "Back", active = 0)
|
||||
user_exit.text("Description1", 15, 70, 320, 80, 0x30003,
|
||||
"[ProductName] setup was interrupted. Your system has not been modified. "
|
||||
"To install this program at a later time, please run the installation again.")
|
||||
user_exit.text("Description2", 15, 155, 320, 20, 0x30003,
|
||||
"Click the Finish button to exit the Installer.")
|
||||
c = user_exit.next("Finish", "Cancel", name="Finish")
|
||||
c.event("EndDialog", "Exit")
|
||||
|
||||
exit_dialog = PyDialog(db, "ExitDialog", x, y, w, h, modal, title,
|
||||
"Finish", "Finish", "Finish")
|
||||
exit_dialog.title("Completing the [ProductName] Installer")
|
||||
exit_dialog.back("< Back", "Finish", active = 0)
|
||||
exit_dialog.cancel("Cancel", "Back", active = 0)
|
||||
exit_dialog.text("Description", 15, 235, 320, 20, 0x30003,
|
||||
"Click the Finish button to exit the Installer.")
|
||||
c = exit_dialog.next("Finish", "Cancel", name="Finish")
|
||||
c.event("EndDialog", "Return")
|
||||
|
||||
#####################################################################
|
||||
# Required dialog: FilesInUse, ErrorDlg
|
||||
inuse = PyDialog(db, "FilesInUse",
|
||||
x, y, w, h,
|
||||
19, # KeepModeless|Modal|Visible
|
||||
title,
|
||||
"Retry", "Retry", "Retry", bitmap=False)
|
||||
inuse.text("Title", 15, 6, 200, 15, 0x30003,
|
||||
r"{\DlgFontBold8}Files in Use")
|
||||
inuse.text("Description", 20, 23, 280, 20, 0x30003,
|
||||
"Some files that need to be updated are currently in use.")
|
||||
inuse.text("Text", 20, 55, 330, 50, 3,
|
||||
"The following applications are using files that need to be updated by this setup. Close these applications and then click Retry to continue the installation or Cancel to exit it.")
|
||||
inuse.control("List", "ListBox", 20, 107, 330, 130, 7, "FileInUseProcess",
|
||||
None, None, None)
|
||||
c=inuse.back("Exit", "Ignore", name="Exit")
|
||||
c.event("EndDialog", "Exit")
|
||||
c=inuse.next("Ignore", "Retry", name="Ignore")
|
||||
c.event("EndDialog", "Ignore")
|
||||
c=inuse.cancel("Retry", "Exit", name="Retry")
|
||||
c.event("EndDialog","Retry")
|
||||
|
||||
# See "Error Dialog". See "ICE20" for the required names of the controls.
|
||||
error = Dialog(db, "ErrorDlg",
|
||||
50, 10, 330, 101,
|
||||
65543, # Error|Minimize|Modal|Visible
|
||||
title,
|
||||
"ErrorText", None, None)
|
||||
error.text("ErrorText", 50,9,280,48,3, "")
|
||||
#error.control("ErrorIcon", "Icon", 15, 9, 24, 24, 5242881, None, "py.ico", None, None)
|
||||
error.pushbutton("N",120,72,81,21,3,"No",None).event("EndDialog","ErrorNo")
|
||||
error.pushbutton("Y",240,72,81,21,3,"Yes",None).event("EndDialog","ErrorYes")
|
||||
error.pushbutton("A",0,72,81,21,3,"Abort",None).event("EndDialog","ErrorAbort")
|
||||
error.pushbutton("C",42,72,81,21,3,"Cancel",None).event("EndDialog","ErrorCancel")
|
||||
error.pushbutton("I",81,72,81,21,3,"Ignore",None).event("EndDialog","ErrorIgnore")
|
||||
error.pushbutton("O",159,72,81,21,3,"Ok",None).event("EndDialog","ErrorOk")
|
||||
error.pushbutton("R",198,72,81,21,3,"Retry",None).event("EndDialog","ErrorRetry")
|
||||
|
||||
#####################################################################
|
||||
# Global "Query Cancel" dialog
|
||||
cancel = Dialog(db, "CancelDlg", 50, 10, 260, 85, 3, title,
|
||||
"No", "No", "No")
|
||||
cancel.text("Text", 48, 15, 194, 30, 3,
|
||||
"Are you sure you want to cancel [ProductName] installation?")
|
||||
#cancel.control("Icon", "Icon", 15, 15, 24, 24, 5242881, None,
|
||||
# "py.ico", None, None)
|
||||
c=cancel.pushbutton("Yes", 72, 57, 56, 17, 3, "Yes", "No")
|
||||
c.event("EndDialog", "Exit")
|
||||
|
||||
c=cancel.pushbutton("No", 132, 57, 56, 17, 3, "No", "Yes")
|
||||
c.event("EndDialog", "Return")
|
||||
|
||||
#####################################################################
|
||||
# Global "Wait for costing" dialog
|
||||
costing = Dialog(db, "WaitForCostingDlg", 50, 10, 260, 85, modal, title,
|
||||
"Return", "Return", "Return")
|
||||
costing.text("Text", 48, 15, 194, 30, 3,
|
||||
"Please wait while the installer finishes determining your disk space requirements.")
|
||||
c = costing.pushbutton("Return", 102, 57, 56, 17, 3, "Return", None)
|
||||
c.event("EndDialog", "Exit")
|
||||
|
||||
#####################################################################
|
||||
# Preparation dialog: no user input except cancellation
|
||||
prep = PyDialog(db, "PrepareDlg", x, y, w, h, modeless, title,
|
||||
"Cancel", "Cancel", "Cancel")
|
||||
prep.text("Description", 15, 70, 320, 40, 0x30003,
|
||||
"Please wait while the Installer prepares to guide you through the installation.")
|
||||
prep.title("Welcome to the [ProductName] Installer")
|
||||
c=prep.text("ActionText", 15, 110, 320, 20, 0x30003, "Pondering...")
|
||||
c.mapping("ActionText", "Text")
|
||||
c=prep.text("ActionData", 15, 135, 320, 30, 0x30003, None)
|
||||
c.mapping("ActionData", "Text")
|
||||
prep.back("Back", None, active=0)
|
||||
prep.next("Next", None, active=0)
|
||||
c=prep.cancel("Cancel", None)
|
||||
c.event("SpawnDialog", "CancelDlg")
|
||||
|
||||
#####################################################################
|
||||
# Feature (Python directory) selection
|
||||
seldlg = PyDialog(db, "SelectFeaturesDlg", x, y, w, h, modal, title,
|
||||
"Next", "Next", "Cancel")
|
||||
seldlg.title("Select Python Installations")
|
||||
|
||||
seldlg.text("Hint", 15, 30, 300, 20, 3,
|
||||
"Select the Python locations where %s should be installed."
|
||||
% self.distribution.get_fullname())
|
||||
|
||||
seldlg.back("< Back", None, active=0)
|
||||
c = seldlg.next("Next >", "Cancel")
|
||||
order = 1
|
||||
c.event("[TARGETDIR]", "[SourceDir]", ordering=order)
|
||||
for version in self.versions + [self.other_version]:
|
||||
order += 1
|
||||
c.event("[TARGETDIR]", "[TARGETDIR%s]" % version,
|
||||
"FEATURE_SELECTED AND &Python%s=3" % version,
|
||||
ordering=order)
|
||||
c.event("SpawnWaitDialog", "WaitForCostingDlg", ordering=order + 1)
|
||||
c.event("EndDialog", "Return", ordering=order + 2)
|
||||
c = seldlg.cancel("Cancel", "Features")
|
||||
c.event("SpawnDialog", "CancelDlg")
|
||||
|
||||
c = seldlg.control("Features", "SelectionTree", 15, 60, 300, 120, 3,
|
||||
"FEATURE", None, "PathEdit", None)
|
||||
c.event("[FEATURE_SELECTED]", "1")
|
||||
ver = self.other_version
|
||||
install_other_cond = "FEATURE_SELECTED AND &Python%s=3" % ver
|
||||
dont_install_other_cond = "FEATURE_SELECTED AND &Python%s<>3" % ver
|
||||
|
||||
c = seldlg.text("Other", 15, 200, 300, 15, 3,
|
||||
"Provide an alternate Python location")
|
||||
c.condition("Enable", install_other_cond)
|
||||
c.condition("Show", install_other_cond)
|
||||
c.condition("Disable", dont_install_other_cond)
|
||||
c.condition("Hide", dont_install_other_cond)
|
||||
|
||||
c = seldlg.control("PathEdit", "PathEdit", 15, 215, 300, 16, 1,
|
||||
"TARGETDIR" + ver, None, "Next", None)
|
||||
c.condition("Enable", install_other_cond)
|
||||
c.condition("Show", install_other_cond)
|
||||
c.condition("Disable", dont_install_other_cond)
|
||||
c.condition("Hide", dont_install_other_cond)
|
||||
|
||||
#####################################################################
|
||||
# Disk cost
|
||||
cost = PyDialog(db, "DiskCostDlg", x, y, w, h, modal, title,
|
||||
"OK", "OK", "OK", bitmap=False)
|
||||
cost.text("Title", 15, 6, 200, 15, 0x30003,
|
||||
r"{\DlgFontBold8}Disk Space Requirements")
|
||||
cost.text("Description", 20, 20, 280, 20, 0x30003,
|
||||
"The disk space required for the installation of the selected features.")
|
||||
cost.text("Text", 20, 53, 330, 60, 3,
|
||||
"The highlighted volumes (if any) do not have enough disk space "
|
||||
"available for the currently selected features. You can either "
|
||||
"remove some files from the highlighted volumes, or choose to "
|
||||
"install less features onto local drive(s), or select different "
|
||||
"destination drive(s).")
|
||||
cost.control("VolumeList", "VolumeCostList", 20, 100, 330, 150, 393223,
|
||||
None, "{120}{70}{70}{70}{70}", None, None)
|
||||
cost.xbutton("OK", "Ok", None, 0.5).event("EndDialog", "Return")
|
||||
|
||||
#####################################################################
|
||||
# WhichUsers Dialog. Only available on NT, and for privileged users.
|
||||
# This must be run before FindRelatedProducts, because that will
|
||||
# take into account whether the previous installation was per-user
|
||||
# or per-machine. We currently don't support going back to this
|
||||
# dialog after "Next" was selected; to support this, we would need to
|
||||
# find how to reset the ALLUSERS property, and how to re-run
|
||||
# FindRelatedProducts.
|
||||
# On Windows9x, the ALLUSERS property is ignored on the command line
|
||||
# and in the Property table, but installer fails according to the documentation
|
||||
# if a dialog attempts to set ALLUSERS.
|
||||
whichusers = PyDialog(db, "WhichUsersDlg", x, y, w, h, modal, title,
|
||||
"AdminInstall", "Next", "Cancel")
|
||||
whichusers.title("Select whether to install [ProductName] for all users of this computer.")
|
||||
# A radio group with two options: allusers, justme
|
||||
g = whichusers.radiogroup("AdminInstall", 15, 60, 260, 50, 3,
|
||||
"WhichUsers", "", "Next")
|
||||
g.add("ALL", 0, 5, 150, 20, "Install for all users")
|
||||
g.add("JUSTME", 0, 25, 150, 20, "Install just for me")
|
||||
|
||||
whichusers.back("Back", None, active=0)
|
||||
|
||||
c = whichusers.next("Next >", "Cancel")
|
||||
c.event("[ALLUSERS]", "1", 'WhichUsers="ALL"', 1)
|
||||
c.event("EndDialog", "Return", ordering = 2)
|
||||
|
||||
c = whichusers.cancel("Cancel", "AdminInstall")
|
||||
c.event("SpawnDialog", "CancelDlg")
|
||||
|
||||
#####################################################################
|
||||
# Installation Progress dialog (modeless)
|
||||
progress = PyDialog(db, "ProgressDlg", x, y, w, h, modeless, title,
|
||||
"Cancel", "Cancel", "Cancel", bitmap=False)
|
||||
progress.text("Title", 20, 15, 200, 15, 0x30003,
|
||||
r"{\DlgFontBold8}[Progress1] [ProductName]")
|
||||
progress.text("Text", 35, 65, 300, 30, 3,
|
||||
"Please wait while the Installer [Progress2] [ProductName]. "
|
||||
"This may take several minutes.")
|
||||
progress.text("StatusLabel", 35, 100, 35, 20, 3, "Status:")
|
||||
|
||||
c=progress.text("ActionText", 70, 100, w-70, 20, 3, "Pondering...")
|
||||
c.mapping("ActionText", "Text")
|
||||
|
||||
#c=progress.text("ActionData", 35, 140, 300, 20, 3, None)
|
||||
#c.mapping("ActionData", "Text")
|
||||
|
||||
c=progress.control("ProgressBar", "ProgressBar", 35, 120, 300, 10, 65537,
|
||||
None, "Progress done", None, None)
|
||||
c.mapping("SetProgress", "Progress")
|
||||
|
||||
progress.back("< Back", "Next", active=False)
|
||||
progress.next("Next >", "Cancel", active=False)
|
||||
progress.cancel("Cancel", "Back").event("SpawnDialog", "CancelDlg")
|
||||
|
||||
###################################################################
|
||||
# Maintenance type: repair/uninstall
|
||||
maint = PyDialog(db, "MaintenanceTypeDlg", x, y, w, h, modal, title,
|
||||
"Next", "Next", "Cancel")
|
||||
maint.title("Welcome to the [ProductName] Setup Wizard")
|
||||
maint.text("BodyText", 15, 63, 330, 42, 3,
|
||||
"Select whether you want to repair or remove [ProductName].")
|
||||
g=maint.radiogroup("RepairRadioGroup", 15, 108, 330, 60, 3,
|
||||
"MaintenanceForm_Action", "", "Next")
|
||||
#g.add("Change", 0, 0, 200, 17, "&Change [ProductName]")
|
||||
g.add("Repair", 0, 18, 200, 17, "&Repair [ProductName]")
|
||||
g.add("Remove", 0, 36, 200, 17, "Re&move [ProductName]")
|
||||
|
||||
maint.back("< Back", None, active=False)
|
||||
c=maint.next("Finish", "Cancel")
|
||||
# Change installation: Change progress dialog to "Change", then ask
|
||||
# for feature selection
|
||||
#c.event("[Progress1]", "Change", 'MaintenanceForm_Action="Change"', 1)
|
||||
#c.event("[Progress2]", "changes", 'MaintenanceForm_Action="Change"', 2)
|
||||
|
||||
# Reinstall: Change progress dialog to "Repair", then invoke reinstall
|
||||
# Also set list of reinstalled features to "ALL"
|
||||
c.event("[REINSTALL]", "ALL", 'MaintenanceForm_Action="Repair"', 5)
|
||||
c.event("[Progress1]", "Repairing", 'MaintenanceForm_Action="Repair"', 6)
|
||||
c.event("[Progress2]", "repairs", 'MaintenanceForm_Action="Repair"', 7)
|
||||
c.event("Reinstall", "ALL", 'MaintenanceForm_Action="Repair"', 8)
|
||||
|
||||
# Uninstall: Change progress to "Remove", then invoke uninstall
|
||||
# Also set list of removed features to "ALL"
|
||||
c.event("[REMOVE]", "ALL", 'MaintenanceForm_Action="Remove"', 11)
|
||||
c.event("[Progress1]", "Removing", 'MaintenanceForm_Action="Remove"', 12)
|
||||
c.event("[Progress2]", "removes", 'MaintenanceForm_Action="Remove"', 13)
|
||||
c.event("Remove", "ALL", 'MaintenanceForm_Action="Remove"', 14)
|
||||
|
||||
# Close dialog when maintenance action scheduled
|
||||
c.event("EndDialog", "Return", 'MaintenanceForm_Action<>"Change"', 20)
|
||||
#c.event("NewDialog", "SelectFeaturesDlg", 'MaintenanceForm_Action="Change"', 21)
|
||||
|
||||
maint.cancel("Cancel", "RepairRadioGroup").event("SpawnDialog", "CancelDlg")
|
||||
|
||||
def get_installer_filename(self, fullname):
|
||||
# Factored out to allow overriding in subclasses
|
||||
if self.target_version:
|
||||
base_name = "%s.%s-py%s.msi" % (fullname, self.plat_name,
|
||||
self.target_version)
|
||||
else:
|
||||
base_name = "%s.%s.msi" % (fullname, self.plat_name)
|
||||
installer_name = os.path.join(self.dist_dir, base_name)
|
||||
return installer_name
|
||||
579
env/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py
vendored
Normal file
579
env/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py
vendored
Normal file
|
|
@ -0,0 +1,579 @@
|
|||
"""distutils.command.bdist_rpm
|
||||
|
||||
Implements the Distutils 'bdist_rpm' command (create RPM source and binary
|
||||
distributions)."""
|
||||
|
||||
import subprocess, sys, os
|
||||
from distutils.core import Command
|
||||
from distutils.debug import DEBUG
|
||||
from distutils.file_util import write_file
|
||||
from distutils.errors import *
|
||||
from distutils.sysconfig import get_python_version
|
||||
from distutils import log
|
||||
|
||||
class bdist_rpm(Command):
|
||||
|
||||
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"),
|
||||
|
||||
# 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"),
|
||||
|
||||
# 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"),
|
||||
|
||||
# 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"),
|
||||
|
||||
('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"),
|
||||
|
||||
('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"),
|
||||
|
||||
# Allow a packager to explicitly force an architecture
|
||||
('force-arch=', None,
|
||||
"Force an architecture onto the RPM build process"),
|
||||
|
||||
('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'}
|
||||
|
||||
|
||||
def initialize_options(self):
|
||||
self.bdist_base = None
|
||||
self.rpm_base = None
|
||||
self.dist_dir = None
|
||||
self.python = None
|
||||
self.fix_python = None
|
||||
self.spec_only = None
|
||||
self.binary_only = None
|
||||
self.source_only = None
|
||||
self.use_bzip2 = None
|
||||
|
||||
self.distribution_name = None
|
||||
self.group = None
|
||||
self.release = None
|
||||
self.serial = None
|
||||
self.vendor = None
|
||||
self.packager = None
|
||||
self.doc_files = None
|
||||
self.changelog = None
|
||||
self.icon = None
|
||||
|
||||
self.prep_script = None
|
||||
self.build_script = None
|
||||
self.install_script = None
|
||||
self.clean_script = None
|
||||
self.verify_script = None
|
||||
self.pre_install = None
|
||||
self.post_install = None
|
||||
self.pre_uninstall = None
|
||||
self.post_uninstall = None
|
||||
self.prep = None
|
||||
self.provides = None
|
||||
self.requires = None
|
||||
self.conflicts = None
|
||||
self.build_requires = None
|
||||
self.obsoletes = None
|
||||
|
||||
self.keep_temp = 0
|
||||
self.use_rpm_opt_flags = 1
|
||||
self.rpm3_mode = 1
|
||||
self.no_autoreq = 0
|
||||
|
||||
self.force_arch = None
|
||||
self.quiet = 0
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('bdist', ('bdist_base', 'bdist_base'))
|
||||
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")
|
||||
|
||||
if self.python is None:
|
||||
if self.fix_python:
|
||||
self.python = sys.executable
|
||||
else:
|
||||
self.python = "python3"
|
||||
elif self.fix_python:
|
||||
raise DistutilsOptionError(
|
||||
"--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)
|
||||
if self.binary_only and self.source_only:
|
||||
raise DistutilsOptionError(
|
||||
"cannot supply both '--source-only' and '--binary-only'")
|
||||
|
||||
# don't pass CFLAGS to pure python distributions
|
||||
if not self.distribution.has_ext_modules():
|
||||
self.use_rpm_opt_flags = 0
|
||||
|
||||
self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
|
||||
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('packager')
|
||||
self.ensure_string_list('doc_files')
|
||||
if isinstance(self.doc_files, list):
|
||||
for readme in ('README', 'README.txt'):
|
||||
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('serial') # should it be an int?
|
||||
|
||||
self.ensure_string('distribution_name')
|
||||
|
||||
self.ensure_string('changelog')
|
||||
# Format changelog correctly
|
||||
self.changelog = self._format_changelog(self.changelog)
|
||||
|
||||
self.ensure_filename('icon')
|
||||
|
||||
self.ensure_filename('prep_script')
|
||||
self.ensure_filename('build_script')
|
||||
self.ensure_filename('install_script')
|
||||
self.ensure_filename('clean_script')
|
||||
self.ensure_filename('verify_script')
|
||||
self.ensure_filename('pre_install')
|
||||
self.ensure_filename('post_install')
|
||||
self.ensure_filename('pre_uninstall')
|
||||
self.ensure_filename('post_uninstall')
|
||||
|
||||
# XXX don't forget we punted on summaries and descriptions -- they
|
||||
# should be handled here eventually!
|
||||
|
||||
# Now *this* is some meta-data that belongs in the setup script...
|
||||
self.ensure_string_list('provides')
|
||||
self.ensure_string_list('requires')
|
||||
self.ensure_string_list('conflicts')
|
||||
self.ensure_string_list('build_requires')
|
||||
self.ensure_string_list('obsoletes')
|
||||
|
||||
self.ensure_string('force_arch')
|
||||
|
||||
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)
|
||||
|
||||
# make directories
|
||||
if self.spec_only:
|
||||
spec_dir = self.dist_dir
|
||||
self.mkpath(spec_dir)
|
||||
else:
|
||||
rpm_dir = {}
|
||||
for d in ('SOURCES', 'SPECS', 'BUILD', 'RPMS', 'SRPMS'):
|
||||
rpm_dir[d] = os.path.join(self.rpm_base, d)
|
||||
self.mkpath(rpm_dir[d])
|
||||
spec_dir = rpm_dir['SPECS']
|
||||
|
||||
# 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)
|
||||
|
||||
if self.spec_only: # stop if requested
|
||||
return
|
||||
|
||||
# Make a source distribution and copy to SOURCES directory with
|
||||
# optional icon.
|
||||
saved_dist_files = self.distribution.dist_files[:]
|
||||
sdist = self.reinitialize_command('sdist')
|
||||
if self.use_bzip2:
|
||||
sdist.formats = ['bztar']
|
||||
else:
|
||||
sdist.formats = ['gztar']
|
||||
self.run_command('sdist')
|
||||
self.distribution.dist_files = saved_dist_files
|
||||
|
||||
source = sdist.get_archive_files()[0]
|
||||
source_dir = rpm_dir['SOURCES']
|
||||
self.copy_file(source, source_dir)
|
||||
|
||||
if self.icon:
|
||||
if os.path.exists(self.icon):
|
||||
self.copy_file(self.icon, source_dir)
|
||||
else:
|
||||
raise DistutilsFileError(
|
||||
"icon file '%s' does not exist" % self.icon)
|
||||
|
||||
# build package
|
||||
log.info("building RPMs")
|
||||
rpm_cmd = ['rpmbuild']
|
||||
|
||||
if self.source_only: # what kind of RPMs?
|
||||
rpm_cmd.append('-bs')
|
||||
elif self.binary_only:
|
||||
rpm_cmd.append('-bb')
|
||||
else:
|
||||
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)])
|
||||
if not self.keep_temp:
|
||||
rpm_cmd.append('--clean')
|
||||
|
||||
if self.quiet:
|
||||
rpm_cmd.append('--quiet')
|
||||
|
||||
rpm_cmd.append(spec_path)
|
||||
# Determine the binary rpm names that should be built out of this spec
|
||||
# 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)
|
||||
|
||||
out = os.popen(q_cmd)
|
||||
try:
|
||||
binary_rpms = []
|
||||
source_rpm = None
|
||||
while True:
|
||||
line = out.readline()
|
||||
if not line:
|
||||
break
|
||||
l = line.strip().split()
|
||||
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:
|
||||
source_rpm = l[0]
|
||||
|
||||
status = out.close()
|
||||
if status:
|
||||
raise DistutilsExecError("Failed to execute: %s" % repr(q_cmd))
|
||||
|
||||
finally:
|
||||
out.close()
|
||||
|
||||
self.spawn(rpm_cmd)
|
||||
|
||||
if not self.dry_run:
|
||||
if self.distribution.has_ext_modules():
|
||||
pyversion = get_python_version()
|
||||
else:
|
||||
pyversion = 'any'
|
||||
|
||||
if not self.binary_only:
|
||||
srpm = os.path.join(rpm_dir['SRPMS'], source_rpm)
|
||||
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))
|
||||
|
||||
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))
|
||||
self.distribution.dist_files.append(
|
||||
('bdist_rpm', pyversion, filename))
|
||||
|
||||
def _dist_path(self, path):
|
||||
return os.path.join(self.dist_dir, os.path.basename(path))
|
||||
|
||||
def _make_spec_file(self):
|
||||
"""Generate the text of an RPM spec file and return it as a
|
||||
list of strings (one per line).
|
||||
"""
|
||||
# definitions and headers
|
||||
spec_file = [
|
||||
'%define name ' + self.distribution.get_name(),
|
||||
'%define version ' + self.distribution.get_version().replace('-','_'),
|
||||
'%define unmangled_version ' + self.distribution.get_version(),
|
||||
'%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)
|
||||
vendor_hook = subprocess.getoutput('rpm --eval %{__os_install_post}')
|
||||
# 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"
|
||||
fixed_hook = vendor_hook.replace(problem, fixed)
|
||||
if fixed_hook != vendor_hook:
|
||||
spec_file.append('# Workaround for http://bugs.python.org/issue14443')
|
||||
spec_file.append('%define __os_install_post ' + fixed_hook + '\n')
|
||||
|
||||
# put locale summaries into spec file
|
||||
# XXX not supported for now (hard to put a dictionary
|
||||
# in a config file -- arg!)
|
||||
#for locale in self.summaries.keys():
|
||||
# spec_file.append('Summary(%s): %s' % (locale,
|
||||
# self.summaries[locale]))
|
||||
|
||||
spec_file.extend([
|
||||
'Name: %{name}',
|
||||
'Version: %{version}',
|
||||
'Release: %{release}',])
|
||||
|
||||
# XXX yuck! this filename is available from the "sdist" command,
|
||||
# but only after it has run: and we create the spec file before
|
||||
# running "sdist", in case of --spec-only.
|
||||
if self.use_bzip2:
|
||||
spec_file.append('Source0: %{name}-%{unmangled_version}.tar.bz2')
|
||||
else:
|
||||
spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz')
|
||||
|
||||
spec_file.extend([
|
||||
'License: ' + self.distribution.get_license(),
|
||||
'Group: ' + self.group,
|
||||
'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot',
|
||||
'Prefix: %{_prefix}', ])
|
||||
|
||||
if not self.force_arch:
|
||||
# noarch if no extension modules
|
||||
if not self.distribution.has_ext_modules():
|
||||
spec_file.append('BuildArch: noarch')
|
||||
else:
|
||||
spec_file.append( 'BuildArch: %s' % self.force_arch )
|
||||
|
||||
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)))
|
||||
elif val is not None:
|
||||
spec_file.append('%s: %s' % (field, val))
|
||||
|
||||
|
||||
if self.distribution.get_url() != 'UNKNOWN':
|
||||
spec_file.append('Url: ' + self.distribution.get_url())
|
||||
|
||||
if self.distribution_name:
|
||||
spec_file.append('Distribution: ' + self.distribution_name)
|
||||
|
||||
if self.build_requires:
|
||||
spec_file.append('BuildRequires: ' +
|
||||
' '.join(self.build_requires))
|
||||
|
||||
if self.icon:
|
||||
spec_file.append('Icon: ' + os.path.basename(self.icon))
|
||||
|
||||
if self.no_autoreq:
|
||||
spec_file.append('AutoReq: 0')
|
||||
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%description',
|
||||
self.distribution.get_long_description()
|
||||
])
|
||||
|
||||
# put locale descriptions into spec file
|
||||
# XXX again, suppressed because config file syntax doesn't
|
||||
# easily support this ;-(
|
||||
#for locale in self.descriptions.keys():
|
||||
# spec_file.extend([
|
||||
# '',
|
||||
# '%description -l ' + locale,
|
||||
# self.descriptions[locale],
|
||||
# ])
|
||||
|
||||
# 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
|
||||
if self.use_rpm_opt_flags:
|
||||
def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build
|
||||
|
||||
# insert contents of files
|
||||
|
||||
# XXX this is kind of misleading: user-supplied options are files
|
||||
# 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
|
||||
|
||||
script_options = [
|
||||
('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"),
|
||||
('verifyscript', 'verify_script', None),
|
||||
('pre', 'pre_install', None),
|
||||
('post', 'post_install', None),
|
||||
('preun', 'pre_uninstall', None),
|
||||
('postun', 'post_uninstall', None),
|
||||
]
|
||||
|
||||
for (rpm_opt, attr, default) in script_options:
|
||||
# Insert contents of file referred to, if no file is referred to
|
||||
# use 'default' as contents of script
|
||||
val = getattr(self, attr)
|
||||
if val or default:
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%' + rpm_opt,])
|
||||
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))
|
||||
|
||||
if self.changelog:
|
||||
spec_file.extend([
|
||||
'',
|
||||
'%changelog',])
|
||||
spec_file.extend(self.changelog)
|
||||
|
||||
return spec_file
|
||||
|
||||
def _format_changelog(self, changelog):
|
||||
"""Format the changelog correctly and convert it to a list of strings
|
||||
"""
|
||||
if not changelog:
|
||||
return changelog
|
||||
new_changelog = []
|
||||
for line in changelog.strip().split('\n'):
|
||||
line = line.strip()
|
||||
if line[0] == '*':
|
||||
new_changelog.extend(['', line])
|
||||
elif line[0] == '-':
|
||||
new_changelog.append(line)
|
||||
else:
|
||||
new_changelog.append(' ' + line)
|
||||
|
||||
# strip trailing newline inserted by first changelog entry
|
||||
if not new_changelog[0]:
|
||||
del new_changelog[0]
|
||||
|
||||
return new_changelog
|
||||
377
env/Lib/site-packages/setuptools/_distutils/command/bdist_wininst.py
vendored
Normal file
377
env/Lib/site-packages/setuptools/_distutils/command/bdist_wininst.py
vendored
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
"""distutils.command.bdist_wininst
|
||||
|
||||
Implements the Distutils 'bdist_wininst' command: create a windows installer
|
||||
exe-program."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
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
|
||||
|
||||
class bdist_wininst(Command):
|
||||
|
||||
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"),
|
||||
]
|
||||
|
||||
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")
|
||||
|
||||
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)
|
||||
|
||||
def initialize_options(self):
|
||||
self.bdist_dir = None
|
||||
self.plat_name = None
|
||||
self.keep_temp = 0
|
||||
self.no_target_compile = 0
|
||||
self.no_target_optimize = 0
|
||||
self.target_version = None
|
||||
self.dist_dir = None
|
||||
self.bitmap = None
|
||||
self.title = None
|
||||
self.skip_build = None
|
||||
self.install_script = None
|
||||
self.pre_install_script = None
|
||||
self.user_access_control = None
|
||||
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('bdist', ('skip_build', 'skip_build'))
|
||||
|
||||
if self.bdist_dir is None:
|
||||
if self.skip_build and self.plat_name:
|
||||
# If build is skipped and plat_name is overridden, bdist will
|
||||
# not see the correct 'plat_name' - so set that up manually.
|
||||
bdist = self.distribution.get_command_obj('bdist')
|
||||
bdist.plat_name = self.plat_name
|
||||
# next the command will be initialized using that name
|
||||
bdist_base = self.get_finalized_command('bdist').bdist_base
|
||||
self.bdist_dir = os.path.join(bdist_base, 'wininst')
|
||||
|
||||
if not 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,))
|
||||
self.target_version = short_version
|
||||
|
||||
self.set_undefined_options('bdist',
|
||||
('dist_dir', 'dist_dir'),
|
||||
('plat_name', 'plat_name'),
|
||||
)
|
||||
|
||||
if self.install_script:
|
||||
for script in self.distribution.scripts:
|
||||
if self.install_script == os.path.basename(script):
|
||||
break
|
||||
else:
|
||||
raise DistutilsOptionError(
|
||||
"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 not self.skip_build:
|
||||
self.run_command('build')
|
||||
|
||||
install = self.reinitialize_command('install', reinit_subcommands=1)
|
||||
install.root = self.bdist_dir
|
||||
install.skip_build = self.skip_build
|
||||
install.warn_dir = 0
|
||||
install.plat_name = self.plat_name
|
||||
|
||||
install_lib = self.reinitialize_command('install_lib')
|
||||
# we do not want to include pyc or pyo files
|
||||
install_lib.compile = 0
|
||||
install_lib.optimize = 0
|
||||
|
||||
if self.distribution.has_ext_modules():
|
||||
# If we are building an installer for a Python version other
|
||||
# than the one we are currently running, then we need to ensure
|
||||
# our build_lib reflects the other Python version rather than ours.
|
||||
# Note that for target_version!=sys.version, we must have skipped the
|
||||
# build step, so there is no issue with enforcing the build of this
|
||||
# version.
|
||||
target_version = self.target_version
|
||||
if not target_version:
|
||||
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)
|
||||
build = self.get_finalized_command('build')
|
||||
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.
|
||||
for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
|
||||
value = key.upper()
|
||||
if key == 'headers':
|
||||
value = value + '/Include/$dist_name'
|
||||
setattr(install,
|
||||
'install_' + key,
|
||||
value)
|
||||
|
||||
log.info("installing to %s", self.bdist_dir)
|
||||
install.ensure_finalized()
|
||||
|
||||
# avoid warning of 'install_lib' about installing
|
||||
# into a directory not in sys.path
|
||||
sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))
|
||||
|
||||
install.run()
|
||||
|
||||
del sys.path[0]
|
||||
|
||||
# And make an archive relative to the root of the
|
||||
# pseudo-installation tree.
|
||||
from tempfile import mktemp
|
||||
archive_basename = mktemp()
|
||||
fullname = self.distribution.get_fullname()
|
||||
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)))
|
||||
# remove the zip-file again
|
||||
log.debug("removing temporary file '%s'", arcname)
|
||||
os.remove(arcname)
|
||||
|
||||
if not self.keep_temp:
|
||||
remove_tree(self.bdist_dir, dry_run=self.dry_run)
|
||||
|
||||
def get_inidata(self):
|
||||
# Return data describing the installation.
|
||||
lines = []
|
||||
metadata = self.distribution.metadata
|
||||
|
||||
# Write the [metadata] section.
|
||||
lines.append("[metadata]")
|
||||
|
||||
# 'info' will be displayed in the installer's dialog box,
|
||||
# describing the items to be installed.
|
||||
info = (metadata.long_description or '') + '\n'
|
||||
|
||||
# Escape newline characters
|
||||
def escape(s):
|
||||
return s.replace("\n", "\\n")
|
||||
|
||||
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)))
|
||||
|
||||
# The [setup] section contains entries controlling
|
||||
# the installer runtime.
|
||||
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))
|
||||
if 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)
|
||||
|
||||
title = self.title or self.distribution.get_fullname()
|
||||
lines.append("title=%s" % escape(title))
|
||||
import time
|
||||
import distutils
|
||||
build_info = "Built %s with distutils-%s" % \
|
||||
(time.ctime(time.time()), distutils.__version__)
|
||||
lines.append("build_info=%s" % build_info)
|
||||
return "\n".join(lines)
|
||||
|
||||
def create_exe(self, arcname, fullname, bitmap=None):
|
||||
import struct
|
||||
|
||||
self.mkpath(self.dist_dir)
|
||||
|
||||
cfgdata = self.get_inidata()
|
||||
|
||||
installer_name = self.get_installer_filename(fullname)
|
||||
self.announce("creating %s" % installer_name)
|
||||
|
||||
if bitmap:
|
||||
with open(bitmap, "rb") as f:
|
||||
bitmapdata = f.read()
|
||||
bitmaplen = len(bitmapdata)
|
||||
else:
|
||||
bitmaplen = 0
|
||||
|
||||
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")
|
||||
|
||||
# Append the pre-install script
|
||||
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"
|
||||
else:
|
||||
# empty pre-install script
|
||||
cfgdata = cfgdata + b"\0"
|
||||
file.write(cfgdata)
|
||||
|
||||
# The 'magic number' 0x1234567B is used to make sure that the
|
||||
# binary layout of 'cfgdata' is what the wininst.exe binary
|
||||
# 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
|
||||
)
|
||||
file.write(header)
|
||||
with open(arcname, "rb") as f:
|
||||
file.write(f.read())
|
||||
|
||||
def get_installer_filename(self, fullname):
|
||||
# Factored out to allow overriding in subclasses
|
||||
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))
|
||||
else:
|
||||
installer_name = os.path.join(self.dist_dir,
|
||||
"%s.%s.exe" % (fullname, self.plat_name))
|
||||
return installer_name
|
||||
|
||||
def get_exe_bytes(self):
|
||||
# If a target-version other than the current version has been
|
||||
# specified, then using the MSVC version from *this* build is no good.
|
||||
# Without actually finding and executing the target version and parsing
|
||||
# its sys.version, we just hard-code our knowledge of old versions.
|
||||
# NOTE: Possible alternative is to allow "--target-version" to
|
||||
# specify a Python executable rather than a simple version string.
|
||||
# We can then execute this program to obtain any info we need, such
|
||||
# as the real sys.version string for the build.
|
||||
cur_version = get_python_version()
|
||||
|
||||
# If the target version is *later* than us, then we assume they
|
||||
# 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":
|
||||
bv = '6.0'
|
||||
elif self.target_version == "2.4":
|
||||
bv = '7.1'
|
||||
elif self.target_version == "2.5":
|
||||
bv = '8.0'
|
||||
elif self.target_version <= "3.2":
|
||||
bv = '9.0'
|
||||
elif self.target_version <= "3.4":
|
||||
bv = '10.0'
|
||||
else:
|
||||
bv = '14.0'
|
||||
else:
|
||||
# for current version - use authoritative check.
|
||||
try:
|
||||
from msvcrt import CRT_ASSEMBLY_VERSION
|
||||
except ImportError:
|
||||
# cross-building, so assume the latest version
|
||||
bv = '14.0'
|
||||
else:
|
||||
# as far as we know, CRT is binary compatible based on
|
||||
# the first field, so assume 'x.0' until proven otherwise
|
||||
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
|
||||
# used for python. XXX What about mingw, borland, and so on?
|
||||
|
||||
# if plat_name starts with "win" but is not "win32"
|
||||
# we want to strip "win" and leave the rest (e.g. -amd64)
|
||||
# for all other cases, we don't want any suffix
|
||||
if self.plat_name != 'win32' and self.plat_name[:3] == 'win':
|
||||
sfix = self.plat_name[3:]
|
||||
else:
|
||||
sfix = ''
|
||||
|
||||
filename = os.path.join(directory, "wininst-%s%s.exe" % (bv, sfix))
|
||||
f = open(filename, "rb")
|
||||
try:
|
||||
return f.read()
|
||||
finally:
|
||||
f.close()
|
||||
157
env/Lib/site-packages/setuptools/_distutils/command/build.py
vendored
Normal file
157
env/Lib/site-packages/setuptools/_distutils/command/build.py
vendored
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
"""distutils.command.build
|
||||
|
||||
Implements the Distutils 'build' command."""
|
||||
|
||||
import sys, os
|
||||
from distutils.core import Command
|
||||
from distutils.errors import DistutilsOptionError
|
||||
from distutils.util import get_platform
|
||||
|
||||
|
||||
def show_compilers():
|
||||
from distutils.ccompiler import show_compilers
|
||||
show_compilers()
|
||||
|
||||
|
||||
class build(Command):
|
||||
|
||||
description = "build everything needed to install"
|
||||
|
||||
user_options = [
|
||||
('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),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_base = 'build'
|
||||
# these are decided only after 'build_base' has its final value
|
||||
# (unless overridden by the user or client)
|
||||
self.build_purelib = None
|
||||
self.build_platlib = None
|
||||
self.build_lib = None
|
||||
self.build_temp = None
|
||||
self.build_scripts = None
|
||||
self.compiler = None
|
||||
self.plat_name = None
|
||||
self.debug = None
|
||||
self.force = 0
|
||||
self.executable = None
|
||||
self.parallel = None
|
||||
|
||||
def finalize_options(self):
|
||||
if self.plat_name is None:
|
||||
self.plat_name = get_platform()
|
||||
else:
|
||||
# plat-name only supported for windows (other platforms are
|
||||
# supported via ./configure flags, if at all). Avoid misleading
|
||||
# other platforms.
|
||||
if os.name != 'nt':
|
||||
raise DistutilsOptionError(
|
||||
"--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])
|
||||
|
||||
# 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
|
||||
# process for C modules
|
||||
if hasattr(sys, 'gettotalrefcount'):
|
||||
plat_specifier += '-pydebug'
|
||||
|
||||
# 'build_purelib' and 'build_platlib' just default to 'lib' and
|
||||
# 'lib.<plat>' under the base build directory. We only use one of
|
||||
# them for a given distribution, though --
|
||||
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)
|
||||
|
||||
# 'build_lib' is the actual directory that we will use for this
|
||||
# particular module distribution -- if user didn't supply it, pick
|
||||
# one of 'build_purelib' or 'build_platlib'.
|
||||
if self.build_lib is None:
|
||||
if self.distribution.ext_modules:
|
||||
self.build_lib = self.build_platlib
|
||||
else:
|
||||
self.build_lib = self.build_purelib
|
||||
|
||||
# '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)
|
||||
if self.build_scripts is None:
|
||||
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)
|
||||
|
||||
if isinstance(self.parallel, str):
|
||||
try:
|
||||
self.parallel = int(self.parallel)
|
||||
except ValueError:
|
||||
raise DistutilsOptionError("parallel should be an integer")
|
||||
|
||||
def run(self):
|
||||
# Run all relevant sub-commands. This will be some subset of:
|
||||
# - build_py - pure Python modules
|
||||
# - build_clib - standalone C libraries
|
||||
# - build_ext - Python extensions
|
||||
# - build_scripts - (Python) scripts
|
||||
for cmd_name in self.get_sub_commands():
|
||||
self.run_command(cmd_name)
|
||||
|
||||
|
||||
# -- Predicates for the sub-command list ---------------------------
|
||||
|
||||
def has_pure_modules(self):
|
||||
return self.distribution.has_pure_modules()
|
||||
|
||||
def has_c_libraries(self):
|
||||
return self.distribution.has_c_libraries()
|
||||
|
||||
def has_ext_modules(self):
|
||||
return self.distribution.has_ext_modules()
|
||||
|
||||
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),
|
||||
]
|
||||
209
env/Lib/site-packages/setuptools/_distutils/command/build_clib.py
vendored
Normal file
209
env/Lib/site-packages/setuptools/_distutils/command/build_clib.py
vendored
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
"""distutils.command.build_clib
|
||||
|
||||
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
|
||||
# that different from what's required to build a shared object file from
|
||||
# a collection of C source files. Nevertheless, I haven't done the
|
||||
# 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.
|
||||
|
||||
import os
|
||||
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
|
||||
show_compilers()
|
||||
|
||||
|
||||
class build_clib(Command):
|
||||
|
||||
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"),
|
||||
]
|
||||
|
||||
boolean_options = ['debug', 'force']
|
||||
|
||||
help_options = [
|
||||
('help-compiler', None,
|
||||
"list available compilers", show_compilers),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_clib = None
|
||||
self.build_temp = None
|
||||
|
||||
# List of libraries to build
|
||||
self.libraries = None
|
||||
|
||||
# Compilation options for all libraries
|
||||
self.include_dirs = None
|
||||
self.define = None
|
||||
self.undef = None
|
||||
self.debug = None
|
||||
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.libraries = self.distribution.libraries
|
||||
if self.libraries:
|
||||
self.check_library_list(self.libraries)
|
||||
|
||||
if self.include_dirs is None:
|
||||
self.include_dirs = self.distribution.include_dirs or []
|
||||
if isinstance(self.include_dirs, str):
|
||||
self.include_dirs = self.include_dirs.split(os.pathsep)
|
||||
|
||||
# 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)
|
||||
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:
|
||||
self.compiler.define_macro(name, value)
|
||||
if self.undef is not None:
|
||||
for macro in self.undef:
|
||||
self.compiler.undefine_macro(macro)
|
||||
|
||||
self.build_libraries(self.libraries)
|
||||
|
||||
|
||||
def check_library_list(self, libraries):
|
||||
"""Ensure that the list of libraries is valid.
|
||||
|
||||
`library` is presumably provided as a command option 'libraries'.
|
||||
This method checks that it is a list of 2-tuples, where the tuples
|
||||
are (library_name, build_info_dict).
|
||||
|
||||
Raise DistutilsSetupError if the structure is invalid anywhere;
|
||||
just returns otherwise.
|
||||
"""
|
||||
if not isinstance(libraries, list):
|
||||
raise DistutilsSetupError(
|
||||
"'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")
|
||||
|
||||
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)")
|
||||
|
||||
if '/' in name or (os.sep != '/' and os.sep in name):
|
||||
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)")
|
||||
|
||||
|
||||
def get_library_names(self):
|
||||
# Assume the library list is valid -- 'check_library_list()' is
|
||||
# called from 'finalize_options()', so it should be!
|
||||
if not self.libraries:
|
||||
return None
|
||||
|
||||
lib_names = []
|
||||
for (lib_name, build_info) in self.libraries:
|
||||
lib_names.append(lib_name)
|
||||
return lib_names
|
||||
|
||||
|
||||
def get_source_files(self):
|
||||
self.check_library_list(self.libraries)
|
||||
filenames = []
|
||||
for (lib_name, build_info) in self.libraries:
|
||||
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)
|
||||
|
||||
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)
|
||||
sources = list(sources)
|
||||
|
||||
log.info("building '%s' library", lib_name)
|
||||
|
||||
# First, compile the source code to object files in the library
|
||||
# directory. (This should probably change to putting object
|
||||
# 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)
|
||||
|
||||
# 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)
|
||||
754
env/Lib/site-packages/setuptools/_distutils/command/build_ext.py
vendored
Normal file
754
env/Lib/site-packages/setuptools/_distutils/command/build_ext.py
vendored
Normal file
|
|
@ -0,0 +1,754 @@
|
|||
"""distutils.command.build_ext
|
||||
|
||||
Implements the Distutils 'build_ext' command, for building extension
|
||||
modules (currently limited to C extensions, should accommodate C++
|
||||
extensions ASAP)."""
|
||||
|
||||
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 site import USER_BASE
|
||||
|
||||
# An extension name is just a dot-separated list of Python NAMEs (ie.
|
||||
# the same as a fully-qualified module name).
|
||||
extension_name_re = re.compile \
|
||||
(r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$')
|
||||
|
||||
|
||||
def show_compilers ():
|
||||
from distutils.ccompiler import show_compilers
|
||||
show_compilers()
|
||||
|
||||
|
||||
class build_ext(Command):
|
||||
|
||||
description = "build C/C++ extensions (compile/link to build directory)"
|
||||
|
||||
# XXX thoughts on how to deal with complex command-line options like
|
||||
# these, i.e. how to make it so fancy_getopt can suck them off the
|
||||
# command line and make it look like setup.py defined the appropriate
|
||||
# lists of tuples of what-have-you.
|
||||
# - each command needs a callback to process its command-line options
|
||||
# - Command.__init__() needs access to its share of the whole
|
||||
# command line (must ultimately come from
|
||||
# Distribution.parse_command_line())
|
||||
# - it then calls the current command class' option-parsing
|
||||
# callback to deal with weird options like -D, which have to
|
||||
# parse the option text and churn out some custom data
|
||||
# structure
|
||||
# - that data structure (in this case, a list of 2-tuples)
|
||||
# will then be present in the command object by the time
|
||||
# we get to finalize_options() (i.e. the constructor
|
||||
# takes care of both command-line and client options
|
||||
# in between initialize_options() and finalize_options())
|
||||
|
||||
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")
|
||||
]
|
||||
|
||||
boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user']
|
||||
|
||||
help_options = [
|
||||
('help-compiler', None,
|
||||
"list available compilers", show_compilers),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.extensions = None
|
||||
self.build_lib = None
|
||||
self.plat_name = None
|
||||
self.build_temp = None
|
||||
self.inplace = 0
|
||||
self.package = None
|
||||
|
||||
self.include_dirs = None
|
||||
self.define = None
|
||||
self.undef = None
|
||||
self.libraries = None
|
||||
self.library_dirs = None
|
||||
self.rpath = None
|
||||
self.link_objects = None
|
||||
self.debug = None
|
||||
self.force = None
|
||||
self.compiler = None
|
||||
self.swig = None
|
||||
self.swig_cpp = None
|
||||
self.swig_opts = None
|
||||
self.user = None
|
||||
self.parallel = None
|
||||
|
||||
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'),
|
||||
)
|
||||
|
||||
if self.package is None:
|
||||
self.package = self.distribution.ext_package
|
||||
|
||||
self.extensions = self.distribution.ext_modules
|
||||
|
||||
# Make sure Python's include directories (for Python.h, pyconfig.h,
|
||||
# etc.) are in the include search path.
|
||||
py_include = sysconfig.get_python_inc()
|
||||
plat_py_include = sysconfig.get_python_inc(plat_specific=1)
|
||||
if self.include_dirs is None:
|
||||
self.include_dirs = self.distribution.include_dirs or []
|
||||
if isinstance(self.include_dirs, str):
|
||||
self.include_dirs = self.include_dirs.split(os.pathsep)
|
||||
|
||||
# If in a virtualenv, add its include directory
|
||||
# Issue 16116
|
||||
if sys.exec_prefix != sys.base_exec_prefix:
|
||||
self.include_dirs.append(os.path.join(sys.exec_prefix, 'include'))
|
||||
|
||||
# Put the Python "system" include dir at the end, so that
|
||||
# any local include dirs take precedence.
|
||||
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))
|
||||
|
||||
self.ensure_string_list('libraries')
|
||||
self.ensure_string_list('link_objects')
|
||||
|
||||
# Life is easier if we're not forever checking for None, so
|
||||
# simplify these options to empty lists if unset
|
||||
if self.libraries is None:
|
||||
self.libraries = []
|
||||
if self.library_dirs is None:
|
||||
self.library_dirs = []
|
||||
elif isinstance(self.library_dirs, str):
|
||||
self.library_dirs = self.library_dirs.split(os.pathsep)
|
||||
|
||||
if self.rpath is None:
|
||||
self.rpath = []
|
||||
elif isinstance(self.rpath, str):
|
||||
self.rpath = self.rpath.split(os.pathsep)
|
||||
|
||||
# for extensions under windows use different directories
|
||||
# for Release and Debug builds.
|
||||
# also Python's library directory must be appended to library_dirs
|
||||
if os.name == 'nt':
|
||||
# the 'libs' directory is for binary installs - we assume that
|
||||
# must be the *native* platform. But we don't really support
|
||||
# cross-compiling via a binary install anyway, so we let it go.
|
||||
self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
|
||||
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")
|
||||
else:
|
||||
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
|
||||
self.include_dirs.append(os.path.dirname(get_config_h_filename()))
|
||||
_sys_home = getattr(sys, '_home', None)
|
||||
if _sys_home:
|
||||
self.library_dirs.append(_sys_home)
|
||||
|
||||
# Use the .lib files for the correct architecture
|
||||
if self.plat_name == 'win32':
|
||||
suffix = 'win32'
|
||||
else:
|
||||
# win-amd64
|
||||
suffix = self.plat_name[4:]
|
||||
new_lib = os.path.join(sys.exec_prefix, 'PCbuild')
|
||||
if suffix:
|
||||
new_lib = os.path.join(new_lib, suffix)
|
||||
self.library_dirs.append(new_lib)
|
||||
|
||||
# For extensions under Cygwin, Python's library directory must be
|
||||
# appended to library_dirs
|
||||
if sys.platform[:6] == 'cygwin':
|
||||
if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
|
||||
# building third party extensions
|
||||
self.library_dirs.append(os.path.join(sys.prefix, "lib",
|
||||
"python" + get_python_version(),
|
||||
"config"))
|
||||
else:
|
||||
# building python standard extensions
|
||||
self.library_dirs.append('.')
|
||||
|
||||
# For building extensions with a shared Python library,
|
||||
# Python's library directory must be appended to library_dirs
|
||||
# See Issues: #1600860, #4366
|
||||
if (sysconfig.get_config_var('Py_ENABLE_SHARED')):
|
||||
if not sysconfig.python_build:
|
||||
# building third party extensions
|
||||
self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
|
||||
else:
|
||||
# building python standard extensions
|
||||
self.library_dirs.append('.')
|
||||
|
||||
# The argument parsing will result in self.define being a string, but
|
||||
# it has to be a list of 2-tuples. All the preprocessor symbols
|
||||
# specified by the 'define' option will be set to '1'. Multiple
|
||||
# symbols can be separated with commas.
|
||||
|
||||
if self.define:
|
||||
defines = self.define.split(',')
|
||||
self.define = [(symbol, '1') for symbol in defines]
|
||||
|
||||
# The option for macros to undefine is also a string from the
|
||||
# option parsing, but has to be a list. Multiple symbols can also
|
||||
# be separated with commas here.
|
||||
if self.undef:
|
||||
self.undef = self.undef.split(',')
|
||||
|
||||
if self.swig_opts is None:
|
||||
self.swig_opts = []
|
||||
else:
|
||||
self.swig_opts = self.swig_opts.split(' ')
|
||||
|
||||
# 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")
|
||||
if os.path.isdir(user_include):
|
||||
self.include_dirs.append(user_include)
|
||||
if os.path.isdir(user_lib):
|
||||
self.library_dirs.append(user_lib)
|
||||
self.rpath.append(user_lib)
|
||||
|
||||
if isinstance(self.parallel, str):
|
||||
try:
|
||||
self.parallel = int(self.parallel)
|
||||
except ValueError:
|
||||
raise DistutilsOptionError("parallel should be an integer")
|
||||
|
||||
def run(self):
|
||||
from distutils.ccompiler import new_compiler
|
||||
|
||||
# 'self.extensions', as supplied by setup.py, is a list of
|
||||
# Extension instances. See the documentation for Extension (in
|
||||
# distutils.extension) for details.
|
||||
#
|
||||
# For backwards compatibility with Distutils 0.8.2 and earlier, we
|
||||
# also allow the 'extensions' list to be a list of tuples:
|
||||
# (ext_name, build_info)
|
||||
# where build_info is a dictionary containing everything that
|
||||
# Extension instances do except the name, with a few things being
|
||||
# differently named. We convert these 2-tuples to Extension
|
||||
# instances as needed.
|
||||
|
||||
if not self.extensions:
|
||||
return
|
||||
|
||||
# If we were asked to build any C/C++ libraries, make sure that the
|
||||
# directory where we put them is in the library search path for
|
||||
# linking extensions.
|
||||
if self.distribution.has_c_libraries():
|
||||
build_clib = self.get_finalized_command('build_clib')
|
||||
self.libraries.extend(build_clib.get_library_names() or [])
|
||||
self.library_dirs.append(build_clib.build_clib)
|
||||
|
||||
# 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)
|
||||
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
|
||||
# late initialization of compiler even if they shouldn't...)
|
||||
if os.name == 'nt' and self.plat_name != get_platform():
|
||||
self.compiler.initialize(self.plat_name)
|
||||
|
||||
# And make sure that any compile/link-related options (which might
|
||||
# come from the command-line or from the setup script) are set in
|
||||
# that CCompiler object -- that way, they automatically apply to
|
||||
# all compiling and linking done here.
|
||||
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:
|
||||
self.compiler.define_macro(name, value)
|
||||
if self.undef is not None:
|
||||
for macro in self.undef:
|
||||
self.compiler.undefine_macro(macro)
|
||||
if self.libraries is not None:
|
||||
self.compiler.set_libraries(self.libraries)
|
||||
if self.library_dirs is not None:
|
||||
self.compiler.set_library_dirs(self.library_dirs)
|
||||
if self.rpath is not None:
|
||||
self.compiler.set_runtime_library_dirs(self.rpath)
|
||||
if self.link_objects is not None:
|
||||
self.compiler.set_link_objects(self.link_objects)
|
||||
|
||||
# Now actually compile and link everything.
|
||||
self.build_extensions()
|
||||
|
||||
def check_extensions_list(self, extensions):
|
||||
"""Ensure that the list of extensions (presumably provided as a
|
||||
command option 'extensions') is valid, i.e. it is a list of
|
||||
Extension objects. We also support the old-style list of 2-tuples,
|
||||
where the tuples are (ext_name, build_info), which are converted to
|
||||
Extension instances here.
|
||||
|
||||
Raise DistutilsSetupError if the structure is invalid anywhere;
|
||||
just returns otherwise.
|
||||
"""
|
||||
if not isinstance(extensions, list):
|
||||
raise DistutilsSetupError(
|
||||
"'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)
|
||||
|
||||
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")
|
||||
|
||||
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)
|
||||
|
||||
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)")
|
||||
|
||||
if not isinstance(build_info, dict):
|
||||
raise DistutilsSetupError(
|
||||
"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.
|
||||
ext = Extension(ext_name, build_info['sources'])
|
||||
|
||||
# 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'):
|
||||
val = build_info.get(key)
|
||||
if val is not None:
|
||||
setattr(ext, key, val)
|
||||
|
||||
# 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")
|
||||
|
||||
# Non-trivial stuff: 'macros' split into 'define_macros'
|
||||
# and 'undef_macros'.
|
||||
macros = build_info.get('macros')
|
||||
if macros:
|
||||
ext.define_macros = []
|
||||
ext.undef_macros = []
|
||||
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")
|
||||
if len(macro) == 1:
|
||||
ext.undef_macros.append(macro[0])
|
||||
elif len(macro) == 2:
|
||||
ext.define_macros.append(macro)
|
||||
|
||||
extensions[i] = ext
|
||||
|
||||
def get_source_files(self):
|
||||
self.check_extensions_list(self.extensions)
|
||||
filenames = []
|
||||
|
||||
# Wouldn't it be neat if we knew the names of header files too...
|
||||
for ext in self.extensions:
|
||||
filenames.extend(ext.sources)
|
||||
return filenames
|
||||
|
||||
def get_outputs(self):
|
||||
# Sanity check the 'extensions' list -- can't assume this is being
|
||||
# done in the same run as a 'build_extensions()' call (in fact, we
|
||||
# can probably assume that it *isn't*!).
|
||||
self.check_extensions_list(self.extensions)
|
||||
|
||||
# And build the list of output (built) filenames. Note that this
|
||||
# ignores the 'inplace' flag, and assumes everything goes in the
|
||||
# "build" tree.
|
||||
outputs = []
|
||||
for ext in self.extensions:
|
||||
outputs.append(self.get_ext_fullpath(ext.name))
|
||||
return outputs
|
||||
|
||||
def build_extensions(self):
|
||||
# First, sanity-check the 'extensions' list
|
||||
self.check_extensions_list(self.extensions)
|
||||
if self.parallel:
|
||||
self._build_extensions_parallel()
|
||||
else:
|
||||
self._build_extensions_serial()
|
||||
|
||||
def _build_extensions_parallel(self):
|
||||
workers = self.parallel
|
||||
if self.parallel is True:
|
||||
workers = os.cpu_count() # may return None
|
||||
try:
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
except ImportError:
|
||||
workers = None
|
||||
|
||||
if workers is None:
|
||||
self._build_extensions_serial()
|
||||
return
|
||||
|
||||
with ThreadPoolExecutor(max_workers=workers) as executor:
|
||||
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()
|
||||
|
||||
def _build_extensions_serial(self):
|
||||
for ext in self.extensions:
|
||||
with self._filter_build_errors(ext):
|
||||
self.build_extension(ext)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _filter_build_errors(self, ext):
|
||||
try:
|
||||
yield
|
||||
except (CCompilerError, DistutilsError, CompileError) as e:
|
||||
if not ext.optional:
|
||||
raise
|
||||
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)
|
||||
# sort to make the resulting .so file build reproducible
|
||||
sources = sorted(sources)
|
||||
|
||||
ext_path = self.get_ext_fullpath(ext.name)
|
||||
depends = sources + ext.depends
|
||||
if not (self.force or newer_group(depends, ext_path, 'newer')):
|
||||
log.debug("skipping '%s' extension (up-to-date)", ext.name)
|
||||
return
|
||||
else:
|
||||
log.info("building '%s' extension", ext.name)
|
||||
|
||||
# First, scan the sources for SWIG definition files (.i), run
|
||||
# SWIG on 'em to create .c files, and modify the sources list
|
||||
# accordingly.
|
||||
sources = self.swig_sources(sources, ext)
|
||||
|
||||
# Next, compile the source code to object files.
|
||||
|
||||
# XXX not honouring 'define_macros' or 'undef_macros' -- the
|
||||
# CCompiler API needs to change to accommodate this, and I
|
||||
# want to do one thing at a time!
|
||||
|
||||
# Two possible sources for extra compiler arguments:
|
||||
# - 'extra_compile_args' in Extension object
|
||||
# - CFLAGS environment variable (not particularly
|
||||
# elegant, but people seem to expect it and I
|
||||
# guess it's useful)
|
||||
# The environment variable should take precedence, and
|
||||
# any sensible compiler will give precedence to later
|
||||
# command line args. Hence we combine them in order:
|
||||
extra_args = ext.extra_compile_args or []
|
||||
|
||||
macros = ext.define_macros[:]
|
||||
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)
|
||||
|
||||
# XXX outdated variable, kept here in case third-part code
|
||||
# needs it.
|
||||
self._built_objects = objects[:]
|
||||
|
||||
# Now link the object files together into a "shared object" --
|
||||
# of course, first we have to figure out all the other things
|
||||
# that go into the mix.
|
||||
if ext.extra_objects:
|
||||
objects.extend(ext.extra_objects)
|
||||
extra_args = ext.extra_link_args or []
|
||||
|
||||
# Detect target language, if not provided
|
||||
language = ext.language or self.compiler.detect_language(sources)
|
||||
|
||||
self.compiler.link_shared_object(
|
||||
objects, ext_path,
|
||||
libraries=self.get_libraries(ext),
|
||||
library_dirs=ext.library_dirs,
|
||||
runtime_library_dirs=ext.runtime_library_dirs,
|
||||
extra_postargs=extra_args,
|
||||
export_symbols=self.get_export_symbols(ext),
|
||||
debug=self.debug,
|
||||
build_temp=self.build_temp,
|
||||
target_lang=language)
|
||||
|
||||
def swig_sources(self, sources, extension):
|
||||
"""Walk the list of source files in 'sources', looking for SWIG
|
||||
interface (.i) files. Run SWIG on all that are found, and
|
||||
return a modified 'sources' list with SWIG source files replaced
|
||||
by the generated C (or C++) files.
|
||||
"""
|
||||
new_sources = []
|
||||
swig_sources = []
|
||||
swig_targets = {}
|
||||
|
||||
# XXX this drops generated C/C++ files into the source tree, which
|
||||
# is fine for developers who want to distribute the generated
|
||||
# source -- but there should be an option to put SWIG output in
|
||||
# the temp dir.
|
||||
|
||||
if self.swig_cpp:
|
||||
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):
|
||||
target_ext = '.cpp'
|
||||
else:
|
||||
target_ext = '.c'
|
||||
|
||||
for source in sources:
|
||||
(base, ext) = os.path.splitext(source)
|
||||
if ext == ".i": # SWIG interface file
|
||||
new_sources.append(base + '_wrap' + target_ext)
|
||||
swig_sources.append(source)
|
||||
swig_targets[source] = new_sources[-1]
|
||||
else:
|
||||
new_sources.append(source)
|
||||
|
||||
if not swig_sources:
|
||||
return new_sources
|
||||
|
||||
swig = self.swig or self.find_swig()
|
||||
swig_cmd = [swig, "-python"]
|
||||
swig_cmd.extend(self.swig_opts)
|
||||
if self.swig_cpp:
|
||||
swig_cmd.append("-c++")
|
||||
|
||||
# Do not override commandline arguments
|
||||
if not self.swig_opts:
|
||||
for o in extension.swig_opts:
|
||||
swig_cmd.append(o)
|
||||
|
||||
for source in swig_sources:
|
||||
target = swig_targets[source]
|
||||
log.info("swigging %s to %s", source, target)
|
||||
self.spawn(swig_cmd + ["-o", target, source])
|
||||
|
||||
return new_sources
|
||||
|
||||
def find_swig(self):
|
||||
"""Return the name of the SWIG executable. On Unix, this is
|
||||
just "swig" -- it should be in the PATH. Tries a bit harder on
|
||||
Windows.
|
||||
"""
|
||||
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")
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
else:
|
||||
return "swig.exe"
|
||||
else:
|
||||
raise DistutilsPlatformError(
|
||||
"I don't know how to find (much less run) SWIG "
|
||||
"on platform '%s'" % os.name)
|
||||
|
||||
# -- Name generators -----------------------------------------------
|
||||
# (extension names, filenames, whatever)
|
||||
def get_ext_fullpath(self, ext_name):
|
||||
"""Returns the path of the filename for a given extension.
|
||||
|
||||
The file is located in `build_lib` or directly in the package
|
||||
(inplace option).
|
||||
"""
|
||||
fullname = self.get_ext_fullname(ext_name)
|
||||
modpath = fullname.split('.')
|
||||
filename = self.get_ext_filename(modpath[-1])
|
||||
|
||||
if not self.inplace:
|
||||
# no further work needed
|
||||
# returning :
|
||||
# build_dir/package/path/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
|
||||
# using the build_py command for that
|
||||
package = '.'.join(modpath[0:-1])
|
||||
build_py = self.get_finalized_command('build_py')
|
||||
package_dir = os.path.abspath(build_py.get_package_dir(package))
|
||||
|
||||
# returning
|
||||
# package_dir/filename
|
||||
return os.path.join(package_dir, filename)
|
||||
|
||||
def get_ext_fullname(self, ext_name):
|
||||
"""Returns the fullname of a given extension name.
|
||||
|
||||
Adds the `package.` prefix"""
|
||||
if self.package is None:
|
||||
return ext_name
|
||||
else:
|
||||
return self.package + '.' + ext_name
|
||||
|
||||
def get_ext_filename(self, ext_name):
|
||||
r"""Convert the name of an extension (eg. "foo.bar") into the name
|
||||
of the file from which it will be loaded (eg. "foo/bar.so", or
|
||||
"foo\bar.pyd").
|
||||
"""
|
||||
from distutils.sysconfig import get_config_var
|
||||
ext_path = ext_name.split('.')
|
||||
ext_suffix = get_config_var('EXT_SUFFIX')
|
||||
return os.path.join(*ext_path) + ext_suffix
|
||||
|
||||
def get_export_symbols(self, ext):
|
||||
"""Return the list of symbols that a shared extension has to
|
||||
export. This either uses 'ext.export_symbols' or, if it's not
|
||||
provided, "PyInit_" + module_name. Only relevant on Windows, where
|
||||
the .pyd file (DLL) must export the module "PyInit_" function.
|
||||
"""
|
||||
suffix = '_' + ext.name.split('.')[-1]
|
||||
try:
|
||||
# Unicode module name support as defined in PEP-489
|
||||
# https://www.python.org/dev/peps/pep-0489/#export-hook-name
|
||||
suffix.encode('ascii')
|
||||
except UnicodeEncodeError:
|
||||
suffix = 'U' + suffix.encode('punycode').replace(b'-', b'_').decode('ascii')
|
||||
|
||||
initfunc_name = "PyInit" + suffix
|
||||
if initfunc_name not in ext.export_symbols:
|
||||
ext.export_symbols.append(initfunc_name)
|
||||
return ext.export_symbols
|
||||
|
||||
def get_libraries(self, ext):
|
||||
"""Return the list of libraries to link against when building a
|
||||
shared extension. On most platforms, this is just 'ext.libraries';
|
||||
on Windows, we add the Python library (eg. python20.dll).
|
||||
"""
|
||||
# The python library is always needed on Windows. For MSVC, this
|
||||
# is redundant, since the library is mentioned in a pragma in
|
||||
# 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":
|
||||
from distutils._msvccompiler import MSVCCompiler
|
||||
if not isinstance(self.compiler, MSVCCompiler):
|
||||
template = "python%d%d"
|
||||
if self.debug:
|
||||
template = template + '_d'
|
||||
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]
|
||||
else:
|
||||
# On Android only the main executable and LD_PRELOADs are considered
|
||||
# to be RTLD_GLOBAL, all the dependencies of the main executable
|
||||
# remain RTLD_LOCAL and so the shared libraries must be linked with
|
||||
# libpython when python is built with a shared python library (issue
|
||||
# bpo-21536).
|
||||
# On Cygwin (and if required, other POSIX-like platforms based on
|
||||
# Windows like MinGW) it is simply necessary that all symbols in
|
||||
# shared libraries are resolved at link time.
|
||||
from distutils.sysconfig import get_config_var
|
||||
link_libpython = False
|
||||
if get_config_var('Py_ENABLE_SHARED'):
|
||||
# A native build on an Android device or on Cygwin
|
||||
if hasattr(sys, 'getandroidapilevel'):
|
||||
link_libpython = True
|
||||
elif sys.platform == 'cygwin':
|
||||
link_libpython = True
|
||||
elif '_PYTHON_HOST_PLATFORM' in os.environ:
|
||||
# We are cross-compiling for one of the relevant platforms
|
||||
if get_config_var('ANDROID_API_LEVEL') != 0:
|
||||
link_libpython = True
|
||||
elif get_config_var('MACHDEP') == 'cygwin':
|
||||
link_libpython = True
|
||||
|
||||
if link_libpython:
|
||||
ldversion = get_config_var('LDVERSION')
|
||||
return ext.libraries + ['python' + ldversion]
|
||||
|
||||
return ext.libraries
|
||||
416
env/Lib/site-packages/setuptools/_distutils/command/build_py.py
vendored
Normal file
416
env/Lib/site-packages/setuptools/_distutils/command/build_py.py
vendored
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
"""distutils.command.build_py
|
||||
|
||||
Implements the Distutils 'build_py' command."""
|
||||
|
||||
import os
|
||||
import importlib.util
|
||||
import sys
|
||||
import glob
|
||||
|
||||
from distutils.core import Command
|
||||
from distutils.errors import *
|
||||
from distutils.util import convert_path, Mixin2to3
|
||||
from distutils import log
|
||||
|
||||
class build_py (Command):
|
||||
|
||||
description = "\"build\" pure Python modules (copy to build directory)"
|
||||
|
||||
user_options = [
|
||||
('build-lib=', 'd', "directory to \"build\" (copy) to"),
|
||||
('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)"),
|
||||
]
|
||||
|
||||
boolean_options = ['compile', 'force']
|
||||
negative_opt = {'no-compile' : 'compile'}
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_lib = None
|
||||
self.py_modules = None
|
||||
self.package = None
|
||||
self.package_data = None
|
||||
self.package_dir = None
|
||||
self.compile = 0
|
||||
self.optimize = 0
|
||||
self.force = None
|
||||
|
||||
def finalize_options(self):
|
||||
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.
|
||||
self.packages = self.distribution.packages
|
||||
self.py_modules = self.distribution.py_modules
|
||||
self.package_data = self.distribution.package_data
|
||||
self.package_dir = {}
|
||||
if self.distribution.package_dir:
|
||||
for name, path in self.distribution.package_dir.items():
|
||||
self.package_dir[name] = convert_path(path)
|
||||
self.data_files = self.get_data_files()
|
||||
|
||||
# Ick, copied straight from install_lib.py (fancy_getopt needs a
|
||||
# type system! Hell, *everything* needs a type system!!!)
|
||||
if not isinstance(self.optimize, int):
|
||||
try:
|
||||
self.optimize = int(self.optimize)
|
||||
assert 0 <= self.optimize <= 2
|
||||
except (ValueError, AssertionError):
|
||||
raise DistutilsOptionError("optimize must be 0, 1, or 2")
|
||||
|
||||
def run(self):
|
||||
# XXX copy_file by default preserves atime and mtime. IMHO this is
|
||||
# the right thing to do, but perhaps it should be an option -- in
|
||||
# particular, a site administrator might want installed files to
|
||||
# reflect the time of installation rather than the last
|
||||
# modification time before the installed release.
|
||||
|
||||
# XXX copy_file by default preserves mode, which appears to be the
|
||||
# wrong thing to do: if a file is read-only in the working
|
||||
# directory, we want it to be installed read/write so that the next
|
||||
# installation of the same module distribution can overwrite it
|
||||
# without problems. (This might be a Unix-specific issue.) Thus
|
||||
# we turn off 'preserve_mode' when copying to the build directory,
|
||||
# since the build directory is supposed to be exactly what the
|
||||
# installation will look like (ie. we preserve mode when
|
||||
# installing).
|
||||
|
||||
# Two options control which modules will be installed: 'packages'
|
||||
# and 'py_modules'. The former lets us work with whole packages, not
|
||||
# specifying individual modules at all; the latter is for
|
||||
# specifying modules one-at-a-time.
|
||||
|
||||
if self.py_modules:
|
||||
self.build_modules()
|
||||
if self.packages:
|
||||
self.build_packages()
|
||||
self.build_package_data()
|
||||
|
||||
self.byte_compile(self.get_outputs(include_bytecode=0))
|
||||
|
||||
def get_data_files(self):
|
||||
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
|
||||
data = []
|
||||
if not self.packages:
|
||||
return data
|
||||
for package in self.packages:
|
||||
# Locate package source directory
|
||||
src_dir = self.get_package_dir(package)
|
||||
|
||||
# Compute package build directory
|
||||
build_dir = os.path.join(*([self.build_lib] + package.split('.')))
|
||||
|
||||
# Length of path to strip from found files
|
||||
plen = 0
|
||||
if src_dir:
|
||||
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, []))
|
||||
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)])
|
||||
return files
|
||||
|
||||
def build_package_data(self):
|
||||
"""Copy data files into build directory"""
|
||||
lastdir = None
|
||||
for package, src_dir, build_dir, filenames in self.data_files:
|
||||
for filename in filenames:
|
||||
target = os.path.join(build_dir, filename)
|
||||
self.mkpath(os.path.dirname(target))
|
||||
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
|
||||
distribution, where package 'package' should be found
|
||||
(at least according to the 'package_dir' option, if any)."""
|
||||
path = package.split('.')
|
||||
|
||||
if not self.package_dir:
|
||||
if path:
|
||||
return os.path.join(*path)
|
||||
else:
|
||||
return ''
|
||||
else:
|
||||
tail = []
|
||||
while path:
|
||||
try:
|
||||
pdir = self.package_dir['.'.join(path)]
|
||||
except KeyError:
|
||||
tail.insert(0, path[-1])
|
||||
del path[-1]
|
||||
else:
|
||||
tail.insert(0, pdir)
|
||||
return os.path.join(*tail)
|
||||
else:
|
||||
# Oops, got all the way through 'path' without finding a
|
||||
# match in package_dir. If package_dir defines a directory
|
||||
# for the root (nameless) package, then fallback on it;
|
||||
# otherwise, we might as well have not consulted
|
||||
# package_dir at all, as we just use the directory implied
|
||||
# by 'tail' (which should be the same as the original value
|
||||
# of 'path' at this point).
|
||||
pdir = self.package_dir.get('')
|
||||
if pdir is not None:
|
||||
tail.insert(0, pdir)
|
||||
|
||||
if tail:
|
||||
return os.path.join(*tail)
|
||||
else:
|
||||
return ''
|
||||
|
||||
def check_package(self, package, package_dir):
|
||||
# Empty dir name means current directory, which we can probably
|
||||
# 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 not os.path.exists(package_dir):
|
||||
raise DistutilsFileError(
|
||||
"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)
|
||||
|
||||
# Require __init__.py for all but the "root package"
|
||||
if package:
|
||||
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)
|
||||
|
||||
# Either not in a package at all (__init__.py not expected), or
|
||||
# __init__.py doesn't exist -- so don't return the filename.
|
||||
return None
|
||||
|
||||
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)
|
||||
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"))
|
||||
modules = []
|
||||
setup_script = os.path.abspath(self.distribution.script_name)
|
||||
|
||||
for f in module_files:
|
||||
abs_f = os.path.abspath(f)
|
||||
if abs_f != setup_script:
|
||||
module = os.path.splitext(os.path.basename(f))[0]
|
||||
modules.append((package, module, f))
|
||||
else:
|
||||
self.debug_print("excluding %s" % setup_script)
|
||||
return modules
|
||||
|
||||
def find_modules(self):
|
||||
"""Finds individually-specified Python modules, ie. those listed by
|
||||
module name in 'self.py_modules'. Returns a list of tuples (package,
|
||||
module_base, filename): 'package' is a tuple of the path through
|
||||
package-space to the module; 'module_base' is the bare (no
|
||||
packages, no dots) module name, and 'filename' is the path to the
|
||||
".py" file (relative to the distribution root) that implements the
|
||||
module.
|
||||
"""
|
||||
# Map package names to tuples of useful info about the package:
|
||||
# (package_dir, checked)
|
||||
# package_dir - the directory where we'll find source files for
|
||||
# this package
|
||||
# checked - true if we have checked that the package directory
|
||||
# is valid (exists, contains __init__.py, ... ?)
|
||||
packages = {}
|
||||
|
||||
# List of (package, module, filename) tuples to return
|
||||
modules = []
|
||||
|
||||
# We treat modules-in-packages almost the same as toplevel modules,
|
||||
# just the "package" for a toplevel is empty (either an empty
|
||||
# string or empty list, depending on context). Differences:
|
||||
# - don't check for __init__.py in directory for empty package
|
||||
for module in self.py_modules:
|
||||
path = module.split('.')
|
||||
package = '.'.join(path[0:-1])
|
||||
module_base = path[-1]
|
||||
|
||||
try:
|
||||
(package_dir, checked) = packages[package]
|
||||
except KeyError:
|
||||
package_dir = self.get_package_dir(package)
|
||||
checked = 0
|
||||
|
||||
if not checked:
|
||||
init_py = self.check_package(package, package_dir)
|
||||
packages[package] = (package_dir, 1)
|
||||
if 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")
|
||||
if not self.check_module(module, module_file):
|
||||
continue
|
||||
|
||||
modules.append((package, module_base, module_file))
|
||||
|
||||
return modules
|
||||
|
||||
def find_all_modules(self):
|
||||
"""Compute the list of all modules that will be built, whether
|
||||
they are specified one-module-at-a-time ('self.py_modules') or
|
||||
by whole packages ('self.packages'). Return a list of tuples
|
||||
(package, module, module_file), just like 'find_modules()' and
|
||||
'find_package_modules()' do."""
|
||||
modules = []
|
||||
if self.py_modules:
|
||||
modules.extend(self.find_modules())
|
||||
if self.packages:
|
||||
for package in self.packages:
|
||||
package_dir = self.get_package_dir(package)
|
||||
m = self.find_package_modules(package, package_dir)
|
||||
modules.extend(m)
|
||||
return modules
|
||||
|
||||
def get_source_files(self):
|
||||
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"]
|
||||
return os.path.join(*outfile_path)
|
||||
|
||||
def get_outputs(self, include_bytecode=1):
|
||||
modules = self.find_all_modules()
|
||||
outputs = []
|
||||
for (package, module, module_file) in modules:
|
||||
package = package.split('.')
|
||||
filename = self.get_module_outfile(self.build_lib, package, module)
|
||||
outputs.append(filename)
|
||||
if include_bytecode:
|
||||
if self.compile:
|
||||
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 += [
|
||||
os.path.join(build_dir, filename)
|
||||
for package, src_dir, build_dir, filenames in self.data_files
|
||||
for filename in filenames
|
||||
]
|
||||
|
||||
return outputs
|
||||
|
||||
def build_module(self, module, module_file, package):
|
||||
if isinstance(package, str):
|
||||
package = package.split('.')
|
||||
elif not isinstance(package, (list, tuple)):
|
||||
raise TypeError(
|
||||
"'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
|
||||
# directory for Python source).
|
||||
outfile = self.get_module_outfile(self.build_lib, package, module)
|
||||
dir = os.path.dirname(outfile)
|
||||
self.mkpath(dir)
|
||||
return self.copy_file(module_file, outfile, preserve_mode=0)
|
||||
|
||||
def build_modules(self):
|
||||
modules = self.find_modules()
|
||||
for (package, module, module_file) in modules:
|
||||
# Now "build" the module -- ie. copy the source file to
|
||||
# self.build_lib (the build directory for Python source).
|
||||
# (Actually, it gets copied to the directory for this package
|
||||
# under self.build_lib.)
|
||||
self.build_module(module, module_file, package)
|
||||
|
||||
def build_packages(self):
|
||||
for package in self.packages:
|
||||
# Get list of (package, module, module_file) tuples based on
|
||||
# scanning the package directory. 'package' is only included
|
||||
# in the tuple so that 'find_modules()' and
|
||||
# 'find_package_tuples()' have a consistent interface; it's
|
||||
# ignored here (apart from a sanity check). Also, 'module' is
|
||||
# the *unqualified* module name (ie. no dots, no package -- we
|
||||
# already know its package!), and 'module_file' is the path to
|
||||
# the .py file, relative to the current directory
|
||||
# (ie. including 'package_dir').
|
||||
package_dir = self.get_package_dir(package)
|
||||
modules = self.find_package_modules(package, package_dir)
|
||||
|
||||
# Now loop over the modules we found, "building" each one (just
|
||||
# copy it to self.build_lib).
|
||||
for (package_, module, module_file) in modules:
|
||||
assert package == package_
|
||||
self.build_module(module, module_file, package)
|
||||
|
||||
def byte_compile(self, files):
|
||||
if sys.dont_write_bytecode:
|
||||
self.warn('byte-compiling is disabled, skipping.')
|
||||
return
|
||||
|
||||
from distutils.util import byte_compile
|
||||
prefix = self.build_lib
|
||||
if prefix[-1] != os.sep:
|
||||
prefix = prefix + os.sep
|
||||
|
||||
# XXX this code is essentially the same as the 'byte_compile()
|
||||
# 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)
|
||||
if self.optimize > 0:
|
||||
byte_compile(files, optimize=self.optimize,
|
||||
force=self.force, prefix=prefix, dry_run=self.dry_run)
|
||||
|
||||
class build_py_2to3(build_py, Mixin2to3):
|
||||
def run(self):
|
||||
self.updated_files = []
|
||||
|
||||
# Base class code
|
||||
if self.py_modules:
|
||||
self.build_modules()
|
||||
if self.packages:
|
||||
self.build_packages()
|
||||
self.build_package_data()
|
||||
|
||||
# 2to3
|
||||
self.run_2to3(self.updated_files)
|
||||
|
||||
# Remaining base class code
|
||||
self.byte_compile(self.get_outputs(include_bytecode=0))
|
||||
|
||||
def build_module(self, module, module_file, package):
|
||||
res = build_py.build_module(self, module, module_file, package)
|
||||
if res[1]:
|
||||
# file was copied
|
||||
self.updated_files.append(res[0])
|
||||
return res
|
||||
160
env/Lib/site-packages/setuptools/_distutils/command/build_scripts.py
vendored
Normal file
160
env/Lib/site-packages/setuptools/_distutils/command/build_scripts.py
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
"""distutils.command.build_scripts
|
||||
|
||||
Implements the Distutils 'build_scripts' command."""
|
||||
|
||||
import os, re
|
||||
from stat import ST_MODE
|
||||
from distutils import sysconfig
|
||||
from distutils.core import Command
|
||||
from distutils.dep_util import newer
|
||||
from distutils.util import convert_path, Mixin2to3
|
||||
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"),
|
||||
]
|
||||
|
||||
boolean_options = ['force']
|
||||
|
||||
|
||||
def initialize_options(self):
|
||||
self.build_dir = None
|
||||
self.scripts = None
|
||||
self.force = None
|
||||
self.executable = None
|
||||
self.outfiles = None
|
||||
|
||||
def finalize_options(self):
|
||||
self.set_undefined_options('build',
|
||||
('build_scripts', 'build_dir'),
|
||||
('force', 'force'),
|
||||
('executable', 'executable'))
|
||||
self.scripts = self.distribution.scripts
|
||||
|
||||
def get_source_files(self):
|
||||
return self.scripts
|
||||
|
||||
def run(self):
|
||||
if not self.scripts:
|
||||
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',
|
||||
ie. starts with "\#!" and contains "python"), then adjust the first
|
||||
line to refer to the current Python interpreter as we copy.
|
||||
"""
|
||||
self.mkpath(self.build_dir)
|
||||
outfiles = []
|
||||
updated_files = []
|
||||
for script in self.scripts:
|
||||
adjust = False
|
||||
script = convert_path(script)
|
||||
outfile = os.path.join(self.build_dir, os.path.basename(script))
|
||||
outfiles.append(outfile)
|
||||
|
||||
if not self.force and not newer(script, outfile):
|
||||
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")
|
||||
except OSError:
|
||||
if not self.dry_run:
|
||||
raise
|
||||
f = None
|
||||
else:
|
||||
encoding, lines = tokenize.detect_encoding(f.readline)
|
||||
f.seek(0)
|
||||
first_line = f.readline()
|
||||
if not first_line:
|
||||
self.warn("%s is an empty file (skipping)" % script)
|
||||
continue
|
||||
|
||||
match = first_line_re.match(first_line)
|
||||
if match:
|
||||
adjust = True
|
||||
post_interp = match.group(1) or b''
|
||||
|
||||
if adjust:
|
||||
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")))
|
||||
executable = os.fsencode(executable)
|
||||
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
|
||||
# written before. So the shebang has to be decodable from
|
||||
# UTF-8.
|
||||
try:
|
||||
shebang.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
raise ValueError(
|
||||
"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.
|
||||
try:
|
||||
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:
|
||||
outf.write(shebang)
|
||||
outf.writelines(f.readlines())
|
||||
if f:
|
||||
f.close()
|
||||
else:
|
||||
if f:
|
||||
f.close()
|
||||
updated_files.append(outfile)
|
||||
self.copy_file(script, outfile)
|
||||
|
||||
if os.name == 'posix':
|
||||
for file in outfiles:
|
||||
if self.dry_run:
|
||||
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)
|
||||
os.chmod(file, newmode)
|
||||
# XXX should we modify self.outfiles?
|
||||
return outfiles, updated_files
|
||||
|
||||
class build_scripts_2to3(build_scripts, Mixin2to3):
|
||||
|
||||
def copy_scripts(self):
|
||||
outfiles, updated_files = build_scripts.copy_scripts(self)
|
||||
if not self.dry_run:
|
||||
self.run_2to3(updated_files)
|
||||
return outfiles, updated_files
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue