Imported Upstream version 36.5.0 upstream/36.5.0
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 14 Jan 2019 01:34:58 +0000 (10:34 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 14 Jan 2019 01:34:58 +0000 (10:34 +0900)
.travis.yml
CHANGES.rst
README.rst
docs/setuptools.txt
pkg_resources/__init__.py
setup.cfg
setup.py
setuptools/package_index.py
setuptools/tests/test_virtualenv.py

index a5e08a2efcda31e0288b94d46578db95af142139..60f5815fd366568ae34cee378cfa05a3ebef3f75 100644 (file)
@@ -18,6 +18,7 @@ jobs:
   - python: *latest_py2
     env: LANG=C
   - stage: deploy (to PyPI for tagged commits)
+    if: tag IS present
     python: *latest_py3
     install: skip
     script: skip
index 8130511e37f1a4ec25e4d3bbc015b25172321824..8217aabad43442b0d20e0c53a6d22d70ffea2009 100644 (file)
@@ -1,3 +1,13 @@
+v36.5.0
+-------
+
+* #170: When working with Mercurial checkouts, use Windows-friendly
+  syntax for suppressing output.
+
+* Inspired by #1134, performed substantial refactoring of
+  ``pkg_resources.find_on_path`` to facilitate an optimization
+  for paths with many non-version entries.
+
 v36.4.0
 -------
 
index 2f55bce106c74a0ccb6aa18bf6d0cf96efc9d12e..1c6ee603541ad32f7f2a023b7cabe67b487b856c 100755 (executable)
@@ -1,6 +1,17 @@
+.. image:: https://img.shields.io/pypi/v/setuptools.svg
+   :target: https://pypi.org/project/setuptools
+
 .. image:: https://readthedocs.org/projects/setuptools/badge/?version=latest
     :target: https://setuptools.readthedocs.io
 
+.. image:: https://img.shields.io/travis/pypa/setuptools/master.svg?label=Linux%20build%20%40%20Travis%20CI
+   :target: http://travis-ci.org/pypa/setuptools
+
+.. image:: https://img.shields.io/appveyor/ci/jaraco/setuptools/master.svg?label=Windows%20build%20%40%20Appveyor
+   :target: https://ci.appveyor.com/project/jaraco/setuptools/branch/master
+
+.. image:: https://img.shields.io/pypi/pyversions/setuptools.svg
+
 See the `Installation Instructions
 <https://packaging.python.org/installing/>`_ in the Python Packaging
 User's Guide for instructions on installing, upgrading, and uninstalling
index 531d727c10769da0d491a2dce23c85c9ae917360..f255cfd21779a610c1f4fddda48db6ca8bdae581 100644 (file)
@@ -2281,21 +2281,23 @@ Configuring setup() using setup.cfg files
 
 .. note:: New in 30.3.0 (8 Dec 2016).
 
-.. important:: ``setup.py`` with ``setup()`` function call is still required even 
-                if your configuration resides in ``setup.cfg``.
+.. important::
+    A ``setup.py`` file containing a ``setup()`` function call is still
+    required even if your configuration resides in ``setup.cfg``.
 
-``Setuptools`` allows using configuration files (usually `setup.cfg`)
-to define package’s metadata and other options which are normally supplied
-to ``setup()`` function.
+``Setuptools`` allows using configuration files (usually :file:`setup.cfg`)
+to define a package’s metadata and other options that are normally supplied
+to the ``setup()`` function.
 
-This approach not only allows automation scenarios, but also reduces
+This approach not only allows automation scenarios but also reduces
 boilerplate code in some cases.
 
 .. note::
-    Implementation presents limited compatibility with distutils2-like
-    ``setup.cfg`` sections (used by ``pbr`` and ``d2to1`` packages).
 
-    Namely: only metadata related keys from ``metadata`` section are supported
+    This implementation has limited compatibility with the distutils2-like
+    ``setup.cfg`` sections used by the ``pbr`` and ``d2to1`` packages.
+
+    Namely: only metadata-related keys from ``metadata`` section are supported
     (except for ``description-file``); keys from ``files``, ``entry_points``
     and ``backwards_compat`` are not supported.
 
@@ -2336,12 +2338,13 @@ boilerplate code in some cases.
         src.subpackage2
 
 
-Metadata and options could be set in sections with the same names.
+Metadata and options are set in the config sections of the same name.
 
-* Keys are the same as keyword arguments one provides to ``setup()`` function.
+* Keys are the same as the keyword arguments one provides to the ``setup()``
+  function.
 
-* Complex values could be placed comma-separated or one per line
-  in *dangling* sections. The following are the same:
+* Complex values can be written comma-separated or placed one per line
+  in *dangling* config values. The following are equivalent:
 
   .. code-block:: ini
 
@@ -2353,10 +2356,11 @@ Metadata and options could be set in sections with the same names.
         one
         two
 
-* In some cases complex values could be provided in subsections for clarity.
+* In some cases, complex values can be provided in dedicated subsections for
+  clarity.
 
-* Some keys allow ``file:``, ``attr:`` and ``find:`` directives to cover
-  common usecases.
+* Some keys allow ``file:``, ``attr:``, and ``find:`` directives in order to
+  cover common usecases.
 
 * Unknown keys are ignored.
 
@@ -2369,33 +2373,34 @@ Some values are treated as simple strings, some allow more logic.
 Type names used below:
 
 * ``str`` - simple string
-* ``list-comma`` - dangling list or comma-separated values string
-* ``list-semi`` - dangling list or semicolon-separated values string
-* ``bool`` -  ``True`` is 1, yes, true
-* ``dict`` - list-comma where keys from values are separated by =
-* ``section`` - values could be read from a dedicated (sub)section
+* ``list-comma`` - dangling list or string of comma-separated values
+* ``list-semi`` - dangling list or string of semicolon-separated values
+* ``bool`` - ``True`` is 1, yes, true
+* ``dict`` - list-comma where keys are separated from values by ``=``
+* ``section`` - values are read from a dedicated (sub)section
 
 
 Special directives:
 
-* ``attr:`` - value could be read from module attribute
-* ``file:`` - value could be read from a list of files and then concatenated
+* ``attr:`` - Value is read from a module attribute.  ``attr:`` supports
+  callables and iterables; unsupported types are cast using ``str()``.
+* ``file:`` - Value is read from a list of files and then concatenated
 
 
 .. note::
-    ``file:`` directive is sandboxed and won't reach anything outside
-    directory with ``setup.py``.
+    The ``file:`` directive is sandboxed and won't reach anything outside
+    the directory containing ``setup.py``.
 
 
 Metadata
 --------
 
 .. note::
-    Aliases given below are supported for compatibility reasons,
-    but not advised.
+    The aliases given below are supported for compatibility reasons,
+    but their use is not advised.
 
 ==============================  =================  =====
-Key                             Aliases            Accepted value type
+Key                             Aliases            Type
 ==============================  =================  =====
 name                                               str
 version                                            attr:, str
@@ -2417,17 +2422,12 @@ requires                                           list-comma
 obsoletes                                          list-comma
 ==============================  =================  =====
 
-.. note::
-
-    **version** - ``attr:`` supports callables; supports iterables;
-    unsupported types are casted using ``str()``.
-
 
 Options
 -------
 
 =======================  =====
-Key                      Accepted value type
+Key                      Type
 =======================  =====
 zip_safe                 bool
 setup_requires           list-semi
@@ -2454,10 +2454,10 @@ py_modules               list-comma
 
 .. note::
 
-    **packages** - ``find:`` directive can be further configured
-    in a dedicated subsection `options.packages.find`. This subsection
-    accepts the same keys as `setuptools.find` function:
-    `where`, `include`, `exclude`.
+    **packages** - The ``find:`` directive can be further configured
+    in a dedicated subsection ``options.packages.find``. This subsection
+    accepts the same keys as the `setuptools.find` function:
+    ``where``, ``include``, and ``exclude``.
 
 
 Configuration API
@@ -2465,7 +2465,7 @@ Configuration API
 
 Some automation tools may wish to access data from a configuration file.
 
-``Setuptools`` exposes ``read_configuration()`` function allowing
+``Setuptools`` exposes a ``read_configuration()`` function for
 parsing ``metadata`` and ``options`` sections into a dictionary.
 
 
@@ -2476,16 +2476,16 @@ parsing ``metadata`` and ``options`` sections into a dictionary.
     conf_dict = read_configuration('/home/user/dev/package/setup.cfg')
 
 
-By default ``read_configuration()`` will read only file provided
+By default, ``read_configuration()`` will read only the file provided
 in the first argument. To include values from other configuration files
-which could be in various places set `find_others` function argument
+which could be in various places, set the ``find_others`` keyword argument
 to ``True``.
 
-If you have only a configuration file but not the whole package you can still
-try to get data out of it with the help of `ignore_option_errors` function
-argument. When it is set to ``True`` all options with errors possibly produced
-by directives, such as ``attr:`` and others will be silently ignored.
-As a consequence the resulting dictionary will include no such options.
+If you have only a configuration file but not the whole package, you can still
+try to get data out of it with the help of the ``ignore_option_errors`` keyword
+argument. When it is set to ``True``, all options with errors possibly produced
+by directives, such as ``attr:`` and others, will be silently ignored.
+As a consequence, the resulting dictionary will include no such options.
 
 
 --------------------------------
index ce6053f170a6d355622d90bc195f0cb0f15054d4..68349df44e642f60ffcd744be189d31f56843fd3 100644 (file)
@@ -2028,51 +2028,117 @@ def find_on_path(importer, path_item, only=False):
                 path_item, os.path.join(path_item, 'EGG-INFO')
             )
         )
