summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2017-02-23 16:38:38 -0500
committerGitHub <noreply@github.com>2017-02-23 16:38:38 -0500
commitd2adf3daa1206b9950b5185fb0a56b6ea84658e3 (patch)
tree6dfa2e121cf70aca7b84cd9db79b9b0034d29a4b
parent05d47d9fc7a5d1509734a2205fd2c976d22996b1 (diff)
parent5c80844b0291ef2b326bcf8cf79e9a69dbd01a6b (diff)
downloadpython-setuptools-git-d2adf3daa1206b9950b5185fb0a56b6ea84658e3.tar.gz
Merge branch 'master' into feature/upload-infer-username
-rw-r--r--.travis.yml2
-rw-r--r--CHANGES.rst16
-rw-r--r--bootstrap.py16
-rw-r--r--docs/conf.py2
-rw-r--r--docs/pkg_resources.txt10
-rw-r--r--docs/requirements.txt1
-rw-r--r--docs/setuptools.txt17
-rw-r--r--pkg_resources/__init__.py6
-rwxr-xr-xsetup.cfg2
-rwxr-xr-xsetup.py2
-rw-r--r--setuptools/config.py11
-rwxr-xr-xsetuptools/namespaces.py2
-rwxr-xr-xsetuptools/package_index.py2
-rw-r--r--setuptools/py27compat.py1
-rw-r--r--setuptools/tests/test_config.py13
-rw-r--r--setuptools/tests/test_packageindex.py42
16 files changed, 103 insertions, 42 deletions
diff --git a/.travis.yml b/.travis.yml
index 7affc0a6..adb2f948 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,7 +35,7 @@ deploy:
on:
tags: true
all_branches: true
- python: 3.5
+ python: 3.6
condition: $LC_ALL != "C"
user: jaraco
password:
diff --git a/CHANGES.rst b/CHANGES.rst
index efe4488e..0e47fe06 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,6 +4,22 @@ v34.3.0
* #941: In the upload command, if the username is blank,
default to ``getpass.getuser()``.
+v34.2.0
+-------
+
+* #966: Add support for reading dist-info metadata and
+ thus locating Distributions from zip files.
+
+* #968: Allow '+' and '!' in egg fragments
+ so that it can take package names that contain
+ PEP 440 conforming version specifiers.
+
+v34.1.1
+-------
+
+* #953: More aggressively employ the compatibility issue
+ originally added in #706.
+
v34.1.0
-------
diff --git a/bootstrap.py b/bootstrap.py
index f7644f12..ee3b53c8 100644
--- a/bootstrap.py
+++ b/bootstrap.py
@@ -17,7 +17,6 @@ import sys
import textwrap
import subprocess
-import pip
minimal_egg_info = textwrap.dedent("""
[distutils.commands]
@@ -75,7 +74,7 @@ def gen_deps():
@contextlib.contextmanager
def install_deps():
"Just in time make the deps available"
- gen_deps()
+ import pip
tmpdir = tempfile.mkdtemp()
args = [
'install',
@@ -90,7 +89,16 @@ def install_deps():
shutil.rmtree(tmpdir)
-if __name__ == '__main__':
+def main():
ensure_egg_info()
- with install_deps():
+ gen_deps()
+ try:
+ # first assume dependencies are present
run_egg_info()
+ except Exception:
+ # but if that fails, try again with dependencies just in time
+ with install_deps():
+ run_egg_info()
+
+
+__name__ == '__main__' and main()
diff --git a/docs/conf.py b/docs/conf.py
index c1854ed8..fe684271 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -29,7 +29,7 @@ import setup as setup_script
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['rst.linker']
+extensions = ['rst.linker', 'sphinx.ext.autosectionlabel']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
diff --git a/docs/pkg_resources.txt b/docs/pkg_resources.txt
index e8412b33..487320ce 100644
--- a/docs/pkg_resources.txt
+++ b/docs/pkg_resources.txt
@@ -143,10 +143,10 @@ namespace package for Zope Corporation packages, and the ``peak`` namespace
package for the Python Enterprise Application Kit.
To create a namespace package, you list it in the ``namespace_packages``
-argument to ``setup()``, in your project's ``setup.py``. (See the `setuptools
-documentation on namespace packages`_ for more information on this.) Also,
-you must add a ``declare_namespace()`` call in the package's ``__init__.py``
-file(s):
+argument to ``setup()``, in your project's ``setup.py``. (See the
+:ref:`setuptools documentation on namespace packages <Namespace Packages>` for
+more information on this.) Also, you must add a ``declare_namespace()`` call
+in the package's ``__init__.py`` file(s):
``declare_namespace(name)``
Declare that the dotted package name `name` is a "namespace package" whose
@@ -175,8 +175,6 @@ filesystem and zip importers, you can extend its support to other "importers"
compatible with PEP 302 using the ``register_namespace_handler()`` function.
See the section below on `Supporting Custom Importers`_ for details.
-.. _setuptools documentation on namespace packages: http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
-
``WorkingSet`` Objects
======================
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 0871ed76..4be41887 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1 +1,2 @@
rst.linker>=1.6.1
+sphinx>=1.4
diff --git a/docs/setuptools.txt b/docs/setuptools.txt
index 2a494fca..f0da6e1d 100644
--- a/docs/setuptools.txt
+++ b/docs/setuptools.txt
@@ -940,14 +940,13 @@ Typically, existing programs manipulate a package's ``__file__`` attribute in
order to find the location of data files. However, this manipulation isn't
compatible with PEP 302-based import hooks, including importing from zip files
and Python Eggs. It is strongly recommended that, if you are using data files,
-you should use the `Resource Management API`_ of ``pkg_resources`` to access
+you should use the :ref:`ResourceManager API` of ``pkg_resources`` to access
them. The ``pkg_resources`` module is distributed as part of setuptools, so if
you're using setuptools to distribute your package, there is no reason not to
use its resource management API. See also `Accessing Package Resources`_ for
a quick example of converting code that uses ``__file__`` to use
``pkg_resources`` instead.
-.. _Resource Management API: http://peak.telecommunity.com/DevCenter/PkgResources#resourcemanager-api
.. _Accessing Package Resources: http://peak.telecommunity.com/DevCenter/PythonEggs#accessing-package-resources
@@ -959,8 +958,8 @@ location (e.g. ``/usr/share``). This feature intended to be used for things
like documentation, example configuration files, and the like. ``setuptools``
does not install these data files in a separate location, however. They are
bundled inside the egg file or directory, alongside the Python modules and
-packages. The data files can also be accessed using the `Resource Management
-API`_, by specifying a ``Requirement`` instead of a package name::
+packages. The data files can also be accessed using the :ref:`ResourceManager
+API`, by specifying a ``Requirement`` instead of a package name::
from pkg_resources import Requirement, resource_filename
filename = resource_filename(Requirement.parse("MyProject"),"sample.conf")
@@ -2303,10 +2302,10 @@ boilerplate code in some cases.
long_description = file: README.rst
keywords = one, two
license = BSD 3-Clause License
-
- [metadata.classifiers]
- Framework :: Django
- Programming Language :: Python :: 3.5
+ classifiers =
+ Framework :: Django
+ Programming Language :: Python :: 3
+ Programming Language :: Python :: 3.5
[options]
zip_safe = False
@@ -2399,7 +2398,7 @@ author str
author_email author-email str
maintainer str
maintainer_email maintainer-email str
-classifiers classifier file:, section, list-comma
+classifiers classifier file:, list-comma
license file:, str
description summary file:, str
long_description long-description file:, str
diff --git a/pkg_resources/__init__.py b/pkg_resources/__init__.py
index e33de0e7..220a7ccc 100644
--- a/pkg_resources/__init__.py
+++ b/pkg_resources/__init__.py
@@ -1956,6 +1956,12 @@ def find_eggs_in_zip(importer, path_item, only=False):
subpath = os.path.join(path_item, subitem)
for dist in find_eggs_in_zip(zipimport.zipimporter(subpath), subpath):
yield dist
+ elif subitem.lower().endswith('.dist-info'):
+ subpath = os.path.join(path_item, subitem)
+ submeta = EggMetadata(zipimport.zipimporter(subpath))
+ submeta.egg_info = subpath
+ yield Distribution.from_location(path_item, subitem, submeta)
+
register_finder(zipimport.zipimporter, find_eggs_in_zip)
diff --git a/setup.cfg b/setup.cfg
index be162bbf..78c3153f 100755
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,5 @@
[bumpversion]
-current_version = 34.1.0
+current_version = 34.2.0
commit = True
tag = True
diff --git a/setup.py b/setup.py
index 88795a23..250d7f39 100755
--- a/setup.py
+++ b/setup.py
@@ -88,7 +88,7 @@ def pypi_link(pkg_filename):
setup_params = dict(
name="setuptools",
- version="34.1.0",
+ version="34.2.0",
description="Easily download, build, install, upgrade, and uninstall "
"Python packages",
author="Python Packaging Authority",
diff --git a/setuptools/config.py b/setuptools/config.py
index 19b39629..39a01f88 100644
--- a/setuptools/config.py
+++ b/setuptools/config.py
@@ -412,17 +412,6 @@ class ConfigMetadataHandler(ConfigHandler):
'version': self._parse_version,
}
- def parse_section_classifiers(self, section_options):
- """Parses configuration file section.
-
- :param dict section_options:
- """
- classifiers = []
- for begin, (_, rest) in section_options.items():
- classifiers.append('%s :%s' % (begin.title(), rest))
-
- self['classifiers'] = classifiers
-
def _parse_version(self, value):
"""Parses `version` option value.
diff --git a/setuptools/namespaces.py b/setuptools/namespaces.py
index 556b5dd2..7c24a566 100755
--- a/setuptools/namespaces.py
+++ b/setuptools/namespaces.py
@@ -52,7 +52,7 @@ class Installer:
"importlib.util.module_from_spec("
"importlib.machinery.PathFinder.find_spec(%(pkg)r, "
"[os.path.dirname(p)])))",
- "m = m or not has_mfs and "
+ "m = m or "
"sys.modules.setdefault(%(pkg)r, types.ModuleType(%(pkg)r))",
"mp = (m or []) and m.__dict__.setdefault('__path__',[])",
"(p not in mp) and mp.append(p)",
diff --git a/setuptools/package_index.py b/setuptools/package_index.py
index 42361058..3544dd54 100755
--- a/setuptools/package_index.py
+++ b/setuptools/package_index.py
@@ -30,7 +30,7 @@ from fnmatch import translate
from setuptools.py26compat import strip_fragment
from setuptools.py27compat import get_all_headers
-EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.]+)$')
+EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.+!]+)$')
HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I)
# this is here to fix emacs' cruddy broken syntax highlighting
PYPI_MD5 = re.compile(
diff --git a/setuptools/py27compat.py b/setuptools/py27compat.py
index a71a936e..f0a80a8e 100644
--- a/setuptools/py27compat.py
+++ b/setuptools/py27compat.py
@@ -21,7 +21,6 @@ if sys.version_info < (3,):
linux_py2_ascii = (
platform.system() == 'Linux' and
- sys.getfilesystemencoding() == 'ascii' and
sys.version_info < (3,)
)
diff --git a/setuptools/tests/test_config.py b/setuptools/tests/test_config.py
index fa8d523b..799fb165 100644
--- a/setuptools/tests/test_config.py
+++ b/setuptools/tests/test_config.py
@@ -257,6 +257,7 @@ class TestMetadata:
def test_classifiers(self, tmpdir):
expected = set([
'Framework :: Django',
+ 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
])
@@ -269,19 +270,21 @@ class TestMetadata:
tmpdir.join('classifiers').write(
'Framework :: Django\n'
+ 'Programming Language :: Python :: 3\n'
'Programming Language :: Python :: 3.5\n'
)
with get_dist(tmpdir) as dist:
assert set(dist.metadata.classifiers) == expected
- # From section.
+ # From list notation
config.write(
- '[metadata.classifiers]\n'
- 'Framework :: Django\n'
- 'Programming Language :: Python :: 3.5\n'
+ '[metadata]\n'
+ 'classifiers =\n'
+ ' Framework :: Django\n'
+ ' Programming Language :: Python :: 3\n'
+ ' Programming Language :: Python :: 3.5\n'
)
-
with get_dist(tmpdir) as dist:
assert set(dist.metadata.classifiers) == expected
diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py
index d68867c2..1a66394f 100644
--- a/setuptools/tests/test_packageindex.py
+++ b/setuptools/tests/test_packageindex.py
@@ -181,6 +181,48 @@ class TestPackageIndex:
res = setuptools.package_index.local_open(url)
assert 'content' in res.read()
+ def test_egg_fragment(self):
+ """
+ EGG fragments must comply to PEP 440
+ """
+ epoch = [
+ '',
+ '1!',
+ ]
+ releases = [
+ '0',
+ '0.0',
+ '0.0.0',
+ ]
+ pre = [
+ 'a0',
+ 'b0',
+ 'rc0',
+ ]
+ post = [
+ '.post0'
+ ]
+ dev = [
+ '.dev0',
+ ]
+ local = [
+ ('', ''),
+ ('+ubuntu.0', '+ubuntu.0'),
+ ('+ubuntu-0', '+ubuntu.0'),
+ ('+ubuntu_0', '+ubuntu.0'),
+ ]
+ versions = [
+ [''.join([e, r, p, l]) for l in ll]
+ for e in epoch
+ for r in releases
+ for p in sum([pre, post, dev], [''])
+ for ll in local]
+ for v, vc in versions:
+ dists = list(setuptools.package_index.distros_for_url(
+ 'http://example.com/example.zip#egg=example-' + v))
+ assert dists[0].version == ''
+ assert dists[1].version == vc
+
class TestContentCheckers:
def test_md5(self):