Commit 69175b94 authored by Steve Kowalik's avatar Steve Kowalik

Merge from master, resolving conflicts.

parents 43d0308a 8ccd428c
......@@ -234,3 +234,15 @@ cc41477ecf92f221c113736fac2830bf8079d40c 19.0
0a2a3d89416e1642cf6f41d22dbc07b3d3c15a4d 19.1.1
5d24cf9d1ced76c406ab3c4a94c25d1fe79b94bc 19.2
66fa131a0d77a1b0e6f89ccb76b254cfb07d3da3 19.3b1
32bba9bf8cce8350b560a7591c9ef5884a194211 19.3
f47f3671508b015e9bb735603d3a0a6ec6a77b01 19.4
0bda3291ac725750b899b4ba3e4b6765e7645daa 19.4.1
0a68cbab72580a6f8d3bf9c45206669eefcd256b 19.5
34121bf49b1a7ac77da7f7c75105c8a920218dd7 19.6b1
3c2332e4ec72717bf17321473e5c3ad6e5778903 19.6
35d9179d04390aada66eceae9ceb7b9274f67646 19.6.1
d2782cbb2f15ca6831ab9426fbf8d4d6ca60db8a 19.6.2
c6e619ce910d1650cc2433f94e5594964085f973 19.7
2a60daeff0cdb039b20b2058aaad7dae7bcd2c1c 20.0
06c9d3ffae80d7f5786c0a454d040d253d47fc03 20.1
919a40f1843131249f98104c73f3aee3fc835e67 20.1.1
......@@ -6,6 +6,10 @@ python:
- 3.4
- 3.5
- pypy
- pypy3
matrix:
allow_failures:
- python: pypy3
env:
- ""
- LC_ALL=C LC_CTYPE=C
......
This diff is collapsed.
......@@ -2328,54 +2328,25 @@ available:
``upload`` - Upload source and/or egg distributions to PyPI
===========================================================
PyPI now supports uploading project files for redistribution; uploaded files
are easily found by EasyInstall, even if you don't have download links on your
project's home page.
The ``upload`` command is implemented and `documented
<https://docs.python.org/3.1/distutils/uploading.html>`_
in distutils.
Although Python 2.5 will support uploading all types of distributions to PyPI,
setuptools only supports source distributions and eggs. (This is partly
because PyPI's upload support is currently broken for various other file
types.) To upload files, you must include the ``upload`` command *after* the
``sdist`` or ``bdist_egg`` commands on the setup command line. For example::
Setuptools augments the ``upload`` command with support
for `keyring <https://pypi.python.org/pypi/keyring>`_,
allowing the password to be stored in a secure
location and not in plaintext in the .pypirc file. To use
keyring, first install keyring and set the password for
the relevant repository, e.g.::
setup.py bdist_egg upload # create an egg and upload it
setup.py sdist upload # create a source distro and upload it
setup.py sdist bdist_egg upload # create and upload both
python -m keyring set <repository> <username>
Password for '<username>' in '<repository>': ********
Note that to upload files for a project, the corresponding version must already
be registered with PyPI, using the distutils ``register`` command. It's
usually a good idea to include the ``register`` command at the start of the
command line, so that any registration problems can be found and fixed before
building and uploading the distributions, e.g.::
Then, in .pypirc, set the repository configuration as normal,
but omit the password. Thereafter, uploads will use the
password from the keyring.
setup.py register sdist bdist_egg upload
This will update PyPI's listing for your project's current version.
Note, by the way, that the metadata in your ``setup()`` call determines what
will be listed in PyPI for your package. Try to fill out as much of it as
possible, as it will save you a lot of trouble manually adding and updating
your PyPI listings. Just put it in ``setup.py`` and use the ``register``
command to keep PyPI up to date.
The ``upload`` command has a few options worth noting:
``--sign, -s``
Sign each uploaded file using GPG (GNU Privacy Guard). The ``gpg`` program
must be available for execution on the system ``PATH``.
``--identity=NAME, -i NAME``
Specify the identity or key name for GPG to use when signing. The value of
this option will be passed through the ``--local-user`` option of the
``gpg`` program.
``--show-response``
Display the full response text from server; this is useful for debugging
PyPI problems.
``--repository=URL, -r URL``
The URL of the repository to upload to. Defaults to
https://pypi.python.org/pypi (i.e., the main PyPI installation).
New in 20.1: Added keyring support.
.. _upload_docs:
......
......@@ -46,7 +46,7 @@ except ImportError:
import imp as _imp
from pkg_resources.extern import six
from pkg_resources.extern.six.moves import urllib
from pkg_resources.extern.six.moves import urllib, map, filter
# capture these to bypass sandboxing
from os import utime
......@@ -60,10 +60,11 @@ except ImportError:
from os import open as os_open
from os.path import isdir, split
# Avoid try/except due to potential problems with delayed import mechanisms.
if sys.version_info >= (3, 3) and sys.implementation.name == "cpython":
try:
import importlib.machinery as importlib_machinery
else:
# access attribute to force import under delayed import mechanisms.
importlib_machinery.__name__
except ImportError:
importlib_machinery = None
try:
......@@ -78,9 +79,6 @@ __import__('pkg_resources._vendor.packaging.requirements')
__import__('pkg_resources._vendor.packaging.markers')
filter = six.moves.filter
map = six.moves.map
if (3, 0) < sys.version_info < (3, 3):
msg = (
"Support for Python 3.0-3.2 has been dropped. Future versions "
......@@ -757,7 +755,7 @@ class WorkingSet(object):
will be called.
"""
if insert:
dist.insert_on(self.entries, entry)
dist.insert_on(self.entries, entry, replace=replace)
if entry is None:
entry = dist.location
......@@ -1178,22 +1176,23 @@ class ResourceManager:
old_exc = sys.exc_info()[1]
cache_path = self.extraction_path or get_default_cache()
err = ExtractionError("""Can't extract file(s) to egg cache
tmpl = textwrap.dedent("""
Can't extract file(s) to egg cache
The following error occurred while trying to extract file(s) to the Python egg
cache:
The following error occurred while trying to extract file(s) to the Python egg
cache:
%s
{old_exc}
The Python egg cache directory is currently set to:
The Python egg cache directory is currently set to:
%s
{cache_path}
Perhaps your account does not have write access to this directory? You can
change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory.
""" % (old_exc, cache_path)
)
Perhaps your account does not have write access to this directory? You can
change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory.
""").lstrip()
err = ExtractionError(tmpl.format(**locals()))
err.manager = self
err.cache_path = cache_path
err.original_error = old_exc
......@@ -1561,10 +1560,13 @@ class DefaultProvider(EggProvider):
with open(path, 'rb') as stream:
return stream.read()
register_loader_type(type(None), DefaultProvider)
@classmethod
def _register(cls):
loader_cls = getattr(importlib_machinery, 'SourceFileLoader',
type(None))
register_loader_type(loader_cls, cls)
if importlib_machinery is not None:
register_loader_type(importlib_machinery.SourceFileLoader, DefaultProvider)
DefaultProvider._register()
class EmptyProvider(NullProvider):
......@@ -1970,7 +1972,7 @@ def find_on_path(importer, path_item, only=False):
break
register_finder(pkgutil.ImpImporter, find_on_path)
if importlib_machinery is not None:
if hasattr(importlib_machinery, 'FileFinder'):
register_finder(importlib_machinery.FileFinder, find_on_path)
_declare_state('dict', _namespace_handlers={})
......@@ -2016,11 +2018,28 @@ def _handle_ns(packageName, path_item):
path = module.__path__
path.append(subpath)
loader.load_module(packageName)
for path_item in path:
if path_item not in module.__path__:
module.__path__.append(path_item)
_rebuild_mod_path(path, packageName, module)
return subpath
def _rebuild_mod_path(orig_path, package_name, module):
"""
Rebuild module.__path__ ensuring that all entries are ordered
corresponding to their sys.path order
"""
sys_path = [_normalize_cached(p) for p in sys.path]
def position_in_sys_path(p):
"""
Return the ordinal of the path based on its position in sys.path
"""
parts = p.split(os.sep)
parts = parts[:-(package_name.count('.') + 1)]
return sys_path.index(_normalize_cached(os.sep.join(parts)))
orig_path.sort(key=position_in_sys_path)
module.__path__[:] = [_normalize_cached(p) for p in orig_path]
def declare_namespace(packageName):
"""Declare that package 'packageName' is a namespace package"""
......@@ -2079,7 +2098,7 @@ def file_ns_handler(importer, path_item, packageName, module):
register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
register_namespace_handler(zipimport.zipimporter, file_ns_handler)
if importlib_machinery is not None:
if hasattr(importlib_machinery, 'FileFinder'):
register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler)
......@@ -2461,7 +2480,7 @@ class Distribution(object):
"""Ensure distribution is importable on `path` (default=sys.path)"""
if path is None:
path = sys.path
self.insert_on(path)
self.insert_on(path, replace=True)
if path is sys.path:
fixup_namespace_packages(self.location)
for pkg in self._get_metadata('namespace_packages.txt'):
......@@ -2538,7 +2557,7 @@ class Distribution(object):
"""Return the EntryPoint object for `group`+`name`, or ``None``"""
return self.get_entry_map(group).get(name)
def insert_on(self, path, loc = None):
def insert_on(self, path, loc=None, replace=False):
"""Insert self.location in path before its nearest parent directory"""
loc = loc or self.location
......@@ -2562,7 +2581,10 @@ class Distribution(object):
else:
if path is sys.path:
self.check_version_conflict()
path.append(loc)
if replace:
path.insert(0, loc)
else:
path.append(loc)
return
# p is the spot where we found or inserted loc; now remove duplicates
......
......@@ -12,6 +12,8 @@ import stat
import distutils.dist
import distutils.command.install_egg_info
from pkg_resources.extern.six.moves import map
import pytest
import pkg_resources
......
from __future__ import unicode_literals
import os
import sys
import tempfile
import shutil
import string
from pkg_resources.extern.six.moves import map
import pytest
from pkg_resources.extern import packaging
......@@ -158,7 +160,7 @@ class TestDistro:
for i in range(3):
targets = list(ws.resolve(parse_requirements("Foo"), ad))
assert targets == [Foo]
list(map(ws.add,targets))
list(map(ws.add, targets))
with pytest.raises(VersionConflict):
ws.resolve(parse_requirements("Foo==0.9"), ad)
ws = WorkingSet([]) # reset
......@@ -608,21 +610,44 @@ class TestParsing:
class TestNamespaces:
def setup_method(self, method):
self._ns_pkgs = pkg_resources._namespace_packages.copy()
self._tmpdir = tempfile.mkdtemp(prefix="tests-setuptools-")
os.makedirs(os.path.join(self._tmpdir, "site-pkgs"))
self._prev_sys_path = sys.path[:]
sys.path.append(os.path.join(self._tmpdir, "site-pkgs"))
def teardown_method(self, method):
shutil.rmtree(self._tmpdir)
pkg_resources._namespace_packages = self._ns_pkgs.copy()
sys.path = self._prev_sys_path[:]
@pytest.mark.skipif(os.path.islink(tempfile.gettempdir()),
reason="Test fails when /tmp is a symlink. See #231")
def test_two_levels_deep(self):
ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n"
@pytest.yield_fixture
def symlinked_tmpdir(self, tmpdir):
"""
Where available, return the tempdir as a symlink,
which as revealed in #231 is more fragile than
a natural tempdir.
"""
if not hasattr(os, 'symlink'):
yield str(tmpdir)
return
link_name = str(tmpdir) + '-linked'
os.symlink(str(tmpdir), link_name)
try:
yield type(tmpdir)(link_name)
finally:
os.unlink(link_name)
@pytest.yield_fixture(autouse=True)
def patched_path(self, tmpdir):
"""
Patch sys.path to include the 'site-pkgs' dir. Also
restore pkg_resources._namespace_packages to its
former state.
"""
saved_ns_pkgs = pkg_resources._namespace_packages.copy()
saved_sys_path = sys.path[:]
site_pkgs = tmpdir.mkdir('site-pkgs')
sys.path.append(str(site_pkgs))
try:
yield
finally:
pkg_resources._namespace_packages = saved_ns_pkgs
sys.path = saved_sys_path
def test_two_levels_deep(self, symlinked_tmpdir):
"""
Test nested namespace packages
Create namespace packages in the following tree :
......@@ -631,19 +656,16 @@ class TestNamespaces:
Check both are in the _namespace_packages dict and that their __path__
is correct
"""
sys.path.append(os.path.join(self._tmpdir, "site-pkgs2"))
os.makedirs(os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2"))
os.makedirs(os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2"))
ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n"
for site in ["site-pkgs", "site-pkgs2"]:
pkg1_init = open(os.path.join(self._tmpdir, site,
"pkg1", "__init__.py"), "w")
pkg1_init.write(ns_str)
pkg1_init.close()
pkg2_init = open(os.path.join(self._tmpdir, site,
"pkg1", "pkg2", "__init__.py"), "w")
pkg2_init.write(ns_str)
pkg2_init.close()
real_tmpdir = symlinked_tmpdir.realpath()
tmpdir = symlinked_tmpdir
sys.path.append(str(tmpdir / 'site-pkgs2'))
site_dirs = tmpdir / 'site-pkgs', tmpdir / 'site-pkgs2'
for site in site_dirs:
pkg1 = site / 'pkg1'
pkg2 = pkg1 / 'pkg2'
pkg2.ensure_dir()
(pkg1 / '__init__.py').write_text(self.ns_str, encoding='utf-8')
(pkg2 / '__init__.py').write_text(self.ns_str, encoding='utf-8')
import pkg1
assert "pkg1" in pkg_resources._namespace_packages
# attempt to import pkg2 from site-pkgs2
......@@ -653,7 +675,44 @@ class TestNamespaces:
assert pkg_resources._namespace_packages["pkg1"] == ["pkg1.pkg2"]
# check the __path__ attribute contains both paths
expected = [
os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2"),
os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2"),
str(real_tmpdir / "site-pkgs" / "pkg1" / "pkg2"),
str(real_tmpdir / "site-pkgs2" / "pkg1" / "pkg2"),
]
assert pkg1.pkg2.__path__ == expected
def test_path_order(self, symlinked_tmpdir):
"""
Test that if multiple versions of the same namespace package subpackage
are on different sys.path entries, that only the one earliest on
sys.path is imported, and that the namespace package's __path__ is in
the correct order.
Regression test for https://bitbucket.org/pypa/setuptools/issues/207
"""
tmpdir = symlinked_tmpdir
site_dirs = (
tmpdir / "site-pkgs",
tmpdir / "site-pkgs2",
tmpdir / "site-pkgs3",
)
vers_str = "__version__ = %r"
for number, site in enumerate(site_dirs, 1):
if number > 1:
sys.path.append(str(site))
nspkg = site / 'nspkg'
subpkg = nspkg / 'subpkg'
subpkg.ensure_dir()
(nspkg / '__init__.py').write_text(self.ns_str, encoding='utf-8')
(subpkg / '__init__.py').write_text(vers_str % number, encoding='utf-8')
import nspkg.subpkg
import nspkg
expected = [
str(site.realpath() / 'nspkg')
for site in site_dirs
]
assert nspkg.__path__ == expected
assert nspkg.subpkg.__version__ == 1
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# declare and require dependencies
__requires__ = [
'twine',
]; __import__('pkg_resources')
import errno
import glob
import hashlib
import json
import os
import shutil
import tarfile
import codecs
import urllib.request
import urllib.parse
import urllib.error
from distutils.version import LooseVersion
from twine.commands import upload
OK = '\033[92m'
FAIL = '\033[91m'
END = '\033[0m'
DISTRIBUTION = "setuptools"
class SetuptoolsOldReleasesWithoutZip:
"""docstring for SetuptoolsOldReleases"""
def __init__(self):
self.dirpath = './dist'
os.makedirs(self.dirpath, exist_ok=True)
print("Downloading %s releases..." % DISTRIBUTION)
print("All releases will be downloaded to %s" % self.dirpath)
self.data_json_setuptools = self.get_json_data(DISTRIBUTION)
self.valid_releases_numbers = sorted([
release
for release in self.data_json_setuptools['releases']
# This condition is motivated by 13.0 release, which
# comes as "13.0": [], in the json
if self.data_json_setuptools['releases'][release]
], key=LooseVersion)
self.total_downloaded_ok = 0
def get_json_data(self, package_name):
"""
"releases": {
"0.7.2": [
{
"has_sig": false,
"upload_time": "2013-06-09T16:10:00",
"comment_text": "",
"python_version": "source",
"url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-0.7.2.tar.gz", # NOQA
"md5_digest": "de44cd90f8a1c713d6c2bff67bbca65d",
"downloads": 159014,
"filename": "setuptools-0.7.2.tar.gz",
"packagetype": "sdist",
"size": 633077
}
],
"0.7.3": [
{
"has_sig": false,
"upload_time": "2013-06-18T21:08:56",
"comment_text": "",
"python_version": "source",
"url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-0.7.3.tar.gz", # NOQA
"md5_digest": "c854adacbf9067d330a847f06f7a8eba",
"downloads": 30594,
"filename": "setuptools-0.7.3.tar.gz",
"packagetype": "sdist",
"size": 751152
}
],
"12.3": [
{
"has_sig": false,
"upload_time": "2015-02-26T19:15:51",
"comment_text": "",
"python_version": "3.4",
"url": "https://pypi.python.org/packages/3.4/s/setuptools/setuptools-12.3-py2.py3-none-any.whl", # NOQA
"md5_digest": "31f51a38497a70efadf5ce8d4c2211ab",
"downloads": 288451,
"filename": "setuptools-12.3-py2.py3-none-any.whl",
"packagetype": "bdist_wheel",
"size": 501904
},
{
"has_sig": false,
"upload_time": "2015-02-26T19:15:43",
"comment_text": "",
"python_version": "source",
"url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-12.3.tar.gz", # NOQA
"md5_digest": "67614b6d560fa4f240e99cd553ec7f32",
"downloads": 110109,
"filename": "setuptools-12.3.tar.gz",
"packagetype": "sdist",
"size": 635025
},
{
"has_sig": false,
"upload_time": "2015-02-26T19:15:47",
"comment_text": "",
"python_version": "source",
"url": "https://pypi.python.org/packages/source/s/setuptools/setuptools-12.3.zip", # NOQA
"md5_digest": "abc799e7db6e7281535bf342bfc41a12",
"downloads": 67539,
"filename": "setuptools-12.3.zip",
"packagetype": "sdist",
"size": 678783
}
],
"""
url = "https://pypi.python.org/pypi/%s/json" % (package_name,)
resp = urllib.request.urlopen(urllib.request.Request(url))
charset = resp.info().get_content_charset()
reader = codecs.getreader(charset)(resp)
data = json.load(reader)
# Mainly for debug.
json_filename = "%s/%s.json" % (self.dirpath, DISTRIBUTION)
with open(json_filename, 'w') as outfile:
json.dump(
data,
outfile,
sort_keys=True,
indent=4,
separators=(',', ': '),
)
return data
def get_setuptools_releases_without_zip_counterpart(self):
# Get set(all_valid_releases) - set(releases_with_zip), so now we have
# the releases without zip.
return set(self.valid_releases_numbers) - set([
release
for release in self.valid_releases_numbers
for same_version_release_dict in self.data_json_setuptools['releases'][release] # NOQA
if 'zip' in same_version_release_dict['filename']
])
def download_setuptools_releases_without_zip_counterpart(self):
try:
releases_without_zip = self.get_setuptools_releases_without_zip_counterpart() # NOQA
failed_md5_releases = []
# This is a "strange" loop, going through all releases and
# testing only the release I need to download, but I thought it
# would be mouch more readable than trying to iterate through
# releases I need and get into traverse hell values inside dicts
# inside dicts of the json to get the distribution's url to
# download.
for release in self.valid_releases_numbers:
if release in releases_without_zip:
for same_version_release_dict in self.data_json_setuptools['releases'][release]: # NOQA
if 'tar.gz' in same_version_release_dict['filename']:
print("Downloading %s..." % release)
local_file = '%s/%s' % (
self.dirpath,
same_version_release_dict["filename"]
)
urllib.request.urlretrieve(
same_version_release_dict["url"],
local_file
)
targz = open(local_file, 'rb').read()
hexdigest = hashlib.md5(targz).hexdigest()
if (hexdigest != same_version_release_dict['md5_digest']): # NOQA
print(FAIL + "FAIL: md5 for %s didn't match!" % release + END) # NOQA
failed_md5_releases.append(release)
else:
self.total_downloaded_ok += 1
print('Total releases without zip: %s' % len(releases_without_zip))
print('Total downloaded: %s' % self.total_downloaded_ok)
if failed_md5_releases:
msg = FAIL + (
"FAIL: these releases %s failed the md5 check!" %
','.join(failed_md5_releases)
) + END
raise Exception(msg)
elif self.total_downloaded_ok != len(releases_without_zip):
msg = FAIL + (
"FAIL: Unknown error occured. Please check the logs."
) + END
raise Exception(msg)
else:
print(OK + "All releases downloaded and md5 checked." + END)
except OSError as e:
if e.errno != errno.EEXIST:
raise e
def convert_targz_to_zip(self):
print("Converting the tar.gz to zip...")
files = glob.glob('%s/*.tar.gz' % self.dirpath)
total_converted = 0
for targz in sorted(files, key=LooseVersion):
# Extract and remove tar.
tar = tarfile.open(targz)
tar.extractall(path=self.dirpath)
tar.close()
os.remove(targz)
# Zip the extracted tar.
setuptools_folder_path = targz.replace('.tar.gz', '')
setuptools_folder_name = setuptools_folder_path.split("/")[-1]
print(setuptools_folder_name)
shutil.make_archive(
setuptools_folder_path,
'zip',
self.dirpath,
setuptools_folder_name
)
# Exclude extracted tar folder.
shutil.rmtree(setuptools_folder_path.replace('.zip', ''))
total_converted += 1
print('Total converted: %s' % total_converted)
if self.total_downloaded_ok != total_converted:
msg = FAIL + (
"FAIL: Total number of downloaded releases is different"
" from converted ones. Please check the logs."
) + END
raise Exception(msg)
print("Done with the tar.gz->zip. Check folder %s." % main.dirpath)
def upload_zips_to_pypi(self):
print('Uploading to pypi...')
zips = sorted(glob.glob('%s/*.zip' % self.dirpath), key=LooseVersion)
print("simulated upload of", zips); return
upload.upload(dists=zips)
if __name__ == '__main__':
main = SetuptoolsOldReleasesWithoutZip()
main.download_setuptools_releases_without_zip_counterpart()
main.convert_targz_to_zip()
main.upload_zips_to_pypi()
......@@ -59,7 +59,8 @@ force_windows_specific_files = (
os.environ.get("SETUPTOOLS_INSTALL_WINDOWS_SPECIFIC_FILES")
not in (None, "", "0")
)
if sys.platform == 'win32' or force_windows_specific_files:
if (sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt')) \
or force_windows_specific_files:
package_data.setdefault('setuptools', []).extend(['*.exe'])
package_data.setdefault('setuptools.command', []).extend(['*.xml'])
......@@ -75,7 +76,6 @@ setup_params = dict(
"Python packages",
author="Python Packaging Authority",
author_email="distutils-sig@python.org",
license="PSF or ZPL",
long_description=long_description,
keywords="CPAN PyPI distutils eggs package management",
url="https://bitbucket.org/pypa/setuptools",
......@@ -134,8 +134,7 @@ setup_params = dict(
classifiers=textwrap.dedent("""
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
License :: OSI Approved :: Python Software Foundation License
License :: OSI Approved :: Zope Public License
License :: OSI Approved :: MIT License
Operating System :: OS Independent
Programming Language :: Python :: 2.6
Programming Language :: Python :: 2.7
......
......@@ -8,7 +8,7 @@ from distutils.core import Command as _Command
from distutils.util import convert_path
from fnmatch import fnmatchcase
from setuptools.extern.six.moves import filterfalse
from setuptools.extern.six.moves import filterfalse, map
import setuptools.version
from setuptools.extension import Extension
......
......@@ -2,7 +2,7 @@ __all__ = [
'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop',
'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts',
'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts',
'register', 'bdist_wininst', 'upload_docs',
'register', 'bdist_wininst', 'upload_docs', 'upload',
]
from distutils.command.bdist import bdist
......
from distutils.errors import DistutilsOptionError
from setuptools.extern.six.moves import map
from setuptools.command.setopt import edit_config, option_base, config_file
......
......@@ -9,6 +9,7 @@ import distutils.errors
import collections
import itertools
from setuptools.extern.six.moves import map
try:
from setuptools.lib2to3_ex import Mixin2to3
......@@ -59,9 +60,10 @@ class build_py(orig.build_py, Mixin2to3):
self.byte_compile(orig.build_py.get_outputs(self, include_bytecode=0))
def __getattr__(self, attr):
if attr == 'data_files': # lazily compute data files
self.data_files = files = self._get_data_files()
return files
"lazily compute data files"
if attr == 'data_files':
self.data_files = self._get_data_files()
return self.data_files
return orig.build_py.__getattr__(self, attr)
def build_module(self, module, module_file, package):
......@@ -74,23 +76,21 @@ class build_py(orig.build_py, Mixin2to3):
def _get_data_files(self):
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
self.analyze_manifest()
data = []
for package in self.packages or ():
# Locate package source directory
src_dir = self.get_package_dir(package)
return list(map(self._get_pkg_data_files, self.packages or ()))
# Compute package build directory
build_dir = os.path.join(*([self.build_lib] + package.split('.')))
def _get_pkg_data_files(self, package):
# Locate package source directory
src_dir = self.get_package_dir(package)
# Length of path to strip from found files
plen = len(src_dir) + 1
# Compute package build directory
build_dir = os.path.join(*([self.build_lib] + package.split('.')))
# 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
# Strip directory from globbed filenames
filenames = [
os.path.relpath(file, src_dir)
for file in self.find_data_files(package, src_dir)
]
return package, src_dir, build_dir, filenames
def find_data_files(self, package, src_dir):
"""Return filenames for package's data files in 'src_dir'"""
......
......@@ -41,7 +41,7 @@ import shlex
import io
from setuptools.extern import six
from setuptools.extern.six.moves import configparser
from setuptools.extern.six.moves import configparser, map
from setuptools import Command
from setuptools.sandbox import run_setup
......@@ -1876,17 +1876,6 @@ def chmod(path, mode):
log.debug("chmod failed: %s", e)
def fix_jython_executable(executable, options):
warnings.warn("Use JythonCommandSpec", DeprecationWarning, stacklevel=2)
if not JythonCommandSpec.relevant():
return executable
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
......@@ -1901,7 +1890,7 @@ class CommandSpec(list):
"""
Choose the best CommandSpec class based on environmental conditions.
"""
return cls if not JythonCommandSpec.relevant() else JythonCommandSpec
return cls
@classmethod
def _sys_executable(cls):
......@@ -1968,36 +1957,6 @@ 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.")
return super(JythonCommandSpec, self).as_header()
items = ['/usr/bin/env'] + self + list(self.options)
return self._render(items)
class ScriptWriter(object):
"""
Encapsulates behavior around writing entry point scripts for console and
......@@ -2074,7 +2033,10 @@ class ScriptWriter(object):
"""
Select the best ScriptWriter for this environment.
"""
return WindowsScriptWriter.best() if sys.platform == 'win32' else cls
if sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt'):
return WindowsScriptWriter.best()
else:
return cls
@classmethod
def _get_script_args(cls, type_, name, header, script_text):
......
......@@ -15,6 +15,7 @@ import warnings
import time
from setuptools.extern import six
from setuptools.extern.six.moves import map
from setuptools import Command
from setuptools.command.sdist import sdist
......
from distutils import log, dir_util
import os
from setuptools.extern.six.moves import map
from setuptools import Command
from setuptools.archive_util import unpack_archive
import pkg_resources
......@@ -27,7 +29,7 @@ class install_egg_info(Command):
).egg_name() + '.egg-info'
self.source = ei_cmd.egg_info
self.target = os.path.join(self.install_dir, basename)
self.outputs = [self.target]
self.outputs = []
def run(self):
self.run_command('egg_info')
......
......@@ -3,6 +3,7 @@ from unittest import TestLoader
import sys
from setuptools.extern import six
from setuptools.extern.six.moves import map
from pkg_resources import (resource_listdir, resource_exists, normalize_path,
working_set, _namespace_packages,
......
from distutils.command import upload as orig
class upload(orig.upload):
"""
Override default upload behavior to look up password
in the keyring if available.
"""
def finalize_options(self):
orig.upload.finalize_options(self)
self.password or self._load_password_from_keyring()
def _load_password_from_keyring(self):
"""
Attempt to load password from keyring. Suppress Exceptions.
"""
try:
keyring = __import__('keyring')
self.password = keyring.get_password(self.repository,
self.username)
except Exception:
pass
......@@ -8,18 +8,17 @@ PyPI's pythonhosted.org).
from base64 import standard_b64encode
from distutils import log
from distutils.errors import DistutilsOptionError
from distutils.command.upload import upload
import os
import socket
import zipfile
import tempfile
import sys
import shutil
from setuptools.extern import six
from setuptools.extern.six.moves import http_client, urllib
from pkg_resources import iter_entry_points
from .upload import upload
errors = 'surrogateescape' if six.PY3 else 'strict'
......
......@@ -14,6 +14,7 @@ from distutils.errors import (DistutilsOptionError, DistutilsPlatformError,
DistutilsSetupError)
from setuptools.extern import six
from setuptools.extern.six.moves import map
from pkg_resources.extern import packaging
from setuptools.depends import Require
......
......@@ -5,6 +5,8 @@ import distutils.core
import distutils.errors
import distutils.extension
from setuptools.extern.six.moves import map
from .dist import _get_unpatched
from . import msvc9_support
......
"""
Launch the Python script on the command line after
setuptools is bootstrapped via import.
"""
# Note that setuptools gets imported implicitly by the
# invocation of this script using python -m setuptools.launch
import tokenize
import sys
def run():
"""
Run the script in sys.argv[1] as if it had
been invoked naturally.
"""
__builtins__
script_name = sys.argv[1]
namespace = dict(
__file__ = script_name,
__name__ = '__main__',
__doc__ = None,
)
sys.argv[:] = sys.argv[1:]
open_ = getattr(tokenize, 'open', open)
script = open_(script_name).read()
norm_script = script.replace('\\r\\n', '\\n')
code = compile(norm_script, script_name, 'exec')
exec(code, namespace)
if __name__ == '__main__':
run()
......@@ -15,7 +15,7 @@ except ImportError:
from urllib2 import splituser
from setuptools.extern import six
from setuptools.extern.six.moves import urllib, http_client, configparser
from setuptools.extern.six.moves import urllib, http_client, configparser, map
from pkg_resources import (
CHECKOUT_DIST, Distribution, BINARY_DIST, normalize_path, SOURCE_DIST,
......
......@@ -9,7 +9,7 @@ import contextlib
import pickle
from setuptools.extern import six
from setuptools.extern.six.moves import builtins
from setuptools.extern.six.moves import builtins, map
import pkg_resources
......@@ -207,8 +207,12 @@ def _needs_hiding(mod_name):
True
>>> _needs_hiding('distutils')
True
>>> _needs_hiding('os')
False
>>> _needs_hiding('Cython')
True
"""
pattern = re.compile('(setuptools|pkg_resources|distutils)(\.|$)')
pattern = re.compile('(setuptools|pkg_resources|distutils|Cython)(\.|$)')
return bool(pattern.match(mod_name))
......
......@@ -3,7 +3,7 @@ import socket
import atexit
import re
from setuptools.extern.six.moves import urllib, http_client
from setuptools.extern.six.moves import urllib, http_client, map
import pkg_resources
from pkg_resources import ResolutionError, ExtractionError
......@@ -25,6 +25,7 @@ cert_paths = """
/usr/local/share/certs/ca-root.crt
/etc/ssl/cert.pem
/System/Library/OpenSSL/certs/cert.pem
/usr/local/share/certs/ca-root-nss.crt
""".strip().split()
......
......@@ -6,6 +6,7 @@ import contextlib
import site
from setuptools.extern import six
import pkg_resources
@contextlib.contextmanager
......@@ -77,6 +78,18 @@ def save_user_site_setting():
site.ENABLE_USER_SITE = saved
@contextlib.contextmanager
def save_pkg_resources_state():
pr_state = pkg_resources.__getstate__()
# also save sys.path
sys_path = sys.path[:]
try:
yield pr_state, sys_path
finally:
sys.path[:] = sys_path
pkg_resources.__setstate__(pr_state)
@contextlib.contextmanager
def suppress_exceptions(*excs):
try:
......
......@@ -4,6 +4,8 @@ import os
import shutil
import tempfile
from setuptools.extern.six.moves import map
import pytest
import pkg_resources
......
This diff is collapsed.
import os
import stat
from setuptools.extern.six.moves import map
import pytest
from . import environment
......
......@@ -10,6 +10,7 @@ import contextlib
import io
from setuptools.extern import six
from setuptools.extern.six.moves import map
import pytest
......
from setuptools import unicode_utils
def test_filesys_decode_fs_encoding_is_None(monkeypatch):
"""
Test filesys_decode does not raise TypeError when
getfilesystemencoding returns None.
"""
monkeypatch.setattr('sys.getfilesystemencoding', lambda: None)
unicode_utils.filesys_decode(b'test')
......@@ -22,11 +22,13 @@ def filesys_decode(path):
NONE when no expected encoding works
"""
fs_enc = sys.getfilesystemencoding()
if isinstance(path, six.text_type):
return path
for enc in (fs_enc, "utf-8"):
fs_enc = sys.getfilesystemencoding() or 'utf-8'
candidates = fs_enc, 'utf-8'
for enc in candidates:
try:
return path.decode(enc)
except UnicodeDecodeError:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment