update Shared
This commit is contained in:
parent
e7ebbedd38
commit
6881f3471a
184 changed files with 13080 additions and 13691 deletions
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
Build .egg distributions"""
|
||||
|
||||
# This module should be kept compatible with Python 2.3
|
||||
from distutils.errors import DistutilsSetupError
|
||||
from distutils.dir_util import remove_tree, mkpath
|
||||
from distutils import log
|
||||
|
|
@ -406,10 +405,6 @@ def scan_module(egg_dir, base, name, stubs):
|
|||
if bad in symbols:
|
||||
log.warn("%s: module MAY be using inspect.%s", module, bad)
|
||||
safe = False
|
||||
if '__name__' in symbols and '__main__' in symbols and '.' not in module:
|
||||
if sys.version[:3] == "2.4": # -m works w/zipfiles in 2.5
|
||||
log.warn("%s: top-level module may be 'python -m' script", module)
|
||||
safe = False
|
||||
return safe
|
||||
|
||||
|
||||
|
|
@ -441,7 +436,7 @@ INSTALL_DIRECTORY_ATTRS = [
|
|||
]
|
||||
|
||||
|
||||
def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=None,
|
||||
def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=True,
|
||||
mode='w'):
|
||||
"""Create a zip file from all the files under 'base_dir'. The output
|
||||
zip file will be named 'base_dir' + ".zip". Uses either the "zipfile"
|
||||
|
|
@ -463,11 +458,7 @@ def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=None,
|
|||
z.write(path, p)
|
||||
log.debug("adding '%s'" % p)
|
||||
|
||||
if compress is None:
|
||||
# avoid 2.3 zipimport bug when 64 bits
|
||||
compress = (sys.version >= "2.4")
|
||||
|
||||
compression = [zipfile.ZIP_STORED, zipfile.ZIP_DEFLATED][bool(compress)]
|
||||
compression = zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED
|
||||
if not dry_run:
|
||||
z = zipfile.ZipFile(zip_filename, mode, compression=compression)
|
||||
for dirname, dirs, files in os.walk(base_dir):
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@ from distutils.errors import DistutilsError
|
|||
from distutils import log
|
||||
import os
|
||||
import sys
|
||||
import itertools
|
||||
|
||||
from setuptools.extension import Library
|
||||
|
||||
try:
|
||||
# Attempt to use Pyrex for building extensions, if available
|
||||
from Pyrex.Distutils.build_ext import build_ext as _build_ext
|
||||
# Attempt to use Cython for building extensions, if available
|
||||
from Cython.Distutils.build_ext import build_ext as _build_ext
|
||||
except ImportError:
|
||||
_build_ext = _du_build_ext
|
||||
|
||||
|
|
@ -33,19 +34,13 @@ if sys.platform == "darwin":
|
|||
use_stubs = True
|
||||
elif os.name != 'nt':
|
||||
try:
|
||||
from dl import RTLD_NOW
|
||||
|
||||
have_rtld = True
|
||||
use_stubs = True
|
||||
import dl
|
||||
use_stubs = have_rtld = hasattr(dl, 'RTLD_NOW')
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def if_dl(s):
|
||||
if have_rtld:
|
||||
return s
|
||||
return ''
|
||||
|
||||
if_dl = lambda s: s if have_rtld else ''
|
||||
|
||||
class build_ext(_build_ext):
|
||||
def run(self):
|
||||
|
|
@ -78,15 +73,6 @@ class build_ext(_build_ext):
|
|||
if ext._needs_stub:
|
||||
self.write_stub(package_dir or os.curdir, ext, True)
|
||||
|
||||
if _build_ext is not _du_build_ext and not hasattr(_build_ext,
|
||||
'pyrex_sources'):
|
||||
# Workaround for problems using some Pyrex versions w/SWIG and/or 2.4
|
||||
def swig_sources(self, sources, *otherargs):
|
||||
# first do any Pyrex processing
|
||||
sources = _build_ext.swig_sources(self, sources) or sources
|
||||
# Then do any actual SWIG stuff on the remainder
|
||||
return _du_build_ext.swig_sources(self, sources, *otherargs)
|
||||
|
||||
def get_ext_filename(self, fullname):
|
||||
filename = _build_ext.get_ext_filename(self, fullname)
|
||||
if fullname in self.ext_map:
|
||||
|
|
@ -123,10 +109,10 @@ class build_ext(_build_ext):
|
|||
# XXX what to do with conflicts?
|
||||
self.ext_map[fullname.split('.')[-1]] = ext
|
||||
|
||||
ltd = ext._links_to_dynamic = \
|
||||
self.shlibs and self.links_to_dynamic(ext) or False
|
||||
ext._needs_stub = ltd and use_stubs and not isinstance(ext,
|
||||
Library)
|
||||
ltd = self.shlibs and self.links_to_dynamic(ext) or False
|
||||
ns = ltd and use_stubs and not isinstance(ext, Library)
|
||||
ext._links_to_dynamic = ltd
|
||||
ext._needs_stub = ns
|
||||
filename = ext._file_name = self.get_ext_filename(fullname)
|
||||
libdir = os.path.dirname(os.path.join(self.build_lib, filename))
|
||||
if ltd and libdir not in ext.library_dirs:
|
||||
|
|
@ -180,15 +166,15 @@ class build_ext(_build_ext):
|
|||
return _build_ext.get_export_symbols(self, ext)
|
||||
|
||||
def build_extension(self, ext):
|
||||
ext._convert_pyx_sources_to_lang()
|
||||
_compiler = self.compiler
|
||||
try:
|
||||
if isinstance(ext, Library):
|
||||
self.compiler = self.shlib_compiler
|
||||
_build_ext.build_extension(self, ext)
|
||||
if ext._needs_stub:
|
||||
self.write_stub(
|
||||
self.get_finalized_command('build_py').build_lib, ext
|
||||
)
|
||||
cmd = self.get_finalized_command('build_py').build_lib
|
||||
self.write_stub(cmd, ext)
|
||||
finally:
|
||||
self.compiler = _compiler
|
||||
|
||||
|
|
@ -199,22 +185,27 @@ class build_ext(_build_ext):
|
|||
# XXX static-compiled version
|
||||
libnames = dict.fromkeys([lib._full_name for lib in self.shlibs])
|
||||
pkg = '.'.join(ext._full_name.split('.')[:-1] + [''])
|
||||
for libname in ext.libraries:
|
||||
if pkg + libname in libnames:
|
||||
return True
|
||||
return False
|
||||
return any(pkg + libname in libnames for libname in ext.libraries)
|
||||
|
||||
def get_outputs(self):
|
||||
outputs = _build_ext.get_outputs(self)
|
||||
optimize = self.get_finalized_command('build_py').optimize
|
||||
for ext in self.extensions:
|
||||
if ext._needs_stub:
|
||||
base = os.path.join(self.build_lib, *ext._full_name.split('.'))
|
||||
outputs.append(base + '.py')
|
||||
outputs.append(base + '.pyc')
|
||||
if optimize:
|
||||
outputs.append(base + '.pyo')
|
||||
return outputs
|
||||
return _build_ext.get_outputs(self) + self.__get_stubs_outputs()
|
||||
|
||||
def __get_stubs_outputs(self):
|
||||
# assemble the base name for each extension that needs a stub
|
||||
ns_ext_bases = (
|
||||
os.path.join(self.build_lib, *ext._full_name.split('.'))
|
||||
for ext in self.extensions
|
||||
if ext._needs_stub
|
||||
)
|
||||
# pair each base with the extension
|
||||
pairs = itertools.product(ns_ext_bases, self.__get_output_extensions())
|
||||
return list(base + fnext for base, fnext in pairs)
|
||||
|
||||
def __get_output_extensions(self):
|
||||
yield '.py'
|
||||
yield '.pyc'
|
||||
if self.get_finalized_command('build_py').optimize:
|
||||
yield '.pyo'
|
||||
|
||||
def write_stub(self, output_dir, ext, compile=False):
|
||||
log.info("writing stub loader for %s to %s", ext._full_name,
|
||||
|
|
|
|||
|
|
@ -136,22 +136,7 @@ class build_py(orig.build_py, Mixin2to3):
|
|||
mf.setdefault(src_dirs[d], []).append(path)
|
||||
|
||||
def get_data_files(self):
|
||||
pass # kludge 2.4 for lazy computation
|
||||
|
||||
if sys.version < "2.4": # Python 2.4 already has this code
|
||||
def get_outputs(self, include_bytecode=1):
|
||||
"""Return complete list of files copied to the build directory
|
||||
|
||||
This includes both '.py' files and data files, as well as '.pyc'
|
||||
and '.pyo' files if 'include_bytecode' is true. (This method is
|
||||
needed for the 'install_lib' command to do its job properly, and to
|
||||
generate a correct installation manifest.)
|
||||
"""
|
||||
return orig.build_py.get_outputs(self, include_bytecode) + [
|
||||
os.path.join(build_dir, filename)
|
||||
for package, src_dir, build_dir, filenames in self.data_files
|
||||
for filename in filenames
|
||||
]
|
||||
pass # Lazily compute data files in _get_data_files() function.
|
||||
|
||||
def check_package(self, package, package_dir):
|
||||
"""Check namespace packages' __init__ for declare_namespace"""
|
||||
|
|
|
|||
|
|
@ -34,8 +34,12 @@ import textwrap
|
|||
import warnings
|
||||
import site
|
||||
import struct
|
||||
import contextlib
|
||||
import subprocess
|
||||
import shlex
|
||||
import io
|
||||
|
||||
from setuptools import Command, _dont_write_bytecode
|
||||
from setuptools import Command
|
||||
from setuptools.sandbox import run_setup
|
||||
from setuptools.py31compat import get_path, get_config_vars
|
||||
from setuptools.command import setopt
|
||||
|
|
@ -53,9 +57,9 @@ from pkg_resources import (
|
|||
)
|
||||
import pkg_resources
|
||||
|
||||
# Turn on PEP440Warnings
|
||||
warnings.filterwarnings("default", category=pkg_resources.PEP440Warning)
|
||||
|
||||
sys_executable = os.environ.get('__PYVENV_LAUNCHER__',
|
||||
os.path.normpath(sys.executable))
|
||||
|
||||
__all__ = [
|
||||
'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg',
|
||||
|
|
@ -148,12 +152,9 @@ class easy_install(Command):
|
|||
create_index = PackageIndex
|
||||
|
||||
def initialize_options(self):
|
||||
if site.ENABLE_USER_SITE:
|
||||
whereami = os.path.abspath(__file__)
|
||||
self.user = whereami.startswith(site.USER_SITE)
|
||||
else:
|
||||
self.user = 0
|
||||
|
||||
# the --user option seems to be an opt-in one,
|
||||
# so the default should be False.
|
||||
self.user = 0
|
||||
self.zip_ok = self.local_snapshots_ok = None
|
||||
self.install_dir = self.script_dir = self.exclude_scripts = None
|
||||
self.index_url = None
|
||||
|
|
@ -199,20 +200,34 @@ class easy_install(Command):
|
|||
)
|
||||
|
||||
def delete_blockers(self, blockers):
|
||||
for filename in blockers:
|
||||
if os.path.exists(filename) or os.path.islink(filename):
|
||||
log.info("Deleting %s", filename)
|
||||
if not self.dry_run:
|
||||
if (os.path.isdir(filename) and
|
||||
not os.path.islink(filename)):
|
||||
rmtree(filename)
|
||||
else:
|
||||
os.unlink(filename)
|
||||
extant_blockers = (
|
||||
filename for filename in blockers
|
||||
if os.path.exists(filename) or os.path.islink(filename)
|
||||
)
|
||||
list(map(self._delete_path, extant_blockers))
|
||||
|
||||
def _delete_path(self, path):
|
||||
log.info("Deleting %s", path)
|
||||
if self.dry_run:
|
||||
return
|
||||
|
||||
is_tree = os.path.isdir(path) and not os.path.islink(path)
|
||||
remover = rmtree if is_tree else os.unlink
|
||||
remover(path)
|
||||
|
||||
@staticmethod
|
||||
def _render_version():
|
||||
"""
|
||||
Render the Setuptools version and installation details, then exit.
|
||||
"""
|
||||
ver = sys.version[:3]
|
||||
dist = get_distribution('setuptools')
|
||||
tmpl = 'setuptools {dist.version} from {dist.location} (Python {ver})'
|
||||
print(tmpl.format(**locals()))
|
||||
raise SystemExit()
|
||||
|
||||
def finalize_options(self):
|
||||
if self.version:
|
||||
print('setuptools %s' % get_distribution('setuptools').version)
|
||||
sys.exit()
|
||||
self.version and self._render_version()
|
||||
|
||||
py_version = sys.version.split()[0]
|
||||
prefix, exec_prefix = get_config_vars('prefix', 'exec_prefix')
|
||||
|
|
@ -236,18 +251,7 @@ class easy_install(Command):
|
|||
self.config_vars['userbase'] = self.install_userbase
|
||||
self.config_vars['usersite'] = self.install_usersite
|
||||
|
||||
# fix the install_dir if "--user" was used
|
||||
# XXX: duplicate of the code in the setup command
|
||||
if self.user and site.ENABLE_USER_SITE:
|
||||
self.create_home_path()
|
||||
if self.install_userbase is None:
|
||||
raise DistutilsPlatformError(
|
||||
"User base directory is not specified")
|
||||
self.install_base = self.install_platbase = self.install_userbase
|
||||
if os.name == 'posix':
|
||||
self.select_scheme("unix_user")
|
||||
else:
|
||||
self.select_scheme(os.name + "_user")
|
||||
self._fix_install_dir_for_user_site()
|
||||
|
||||
self.expand_basedirs()
|
||||
self.expand_dirs()
|
||||
|
|
@ -342,6 +346,21 @@ class easy_install(Command):
|
|||
|
||||
self.outputs = []
|
||||
|
||||
def _fix_install_dir_for_user_site(self):
|
||||
"""
|
||||
Fix the install_dir if "--user" was used.
|
||||
"""
|
||||
if not self.user or not site.ENABLE_USER_SITE:
|
||||
return
|
||||
|
||||
self.create_home_path()
|
||||
if self.install_userbase is None:
|
||||
msg = "User base directory is not specified"
|
||||
raise DistutilsPlatformError(msg)
|
||||
self.install_base = self.install_platbase = self.install_userbase
|
||||
scheme_name = os.name.replace('posix', 'unix') + '_user'
|
||||
self.select_scheme(scheme_name)
|
||||
|
||||
def _expand_attrs(self, attrs):
|
||||
for attr in attrs:
|
||||
val = getattr(self, attr)
|
||||
|
|
@ -434,7 +453,7 @@ class easy_install(Command):
|
|||
self.pth_file = None
|
||||
|
||||
PYTHONPATH = os.environ.get('PYTHONPATH', '').split(os.pathsep)
|
||||
if instdir not in map(normalize_path, [_f for _f in PYTHONPATH if _f]):
|
||||
if instdir not in map(normalize_path, filter(None, PYTHONPATH)):
|
||||
# only PYTHONPATH dirs need a site.py, so pretend it's there
|
||||
self.sitepy_installed = True
|
||||
elif self.multi_version and not os.path.exists(pth_file):
|
||||
|
|
@ -442,43 +461,49 @@ class easy_install(Command):
|
|||
self.pth_file = None # and don't create a .pth file
|
||||
self.install_dir = instdir
|
||||
|
||||
__cant_write_msg = textwrap.dedent("""
|
||||
can't create or remove files in install directory
|
||||
|
||||
The following error occurred while trying to add or remove files in the
|
||||
installation directory:
|
||||
|
||||
%s
|
||||
|
||||
The installation directory you specified (via --install-dir, --prefix, or
|
||||
the distutils default setting) was:
|
||||
|
||||
%s
|
||||
""").lstrip()
|
||||
|
||||
__not_exists_id = textwrap.dedent("""
|
||||
This directory does not currently exist. Please create it and try again, or
|
||||
choose a different installation directory (using the -d or --install-dir
|
||||
option).
|
||||
""").lstrip()
|
||||
|
||||
__access_msg = textwrap.dedent("""
|
||||
Perhaps your account does not have write access to this directory? If the
|
||||
installation directory is a system-owned directory, you may need to sign in
|
||||
as the administrator or "root" account. If you do not have administrative
|
||||
access to this machine, you may wish to choose a different installation
|
||||
directory, preferably one that is listed in your PYTHONPATH environment
|
||||
variable.
|
||||
|
||||
For information on other options, you may wish to consult the
|
||||
documentation at:
|
||||
|
||||
https://pythonhosted.org/setuptools/easy_install.html
|
||||
|
||||
Please make the appropriate changes for your system and try again.
|
||||
""").lstrip()
|
||||
|
||||
def cant_write_to_target(self):
|
||||
template = """can't create or remove files in install directory
|
||||
|
||||
The following error occurred while trying to add or remove files in the
|
||||
installation directory:
|
||||
|
||||
%s
|
||||
|
||||
The installation directory you specified (via --install-dir, --prefix, or
|
||||
the distutils default setting) was:
|
||||
|
||||
%s
|
||||
"""
|
||||
msg = template % (sys.exc_info()[1], self.install_dir,)
|
||||
msg = self.__cant_write_msg % (sys.exc_info()[1], self.install_dir,)
|
||||
|
||||
if not os.path.exists(self.install_dir):
|
||||
msg += """
|
||||
This directory does not currently exist. Please create it and try again, or
|
||||
choose a different installation directory (using the -d or --install-dir
|
||||
option).
|
||||
"""
|
||||
msg += '\n' + self.__not_exists_id
|
||||
else:
|
||||
msg += """
|
||||
Perhaps your account does not have write access to this directory? If the
|
||||
installation directory is a system-owned directory, you may need to sign in
|
||||
as the administrator or "root" account. If you do not have administrative
|
||||
access to this machine, you may wish to choose a different installation
|
||||
directory, preferably one that is listed in your PYTHONPATH environment
|
||||
variable.
|
||||
|
||||
For information on other options, you may wish to consult the
|
||||
documentation at:
|
||||
|
||||
https://pythonhosted.org/setuptools/easy_install.html
|
||||
|
||||
Please make the appropriate changes for your system and try again.
|
||||
"""
|
||||
msg += '\n' + self.__access_msg
|
||||
raise DistutilsError(msg)
|
||||
|
||||
def check_pth_processing(self):
|
||||
|
|
@ -692,17 +717,10 @@ Please make the appropriate changes for your system and try again.
|
|||
distros = WorkingSet([]).resolve(
|
||||
[requirement], self.local_index, self.easy_install
|
||||
)
|
||||
except DistributionNotFound:
|
||||
e = sys.exc_info()[1]
|
||||
raise DistutilsError(
|
||||
"Could not find required distribution %s" % e.args
|
||||
)
|
||||
except VersionConflict:
|
||||
e = sys.exc_info()[1]
|
||||
raise DistutilsError(
|
||||
"Installed distribution %s conflicts with requirement %s"
|
||||
% e.args
|
||||
)
|
||||
except DistributionNotFound as e:
|
||||
raise DistutilsError(str(e))
|
||||
except VersionConflict as e:
|
||||
raise DistutilsError(e.report())
|
||||
if self.always_copy or self.always_copy_from:
|
||||
# Force all the relevant distros to be copied or activated
|
||||
for dist in distros:
|
||||
|
|
@ -743,7 +761,7 @@ Please make the appropriate changes for your system and try again.
|
|||
|
||||
def install_wrapper_scripts(self, dist):
|
||||
if not self.exclude_scripts:
|
||||
for args in get_script_args(dist):
|
||||
for args in ScriptWriter.best().get_args(dist):
|
||||
self.write_script(*args)
|
||||
|
||||
def install_script(self, dist, script_name, script_text, dev_path=None):
|
||||
|
|
@ -752,7 +770,7 @@ Please make the appropriate changes for your system and try again.
|
|||
is_script = is_python_script(script_text, script_name)
|
||||
|
||||
if is_script:
|
||||
script_text = (get_script_header(script_text) +
|
||||
script_text = (ScriptWriter.get_header(script_text) +
|
||||
self._load_template(dev_path) % locals())
|
||||
self.write_script(script_name, _to_ascii(script_text), 'b')
|
||||
|
||||
|
|
@ -916,9 +934,10 @@ Please make the appropriate changes for your system and try again.
|
|||
f.write('%s: %s\n' % (k.replace('_', '-').title(), v))
|
||||
f.close()
|
||||
script_dir = os.path.join(_egg_info, 'scripts')
|
||||
self.delete_blockers( # delete entry-point scripts to avoid duping
|
||||
# delete entry-point scripts to avoid duping
|
||||
self.delete_blockers(
|
||||
[os.path.join(script_dir, args[0]) for args in
|
||||
get_script_args(dist)]
|
||||
ScriptWriter.get_args(dist)]
|
||||
)
|
||||
# Build .egg file from tmpdir
|
||||
bdist_egg.make_zipfile(
|
||||
|
|
@ -980,46 +999,52 @@ Please make the appropriate changes for your system and try again.
|
|||
f.write('\n'.join(locals()[name]) + '\n')
|
||||
f.close()
|
||||
|
||||
__mv_warning = textwrap.dedent("""
|
||||
Because this distribution was installed --multi-version, before you can
|
||||
import modules from this package in an application, you will need to
|
||||
'import pkg_resources' and then use a 'require()' call similar to one of
|
||||
these examples, in order to select the desired version:
|
||||
|
||||
pkg_resources.require("%(name)s") # latest installed version
|
||||
pkg_resources.require("%(name)s==%(version)s") # this exact version
|
||||
pkg_resources.require("%(name)s>=%(version)s") # this version or higher
|
||||
""").lstrip()
|
||||
|
||||
__id_warning = textwrap.dedent("""
|
||||
Note also that the installation directory must be on sys.path at runtime for
|
||||
this to work. (e.g. by being the application's script directory, by being on
|
||||
PYTHONPATH, or by being added to sys.path by your code.)
|
||||
""")
|
||||
|
||||
def installation_report(self, req, dist, what="Installed"):
|
||||
"""Helpful installation message for display to package users"""
|
||||
msg = "\n%(what)s %(eggloc)s%(extras)s"
|
||||
if self.multi_version and not self.no_report:
|
||||
msg += """
|
||||
|
||||
Because this distribution was installed --multi-version, before you can
|
||||
import modules from this package in an application, you will need to
|
||||
'import pkg_resources' and then use a 'require()' call similar to one of
|
||||
these examples, in order to select the desired version:
|
||||
|
||||
pkg_resources.require("%(name)s") # latest installed version
|
||||
pkg_resources.require("%(name)s==%(version)s") # this exact version
|
||||
pkg_resources.require("%(name)s>=%(version)s") # this version or higher
|
||||
"""
|
||||
msg += '\n' + self.__mv_warning
|
||||
if self.install_dir not in map(normalize_path, sys.path):
|
||||
msg += """
|
||||
msg += '\n' + self.__id_warning
|
||||
|
||||
Note also that the installation directory must be on sys.path at runtime for
|
||||
this to work. (e.g. by being the application's script directory, by being on
|
||||
PYTHONPATH, or by being added to sys.path by your code.)
|
||||
"""
|
||||
eggloc = dist.location
|
||||
name = dist.project_name
|
||||
version = dist.version
|
||||
extras = '' # TODO: self.report_extras(req, dist)
|
||||
return msg % locals()
|
||||
|
||||
__editable_msg = textwrap.dedent("""
|
||||
Extracted editable version of %(spec)s to %(dirname)s
|
||||
|
||||
If it uses setuptools in its setup script, you can activate it in
|
||||
"development" mode by going to that directory and running::
|
||||
|
||||
%(python)s setup.py develop
|
||||
|
||||
See the setuptools documentation for the "develop" command for more info.
|
||||
""").lstrip()
|
||||
|
||||
def report_editable(self, spec, setup_script):
|
||||
dirname = os.path.dirname(setup_script)
|
||||
python = sys.executable
|
||||
return """\nExtracted editable version of %(spec)s to %(dirname)s
|
||||
|
||||
If it uses setuptools in its setup script, you can activate it in
|
||||
"development" mode by going to that directory and running::
|
||||
|
||||
%(python)s setup.py develop
|
||||
|
||||
See the setuptools documentation for the "develop" command for more info.
|
||||
""" % locals()
|
||||
return '\n' + self.__editable_msg % locals()
|
||||
|
||||
def run_setup(self, setup_script, setup_base, args):
|
||||
sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg)
|
||||
|
|
@ -1038,8 +1063,7 @@ See the setuptools documentation for the "develop" command for more info.
|
|||
)
|
||||
try:
|
||||
run_setup(setup_script, args)
|
||||
except SystemExit:
|
||||
v = sys.exc_info()[1]
|
||||
except SystemExit as v:
|
||||
raise DistutilsError("Setup script exited with %s" % (v.args[0],))
|
||||
|
||||
def build_and_install(self, setup_script, setup_base):
|
||||
|
|
@ -1152,7 +1176,7 @@ See the setuptools documentation for the "develop" command for more info.
|
|||
chmod(f, mode)
|
||||
|
||||
def byte_compile(self, to_compile):
|
||||
if _dont_write_bytecode:
|
||||
if sys.dont_write_bytecode:
|
||||
self.warn('byte-compiling is disabled, skipping.')
|
||||
return
|
||||
|
||||
|
|
@ -1171,35 +1195,38 @@ See the setuptools documentation for the "develop" command for more info.
|
|||
finally:
|
||||
log.set_verbosity(self.verbose) # restore original verbosity
|
||||
|
||||
__no_default_msg = textwrap.dedent("""
|
||||
bad install directory or PYTHONPATH
|
||||
|
||||
You are attempting to install a package to a directory that is not
|
||||
on PYTHONPATH and which Python does not read ".pth" files from. The
|
||||
installation directory you specified (via --install-dir, --prefix, or
|
||||
the distutils default setting) was:
|
||||
|
||||
%s
|
||||
|
||||
and your PYTHONPATH environment variable currently contains:
|
||||
|
||||
%r
|
||||
|
||||
Here are some of your options for correcting the problem:
|
||||
|
||||
* You can choose a different installation directory, i.e., one that is
|
||||
on PYTHONPATH or supports .pth files
|
||||
|
||||
* You can add the installation directory to the PYTHONPATH environment
|
||||
variable. (It must then also be on PYTHONPATH whenever you run
|
||||
Python and want to use the package(s) you are installing.)
|
||||
|
||||
* You can set up the installation directory to support ".pth" files by
|
||||
using one of the approaches described here:
|
||||
|
||||
https://pythonhosted.org/setuptools/easy_install.html#custom-installation-locations
|
||||
|
||||
Please make the appropriate changes for your system and try again.""").lstrip()
|
||||
|
||||
def no_default_version_msg(self):
|
||||
template = """bad install directory or PYTHONPATH
|
||||
|
||||
You are attempting to install a package to a directory that is not
|
||||
on PYTHONPATH and which Python does not read ".pth" files from. The
|
||||
installation directory you specified (via --install-dir, --prefix, or
|
||||
the distutils default setting) was:
|
||||
|
||||
%s
|
||||
|
||||
and your PYTHONPATH environment variable currently contains:
|
||||
|
||||
%r
|
||||
|
||||
Here are some of your options for correcting the problem:
|
||||
|
||||
* You can choose a different installation directory, i.e., one that is
|
||||
on PYTHONPATH or supports .pth files
|
||||
|
||||
* You can add the installation directory to the PYTHONPATH environment
|
||||
variable. (It must then also be on PYTHONPATH whenever you run
|
||||
Python and want to use the package(s) you are installing.)
|
||||
|
||||
* You can set up the installation directory to support ".pth" files by
|
||||
using one of the approaches described here:
|
||||
|
||||
https://pythonhosted.org/setuptools/easy_install.html#custom-installation-locations
|
||||
|
||||
Please make the appropriate changes for your system and try again."""
|
||||
template = self.__no_default_msg
|
||||
return template % (self.install_dir, os.environ.get('PYTHONPATH', ''))
|
||||
|
||||
def install_site_py(self):
|
||||
|
|
@ -1399,13 +1426,8 @@ def extract_wininst_cfg(dist_filename):
|
|||
{'version': '', 'target_version': ''})
|
||||
try:
|
||||
part = f.read(cfglen)
|
||||
# part is in bytes, but we need to read up to the first null
|
||||
# byte.
|
||||
if sys.version_info >= (2, 6):
|
||||
null_byte = bytes([0])
|
||||
else:
|
||||
null_byte = chr(0)
|
||||
config = part.split(null_byte, 1)[0]
|
||||
# Read up to the first null byte.
|
||||
config = part.split(b'\0', 1)[0]
|
||||
# Now the config is in bytes, but for RawConfigParser, it should
|
||||
# be text, so decode it.
|
||||
config = config.decode(sys.getfilesystemencoding())
|
||||
|
|
@ -1517,23 +1539,16 @@ class PthDistributions(Environment):
|
|||
if not self.dirty:
|
||||
return
|
||||
|
||||
data = '\n'.join(map(self.make_relative, self.paths))
|
||||
if data:
|
||||
rel_paths = list(map(self.make_relative, self.paths))
|
||||
if rel_paths:
|
||||
log.debug("Saving %s", self.filename)
|
||||
data = (
|
||||
"import sys; sys.__plen = len(sys.path)\n"
|
||||
"%s\n"
|
||||
"import sys; new=sys.path[sys.__plen:];"
|
||||
" del sys.path[sys.__plen:];"
|
||||
" p=getattr(sys,'__egginsert',0); sys.path[p:p]=new;"
|
||||
" sys.__egginsert = p+len(new)\n"
|
||||
) % data
|
||||
lines = self._wrap_lines(rel_paths)
|
||||
data = '\n'.join(lines) + '\n'
|
||||
|
||||
if os.path.islink(self.filename):
|
||||
os.unlink(self.filename)
|
||||
f = open(self.filename, 'wt')
|
||||
f.write(data)
|
||||
f.close()
|
||||
with open(self.filename, 'wt') as f:
|
||||
f.write(data)
|
||||
|
||||
elif os.path.exists(self.filename):
|
||||
log.debug("Deleting empty %s", self.filename)
|
||||
|
|
@ -1541,12 +1556,20 @@ class PthDistributions(Environment):
|
|||
|
||||
self.dirty = False
|
||||
|
||||
@staticmethod
|
||||
def _wrap_lines(lines):
|
||||
return lines
|
||||
|
||||
def add(self, dist):
|
||||
"""Add `dist` to the distribution map"""
|
||||
if (dist.location not in self.paths and (
|
||||
dist.location not in self.sitedirs or
|
||||
dist.location == os.getcwd() # account for '.' being in PYTHONPATH
|
||||
)):
|
||||
new_path = (
|
||||
dist.location not in self.paths and (
|
||||
dist.location not in self.sitedirs or
|
||||
# account for '.' being in PYTHONPATH
|
||||
dist.location == os.getcwd()
|
||||
)
|
||||
)
|
||||
if new_path:
|
||||
self.paths.append(dist.location)
|
||||
self.dirty = True
|
||||
Environment.add(self, dist)
|
||||
|
|
@ -1574,6 +1597,34 @@ class PthDistributions(Environment):
|
|||
return path
|
||||
|
||||
|
||||
class RewritePthDistributions(PthDistributions):
|
||||
|
||||
@classmethod
|
||||
def _wrap_lines(cls, lines):
|
||||
yield cls.prelude
|
||||
for line in lines:
|
||||
yield line
|
||||
yield cls.postlude
|
||||
|
||||
_inline = lambda text: textwrap.dedent(text).strip().replace('\n', '; ')
|
||||
prelude = _inline("""
|
||||
import sys
|
||||
sys.__plen = len(sys.path)
|
||||
""")
|
||||
postlude = _inline("""
|
||||
import sys
|
||||
new = sys.path[sys.__plen:]
|
||||
del sys.path[sys.__plen:]
|
||||
p = getattr(sys, '__egginsert', 0)
|
||||
sys.path[p:p] = new
|
||||
sys.__egginsert = p + len(new)
|
||||
""")
|
||||
|
||||
|
||||
if os.environ.get('SETUPTOOLS_SYS_PATH_TECHNIQUE', 'rewrite') == 'rewrite':
|
||||
PthDistributions = RewritePthDistributions
|
||||
|
||||
|
||||
def _first_line_re():
|
||||
"""
|
||||
Return a regular expression based on first_line_re suitable for matching
|
||||
|
|
@ -1586,33 +1637,6 @@ def _first_line_re():
|
|||
return re.compile(first_line_re.pattern.decode())
|
||||
|
||||
|
||||
def get_script_header(script_text, executable=sys_executable, wininst=False):
|
||||
"""Create a #! line, getting options (if any) from script_text"""
|
||||
first = (script_text + '\n').splitlines()[0]
|
||||
match = _first_line_re().match(first)
|
||||
options = ''
|
||||
if match:
|
||||
options = match.group(1) or ''
|
||||
if options:
|
||||
options = ' ' + options
|
||||
if wininst:
|
||||
executable = "python.exe"
|
||||
else:
|
||||
executable = nt_quote_arg(executable)
|
||||
hdr = "#!%(executable)s%(options)s\n" % locals()
|
||||
if not isascii(hdr):
|
||||
# Non-ascii path to sys.executable, use -x to prevent warnings
|
||||
if options:
|
||||
if options.strip().startswith('-'):
|
||||
options = ' -x' + options.strip()[1:]
|
||||
# else: punt, we can't do it, let the warning happen anyway
|
||||
else:
|
||||
options = ' -x'
|
||||
executable = fix_jython_executable(executable, options)
|
||||
hdr = "#!%(executable)s%(options)s\n" % locals()
|
||||
return hdr
|
||||
|
||||
|
||||
def auto_chmod(func, arg, exc):
|
||||
if func is os.remove and os.name == 'nt':
|
||||
chmod(arg, stat.S_IWRITE)
|
||||
|
|
@ -1811,9 +1835,8 @@ def is_python(text, filename='<string>'):
|
|||
def is_sh(executable):
|
||||
"""Determine if the specified executable is a .sh (contains a #! line)"""
|
||||
try:
|
||||
fp = open(executable)
|
||||
magic = fp.read(2)
|
||||
fp.close()
|
||||
with io.open(executable, encoding='latin-1') as fp:
|
||||
magic = fp.read(2)
|
||||
except (OSError, IOError):
|
||||
return executable
|
||||
return magic == '#!'
|
||||
|
|
@ -1821,36 +1844,7 @@ def is_sh(executable):
|
|||
|
||||
def nt_quote_arg(arg):
|
||||
"""Quote a command line argument according to Windows parsing rules"""
|
||||
|
||||
result = []
|
||||
needquote = False
|
||||
nb = 0
|
||||
|
||||
needquote = (" " in arg) or ("\t" in arg)
|
||||
if needquote:
|
||||
result.append('"')
|
||||
|
||||
for c in arg:
|
||||
if c == '\\':
|
||||
nb += 1
|
||||
elif c == '"':
|
||||
# double preceding backslashes, then add a \"
|
||||
result.append('\\' * (nb * 2) + '\\"')
|
||||
nb = 0
|
||||
else:
|
||||
if nb:
|
||||
result.append('\\' * nb)
|
||||
nb = 0
|
||||
result.append(c)
|
||||
|
||||
if nb:
|
||||
result.append('\\' * nb)
|
||||
|
||||
if needquote:
|
||||
result.append('\\' * nb) # double the trailing backslashes
|
||||
result.append('"')
|
||||
|
||||
return ''.join(result)
|
||||
return subprocess.list2cmdline([arg])
|
||||
|
||||
|
||||
def is_python_script(script_text, filename):
|
||||
|
|
@ -1879,31 +1873,130 @@ def chmod(path, mode):
|
|||
log.debug("changing mode of %s to %o", path, mode)
|
||||
try:
|
||||
_chmod(path, mode)
|
||||
except os.error:
|
||||
e = sys.exc_info()[1]
|
||||
except os.error as e:
|
||||
log.debug("chmod failed: %s", e)
|
||||
|
||||
|
||||
def fix_jython_executable(executable, options):
|
||||
if sys.platform.startswith('java') and is_sh(executable):
|
||||
# Workaround for Jython is not needed on Linux systems.
|
||||
import java
|
||||
warnings.warn("Use JythonCommandSpec", DeprecationWarning, stacklevel=2)
|
||||
|
||||
if java.lang.System.getProperty("os.name") == "Linux":
|
||||
return executable
|
||||
if not JythonCommandSpec.relevant():
|
||||
return executable
|
||||
|
||||
# Workaround Jython's sys.executable being a .sh (an invalid
|
||||
# shebang line interpreter)
|
||||
if options:
|
||||
cmd = CommandSpec.best().from_param(executable)
|
||||
cmd.install_options(options)
|
||||
return cmd.as_header().lstrip('#!').rstrip('\n')
|
||||
|
||||
|
||||
class CommandSpec(list):
|
||||
"""
|
||||
A command spec for a #! header, specified as a list of arguments akin to
|
||||
those passed to Popen.
|
||||
"""
|
||||
|
||||
options = []
|
||||
split_args = dict()
|
||||
|
||||
@classmethod
|
||||
def best(cls):
|
||||
"""
|
||||
Choose the best CommandSpec class based on environmental conditions.
|
||||
"""
|
||||
return cls if not JythonCommandSpec.relevant() else JythonCommandSpec
|
||||
|
||||
@classmethod
|
||||
def _sys_executable(cls):
|
||||
_default = os.path.normpath(sys.executable)
|
||||
return os.environ.get('__PYVENV_LAUNCHER__', _default)
|
||||
|
||||
@classmethod
|
||||
def from_param(cls, param):
|
||||
"""
|
||||
Construct a CommandSpec from a parameter to build_scripts, which may
|
||||
be None.
|
||||
"""
|
||||
if isinstance(param, cls):
|
||||
return param
|
||||
if isinstance(param, list):
|
||||
return cls(param)
|
||||
if param is None:
|
||||
return cls.from_environment()
|
||||
# otherwise, assume it's a string.
|
||||
return cls.from_string(param)
|
||||
|
||||
@classmethod
|
||||
def from_environment(cls):
|
||||
return cls([cls._sys_executable()])
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, string):
|
||||
"""
|
||||
Construct a command spec from a simple string representing a command
|
||||
line parseable by shlex.split.
|
||||
"""
|
||||
items = shlex.split(string, **cls.split_args)
|
||||
return cls(items)
|
||||
|
||||
def install_options(self, script_text):
|
||||
self.options = shlex.split(self._extract_options(script_text))
|
||||
cmdline = subprocess.list2cmdline(self)
|
||||
if not isascii(cmdline):
|
||||
self.options[:0] = ['-x']
|
||||
|
||||
@staticmethod
|
||||
def _extract_options(orig_script):
|
||||
"""
|
||||
Extract any options from the first line of the script.
|
||||
"""
|
||||
first = (orig_script + '\n').splitlines()[0]
|
||||
match = _first_line_re().match(first)
|
||||
options = match.group(1) or '' if match else ''
|
||||
return options.strip()
|
||||
|
||||
def as_header(self):
|
||||
return self._render(self + list(self.options))
|
||||
|
||||
@staticmethod
|
||||
def _render(items):
|
||||
cmdline = subprocess.list2cmdline(items)
|
||||
return '#!' + cmdline + '\n'
|
||||
|
||||
# For pbr compat; will be removed in a future version.
|
||||
sys_executable = CommandSpec._sys_executable()
|
||||
|
||||
|
||||
class WindowsCommandSpec(CommandSpec):
|
||||
split_args = dict(posix=False)
|
||||
|
||||
|
||||
class JythonCommandSpec(CommandSpec):
|
||||
@classmethod
|
||||
def relevant(cls):
|
||||
return (
|
||||
sys.platform.startswith('java')
|
||||
and
|
||||
__import__('java').lang.System.getProperty('os.name') != 'Linux'
|
||||
)
|
||||
|
||||
def as_header(self):
|
||||
"""
|
||||
Workaround Jython's sys.executable being a .sh (an invalid
|
||||
shebang line interpreter)
|
||||
"""
|
||||
if not is_sh(self[0]):
|
||||
return super(JythonCommandSpec, self).as_header()
|
||||
|
||||
if self.options:
|
||||
# Can't apply the workaround, leave it broken
|
||||
log.warn(
|
||||
"WARNING: Unable to adapt shebang line for Jython,"
|
||||
" the following script is NOT executable\n"
|
||||
" see http://bugs.jython.org/issue1112 for"
|
||||
" more information.")
|
||||
else:
|
||||
return '/usr/bin/env %s' % executable
|
||||
return executable
|
||||
return super(JythonCommandSpec, self).as_header()
|
||||
|
||||
items = ['/usr/bin/env'] + self + list(self.options)
|
||||
return self._render(items)
|
||||
|
||||
|
||||
class ScriptWriter(object):
|
||||
|
|
@ -1924,39 +2017,92 @@ class ScriptWriter(object):
|
|||
)
|
||||
""").lstrip()
|
||||
|
||||
command_spec_class = CommandSpec
|
||||
|
||||
@classmethod
|
||||
def get_script_args(cls, dist, executable=sys_executable, wininst=False):
|
||||
def get_script_args(cls, dist, executable=None, wininst=False):
|
||||
# for backward compatibility
|
||||
warnings.warn("Use get_args", DeprecationWarning)
|
||||
writer = (WindowsScriptWriter if wininst else ScriptWriter).best()
|
||||
header = cls.get_script_header("", executable, wininst)
|
||||
return writer.get_args(dist, header)
|
||||
|
||||
@classmethod
|
||||
def get_script_header(cls, script_text, executable=None, wininst=False):
|
||||
# for backward compatibility
|
||||
warnings.warn("Use get_header", DeprecationWarning)
|
||||
if wininst:
|
||||
executable = "python.exe"
|
||||
cmd = cls.command_spec_class.best().from_param(executable)
|
||||
cmd.install_options(script_text)
|
||||
return cmd.as_header()
|
||||
|
||||
@classmethod
|
||||
def get_args(cls, dist, header=None):
|
||||
"""
|
||||
Yield write_script() argument tuples for a distribution's entrypoints
|
||||
Yield write_script() argument tuples for a distribution's
|
||||
console_scripts and gui_scripts entry points.
|
||||
"""
|
||||
gen_class = cls.get_writer(wininst)
|
||||
if header is None:
|
||||
header = cls.get_header()
|
||||
spec = str(dist.as_requirement())
|
||||
header = get_script_header("", executable, wininst)
|
||||
for type_ in 'console', 'gui':
|
||||
group = type_ + '_scripts'
|
||||
for name, ep in dist.get_entry_map(group).items():
|
||||
script_text = gen_class.template % locals()
|
||||
for res in gen_class._get_script_args(type_, name, header,
|
||||
script_text):
|
||||
cls._ensure_safe_name(name)
|
||||
script_text = cls.template % locals()
|
||||
args = cls._get_script_args(type_, name, header, script_text)
|
||||
for res in args:
|
||||
yield res
|
||||
|
||||
@staticmethod
|
||||
def _ensure_safe_name(name):
|
||||
"""
|
||||
Prevent paths in *_scripts entry point names.
|
||||
"""
|
||||
has_path_sep = re.search(r'[\\/]', name)
|
||||
if has_path_sep:
|
||||
raise ValueError("Path separators not allowed in script names")
|
||||
|
||||
@classmethod
|
||||
def get_writer(cls, force_windows):
|
||||
if force_windows or sys.platform == 'win32':
|
||||
return WindowsScriptWriter.get_writer()
|
||||
return cls
|
||||
# for backward compatibility
|
||||
warnings.warn("Use best", DeprecationWarning)
|
||||
return WindowsScriptWriter.best() if force_windows else cls.best()
|
||||
|
||||
@classmethod
|
||||
def best(cls):
|
||||
"""
|
||||
Select the best ScriptWriter for this environment.
|
||||
"""
|
||||
return WindowsScriptWriter.best() if sys.platform == 'win32' else cls
|
||||
|
||||
@classmethod
|
||||
def _get_script_args(cls, type_, name, header, script_text):
|
||||
# Simply write the stub with no extension.
|
||||
yield (name, header + script_text)
|
||||
|
||||
@classmethod
|
||||
def get_header(cls, script_text="", executable=None):
|
||||
"""Create a #! line, getting options (if any) from script_text"""
|
||||
cmd = cls.command_spec_class.best().from_param(executable)
|
||||
cmd.install_options(script_text)
|
||||
return cmd.as_header()
|
||||
|
||||
|
||||
class WindowsScriptWriter(ScriptWriter):
|
||||
command_spec_class = WindowsCommandSpec
|
||||
|
||||
@classmethod
|
||||
def get_writer(cls):
|
||||
# for backward compatibility
|
||||
warnings.warn("Use best", DeprecationWarning)
|
||||
return cls.best()
|
||||
|
||||
@classmethod
|
||||
def best(cls):
|
||||
"""
|
||||
Get a script writer suitable for Windows
|
||||
Select the best ScriptWriter suitable for Windows
|
||||
"""
|
||||
writer_lookup = dict(
|
||||
executable=WindowsExecutableLauncherWriter,
|
||||
|
|
@ -2031,6 +2177,7 @@ class WindowsExecutableLauncherWriter(WindowsScriptWriter):
|
|||
|
||||
# for backward-compatibility
|
||||
get_script_args = ScriptWriter.get_script_args
|
||||
get_script_header = ScriptWriter.get_script_header
|
||||
|
||||
|
||||
def get_win_launcher(type):
|
||||
|
|
@ -2114,39 +2261,41 @@ def bootstrap():
|
|||
def main(argv=None, **kw):
|
||||
from setuptools import setup
|
||||
from setuptools.dist import Distribution
|
||||
import distutils.core
|
||||
|
||||
USAGE = """\
|
||||
usage: %(script)s [options] requirement_or_url ...
|
||||
or: %(script)s --help
|
||||
"""
|
||||
class DistributionWithoutHelpCommands(Distribution):
|
||||
common_usage = ""
|
||||
|
||||
def _show_help(self, *args, **kw):
|
||||
with _patch_usage():
|
||||
Distribution._show_help(self, *args, **kw)
|
||||
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
with _patch_usage():
|
||||
setup(
|
||||
script_args=['-q', 'easy_install', '-v'] + argv,
|
||||
script_name=sys.argv[0] or 'easy_install',
|
||||
distclass=DistributionWithoutHelpCommands, **kw
|
||||
)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _patch_usage():
|
||||
import distutils.core
|
||||
USAGE = textwrap.dedent("""
|
||||
usage: %(script)s [options] requirement_or_url ...
|
||||
or: %(script)s --help
|
||||
""").lstrip()
|
||||
|
||||
def gen_usage(script_name):
|
||||
return USAGE % dict(
|
||||
script=os.path.basename(script_name),
|
||||
)
|
||||
|
||||
def with_ei_usage(f):
|
||||
old_gen_usage = distutils.core.gen_usage
|
||||
try:
|
||||
distutils.core.gen_usage = gen_usage
|
||||
return f()
|
||||
finally:
|
||||
distutils.core.gen_usage = old_gen_usage
|
||||
|
||||
class DistributionWithoutHelpCommands(Distribution):
|
||||
common_usage = ""
|
||||
|
||||
def _show_help(self, *args, **kw):
|
||||
with_ei_usage(lambda: Distribution._show_help(self, *args, **kw))
|
||||
|
||||
if argv is None:
|
||||
argv = sys.argv[1:]
|
||||
|
||||
with_ei_usage(
|
||||
lambda: setup(
|
||||
script_args=['-q', 'easy_install', '-v'] + argv,
|
||||
script_name=sys.argv[0] or 'easy_install',
|
||||
distclass=DistributionWithoutHelpCommands, **kw
|
||||
)
|
||||
)
|
||||
saved = distutils.core.gen_usage
|
||||
distutils.core.gen_usage = gen_usage
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
distutils.core.gen_usage = saved
|
||||
|
|
|
|||
|
|
@ -6,20 +6,26 @@ from distutils.filelist import FileList as _FileList
|
|||
from distutils.util import convert_path
|
||||
from distutils import log
|
||||
import distutils.errors
|
||||
import distutils.filelist
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
try:
|
||||
from setuptools_svn import svn_utils
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
from setuptools import Command
|
||||
from setuptools.command.sdist import sdist
|
||||
from setuptools.compat import basestring, PY3, StringIO
|
||||
from setuptools import svn_utils
|
||||
from setuptools.command.sdist import walk_revctrl
|
||||
from pkg_resources import (
|
||||
parse_requirements, safe_name, parse_version,
|
||||
safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename)
|
||||
import setuptools.unicode_utils as unicode_utils
|
||||
|
||||
from pkg_resources import packaging
|
||||
|
||||
class egg_info(Command):
|
||||
description = "create a distribution's .egg-info directory"
|
||||
|
|
@ -68,10 +74,15 @@ class egg_info(Command):
|
|||
self.vtags = self.tags()
|
||||
self.egg_version = self.tagged_version()
|
||||
|
||||
parsed_version = parse_version(self.egg_version)
|
||||
|
||||
try:
|
||||
is_version = isinstance(parsed_version, packaging.version.Version)
|
||||
spec = (
|
||||
"%s==%s" if is_version else "%s===%s"
|
||||
)
|
||||
list(
|
||||
parse_requirements('%s==%s' % (self.egg_name,
|
||||
self.egg_version))
|
||||
parse_requirements(spec % (self.egg_name, self.egg_version))
|
||||
)
|
||||
except ValueError:
|
||||
raise distutils.errors.DistutilsOptionError(
|
||||
|
|
@ -157,7 +168,8 @@ class egg_info(Command):
|
|||
self.mkpath(self.egg_info)
|
||||
installer = self.distribution.fetch_build_egg
|
||||
for ep in iter_entry_points('egg_info.writers'):
|
||||
writer = ep.load(installer=installer)
|
||||
ep.require(installer=installer)
|
||||
writer = ep.resolve()
|
||||
writer(self, ep.name, os.path.join(self.egg_info, ep.name))
|
||||
|
||||
# Get rid of native_libs.txt if it was put there by older bdist_egg
|
||||
|
|
@ -183,6 +195,8 @@ class egg_info(Command):
|
|||
|
||||
@staticmethod
|
||||
def get_svn_revision():
|
||||
if 'svn_utils' not in globals():
|
||||
return "0"
|
||||
return str(svn_utils.SvnInfo.load(os.curdir).get_revision())
|
||||
|
||||
def find_sources(self):
|
||||
|
|
@ -312,8 +326,33 @@ class manifest_maker(sdist):
|
|||
elif os.path.exists(self.manifest):
|
||||
self.read_manifest()
|
||||
ei_cmd = self.get_finalized_command('egg_info')
|
||||
self._add_egg_info(cmd=ei_cmd)
|
||||
self.filelist.include_pattern("*", prefix=ei_cmd.egg_info)
|
||||
|
||||
def _add_egg_info(self, cmd):
|
||||
"""
|
||||
Add paths for egg-info files for an external egg-base.
|
||||
|
||||
The egg-info files are written to egg-base. If egg-base is
|
||||
outside the current working directory, this method
|
||||
searchs the egg-base directory for files to include
|
||||
in the manifest. Uses distutils.filelist.findall (which is
|
||||
really the version monkeypatched in by setuptools/__init__.py)
|
||||
to perform the search.
|
||||
|
||||
Since findall records relative paths, prefix the returned
|
||||
paths with cmd.egg_base, so add_default's include_pattern call
|
||||
(which is looking for the absolute cmd.egg_info) will match
|
||||
them.
|
||||
"""
|
||||
if cmd.egg_base == os.curdir:
|
||||
# egg-info files were already added by something else
|
||||
return
|
||||
|
||||
discovered = distutils.filelist.findall(cmd.egg_base)
|
||||
resolved = (os.path.join(cmd.egg_base, path) for path in discovered)
|
||||
self.filelist.allfiles.extend(resolved)
|
||||
|
||||
def prune_file_list(self):
|
||||
build = self.get_finalized_command('build')
|
||||
base_dir = self.distribution.get_fullname()
|
||||
|
|
@ -382,6 +421,12 @@ def write_requirements(cmd, basename, filename):
|
|||
cmd.write_or_delete_file("requirements", filename, data.getvalue())
|
||||
|
||||
|
||||
def write_setup_requirements(cmd, basename, filename):
|
||||
data = StringIO()
|
||||
_write_requirements(data, cmd.distribution.setup_requires)
|
||||
cmd.write_or_delete_file("setup-requirements", filename, data.getvalue())
|
||||
|
||||
|
||||
def write_toplevel_names(cmd, basename, filename):
|
||||
pkgs = dict.fromkeys(
|
||||
[
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ class install_scripts(orig.install_scripts):
|
|||
self.no_ep = False
|
||||
|
||||
def run(self):
|
||||
from setuptools.command.easy_install import get_script_args
|
||||
from setuptools.command.easy_install import sys_executable
|
||||
import setuptools.command.easy_install as ei
|
||||
|
||||
self.run_command("egg_info")
|
||||
if self.distribution.scripts:
|
||||
|
|
@ -31,11 +30,17 @@ class install_scripts(orig.install_scripts):
|
|||
ei_cmd.egg_name, ei_cmd.egg_version,
|
||||
)
|
||||
bs_cmd = self.get_finalized_command('build_scripts')
|
||||
executable = getattr(bs_cmd, 'executable', sys_executable)
|
||||
is_wininst = getattr(
|
||||
self.get_finalized_command("bdist_wininst"), '_is_running', False
|
||||
)
|
||||
for args in get_script_args(dist, executable, is_wininst):
|
||||
exec_param = getattr(bs_cmd, 'executable', None)
|
||||
bw_cmd = self.get_finalized_command("bdist_wininst")
|
||||
is_wininst = getattr(bw_cmd, '_is_running', False)
|
||||
writer = ei.ScriptWriter
|
||||
if is_wininst:
|
||||
exec_param = "python.exe"
|
||||
writer = ei.WindowsScriptWriter
|
||||
# resolve the writer to the environment
|
||||
writer = writer.best()
|
||||
cmd = writer.command_spec_class.best().from_param(exec_param)
|
||||
for args in writer.get_args(dist, cmd.as_header()):
|
||||
self.write_script(*args)
|
||||
|
||||
def write_script(self, script_name, contents, mode="t", *ignored):
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
from glob import glob
|
||||
from distutils.util import convert_path
|
||||
from distutils import log
|
||||
import distutils.command.sdist as orig
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from setuptools import svn_utils
|
||||
from setuptools.compat import PY3
|
||||
from setuptools.utils import cs_path_exists
|
||||
|
||||
import pkg_resources
|
||||
|
||||
READMES = ('README', 'README.rst', 'README.txt')
|
||||
READMES = 'README', 'README.rst', 'README.txt'
|
||||
|
||||
_default_revctrl = list
|
||||
|
||||
def walk_revctrl(dirname=''):
|
||||
"""Find all files under revision control"""
|
||||
|
|
@ -22,60 +20,6 @@ def walk_revctrl(dirname=''):
|
|||
yield item
|
||||
|
||||
|
||||
# TODO will need test case
|
||||
class re_finder(object):
|
||||
"""
|
||||
Finder that locates files based on entries in a file matched by a
|
||||
regular expression.
|
||||
"""
|
||||
|
||||
def __init__(self, path, pattern, postproc=lambda x: x):
|
||||
self.pattern = pattern
|
||||
self.postproc = postproc
|
||||
self.entries_path = convert_path(path)
|
||||
|
||||
def _finder(self, dirname, filename):
|
||||
f = open(filename, 'rU')
|
||||
try:
|
||||
data = f.read()
|
||||
finally:
|
||||
f.close()
|
||||
for match in self.pattern.finditer(data):
|
||||
path = match.group(1)
|
||||
# postproc was formerly used when the svn finder
|
||||
# was an re_finder for calling unescape
|
||||
path = self.postproc(path)
|
||||
yield svn_utils.joinpath(dirname, path)
|
||||
|
||||
def find(self, dirname=''):
|
||||
path = svn_utils.joinpath(dirname, self.entries_path)
|
||||
|
||||
if not os.path.isfile(path):
|
||||
# entries file doesn't exist
|
||||
return
|
||||
for path in self._finder(dirname, path):
|
||||
if os.path.isfile(path):
|
||||
yield path
|
||||
elif os.path.isdir(path):
|
||||
for item in self.find(path):
|
||||
yield item
|
||||
|
||||
__call__ = find
|
||||
|
||||
|
||||
def _default_revctrl(dirname=''):
|
||||
'Primary svn_cvs entry point'
|
||||
for finder in finders:
|
||||
for item in finder(dirname):
|
||||
yield item
|
||||
|
||||
|
||||
finders = [
|
||||
re_finder('CVS/Entries', re.compile(r"^\w?/([^/]+)/", re.M)),
|
||||
svn_utils.svn_finder,
|
||||
]
|
||||
|
||||
|
||||
class sdist(orig.sdist):
|
||||
"""Smart sdist that finds anything supported by revision control"""
|
||||
|
||||
|
|
@ -126,7 +70,8 @@ class sdist(orig.sdist):
|
|||
try:
|
||||
orig.sdist.read_template(self)
|
||||
except:
|
||||
sys.exc_info()[2].tb_next.tb_frame.f_locals['template'].close()
|
||||
_, _, tb = sys.exc_info()
|
||||
tb.tb_next.tb_frame.f_locals['template'].close()
|
||||
raise
|
||||
|
||||
# Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from distutils.errors import DistutilsOptionError
|
||||
from unittest import TestLoader
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
from pkg_resources import (resource_listdir, resource_exists, normalize_path,
|
||||
|
|
@ -12,7 +11,7 @@ from setuptools.py31compat import unittest_main
|
|||
|
||||
|
||||
class ScanningLoader(TestLoader):
|
||||
def loadTestsFromModule(self, module):
|
||||
def loadTestsFromModule(self, module, pattern=None):
|
||||
"""Return a suite of all tests cases contained in the given module
|
||||
|
||||
If the module is a package, load tests from all the modules in it.
|
||||
|
|
@ -62,20 +61,16 @@ class test(Command):
|
|||
|
||||
def finalize_options(self):
|
||||
|
||||
if self.test_suite and self.test_module:
|
||||
msg = "You may specify a module or a suite, but not both"
|
||||
raise DistutilsOptionError(msg)
|
||||
|
||||
if self.test_suite is None:
|
||||
if self.test_module is None:
|
||||
self.test_suite = self.distribution.test_suite
|
||||
else:
|
||||
self.test_suite = self.test_module + ".test_suite"
|
||||
elif self.test_module:
|
||||
raise DistutilsOptionError(
|
||||
"You may specify a module or a suite, but not both"
|
||||
)
|
||||
|
||||
self.test_args = [self.test_suite]
|
||||
|
||||
if self.verbose:
|
||||
self.test_args.insert(0, '--verbose')
|
||||
if self.test_loader is None:
|
||||
self.test_loader = getattr(self.distribution, 'test_loader', None)
|
||||
if self.test_loader is None:
|
||||
|
|
@ -83,6 +78,16 @@ class test(Command):
|
|||
if self.test_runner is None:
|
||||
self.test_runner = getattr(self.distribution, 'test_runner', None)
|
||||
|
||||
@property
|
||||
def test_args(self):
|
||||
return list(self._test_args())
|
||||
|
||||
def _test_args(self):
|
||||
if self.verbose:
|
||||
yield '--verbose'
|
||||
if self.test_suite:
|
||||
yield self.test_suite
|
||||
|
||||
def with_project_on_sys_path(self, func):
|
||||
with_2to3 = PY3 and getattr(self.distribution, 'use_2to3', False)
|
||||
|
||||
|
|
@ -133,20 +138,19 @@ class test(Command):
|
|||
if self.distribution.tests_require:
|
||||
self.distribution.fetch_build_eggs(self.distribution.tests_require)
|
||||
|
||||
if self.test_suite:
|
||||
cmd = ' '.join(self.test_args)
|
||||
if self.dry_run:
|
||||
self.announce('skipping "unittest %s" (dry run)' % cmd)
|
||||
else:
|
||||
self.announce('running "unittest %s"' % cmd)
|
||||
self.with_project_on_sys_path(self.run_tests)
|
||||
cmd = ' '.join(self._argv)
|
||||
if self.dry_run:
|
||||
self.announce('skipping "%s" (dry run)' % cmd)
|
||||
else:
|
||||
self.announce('running "%s"' % cmd)
|
||||
self.with_project_on_sys_path(self.run_tests)
|
||||
|
||||
def run_tests(self):
|
||||
# Purge modules under test from sys.modules. The test loader will
|
||||
# re-import them from the build location. Required when 2to3 is used
|
||||
# with namespace packages.
|
||||
if PY3 and getattr(self.distribution, 'use_2to3', False):
|
||||
module = self.test_args[-1].split('.')[0]
|
||||
module = self.test_suite.split('.')[0]
|
||||
if module in _namespace_packages:
|
||||
del_modules = []
|
||||
if module in sys.modules:
|
||||
|
|
@ -158,11 +162,15 @@ class test(Command):
|
|||
list(map(sys.modules.__delitem__, del_modules))
|
||||
|
||||
unittest_main(
|
||||
None, None, [unittest.__file__] + self.test_args,
|
||||
None, None, self._argv,
|
||||
testLoader=self._resolve_as_ep(self.test_loader),
|
||||
testRunner=self._resolve_as_ep(self.test_runner),
|
||||
)
|
||||
|
||||
@property
|
||||
def _argv(self):
|
||||
return ['unittest'] + self.test_args
|
||||
|
||||
@staticmethod
|
||||
def _resolve_as_ep(val):
|
||||
"""
|
||||
|
|
@ -172,4 +180,4 @@ class test(Command):
|
|||
if val is None:
|
||||
return
|
||||
parsed = EntryPoint.parse("x=" + val)
|
||||
return parsed.load(require=False)()
|
||||
return parsed.resolve()()
|
||||
|
|
|
|||
|
|
@ -169,8 +169,7 @@ class upload_docs(upload):
|
|||
conn.putheader('Authorization', auth)
|
||||
conn.endheaders()
|
||||
conn.send(body)
|
||||
except socket.error:
|
||||
e = sys.exc_info()[1]
|
||||
except socket.error as e:
|
||||
self.announce(str(e), log.ERROR)
|
||||
return
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue