Hello community,
here is the log from the commit of package python-importlib-metadata for
openSUSE:Factory checked in at 2019-09-23 12:08:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-importlib-metadata (Old)
and /work/SRC/openSUSE:Factory/.python-importlib-metadata.new.7948 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-importlib-metadata"
Mon Sep 23 12:08:50 2019 rev:7 rq:730194 version:0.21
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-importlib-metadata/python-importlib-metadata.changes
2019-08-09 16:51:41.961492925 +0200
+++
/work/SRC/openSUSE:Factory/.python-importlib-metadata.new.7948/python-importlib-metadata.changes
2019-09-23 12:08:52.853890801 +0200
@@ -1,0 +2,6 @@
+Wed Sep 11 14:57:50 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 0.21:
+ * various minor fixes
+
+-------------------------------------------------------------------
Old:
----
importlib_metadata-0.19.tar.gz
New:
----
importlib_metadata-0.21.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-importlib-metadata.spec ++++++
--- /var/tmp/diff_new_pack.4uK39a/_old 2019-09-23 12:08:53.685890664 +0200
+++ /var/tmp/diff_new_pack.4uK39a/_new 2019-09-23 12:08:53.689890663 +0200
@@ -21,7 +21,7 @@
%define skip_python3 1
%endif
Name: python-importlib-metadata
-Version: 0.19
+Version: 0.21
Release: 0
Summary: Tool to read metadata from Python packages
License: Apache-2.0
++++++ importlib_metadata-0.19.tar.gz -> importlib_metadata-0.21.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-0.19/PKG-INFO
new/importlib_metadata-0.21/PKG-INFO
--- old/importlib_metadata-0.19/PKG-INFO 2019-07-28 19:52:18.000000000
+0200
+++ new/importlib_metadata-0.21/PKG-INFO 2019-09-10 13:38:52.000000000
+0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: importlib_metadata
-Version: 0.19
+Version: 0.21
Summary: Read metadata from Python packages
Home-page: http://importlib-metadata.readthedocs.io/
Author: Barry Warsaw
@@ -51,5 +51,5 @@
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 2
Requires-Python: >=2.7,!=3.0,!=3.1,!=3.2,!=3.3
-Provides-Extra: testing
Provides-Extra: docs
+Provides-Extra: testing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata/__init__.py
new/importlib_metadata-0.21/importlib_metadata/__init__.py
--- old/importlib_metadata-0.19/importlib_metadata/__init__.py 2019-07-28
19:51:04.000000000 +0200
+++ new/importlib_metadata-0.21/importlib_metadata/__init__.py 2019-09-10
13:38:27.000000000 +0200
@@ -27,6 +27,7 @@
ModuleNotFoundError,
MetaPathFinder,
email_message_from_string,
+ ensure_is_path,
)
from importlib import import_module
from itertools import starmap
@@ -37,6 +38,7 @@
__all__ = [
'Distribution',
+ 'DistributionFinder',
'PackageNotFoundError',
'distribution',
'distributions',
@@ -176,7 +178,7 @@
metadata cannot be found.
"""
for resolver in cls._discover_resolvers():
- dists = resolver(name)
+ dists = resolver(DistributionFinder.Context(name=name))
dist = next(dists, None)
if dist is not None:
return dist
@@ -184,17 +186,34 @@
raise PackageNotFoundError(name)
@classmethod
- def discover(cls):
+ def discover(cls, **kwargs):
"""Return an iterable of Distribution objects for all packages.
+ Pass a ``context`` or pass keyword arguments for constructing
+ a context.
+
+ :context: A ``DistributionFinder.Context`` object.
:return: Iterable of Distribution objects for all packages.
"""
+ context = kwargs.pop('context', None)
+ if context and kwargs:
+ raise ValueError("cannot accept context and kwargs")
+ context = context or DistributionFinder.Context(**kwargs)
return itertools.chain.from_iterable(
- resolver()
+ resolver(context)
for resolver in cls._discover_resolvers()
)
@staticmethod
+ def at(path):
+ """Return a Distribution for the indicated metadata path
+
+ :param path: a string or path-like object
+ :return: a concrete Distribution instance for the path
+ """
+ return PathDistribution(ensure_is_path(path))
+
+ @staticmethod
def _discover_resolvers():
"""Search the meta_path for resolvers."""
declared = (
@@ -231,6 +250,15 @@
@property
def files(self):
+ """Files in this distribution.
+
+ :return: List of PackagePath for this distribution or None
+
+ Result is `None` if the metadata file that enumerates files
+ (i.e. RECORD for dist-info or SOURCES.txt for egg-info) is
+ missing.
+ Result may be empty if the metadata exists but is empty.
+ """
file_lines = self._read_files_distinfo() or self._read_files_egginfo()
def make_file(name, hash=None, size_str=None):
@@ -240,7 +268,7 @@
result.dist = self
return result
- return file_lines and starmap(make_file, csv.reader(file_lines))
+ return file_lines and list(starmap(make_file, csv.reader(file_lines)))
def _read_files_distinfo(self):
"""
@@ -260,11 +288,11 @@
@property
def requires(self):
"""Generated requirements specified for this Distribution"""
- return self._read_dist_info_reqs() or self._read_egg_info_reqs()
+ reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs()
+ return reqs and list(reqs)
def _read_dist_info_reqs(self):
- spec = self.metadata['Requires-Dist']
- return spec and filter(None, spec.splitlines())
+ return self.metadata.get_all('Requires-Dist')
def _read_egg_info_reqs(self):
source = self.read_text('requires.txt')
@@ -322,15 +350,35 @@
A MetaPathFinder capable of discovering installed distributions.
"""
+ class Context:
+
+ name = None
+ """
+ Specific name for which a distribution finder should match.
+ """
+
+ def __init__(self, **kwargs):
+ vars(self).update(kwargs)
+
+ @property
+ def path(self):
+ """
+ The path that a distribution finder should search.
+ """
+ return vars(self).get('path', sys.path)
+
+ @property
+ def pattern(self):
+ return '.*' if self.name is None else re.escape(self.name)
+
@abc.abstractmethod
- def find_distributions(self, name=None, path=None):
+ def find_distributions(self, context=Context()):
"""
Find distributions.
Return an iterable of all Distribution instances capable of
- loading the metadata for packages matching the ``name``
- (or all names if not supplied) along the paths in the list
- of directories ``path`` (defaults to sys.path).
+ loading the metadata for packages matching the ``context``,
+ a DistributionFinder.Context instance.
"""
@@ -342,19 +390,16 @@
of Python that do not have a PathFinder find_distributions().
"""
- def find_distributions(self, name=None, path=None):
+ def find_distributions(self, context=DistributionFinder.Context()):
"""
Find distributions.
Return an iterable of all Distribution instances capable of
- loading the metadata for packages matching the ``name``
- (or all names if not supplied) along the paths in the list
- of directories ``path`` (defaults to sys.path).
- """
- if path is None:
- path = sys.path
- pattern = '.*' if name is None else re.escape(name)
- found = self._search_paths(pattern, path)
+ loading the metadata for packages matching ``context.name``
+ (or all names if ``None`` indicated) along the paths in the list
+ of directories ``context.path``.
+ """
+ found = self._search_paths(context.pattern, context.path)
return map(PathDistribution, found)
@classmethod
@@ -396,7 +441,11 @@
class PathDistribution(Distribution):
def __init__(self, path):
- """Construct a distribution from a path to the metadata directory."""
+ """Construct a distribution from a path to the metadata directory.
+
+ :param path: A pathlib.Path or similar object supporting
+ .joinpath(), __div__, .parent, and .read_text().
+ """
self._path = path
def read_text(self, filename):
@@ -418,12 +467,12 @@
return Distribution.from_name(package)
-def distributions():
+def distributions(**kwargs):
"""Get all ``Distribution`` instances in the current environment.
:return: An iterable of ``Distribution`` instances.
"""
- return Distribution.discover()
+ return Distribution.discover(**kwargs)
def metadata(package):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata/_compat.py
new/importlib_metadata-0.21/importlib_metadata/_compat.py
--- old/importlib_metadata-0.19/importlib_metadata/_compat.py 2019-07-28
19:51:04.000000000 +0200
+++ new/importlib_metadata-0.21/importlib_metadata/_compat.py 2019-09-10
13:38:27.000000000 +0200
@@ -89,3 +89,12 @@
#
https://bitbucket.org/pypy/pypy/issues/3021/ioopen-directory-leaks-a-file-descriptor
PYPY_OPEN_BUG = getattr(sys, 'pypy_version_info', (9, 9, 9))[:3] <= (7, 1, 1)
+
+
+def ensure_is_path(ob):
+ """Construct a Path from ob even if it's already one.
+ Specialized for Python 3.4.
+ """
+ if (3,) < sys.version_info < (3, 5):
+ ob = str(ob) # pragma: nocover
+ return pathlib.Path(ob)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata/docs/changelog.rst
new/importlib_metadata-0.21/importlib_metadata/docs/changelog.rst
--- old/importlib_metadata-0.19/importlib_metadata/docs/changelog.rst
2019-07-28 19:51:04.000000000 +0200
+++ new/importlib_metadata-0.21/importlib_metadata/docs/changelog.rst
2019-09-10 13:38:27.000000000 +0200
@@ -2,6 +2,30 @@
importlib_metadata NEWS
=========================
+0.21
+====
+* ``importlib.metadata`` now exposes the ``DistributionFinder``
+ metaclass and references it in the docs for extending the
+ search algorithm.
+* Add ``Distribution.at`` for constructing a Distribution object
+ from a known metadata directory on the file system. Closes #80.
+* Distribution finders now receive a context object that
+ supplies ``.path`` and ``.name`` properties. This change
+ introduces a fundamental backward incompatibility for
+ any projects implementing a ``find_distributions`` method
+ on a ``MetaPathFinder``. This new layer of abstraction
+ allows this context to be supplied directly or constructed
+ on demand and opens the opportunity for a
+ ``find_distributions`` method to solicit additional
+ context from the caller. Closes #85.
+
+0.20
+====
+* Clarify in the docs that calls to ``.files`` could return
+ ``None`` when the metadata is not present. Closes #69.
+* Return all requirements and not just the first for dist-info
+ packages. Closes #67.
+
0.19
====
* Restrain over-eager egg metadata resolution.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata/docs/using.rst
new/importlib_metadata-0.21/importlib_metadata/docs/using.rst
--- old/importlib_metadata-0.19/importlib_metadata/docs/using.rst
2019-07-28 19:51:04.000000000 +0200
+++ new/importlib_metadata-0.21/importlib_metadata/docs/using.rst
2019-09-10 13:38:27.000000000 +0200
@@ -151,6 +151,13 @@
return s.encode('utf-8')
return s
+In the case where the metadata file listing files
+(RECORD or SOURCES.txt) is missing, ``files()`` will
+return ``None``. The caller may wish to wrap calls to
+``files()`` in `always_iterable
+<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.always_iterable>`_
+or otherwise guard against this condition if the target
+distribution is not known to have the metadata present.
.. _requirements:
@@ -158,10 +165,10 @@
-------------------------
To get the full set of requirements for a distribution, use the ``requires()``
-function. Note that this returns an iterator::
+function::
- >>> list(requires('wheel'))
- ["pytest (>=3.0.0) ; extra == 'test'"]
+ >>> requires('wheel')
+ ["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]
Distributions
@@ -210,23 +217,25 @@
interface expected of finders by Python's import system.
``importlib_metadata`` extends this protocol by looking for an optional
``find_distributions`` callable on the finders from
-``sys.meta_path``. If the finder has this method, it must return
-an iterator over instances of the ``Distribution`` abstract class. This
-method must have the signature::
+``sys.meta_path`` and presents this extended interface as the
+``DistributionFinder`` abstract base class, which defines this abstract
+method::
- def find_distributions(name=None, path=None):
+ @abc.abstractmethod
+ def find_distributions(context=DistributionFinder.Context()):
"""Return an iterable of all Distribution instances capable of
- loading the metadata for packages matching the name
- (or all names if not supplied) along the paths in the list
- of directories ``path`` (defaults to sys.path).
+ loading the metadata for packages for the indicated ``context``.
"""
+The ``DistributionFinder.Context`` object provides ``.path`` and ``.name``
+properties indicating the path to search and names to match and may
+supply other relevant context.
+
What this means in practice is that to support finding distribution package
metadata in locations other than the file system, you should derive from
-``Distribution`` and implement the ``load_metadata()`` method. This takes a
-single argument which is the name of the package whose metadata is being
-found. This instance of the ``Distribution`` base abstract class is what your
-finder's ``find_distributions()`` method should return.
+``Distribution`` and implement the ``load_metadata()`` method. Then from
+your finder, return instances of this derived ``Distribution`` in the
+``find_distributions()`` method.
.. _`entry point API`:
https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata/tests/test_api.py
new/importlib_metadata-0.21/importlib_metadata/tests/test_api.py
--- old/importlib_metadata-0.19/importlib_metadata/tests/test_api.py
2019-07-28 19:51:04.000000000 +0200
+++ new/importlib_metadata-0.21/importlib_metadata/tests/test_api.py
2019-09-10 13:38:27.000000000 +0200
@@ -1,7 +1,6 @@
import re
import textwrap
import unittest
-import itertools
from . import fixtures
from .. import (
@@ -72,9 +71,7 @@
assert re.match(self.version_pattern, __version__)
@staticmethod
- def _test_files(files_iter):
- assert isinstance(files_iter, Iterator), files_iter
- files = list(files_iter)
+ def _test_files(files):
root = files[0].root
for file in files:
assert file.root == root
@@ -114,16 +111,20 @@
requirements = requires('egginfo-file')
self.assertIsNone(requirements)
- def test_requires(self):
+ def test_requires_egg_info(self):
deps = requires('egginfo-pkg')
+ assert len(deps) == 2
assert any(
dep == 'wheel >= 1.0; python_version >= "2.7"'
for dep in deps
)
def test_requires_dist_info(self):
- deps = list(requires('distinfo-pkg'))
- assert deps and all(deps)
+ deps = requires('distinfo-pkg')
+ assert len(deps) == 2
+ assert all(deps)
+ assert 'wheel >= 1.0' in deps
+ assert "pytest; extra == 'test'" in deps
def test_more_complex_deps_requires_text(self):
requires = textwrap.dedent("""
@@ -156,11 +157,20 @@
class OffSysPathTests(fixtures.DistInfoPkgOffPath, unittest.TestCase):
def test_find_distributions_specified_path(self):
- dists = itertools.chain.from_iterable(
- resolver(path=[str(self.site_dir)])
- for resolver in Distribution._discover_resolvers()
- )
+ dists = Distribution.discover(path=[str(self.site_dir)])
assert any(
dist.metadata['Name'] == 'distinfo-pkg'
for dist in dists
)
+
+ def test_distribution_at_pathlib(self):
+ """Demonstrate how to load metadata direct from a directory.
+ """
+ dist_info_path = self.site_dir / 'distinfo_pkg-1.0.0.dist-info'
+ dist = Distribution.at(dist_info_path)
+ assert dist.version == '1.0.0'
+
+ def test_distribution_at_str(self):
+ dist_info_path = self.site_dir / 'distinfo_pkg-1.0.0.dist-info'
+ dist = Distribution.at(str(dist_info_path))
+ assert dist.version == '1.0.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata/tests/test_integration.py
new/importlib_metadata-0.21/importlib_metadata/tests/test_integration.py
--- old/importlib_metadata-0.19/importlib_metadata/tests/test_integration.py
1970-01-01 01:00:00.000000000 +0100
+++ new/importlib_metadata-0.21/importlib_metadata/tests/test_integration.py
2019-09-10 13:38:27.000000000 +0200
@@ -0,0 +1,22 @@
+import unittest
+import packaging.requirements
+import packaging.version
+
+from . import fixtures
+from .. import version
+
+
+class IntegrationTests(fixtures.DistInfoPkg, unittest.TestCase):
+
+ def test_package_spec_installed(self):
+ """
+ Illustrate the recommended procedure to determine if
+ a specified version of a package is installed.
+ """
+ def is_installed(package_spec):
+ req = packaging.requirements.Requirement(package_spec)
+ return version(req.name) in req.specifier
+
+ assert is_installed('distinfo-pkg==1.0')
+ assert is_installed('distinfo-pkg>=1.0,<2.0')
+ assert not is_installed('distinfo-pkg<1.0')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata/tests/test_main.py
new/importlib_metadata-0.21/importlib_metadata/tests/test_main.py
--- old/importlib_metadata-0.19/importlib_metadata/tests/test_main.py
2019-07-28 19:51:04.000000000 +0200
+++ new/importlib_metadata-0.21/importlib_metadata/tests/test_main.py
2019-09-10 13:38:27.000000000 +0200
@@ -40,7 +40,7 @@
class ImportTests(fixtures.DistInfoPkg, unittest.TestCase):
def test_import_nonexistent_module(self):
# Ensure that the MetadataPathFinder does not crash an import of a
- # non-existant module.
+ # non-existent module.
with self.assertRaises(ImportError):
importlib.import_module('does_not_exist')
@@ -170,6 +170,10 @@
for dist in dists
)
+ def test_invalid_usage(self):
+ with self.assertRaises(ValueError):
+ list(distributions(context='something', name='else'))
+
class DirectoryTest(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase):
def test_egg_info(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata.egg-info/PKG-INFO
new/importlib_metadata-0.21/importlib_metadata.egg-info/PKG-INFO
--- old/importlib_metadata-0.19/importlib_metadata.egg-info/PKG-INFO
2019-07-28 19:52:18.000000000 +0200
+++ new/importlib_metadata-0.21/importlib_metadata.egg-info/PKG-INFO
2019-09-10 13:38:51.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: importlib-metadata
-Version: 0.19
+Version: 0.21
Summary: Read metadata from Python packages
Home-page: http://importlib-metadata.readthedocs.io/
Author: Barry Warsaw
@@ -51,5 +51,5 @@
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 2
Requires-Python: >=2.7,!=3.0,!=3.1,!=3.2,!=3.3
-Provides-Extra: testing
Provides-Extra: docs
+Provides-Extra: testing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata.egg-info/SOURCES.txt
new/importlib_metadata-0.21/importlib_metadata.egg-info/SOURCES.txt
--- old/importlib_metadata-0.19/importlib_metadata.egg-info/SOURCES.txt
2019-07-28 19:52:18.000000000 +0200
+++ new/importlib_metadata-0.21/importlib_metadata.egg-info/SOURCES.txt
2019-09-10 13:38:52.000000000 +0200
@@ -25,6 +25,7 @@
importlib_metadata/tests/__init__.py
importlib_metadata/tests/fixtures.py
importlib_metadata/tests/test_api.py
+importlib_metadata/tests/test_integration.py
importlib_metadata/tests/test_main.py
importlib_metadata/tests/test_zip.py
importlib_metadata/tests/data/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-0.19/importlib_metadata.egg-info/requires.txt
new/importlib_metadata-0.21/importlib_metadata.egg-info/requires.txt
--- old/importlib_metadata-0.19/importlib_metadata.egg-info/requires.txt
2019-07-28 19:52:18.000000000 +0200
+++ new/importlib_metadata-0.21/importlib_metadata.egg-info/requires.txt
2019-09-10 13:38:51.000000000 +0200
@@ -12,6 +12,7 @@
rst.linker
[testing]
+packaging
[testing:python_version < "3.7"]
importlib_resources
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-0.19/setup.cfg
new/importlib_metadata-0.21/setup.cfg
--- old/importlib_metadata-0.19/setup.cfg 2019-07-28 19:52:18.000000000
+0200
+++ new/importlib_metadata-0.21/setup.cfg 2019-09-10 13:38:52.000000000
+0200
@@ -49,6 +49,7 @@
[options.extras_require]
testing =
importlib_resources; python_version < "3.7"
+ packaging
docs =
sphinx
rst.linker