-    else:
-        try:
-            entries = os.listdir(path_item)
-        except (PermissionError, NotADirectoryError):
-            return
-        except OSError as e:
-            # Ignore the directory if does not exist, not a directory or we
-            # don't have permissions
-            if (e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT)
-                # Python 2 on Windows needs to be handled this way :(
-               or hasattr(e, "winerror") and e.winerror == 267):
-                return
+        return
+
+    entries = safe_listdir(path_item)
+
+    # for performance, before sorting by version,
+    # screen entries for only those that will yield
+    # distributions
+    filtered = (
+        entry
+        for entry in entries
+        if dist_factory(path_item, entry, only)
+    )
+
+    # scan for .egg and .egg-info in directory
+    path_item_entries = _by_version_descending(filtered)
+    for entry in path_item_entries:
+        fullpath = os.path.join(path_item, entry)
+        factory = dist_factory(path_item, entry, only)
+        for dist in factory(fullpath):
+            yield dist
+
+
+def dist_factory(path_item, entry, only):
+    """
+    Return a dist_factory for a path_item and entry
+    """
+    lower = entry.lower()
+    is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info')))
+    return (
+        distributions_from_metadata
+        if is_meta else
+        find_distributions
+        if not only and _is_egg_path(entry) else
+        resolve_egg_link
+        if not only and lower.endswith('.egg-link') else
+        NoDists()
+    )
+
+
+class NoDists:
+    """
+    >>> bool(NoDists())
+    False
+
+    >>> list(NoDists()('anything'))
+    []
+    """
+    def __bool__(self):
+        return False
+    if six.PY2:
+        __nonzero__ = __bool__
+
+    def __call__(self, fullpath):
+        return iter(())
+
+
+def safe_listdir(path):
+    """
+    Attempt to list contents of path, but suppress some exceptions.
+    """
+    try:
+        return os.listdir(path)
+    except (PermissionError, NotADirectoryError):
+        pass
+    except OSError as e:
+        # Ignore the directory if does not exist, not a directory or
+        # permission denied
+        ignorable = (
+            e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT)
+            # Python 2 on Windows needs to be handled this way :(
+            or getattr(e, "winerror", None) == 267
+        )
+        if not ignorable:
             raise
