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 ...@@ -234,3 +234,15 @@ cc41477ecf92f221c113736fac2830bf8079d40c 19.0
0a2a3d89416e1642cf6f41d22dbc07b3d3c15a4d 19.1.1 0a2a3d89416e1642cf6f41d22dbc07b3d3c15a4d 19.1.1
5d24cf9d1ced76c406ab3c4a94c25d1fe79b94bc 19.2 5d24cf9d1ced76c406ab3c4a94c25d1fe79b94bc 19.2
66fa131a0d77a1b0e6f89ccb76b254cfb07d3da3 19.3b1 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: ...@@ -6,6 +6,10 @@ python:
- 3.4 - 3.4
- 3.5 - 3.5
- pypy - pypy
- pypy3
matrix:
allow_failures:
- python: pypy3
env: env:
- "" - ""
- LC_ALL=C LC_CTYPE=C - LC_ALL=C LC_CTYPE=C
......
This diff is collapsed.
...@@ -2328,54 +2328,25 @@ available: ...@@ -2328,54 +2328,25 @@ available:
``upload`` - Upload source and/or egg distributions to PyPI ``upload`` - Upload source and/or egg distributions to PyPI
=========================================================== ===========================================================
PyPI now supports uploading project files for redistribution; uploaded files The ``upload`` command is implemented and `documented
are easily found by EasyInstall, even if you don't have download links on your <https://docs.python.org/3.1/distutils/uploading.html>`_
project's home page. in distutils.
Although Python 2.5 will support uploading all types of distributions to PyPI, Setuptools augments the ``upload`` command with support
setuptools only supports source distributions and eggs. (This is partly for `keyring <https://pypi.python.org/pypi/keyring>`_,
because PyPI's upload support is currently broken for various other file allowing the password to be stored in a secure
types.) To upload files, you must include the ``upload`` command *after* the location and not in plaintext in the .pypirc file. To use
``sdist`` or ``bdist_egg`` commands on the setup command line. For example:: 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 python -m keyring set <repository> <username>
setup.py sdist upload # create a source distro and upload it Password for '<username>' in '<repository>': ********
setup.py sdist bdist_egg upload # create and upload both
Note that to upload files for a project, the corresponding version must already Then, in .pypirc, set the repository configuration as normal,
be registered with PyPI, using the distutils ``register`` command. It's but omit the password. Thereafter, uploads will use the
usually a good idea to include the ``register`` command at the start of the password from the keyring.
command line, so that any registration problems can be found and fixed before
building and uploading the distributions, e.g.::
setup.py register sdist bdist_egg upload New in 20.1: Added keyring support.
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).
.. _upload_docs: .. _upload_docs:
......
...@@ -46,7 +46,7 @@ except ImportError: ...@@ -46,7 +46,7 @@ except ImportError:
import imp as _imp import imp as _imp
from pkg_resources.extern import six 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 # capture these to bypass sandboxing
from os import utime from os import utime
...@@ -60,10 +60,11 @@ except ImportError: ...@@ -60,10 +60,11 @@ except ImportError:
from os import open as os_open from os import open as os_open
from os.path import isdir, split from os.path import isdir, split
# Avoid try/except due to potential problems with delayed import mechanisms. try:
if sys.version_info >= (3, 3) and sys.implementation.name == "cpython":
import importlib.machinery as importlib_machinery import importlib.machinery as importlib_machinery
else: # access attribute to force import under delayed import mechanisms.
importlib_machinery.__name__
except ImportError:
importlib_machinery = None importlib_machinery = None
try: try:
...@@ -78,9 +79,6 @@ __import__('pkg_resources._vendor.packaging.requirements') ...@@ -78,9 +79,6 @@ __import__('pkg_resources._vendor.packaging.requirements')
__import__('pkg_resources._vendor.packaging.markers') __import__('pkg_resources._vendor.packaging.markers')
filter = six.moves.filter
map = six.moves.map
if (3, 0) < sys.version_info < (3, 3): if (3, 0) < sys.version_info < (3, 3):
msg = ( msg = (
"Support for Python 3.0-3.2 has been dropped. Future versions " "Support for Python 3.0-3.2 has been dropped. Future versions "
...@@ -757,7 +755,7 @@ class WorkingSet(object): ...@@ -757,7 +755,7 @@ class WorkingSet(object):
will be called. will be called.
""" """
if insert: if insert:
dist.insert_on(self.entries, entry) dist.insert_on(self.entries, entry, replace=replace)
if entry is None: if entry is None:
entry = dist.location entry = dist.location
...@@ -1178,22 +1176,23 @@ class ResourceManager: ...@@ -1178,22 +1176,23 @@ class ResourceManager:
old_exc = sys.exc_info()[1] old_exc = sys.exc_info()[1]
cache_path = self.extraction_path or get_default_cache() 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 The following error occurred while trying to extract file(s) to the Python egg
cache: 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 Perhaps your account does not have write access to this directory? You can
change the cache directory by setting the PYTHON_EGG_CACHE environment change the cache directory by setting the PYTHON_EGG_CACHE environment
variable to point to an accessible directory. variable to point to an accessible directory.
""" % (old_exc, cache_path) """).lstrip()
) err = ExtractionError(tmpl.format(**locals()))
err.manager = self err.manager = self
err.cache_path = cache_path err.cache_path = cache_path
err.original_error = old_exc err.original_error = old_exc
...@@ -1561,10 +1560,13 @@ class DefaultProvider(EggProvider): ...@@ -1561,10 +1560,13 @@ class DefaultProvider(EggProvider):
with open(path, 'rb') as stream: with open(path, 'rb') as stream:
return stream.read() 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: DefaultProvider._register()
register_loader_type(importlib_machinery.SourceFileLoader, DefaultProvider)
class EmptyProvider(NullProvider): class EmptyProvider(NullProvider):
...@@ -1970,7 +1972,7 @@ def find_on_path(importer, path_item, only=False): ...@@ -1970,7 +1972,7 @@ def find_on_path(importer, path_item, only=False):
break break
register_finder(pkgutil.ImpImporter, find_on_path) 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) register_finder(importlib_machinery.FileFinder, find_on_path)
_declare_state('dict', _namespace_handlers={}) _declare_state('dict', _namespace_handlers={})
...@@ -2016,11 +2018,28 @@ def _handle_ns(packageName, path_item): ...@@ -2016,11 +2018,28 @@ def _handle_ns(packageName, path_item):
path = module.__path__ path = module.__path__
path.append(subpath) path.append(subpath)
loader.load_module(packageName) loader.load_module(packageName)
for path_item in path: _rebuild_mod_path(path, packageName, module)
if path_item not in module.__path__:
module.__path__.append(path_item)
return subpath 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): def declare_namespace(packageName):
"""Declare that package 'packageName' is a namespace package""" """Declare that package 'packageName' is a namespace package"""
...@@ -2079,7 +2098,7 @@ def file_ns_handler(importer, path_item, packageName, module): ...@@ -2079,7 +2098,7 @@ def file_ns_handler(importer, path_item, packageName, module):
register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
register_namespace_handler(zipimport.zipimporter, 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) register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler)
...@@ -2461,7 +2480,7 @@ class Distribution(object): ...@@ -2461,7 +2480,7 @@ class Distribution(object):
"""Ensure distribution is importable on `path` (default=sys.path)""" """Ensure distribution is importable on `path` (default=sys.path)"""
if path is None: if path is None:
path = sys.path path = sys.path
self.insert_on(path) self.insert_on(path, replace=True)
if path is sys.path: if path is sys.path:
fixup_namespace_packages(self.location) fixup_namespace_packages(self.location)
for pkg in self._get_metadata('namespace_packages.txt'): for pkg in self._get_metadata('namespace_packages.txt'):
...@@ -2538,7 +2557,7 @@ class Distribution(object): ...@@ -2538,7 +2557,7 @@ class Distribution(object):
"""Return the EntryPoint object for `group`+`name`, or ``None``""" """Return the EntryPoint object for `group`+`name`, or ``None``"""
return self.get_entry_map(group).get(name) 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""" """Insert self.location in path before its nearest parent directory"""
loc = loc or self.location loc = loc or self.location
...@@ -2562,6 +2581,9 @@ class Distribution(object): ...@@ -2562,6 +2581,9 @@ class Distribution(object):
else: else:
if path is sys.path: if path is sys.path:
self.check_version_conflict() self.check_version_conflict()
if replace:
path.insert(0, loc)
else:
path.append(loc) path.append(loc)
return return
......
...@@ -12,6 +12,8 @@ import stat ...@@ -12,6 +12,8 @@ import stat
import distutils.dist import distutils.dist
import distutils.command.install_egg_info import distutils.command.install_egg_info
from pkg_resources.extern.six.moves import map
import pytest import pytest
import pkg_resources import pkg_resources
......
from __future__ import unicode_literals
import os import os
import sys import sys
import tempfile
import shutil
import string import string
from pkg_resources.extern.six.moves import map
import pytest import pytest
from pkg_resources.extern import packaging from pkg_resources.extern import packaging
...@@ -158,7 +160,7 @@ class TestDistro: ...@@ -158,7 +160,7 @@ class TestDistro:
for i in range(3): for i in range(3):
targets = list(ws.resolve(parse_requirements("Foo"), ad)) targets = list(ws.resolve(parse_requirements("Foo"), ad))
assert targets == [Foo] assert targets == [Foo]
list(map(ws.add,targets)) list(map(ws.add, targets))
with pytest.raises(VersionConflict): with pytest.raises(VersionConflict):
ws.resolve(parse_requirements("Foo==0.9"), ad) ws.resolve(parse_requirements("Foo==0.9"), ad)
ws = WorkingSet([]) # reset ws = WorkingSet([]) # reset
...@@ -608,21 +610,44 @@ class TestParsing: ...@@ -608,21 +610,44 @@ class TestParsing:
class TestNamespaces: class TestNamespaces:
def setup_method(self, method): ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n"
self._ns_pkgs = pkg_resources._namespace_packages.copy()
self._tmpdir = tempfile.mkdtemp(prefix="tests-setuptools-") @pytest.yield_fixture
os.makedirs(os.path.join(self._tmpdir, "site-pkgs")) def symlinked_tmpdir(self, tmpdir):
self._prev_sys_path = sys.path[:] """
sys.path.append(os.path.join(self._tmpdir, "site-pkgs")) Where available, return the tempdir as a symlink,
which as revealed in #231 is more fragile than
def teardown_method(self, method): a natural tempdir.
shutil.rmtree(self._tmpdir) """
pkg_resources._namespace_packages = self._ns_pkgs.copy() if not hasattr(os, 'symlink'):
sys.path = self._prev_sys_path[:] yield str(tmpdir)
return
@pytest.mark.skipif(os.path.islink(tempfile.gettempdir()),
reason="Test fails when /tmp is a symlink. See #231") link_name = str(tmpdir) + '-linked'
def test_two_levels_deep(self): 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 Test nested namespace packages
Create namespace packages in the following tree : Create namespace packages in the following tree :
...@@ -631,19 +656,16 @@ class TestNamespaces: ...@@ -631,19 +656,16 @@ class TestNamespaces:
Check both are in the _namespace_packages dict and that their __path__ Check both are in the _namespace_packages dict and that their __path__
is correct is correct
""" """
sys.path.append(os.path.join(self._tmpdir, "site-pkgs2")) real_tmpdir = symlinked_tmpdir.realpath()
os.makedirs(os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2")) tmpdir = symlinked_tmpdir
os.makedirs(os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2")) sys.path.append(str(tmpdir / 'site-pkgs2'))
ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n" site_dirs = tmpdir / 'site-pkgs', tmpdir / 'site-pkgs2'
for site in ["site-pkgs", "site-pkgs2"]: for site in site_dirs:
pkg1_init = open(os.path.join(self._tmpdir, site, pkg1 = site / 'pkg1'
"pkg1", "__init__.py"), "w") pkg2 = pkg1 / 'pkg2'
pkg1_init.write(ns_str) pkg2.ensure_dir()
pkg1_init.close() (pkg1 / '__init__.py').write_text(self.ns_str, encoding='utf-8')
pkg2_init = open(os.path.join(self._tmpdir, site, (pkg2 / '__init__.py').write_text(self.ns_str, encoding='utf-8')
"pkg1", "pkg2", "__init__.py"), "w")
pkg2_init.write(ns_str)
pkg2_init.close()
import pkg1 import pkg1
assert "pkg1" in pkg_resources._namespace_packages assert "pkg1" in pkg_resources._namespace_packages
# attempt to import pkg2 from site-pkgs2 # attempt to import pkg2 from site-pkgs2
...@@ -653,7 +675,44 @@ class TestNamespaces: ...@@ -653,7 +675,44 @@ class TestNamespaces:
assert pkg_resources._namespace_packages["pkg1"] == ["pkg1.pkg2"] assert pkg_resources._namespace_packages["pkg1"] == ["pkg1.pkg2"]
# check the __path__ attribute contains both paths # check the __path__ attribute contains both paths
expected = [ expected = [
os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2"), str(real_tmpdir / "site-pkgs" / "pkg1" / "pkg2"),
os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2"), str(real_tmpdir / "site-pkgs2" / "pkg1" / "pkg2"),
] ]
assert pkg1.pkg2.__path__ == expected 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 = ( ...@@ -59,7 +59,8 @@ force_windows_specific_files = (
os.environ.get("SETUPTOOLS_INSTALL_WINDOWS_SPECIFIC_FILES") os.environ.get("SETUPTOOLS_INSTALL_WINDOWS_SPECIFIC_FILES")
not in (None, "", "0") 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', []).extend(['*.exe'])
package_data.setdefault('setuptools.command', []).extend(['*.xml']) package_data.setdefault('setuptools.command', []).extend(['*.xml'])
...@@ -75,7 +76,6 @@ setup_params = dict( ...@@ -75,7 +76,6 @@ setup_params = dict(
"Python packages", "Python packages",
author="Python Packaging Authority", author="Python Packaging Authority",
author_email="distutils-sig@python.org", author_email="distutils-sig@python.org",
license="PSF or ZPL",
long_description=long_description, long_description=long_description,
keywords="CPAN PyPI distutils eggs package management", keywords="CPAN PyPI distutils eggs package management",
url="https://bitbucket.org/pypa/setuptools", url="https://bitbucket.org/pypa/setuptools",
...@@ -134,8 +134,7 @@ setup_params = dict( ...@@ -134,8 +134,7 @@ setup_params = dict(
classifiers=textwrap.dedent(""" classifiers=textwrap.dedent("""
Development Status :: 5 - Production/Stable Development Status :: 5 - Production/Stable
Intended Audience :: Developers Intended Audience :: Developers
License :: OSI Approved :: Python Software Foundation License License :: OSI Approved :: MIT License
License :: OSI Approved :: Zope Public License
Operating System :: OS Independent Operating System :: OS Independent
Programming Language :: Python :: 2.6 Programming Language :: Python :: 2.6
Programming Language :: Python :: 2.7 Programming Language :: Python :: 2.7
......
...@@ -8,7 +8,7 @@ from distutils.core import Command as _Command ...@@ -8,7 +8,7 @@ from distutils.core import Command as _Command
from distutils.util import convert_path from distutils.util import convert_path
from fnmatch import fnmatchcase from fnmatch import fnmatchcase
from setuptools.extern.six.moves import filterfalse from setuptools.extern.six.moves import filterfalse, map
import setuptools.version import setuptools.version
from setuptools.extension import Extension from setuptools.extension import Extension
......
...@@ -2,7 +2,7 @@ __all__ = [ ...@@ -2,7 +2,7 @@ __all__ = [
'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop', 'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop',
'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts', 'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts',
'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts', '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.command.bdist import bdist
......
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
from setuptools.extern.six.moves import map
from setuptools.command.setopt import edit_config, option_base, config_file from setuptools.command.setopt import edit_config, option_base, config_file
......
...@@ -9,6 +9,7 @@ import distutils.errors ...@@ -9,6 +9,7 @@ import distutils.errors
import collections import collections
import itertools import itertools
from setuptools.extern.six.moves import map
try: try:
from setuptools.lib2to3_ex import Mixin2to3 from setuptools.lib2to3_ex import Mixin2to3
...@@ -59,9 +60,10 @@ class build_py(orig.build_py, Mixin2to3): ...@@ -59,9 +60,10 @@ class build_py(orig.build_py, Mixin2to3):
self.byte_compile(orig.build_py.get_outputs(self, include_bytecode=0)) self.byte_compile(orig.build_py.get_outputs(self, include_bytecode=0))
def __getattr__(self, attr): def __getattr__(self, attr):
if attr == 'data_files': # lazily compute data files "lazily compute data files"
self.data_files = files = self._get_data_files() if attr == 'data_files':
return files self.data_files = self._get_data_files()
return self.data_files
return orig.build_py.__getattr__(self, attr) return orig.build_py.__getattr__(self, attr)
def build_module(self, module, module_file, package): def build_module(self, module, module_file, package):
...@@ -74,23 +76,21 @@ class build_py(orig.build_py, Mixin2to3): ...@@ -74,23 +76,21 @@ class build_py(orig.build_py, Mixin2to3):
def _get_data_files(self): def _get_data_files(self):
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples""" """Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
self.analyze_manifest() self.analyze_manifest()
data = [] return list(map(self._get_pkg_data_files, self.packages or ()))
for package in self.packages or ():
def _get_pkg_data_files(self, package):
# Locate package source directory # Locate package source directory
src_dir = self.get_package_dir(package) src_dir = self.get_package_dir(package)
# Compute package build directory # Compute package build directory
build_dir = os.path.join(*([self.build_lib] + package.split('.'))) build_dir = os.path.join(*([self.build_lib] + package.split('.')))
# Length of path to strip from found files
plen = len(src_dir) + 1
# Strip directory from globbed filenames # Strip directory from globbed filenames
filenames = [ filenames = [
file[plen:] for file in self.find_data_files(package, src_dir) os.path.relpath(file, src_dir)
for file in self.find_data_files(package, src_dir)
] ]
data.append((package, src_dir, build_dir, filenames)) return package, src_dir, build_dir, filenames
return data
def find_data_files(self, package, src_dir): def find_data_files(self, package, src_dir):
"""Return filenames for package's data files in 'src_dir'""" """Return filenames for package's data files in 'src_dir'"""
......
...@@ -41,7 +41,7 @@ import shlex ...@@ -41,7 +41,7 @@ import shlex
import io import io
from setuptools.extern import six 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 import Command
from setuptools.sandbox import run_setup from setuptools.sandbox import run_setup
...@@ -1876,17 +1876,6 @@ def chmod(path, mode): ...@@ -1876,17 +1876,6 @@ def chmod(path, mode):
log.debug("chmod failed: %s", e) 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): class CommandSpec(list):
""" """
A command spec for a #! header, specified as a list of arguments akin to A command spec for a #! header, specified as a list of arguments akin to
...@@ -1901,7 +1890,7 @@ class CommandSpec(list): ...@@ -1901,7 +1890,7 @@ class CommandSpec(list):
""" """
Choose the best CommandSpec class based on environmental conditions. Choose the best CommandSpec class based on environmental conditions.
""" """
return cls if not JythonCommandSpec.relevant() else JythonCommandSpec return cls
@classmethod @classmethod
def _sys_executable(cls): def _sys_executable(cls):
...@@ -1968,36 +1957,6 @@ class WindowsCommandSpec(CommandSpec): ...@@ -1968,36 +1957,6 @@ class WindowsCommandSpec(CommandSpec):
split_args = dict(posix=False) 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): class ScriptWriter(object):
""" """
Encapsulates behavior around writing entry point scripts for console and Encapsulates behavior around writing entry point scripts for console and
...@@ -2074,7 +2033,10 @@ class ScriptWriter(object): ...@@ -2074,7 +2033,10 @@ class ScriptWriter(object):
""" """
Select the best ScriptWriter for this environment. 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 @classmethod
def _get_script_args(cls, type_, name, header, script_text): def _get_script_args(cls, type_, name, header, script_text):
......
...@@ -15,6 +15,7 @@ import warnings ...@@ -15,6 +15,7 @@ import warnings
import time import time
from setuptools.extern import six from setuptools.extern import six
from setuptools.extern.six.moves import map
from setuptools import Command from setuptools import Command
from setuptools.command.sdist import sdist from setuptools.command.sdist import sdist
......
from distutils import log, dir_util from distutils import log, dir_util
import os import os
from setuptools.extern.six.moves import map
from setuptools import Command from setuptools import Command
from setuptools.archive_util import unpack_archive from setuptools.archive_util import unpack_archive
import pkg_resources import pkg_resources
...@@ -27,7 +29,7 @@ class install_egg_info(Command): ...@@ -27,7 +29,7 @@ class install_egg_info(Command):
).egg_name() + '.egg-info' ).egg_name() + '.egg-info'
self.source = ei_cmd.egg_info self.source = ei_cmd.egg_info
self.target = os.path.join(self.install_dir, basename) self.target = os.path.join(self.install_dir, basename)
self.outputs = [self.target] self.outputs = []
def run(self): def run(self):
self.run_command('egg_info') self.run_command('egg_info')
......
...@@ -3,6 +3,7 @@ from unittest import TestLoader ...@@ -3,6 +3,7 @@ from unittest import TestLoader
import sys import sys
from setuptools.extern import six from setuptools.extern import six
from setuptools.extern.six.moves import map
from pkg_resources import (resource_listdir, resource_exists, normalize_path, from pkg_resources import (resource_listdir, resource_exists, normalize_path,
working_set, _namespace_packages, 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). ...@@ -8,18 +8,17 @@ PyPI's pythonhosted.org).
from base64 import standard_b64encode from base64 import standard_b64encode
from distutils import log from distutils import log
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
from distutils.command.upload import upload
import os import os
import socket import socket
import zipfile import zipfile
import tempfile import tempfile
import sys
import shutil import shutil
from setuptools.extern import six from setuptools.extern import six
from setuptools.extern.six.moves import http_client, urllib from setuptools.extern.six.moves import http_client, urllib
from pkg_resources import iter_entry_points from pkg_resources import iter_entry_points
from .upload import upload
errors = 'surrogateescape' if six.PY3 else 'strict' errors = 'surrogateescape' if six.PY3 else 'strict'
......
...@@ -14,6 +14,7 @@ from distutils.errors import (DistutilsOptionError, DistutilsPlatformError, ...@@ -14,6 +14,7 @@ from distutils.errors import (DistutilsOptionError, DistutilsPlatformError,
DistutilsSetupError) DistutilsSetupError)
from setuptools.extern import six from setuptools.extern import six
from setuptools.extern.six.moves import map
from pkg_resources.extern import packaging from pkg_resources.extern import packaging
from setuptools.depends import Require from setuptools.depends import Require
......
...@@ -5,6 +5,8 @@ import distutils.core ...@@ -5,6 +5,8 @@ import distutils.core
import distutils.errors import distutils.errors
import distutils.extension import distutils.extension
from setuptools.extern.six.moves import map
from .dist import _get_unpatched from .dist import _get_unpatched
from . import msvc9_support 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: ...@@ -15,7 +15,7 @@ except ImportError:
from urllib2 import splituser from urllib2 import splituser
from setuptools.extern import six 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 ( from pkg_resources import (
CHECKOUT_DIST, Distribution, BINARY_DIST, normalize_path, SOURCE_DIST, CHECKOUT_DIST, Distribution, BINARY_DIST, normalize_path, SOURCE_DIST,
......
...@@ -9,7 +9,7 @@ import contextlib ...@@ -9,7 +9,7 @@ import contextlib
import pickle import pickle
from setuptools.extern import six from setuptools.extern import six
from setuptools.extern.six.moves import builtins from setuptools.extern.six.moves import builtins, map
import pkg_resources import pkg_resources
...@@ -207,8 +207,12 @@ def _needs_hiding(mod_name): ...@@ -207,8 +207,12 @@ def _needs_hiding(mod_name):
True True
>>> _needs_hiding('distutils') >>> _needs_hiding('distutils')
True 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)) return bool(pattern.match(mod_name))
......
...@@ -3,7 +3,7 @@ import socket ...@@ -3,7 +3,7 @@ import socket
import atexit import atexit
import re import re
from setuptools.extern.six.moves import urllib, http_client from setuptools.extern.six.moves import urllib, http_client, map
import pkg_resources import pkg_resources
from pkg_resources import ResolutionError, ExtractionError from pkg_resources import ResolutionError, ExtractionError
...@@ -25,6 +25,7 @@ cert_paths = """ ...@@ -25,6 +25,7 @@ cert_paths = """
/usr/local/share/certs/ca-root.crt /usr/local/share/certs/ca-root.crt
/etc/ssl/cert.pem /etc/ssl/cert.pem
/System/Library/OpenSSL/certs/cert.pem /System/Library/OpenSSL/certs/cert.pem
/usr/local/share/certs/ca-root-nss.crt
""".strip().split() """.strip().split()
......
...@@ -6,6 +6,7 @@ import contextlib ...@@ -6,6 +6,7 @@ import contextlib
import site import site
from setuptools.extern import six from setuptools.extern import six
import pkg_resources
@contextlib.contextmanager @contextlib.contextmanager
...@@ -77,6 +78,18 @@ def save_user_site_setting(): ...@@ -77,6 +78,18 @@ def save_user_site_setting():
site.ENABLE_USER_SITE = saved 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 @contextlib.contextmanager
def suppress_exceptions(*excs): def suppress_exceptions(*excs):
try: try:
......
...@@ -4,6 +4,8 @@ import os ...@@ -4,6 +4,8 @@ import os
import shutil import shutil
import tempfile import tempfile
from setuptools.extern.six.moves import map
import pytest import pytest
import pkg_resources import pkg_resources
......
This diff is collapsed.
import os import os
import stat import stat
from setuptools.extern.six.moves import map
import pytest import pytest
from . import environment from . import environment
......
...@@ -10,6 +10,7 @@ import contextlib ...@@ -10,6 +10,7 @@ import contextlib
import io import io
from setuptools.extern import six from setuptools.extern import six
from setuptools.extern.six.moves import map
import pytest 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): ...@@ -22,11 +22,13 @@ def filesys_decode(path):
NONE when no expected encoding works NONE when no expected encoding works
""" """
fs_enc = sys.getfilesystemencoding()
if isinstance(path, six.text_type): if isinstance(path, six.text_type):
return path 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: try:
return path.decode(enc) return path.decode(enc)
except UnicodeDecodeError: 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