[Python-checkins] distutils2: Added fallback support for .egg-info distributions
tarek.ziade
python-checkins at python.org
Mon May 31 01:56:09 CEST 2010
tarek.ziade pushed a838155c9fe2 to distutils2:
http://hg.python.org/distutils2/rev/a838155c9fe2
changeset: 181:a838155c9fe2
user: Josip Djolonga
date: Sat May 29 18:02:57 2010 +0200
summary: Added fallback support for .egg-info distributions
files: src/distutils2/_backport/pkgutil.py, src/distutils2/_backport/tests/test_pkgutil.py
diff --git a/src/distutils2/_backport/pkgutil.py b/src/distutils2/_backport/pkgutil.py
--- a/src/distutils2/_backport/pkgutil.py
+++ b/src/distutils2/_backport/pkgutil.py
@@ -17,8 +17,9 @@
'get_importer', 'iter_importers', 'get_loader', 'find_loader',
'walk_packages', 'iter_modules',
'ImpImporter', 'ImpLoader', 'read_code', 'extend_path',
- 'Distribution', 'distinfo_dirname', 'get_distributions',
- 'get_distribution', 'get_file_users',
+ 'Distribution', 'EggInfoDistribution', 'distinfo_dirname',
+ 'get_distributions', 'get_distribution', 'get_file_users',
+ 'provides_distribution', 'obsoletes_distribution',
]
def read_code(stream):
@@ -604,7 +605,7 @@
name = ''
"""The name of the distribution."""
metadata = None
- """A :class:`distutils2.metadata.DistributionMetadata` instance loaded with
+ """A :class:`distutils2.metadata.DistributionMetadata` instance loaded with
the distribution's METADATA file."""
requested = False
"""A boolean that indicates whether the REQUESTED metadata file is present
@@ -646,7 +647,7 @@
def uses(self, path):
"""
- Returns ``True`` if path is listed in RECORD. *path* can be a local
+ Returns ``True`` if path is listed in RECORD. *path* can be a local
absolute path or a relative ``'/'``-separated path.
:rtype: boolean
@@ -709,6 +710,29 @@
for path, md5, size in self._get_records(local):
yield path
+class EggInfoDistribution:
+ """Created with the *path* of the ``.egg-info`` directory or file provided
+ to the constructor. It reads the metadata contained in the file itself, or
+ if the given path happens to be a directory, the metadata is read from the
+ file PKG-INFO under that directory."""
+
+ name = ''
+ """The name of the distribution."""
+ metadata = None
+ """A :class:`distutils2.metadata.DistributionMetadata` instance loaded with
+ the distribution's METADATA file."""
+
+ def __init__(self, path):
+ if os.path.isdir(path):
+ path = os.path.join(path, 'PKG-INFO')
+ self.metadata = DistributionMetadata(path=path)
+ self.name = self.metadata['name']
+
+ def get_installed_files(self, local=False):
+ return []
+
+ def uses(self, path):
+ return False
def _normalize_dist_name(name):
"""Returns a normalized name from the given *name*.
@@ -719,7 +743,7 @@
"""
The *name* and *version* parameters are converted into their
filename-escaped form, i.e. any ``'-'`` characters are replaced with ``'_'``
- other than the one in ``'dist-info'`` and the one separating the name from
+ other than the one in ``'dist-info'`` and the one separating the name from
the version number.
:parameter name: is converted to a standard distribution name by replacing
@@ -743,13 +767,15 @@
normalized_version = version
return '-'.join([name, normalized_version]) + file_extension
-def get_distributions():
+def get_distributions(use_egg_info = False):
"""
Provides an iterator that looks for ``.dist-info`` directories in
``sys.path`` and returns :class:`Distribution` instances for each one of
- them.
+ them. If the parameters *use_egg_info* is ``True``, then the ``.egg-info``
+ files and directores are iterated as well.
- :rtype: iterator of :class:`Distribution` instances"""
+ :rtype: iterator of :class:`Distribution` and :class:`EggInfoDistribution`
+ instances"""
for path in sys.path:
realpath = os.path.realpath(path)
if not os.path.isdir(realpath):
@@ -758,35 +784,50 @@
if dir.endswith('.dist-info'):
dist = Distribution(os.path.join(realpath, dir))
yield dist
+ elif use_egg_info and dir.endswith('.egg-info'):
+ dist = EggInfoDistribution(os.path.join(realpath, dir))
+ yield dist
-def get_distribution(name):
+def get_distribution(name, use_egg_info = False):
"""
Scans all elements in ``sys.path`` and looks for all directories ending with
``.dist-info``. Returns a :class:`Distribution` corresponding to the
``.dist-info`` directory that contains the METADATA that matches *name* for
- the *name* metadata.
+ the *name* metadata field.
+ If no distribution exists with the given *name* and the parameter
+ *use_egg_info* is set to ``True``, then all files and directories ending
+ with ``.egg-info`` are scanned. A :class:`EggInfoDistribution` instance is
+ returned if one is found that has metadata that matches *name* for the
+ *name* metadata field.
This function only returns the first result founded, as no more than one
value is expected. If the directory is not found, ``None`` is returned.
- :rtype: :class:`Distribution` or None"""
+ :rtype: :class:`Distribution` or :class:`EggInfoDistribution: or None"""
found = None
for dist in get_distributions():
if dist.name == name:
found = dist
break
+ if use_egg_info:
+ for dist in get_distributions(True):
+ if dist.name == name:
+ found = dist
+ break
return found
-def obsoletes_distribution(name, version=None):
+def obsoletes_distribution(name, version=None, use_egg_info = False):
"""
Iterates over all distributions to find which distributions obsolete *name*.
If a *version* is provided, it will be used to filter the results.
+ If the argument *use_egg_info* is set to ``True``, then ``.egg-info``
+ distributions will be considered as well.
:type name: string
:type version: string
:parameter name:
"""
- for dist in get_distributions():
+ for dist in get_distributions(use_egg_info):
obsoleted = dist.metadata['Obsoletes-Dist'] + dist.metadata['Obsoletes']
for obs in obsoleted:
o_components = obs.split(' ', 1)
@@ -804,14 +845,16 @@
yield dist
break
-def provides_distribution(name, version=None):
+def provides_distribution(name, version=None, use_egg_info = False):
"""
Iterates over all distributions to find which distributions provide *name*.
If a *version* is provided, it will be used to filter the results. Scans
all elements in ``sys.path`` and looks for all directories ending with
``.dist-info``. Returns a :class:`Distribution` corresponding to the
``.dist-info`` directory that contains a ``METADATA`` that matches *name*
- for the name metadata.
+ for the name metadata. If the argument *use_egg_info* is set to ``True``,
+ then all files and directories ending with ``.egg-info`` are considered
+ as well and returns an :class:`EggInfoDistribution` instance.
This function only returns the first result founded, since no more than
one values are expected. If the directory is not found, returns ``None``.
@@ -829,7 +872,7 @@
except ValueError:
raise DistutilsError('Invalid name or version')
- for dist in get_distributions():
+ for dist in get_distributions(use_egg_info):
provided = dist.metadata['Provides-Dist'] + dist.metadata['Provides']
for p in provided:
diff --git a/src/distutils2/_backport/tests/test_pkgutil.py b/src/distutils2/_backport/tests/test_pkgutil.py
--- a/src/distutils2/_backport/tests/test_pkgutil.py
+++ b/src/distutils2/_backport/tests/test_pkgutil.py
@@ -216,7 +216,9 @@
found_dists = []
# Import the function in question
- from distutils2._backport.pkgutil import get_distributions, Distribution
+ from distutils2._backport.pkgutil import get_distributions, \
+ Distribution, \
+ EggInfoDistribution
# Verify the fake dists have been found.
dists = [ dist for dist in get_distributions() ]
@@ -231,13 +233,31 @@
# Finally, test that we found all that we were looking for
self.assertListEqual(sorted(found_dists), sorted(fake_dists))
+ # Now, test if the egg-info distributions are found correctly as well
+ fake_dists += [('bacon', '0.1'), ('cheese', '2.0.2')]
+ found_dists = []
+
+ dists = [ dist for dist in get_distributions(use_egg_info=True) ]
+ for dist in dists:
+ if not (isinstance(dist, Distribution) or \
+ isinstance(dist, EggInfoDistribution)):
+ self.fail("item received was not a Distribution or "
+ "EggInfoDistribution instance: %s" % type(dist))
+ if dist.name in dict(fake_dists).keys():
+ found_dists.append((dist.name, dist.metadata['version']))
+
+ self.assertListEqual(sorted(fake_dists), sorted(found_dists))
+
+
def test_get_distribution(self):
"""Test for looking up a distribution by name."""
# Test the lookup of the towel-stuff distribution
name = 'towel-stuff' # Note: This is different from the directory name
# Import the function in question
- from distutils2._backport.pkgutil import get_distribution, Distribution
+ from distutils2._backport.pkgutil import get_distribution, \
+ Distribution, \
+ EggInfoDistribution
# Lookup the distribution
dist = get_distribution(name)
@@ -250,6 +270,21 @@
# Verify partial name matching doesn't work
self.assertEqual(None, get_distribution('towel'))
+ # Verify that it does not find egg-info distributions, when not
+ # instructed to
+ self.assertEqual(None, get_distribution('bacon'))
+ self.assertEqual(None, get_distribution('cheese'))
+
+ # Now check that it works well in both situations, when egg-info
+ # is a file and directory respectively.
+ dist = get_distribution('cheese', use_egg_info=True)
+ self.assertTrue(isinstance(dist, EggInfoDistribution))
+ self.assertEqual(dist.name, 'cheese')
+
+ dist = get_distribution('bacon', use_egg_info=True)
+ self.assertTrue(isinstance(dist, EggInfoDistribution))
+ self.assertEqual(dist.name, 'bacon')
+
def test_get_file_users(self):
"""Test the iteration of distributions that use a file."""
from distutils2._backport.pkgutil import get_file_users, Distribution
@@ -265,46 +300,74 @@
from distutils2._backport.pkgutil import provides_distribution
from distutils2.errors import DistutilsError
+ checkLists = lambda x,y: self.assertListEqual(sorted(x), sorted(y))
+
l = [dist.name for dist in provides_distribution('truffles')]
- self.assertListEqual(l, ['choxie', 'towel-stuff'])
+ checkLists(l, ['choxie', 'towel-stuff'])
l = [dist.name for dist in provides_distribution('truffles', '1.0')]
- self.assertListEqual(l, ['choxie'])
+ checkLists(l, ['choxie'])
+
+ l = [dist.name for dist in provides_distribution('truffles', '1.0',
+ use_egg_info=True)]
+ checkLists(l, ['choxie', 'cheese'])
l = [dist.name for dist in provides_distribution('truffles', '1.1.2')]
- self.assertListEqual(l, ['towel-stuff'])
+ checkLists(l, ['towel-stuff'])
l = [dist.name for dist in provides_distribution('truffles', '1.1')]
- self.assertListEqual(l, ['towel-stuff'])
+ checkLists(l, ['towel-stuff'])
l = [dist.name for dist in provides_distribution('truffles', '!=1.1,<=2.0')]
- self.assertListEqual(l, ['choxie'])
+ checkLists(l, ['choxie'])
+
+ l = [dist.name for dist in provides_distribution('truffles', '!=1.1,<=2.0',
+ use_egg_info=True)]
+ checkLists(l, ['choxie', 'bacon', 'cheese'])
l = [dist.name for dist in provides_distribution('truffles', '>1.0')]
- self.assertListEqual(l, ['towel-stuff'])
+ checkLists(l, ['towel-stuff'])
+
+ l = [dist.name for dist in provides_distribution('truffles', '>1.5')]
+ checkLists(l, [])
+
+ l = [dist.name for dist in provides_distribution('truffles', '>1.5',
+ use_egg_info=True)]
+ checkLists(l, ['bacon'])
l = [dist.name for dist in provides_distribution('truffles', '>=1.0')]
- self.assertListEqual(l, ['choxie', 'towel-stuff'])
+ checkLists(l, ['choxie', 'towel-stuff'])
def test_obsoletes(self):
""" Test looking for distributions based on what they obsolete """
from distutils2._backport.pkgutil import obsoletes_distribution
from distutils2.errors import DistutilsError
+ checkLists = lambda x,y: self.assertListEqual(sorted(x), sorted(y))
+
l = [dist.name for dist in obsoletes_distribution('truffles', '1.0')]
- self.assertListEqual(l, [])
+ checkLists(l, [])
+
+ l = [dist.name for dist in obsoletes_distribution('truffles', '1.0',
+ use_egg_info=True)]
+ checkLists(l, ['cheese', 'bacon'])
+
l = [dist.name for dist in obsoletes_distribution('truffles', '0.8')]
- self.assertListEqual(l, ['choxie'])
+ checkLists(l, ['choxie'])
+
+ l = [dist.name for dist in obsoletes_distribution('truffles', '0.8',
+ use_egg_info=True)]
+ checkLists(l, ['choxie', 'cheese'])
l = [dist.name for dist in obsoletes_distribution('truffles', '0.9.6')]
- self.assertListEqual(l, ['choxie', 'towel-stuff'])
+ checkLists(l, ['choxie', 'towel-stuff'])
l = [dist.name for dist in obsoletes_distribution('truffles', '0.5.2.3')]
- self.assertListEqual(l, ['choxie', 'towel-stuff'])
+ checkLists(l, ['choxie', 'towel-stuff'])
l = [dist.name for dist in obsoletes_distribution('truffles', '0.2')]
- self.assertListEqual(l, ['towel-stuff'])
+ checkLists(l, ['towel-stuff'])
def test_suite():
--
Repository URL: http://hg.python.org/distutils2
More information about the Python-checkins
mailing list