-        # scan for .egg and .egg-info in directory
-        path_item_entries = _by_version_descending(entries)
-        for entry in path_item_entries:
-            lower = entry.lower()
-            if lower.endswith('.egg-info') or lower.endswith('.dist-info'):
-                fullpath = os.path.join(path_item, entry)
-                if os.path.isdir(fullpath):
-                    # egg-info directory, allow getting metadata
-                    if len(os.listdir(fullpath)) == 0:
-                        # Empty egg directory, skip.
-                        continue
-                    metadata = PathMetadata(path_item, fullpath)
-                else:
-                    metadata = FileMetadata(fullpath)
-                yield Distribution.from_location(
-                    path_item, entry, metadata, precedence=DEVELOP_DIST
-                )
-            elif not only and _is_egg_path(entry):
-                dists = find_distributions(os.path.join(path_item, entry))
-                for dist in dists:
-                    yield dist
-            elif not only and lower.endswith('.egg-link'):
-                with open(os.path.join(path_item, entry)) as entry_file:
-                    entry_lines = entry_file.readlines()
-                for line in entry_lines:
-                    if not line.strip():
-                        continue
-                    path = os.path.join(path_item, line.rstrip())
-                    dists = find_distributions(path)
-                    for item in dists:
-                        yield item
-                    break
+    return ()
+
+
+def distributions_from_metadata(path):
+    root = os.path.dirname(path)
+    if os.path.isdir(path):
+        if len(os.listdir(path)) == 0:
+            # empty metadata dir; skip
+            return
+        metadata = PathMetadata(root, path)
+    else:
+        metadata = FileMetadata(path)
+    entry = os.path.basename(path)
+    yield Distribution.from_location(
+        root, entry, metadata, precedence=DEVELOP_DIST,
+    )
+
+
+def non_empty_lines(path):
+    """
+    Yield non-empty lines from file at path
+    """
+    return (line.rstrip() for line in open(path) if line.strip())
+
+
+def resolve_egg_link(path):
+    """
+    Given a path to an .egg-link, resolve distributions
+    present in the referenced path.
+    """
+    referenced_paths = non_empty_lines(path)
+    resolved_paths = (
+        os.path.join(os.path.dirname(path), ref)
+        for ref in referenced_paths
+    )
+    dist_groups = map(find_distributions, resolved_paths)
+    return next(dist_groups, ())
 
 
 register_finder(pkgutil.ImpImporter, find_on_path)
