Commit d2adf3da authored by Jason R. Coombs's avatar Jason R. Coombs Committed by GitHub

Merge branch 'master' into feature/upload-infer-username

parents 05d47d9f 5c80844b
...@@ -35,7 +35,7 @@ deploy: ...@@ -35,7 +35,7 @@ deploy:
on: on:
tags: true tags: true
all_branches: true all_branches: true
python: 3.5 python: 3.6
condition: $LC_ALL != "C" condition: $LC_ALL != "C"
user: jaraco user: jaraco
password: password:
......
...@@ -4,6 +4,22 @@ v34.3.0 ...@@ -4,6 +4,22 @@ v34.3.0
* #941: In the upload command, if the username is blank, * #941: In the upload command, if the username is blank,
default to ``getpass.getuser()``. 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 v34.1.0
------- -------
......
...@@ -17,7 +17,6 @@ import sys ...@@ -17,7 +17,6 @@ import sys
import textwrap import textwrap
import subprocess import subprocess
import pip
minimal_egg_info = textwrap.dedent(""" minimal_egg_info = textwrap.dedent("""
[distutils.commands] [distutils.commands]
...@@ -75,7 +74,7 @@ def gen_deps(): ...@@ -75,7 +74,7 @@ def gen_deps():
@contextlib.contextmanager @contextlib.contextmanager
def install_deps(): def install_deps():
"Just in time make the deps available" "Just in time make the deps available"
gen_deps() import pip
tmpdir = tempfile.mkdtemp() tmpdir = tempfile.mkdtemp()
args = [ args = [
'install', 'install',
...@@ -90,7 +89,16 @@ def install_deps(): ...@@ -90,7 +89,16 @@ def install_deps():
shutil.rmtree(tmpdir) shutil.rmtree(tmpdir)
if __name__ == '__main__': def main():
ensure_egg_info() ensure_egg_info()
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(): with install_deps():
run_egg_info() run_egg_info()
__name__ == '__main__' and main()
...@@ -29,7 +29,7 @@ import setup as setup_script ...@@ -29,7 +29,7 @@ import setup as setup_script
# Add any Sphinx extension module names here, as strings. They can be extensions # Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. # 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. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ['_templates']
......
...@@ -143,10 +143,10 @@ namespace package for Zope Corporation packages, and the ``peak`` namespace ...@@ -143,10 +143,10 @@ namespace package for Zope Corporation packages, and the ``peak`` namespace
package for the Python Enterprise Application Kit. package for the Python Enterprise Application Kit.
To create a namespace package, you list it in the ``namespace_packages`` To create a namespace package, you list it in the ``namespace_packages``
argument to ``setup()``, in your project's ``setup.py``. (See the `setuptools argument to ``setup()``, in your project's ``setup.py``. (See the
documentation on namespace packages`_ for more information on this.) Also, :ref:`setuptools documentation on namespace packages <Namespace Packages>` for
you must add a ``declare_namespace()`` call in the package's ``__init__.py`` more information on this.) Also, you must add a ``declare_namespace()`` call
file(s): in the package's ``__init__.py`` file(s):
``declare_namespace(name)`` ``declare_namespace(name)``
Declare that the dotted package name `name` is a "namespace package" whose 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" ...@@ -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. compatible with PEP 302 using the ``register_namespace_handler()`` function.
See the section below on `Supporting Custom Importers`_ for details. 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 ``WorkingSet`` Objects
====================== ======================
......
rst.linker>=1.6.1 rst.linker>=1.6.1
sphinx>=1.4
...@@ -940,14 +940,13 @@ Typically, existing programs manipulate a package's ``__file__`` attribute in ...@@ -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 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 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, 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 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 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 use its resource management API. See also `Accessing Package Resources`_ for
a quick example of converting code that uses ``__file__`` to use a quick example of converting code that uses ``__file__`` to use
``pkg_resources`` instead. ``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 .. _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 ...@@ -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`` like documentation, example configuration files, and the like. ``setuptools``
does not install these data files in a separate location, however. They are 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 bundled inside the egg file or directory, alongside the Python modules and
packages. The data files can also be accessed using the `Resource Management packages. The data files can also be accessed using the :ref:`ResourceManager
API`_, by specifying a ``Requirement`` instead of a package name:: API`, by specifying a ``Requirement`` instead of a package name::
from pkg_resources import Requirement, resource_filename from pkg_resources import Requirement, resource_filename
filename = resource_filename(Requirement.parse("MyProject"),"sample.conf") filename = resource_filename(Requirement.parse("MyProject"),"sample.conf")
...@@ -2303,9 +2302,9 @@ boilerplate code in some cases. ...@@ -2303,9 +2302,9 @@ boilerplate code in some cases.
long_description = file: README.rst long_description = file: README.rst
keywords = one, two keywords = one, two
license = BSD 3-Clause License license = BSD 3-Clause License
classifiers =
[metadata.classifiers]
Framework :: Django Framework :: Django
Programming Language :: Python :: 3
Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.5
[options] [options]
...@@ -2399,7 +2398,7 @@ author str ...@@ -2399,7 +2398,7 @@ author str
author_email author-email str author_email author-email str
maintainer str maintainer str
maintainer_email maintainer-email str maintainer_email maintainer-email str
classifiers classifier file:, section, list-comma classifiers classifier file:, list-comma
license file:, str license file:, str
description summary file:, str description summary file:, str
long_description long-description file:, str long_description long-description file:, str
......
...@@ -1956,6 +1956,12 @@ def find_eggs_in_zip(importer, path_item, only=False): ...@@ -1956,6 +1956,12 @@ def find_eggs_in_zip(importer, path_item, only=False):
subpath = os.path.join(path_item, subitem) subpath = os.path.join(path_item, subitem)
for dist in find_eggs_in_zip(zipimport.zipimporter(subpath), subpath): for dist in find_eggs_in_zip(zipimport.zipimporter(subpath), subpath):
yield dist 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) register_finder(zipimport.zipimporter, find_eggs_in_zip)
......
[bumpversion] [bumpversion]
current_version = 34.1.0 current_version = 34.2.0
commit = True commit = True
tag = True tag = True
......
...@@ -88,7 +88,7 @@ def pypi_link(pkg_filename): ...@@ -88,7 +88,7 @@ def pypi_link(pkg_filename):
setup_params = dict( setup_params = dict(
name="setuptools", name="setuptools",
version="34.1.0", version="34.2.0",
description="Easily download, build, install, upgrade, and uninstall " description="Easily download, build, install, upgrade, and uninstall "
"Python packages", "Python packages",
author="Python Packaging Authority", author="Python Packaging Authority",
......
...@@ -412,17 +412,6 @@ class ConfigMetadataHandler(ConfigHandler): ...@@ -412,17 +412,6 @@ class ConfigMetadataHandler(ConfigHandler):
'version': self._parse_version, '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): def _parse_version(self, value):
"""Parses `version` option value. """Parses `version` option value.
......
...@@ -52,7 +52,7 @@ class Installer: ...@@ -52,7 +52,7 @@ class Installer:
"importlib.util.module_from_spec(" "importlib.util.module_from_spec("
"importlib.machinery.PathFinder.find_spec(%(pkg)r, " "importlib.machinery.PathFinder.find_spec(%(pkg)r, "
"[os.path.dirname(p)])))", "[os.path.dirname(p)])))",
"m = m or not has_mfs and " "m = m or "
"sys.modules.setdefault(%(pkg)r, types.ModuleType(%(pkg)r))", "sys.modules.setdefault(%(pkg)r, types.ModuleType(%(pkg)r))",
"mp = (m or []) and m.__dict__.setdefault('__path__',[])", "mp = (m or []) and m.__dict__.setdefault('__path__',[])",
"(p not in mp) and mp.append(p)", "(p not in mp) and mp.append(p)",
......
...@@ -30,7 +30,7 @@ from fnmatch import translate ...@@ -30,7 +30,7 @@ from fnmatch import translate
from setuptools.py26compat import strip_fragment from setuptools.py26compat import strip_fragment
from setuptools.py27compat import get_all_headers 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) HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I)
# this is here to fix emacs' cruddy broken syntax highlighting # this is here to fix emacs' cruddy broken syntax highlighting
PYPI_MD5 = re.compile( PYPI_MD5 = re.compile(
......
...@@ -21,7 +21,6 @@ if sys.version_info < (3,): ...@@ -21,7 +21,6 @@ if sys.version_info < (3,):
linux_py2_ascii = ( linux_py2_ascii = (
platform.system() == 'Linux' and platform.system() == 'Linux' and
sys.getfilesystemencoding() == 'ascii' and
sys.version_info < (3,) sys.version_info < (3,)
) )
......
...@@ -257,6 +257,7 @@ class TestMetadata: ...@@ -257,6 +257,7 @@ class TestMetadata:
def test_classifiers(self, tmpdir): def test_classifiers(self, tmpdir):
expected = set([ expected = set([
'Framework :: Django', 'Framework :: Django',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.5',
]) ])
...@@ -269,19 +270,21 @@ class TestMetadata: ...@@ -269,19 +270,21 @@ class TestMetadata:
tmpdir.join('classifiers').write( tmpdir.join('classifiers').write(
'Framework :: Django\n' 'Framework :: Django\n'
'Programming Language :: Python :: 3\n'
'Programming Language :: Python :: 3.5\n' 'Programming Language :: Python :: 3.5\n'
) )
with get_dist(tmpdir) as dist: with get_dist(tmpdir) as dist:
assert set(dist.metadata.classifiers) == expected assert set(dist.metadata.classifiers) == expected
# From section. # From list notation
config.write( config.write(
'[metadata.classifiers]\n' '[metadata]\n'
'Framework :: Django\n' 'classifiers =\n'
'Programming Language :: Python :: 3.5\n' ' Framework :: Django\n'
' Programming Language :: Python :: 3\n'
' Programming Language :: Python :: 3.5\n'
) )
with get_dist(tmpdir) as dist: with get_dist(tmpdir) as dist:
assert set(dist.metadata.classifiers) == expected assert set(dist.metadata.classifiers) == expected
......
...@@ -181,6 +181,48 @@ class TestPackageIndex: ...@@ -181,6 +181,48 @@ class TestPackageIndex:
res = setuptools.package_index.local_open(url) res = setuptools.package_index.local_open(url)
assert 'content' in res.read() 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: class TestContentCheckers:
def test_md5(self): def test_md5(self):
......
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