@@ -2250,9 +2316,7 @@ def _is_egg_path(path):
     """
     Determine if given path appears to be an egg.
     """
-    return (
-        path.lower().endswith('.egg')
-    )
+    return path.lower().endswith('.egg')
 
 
 def _is_unpacked_egg(path):
index ea649893f1912ca9c63ef5d68d2fda1ab9aab623..e5ebf4b8dfaf6be5fffdffd6ff603a303ae85809 100755 (executable)
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 36.4.0
+current_version = 36.5.0
 commit = True
 tag = True
 
index eb939ff370b179ef7cb74c90ecc61a678631d35a..ee968d9a89c885bf5165dc2da1ddfea7b2bd0377 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -89,7 +89,7 @@ def pypi_link(pkg_filename):
 
 setup_params = dict(
     name="setuptools",
-    version="36.4.0",
+    version="36.5.0",
     description="Easily download, build, install, upgrade, and uninstall "
         "Python packages",
     author="Python Packaging Authority",
index 2acc817a6649e6414dae40ef6deee85f4a83a9dc..a6363b1856c78d54ce86e64e506bc75ad38b63bf 100755 (executable)
@@ -893,7 +893,7 @@ class PackageIndex(Environment):
 
         if rev is not None:
             self.info("Updating to %s", rev)
-            os.system("(cd %s && hg up -C -r %s >&-)" % (
+            os.system("(cd %s && hg up -C -r %s -q)" % (
                 filename,
                 rev,
             ))
index 17b8793cf66a1388e8f603c1e418b7c4ffab6bcf..9dbd3c86ed6f65427cf21fffb08b55f4f257d66a 100644 (file)
@@ -1,5 +1,6 @@
 import glob
 import os
+import sys
 
 from pytest import yield_fixture
 from pytest_fixture_config import yield_requires_config
@@ -39,6 +40,9 @@ def test_pip_upgrade_from_source(virtualenv):
     Check pip can upgrade setuptools from source.
     """
     dist_dir = virtualenv.workspace
+    if sys.version_info < (2, 7):
+        # Python 2.6 support was dropped in wheel 0.30.0.
+        virtualenv.run('pip install -U "wheel<0.30.0"')
     # Generate source distribution / wheel.
     virtualenv.run(' && '.join((
         'cd {source}',