summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2012-07-21 17:20:05 -0400
committerJason R. Coombs <jaraco@jaraco.com>2012-07-21 17:20:05 -0400
commit7e5b8c11932a172701fb15a523fa52851f3dabc5 (patch)
tree0fccf7f8be20680aa3acff751b3c863ef4aba5d4
parent0e304af1678c960405fdc5ed59567040fa872d67 (diff)
parentc62d8121c4660daa4fd6132643b8e98918faf58f (diff)
downloadpython-setuptools-git-7e5b8c11932a172701fb15a523fa52851f3dabc5.tar.gz
Merged in dholth/distribute (pull request #11)
--HG-- branch : distribute extra : rebase_source : 1598139e29770c9ef7cdcfbe8e64145c9e13b330
-rw-r--r--pkg_resources.py88
-rw-r--r--setuptools/tests/test_dist_info.py65
2 files changed, 149 insertions, 4 deletions
diff --git a/pkg_resources.py b/pkg_resources.py
index a61c0efe..27b9f834 100644
--- a/pkg_resources.py
+++ b/pkg_resources.py
@@ -1746,7 +1746,7 @@ def find_on_path(importer, path_item, only=False):
# scan for .egg and .egg-info in directory
for entry in os.listdir(path_item):
lower = entry.lower()
- if lower.endswith('.egg-info'):
+ 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
@@ -2119,6 +2119,8 @@ def _remove_md5_fragment(location):
class Distribution(object):
"""Wrap an actual or potential sys.path entry w/metadata"""
+ PKG_INFO = 'PKG-INFO'
+
def __init__(self,
location=None, metadata=None, project_name=None, version=None,
py_version=PY_MAJOR, platform=None, precedence = EGG_DIST
@@ -2136,12 +2138,14 @@ class Distribution(object):
def from_location(cls,location,basename,metadata=None,**kw):
project_name, version, py_version, platform = [None]*4
basename, ext = os.path.splitext(basename)
- if ext.lower() in (".egg",".egg-info"):
+ if ext.lower() in _distributionImpl:
+ # .dist-info gets much metadata differently
match = EGG_NAME(basename)
if match:
project_name, version, py_version, platform = match.group(
'name','ver','pyver','plat'
)
+ cls = _distributionImpl[ext.lower()]
return cls(
location, metadata, project_name=project_name, version=version,
py_version=py_version, platform=platform, **kw
@@ -2204,13 +2208,13 @@ class Distribution(object):
try:
return self._version
except AttributeError:
- for line in self._get_metadata('PKG-INFO'):
+ for line in self._get_metadata(self.PKG_INFO):
if line.lower().startswith('version:'):
self._version = safe_version(line.split(':',1)[1].strip())
return self._version
else:
raise ValueError(
- "Missing 'Version:' header and/or PKG-INFO file", self
+ "Missing 'Version:' header and/or %s file" % self.PKG_INFO, self
)
version = property(version)
@@ -2441,6 +2445,82 @@ class Distribution(object):
extras = property(extras)
+class DistInfoDistribution(Distribution):
+ """Wrap an actual or potential sys.path entry w/metadata, .dist-info style"""
+ PKG_INFO = 'METADATA'
+ EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])")
+
+ @property
+ def _parsed_pkg_info(self):
+ """Parse and cache metadata"""
+ try:
+ return self._pkg_info
+ except AttributeError:
+ from email.parser import Parser
+ self._pkg_info = Parser().parsestr(self.get_metadata(self.PKG_INFO))
+ return self._pkg_info
+
+ @property
+ def _dep_map(self):
+ try:
+ return self.__dep_map
+ except AttributeError:
+ self.__dep_map = self._compute_dependencies()
+ return self.__dep_map
+
+ def _preparse_requirement(self, requires_dist):
+ """Convert 'Foobar (1); baz' to ('Foobar ==1', 'baz')
+ Split environment marker, add == prefix to version specifiers as
+ necessary, and remove parenthesis.
+ """
+ parts = requires_dist.split(';', 1) + ['']
+ distvers = parts[0].strip()
+ mark = parts[1].strip()
+ distvers = re.sub(self.EQEQ, r"\1==\2\3", distvers)
+ distvers = distvers.replace('(', '').replace(')', '')
+ return (distvers, mark)
+
+ def _compute_dependencies(self):
+ """Recompute this distribution's dependencies."""
+ def dummy_marker(marker):
+ def marker_fn(environment=None, override=None):
+ return True
+ marker_fn.__doc__ = marker
+ return marker_fn
+ try:
+ from markerlib import as_function
+ except ImportError:
+ as_function = dummy_marker
+ dm = self.__dep_map = {None: []}
+
+ reqs = []
+ # Including any condition expressions
+ for req in self._parsed_pkg_info.get_all('Requires-Dist') or []:
+ distvers, mark = self._preparse_requirement(req)
+ parsed = parse_requirements(distvers).next()
+ parsed.marker_fn = as_function(mark)
+ reqs.append(parsed)
+
+ def reqs_for_extra(extra):
+ for req in reqs:
+ if req.marker_fn(override={'extra':extra}):
+ yield req
+
+ common = set(reqs_for_extra(None))
+ dm[None].extend(common)
+
+ for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []:
+ extra = safe_extra(extra.strip())
+ dm[extra] = list(set(reqs_for_extra(extra)) - common)
+
+ return dm
+
+
+_distributionImpl = {'.egg': Distribution,
+ '.egg-info': Distribution,
+ '.dist-info': DistInfoDistribution }
+
+
def issue_warning(*args,**kw):
level = 1
g = globals()
diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py
new file mode 100644
index 00000000..119cc68b
--- /dev/null
+++ b/setuptools/tests/test_dist_info.py
@@ -0,0 +1,65 @@
+"""Test .dist-info style distributions.
+"""
+import os, shutil, tempfile, unittest
+import pkg_resources
+from pkg_resources import Requirement
+try:
+ import markerlib
+ has_markerlib = True
+except:
+ has_markerlib = False
+
+class TestDistInfo(unittest.TestCase):
+
+ def test_distinfo(self):
+ dists = {}
+ for d in pkg_resources.find_distributions(self.tmpdir):
+ dists[d.project_name] = d
+
+ assert len(dists) == 2, dists
+
+ unversioned = dists['UnversionedDistribution']
+ versioned = dists['VersionedDistribution']
+
+ assert versioned.version == '2.718' # from filename
+ assert unversioned.version == '0.3' # from METADATA
+
+ @unittest.skipIf(not has_markerlib,
+ "install markerlib to test conditional dependencies")
+ def test_conditional_dependencies(self):
+ requires = [Requirement.parse('splort==4'),
+ Requirement.parse('quux>=1.1')]
+
+ for d in pkg_resources.find_distributions(self.tmpdir):
+ self.assertEquals(d.requires(), requires[:1])
+ self.assertEquals(d.requires(extras=('baz',)), requires)
+ self.assertEquals(d.extras, ['baz'])
+
+ def setUp(self):
+ self.tmpdir = tempfile.mkdtemp()
+ versioned = os.path.join(self.tmpdir,
+ 'VersionedDistribution-2.718.dist-info')
+ os.mkdir(versioned)
+ open(os.path.join(versioned, 'METADATA'), 'w+').write(
+"""Metadata-Version: 1.2
+Name: VersionedDistribution
+Requires-Dist: splort (4)
+Provides-Extra: baz
+Requires-Dist: quux (>=1.1); extra == 'baz'
+""")
+
+ unversioned = os.path.join(self.tmpdir,
+ 'UnversionedDistribution.dist-info')
+ os.mkdir(unversioned)
+ open(os.path.join(unversioned, 'METADATA'), 'w+').write(
+"""Metadata-Version: 1.2
+Name: UnversionedDistribution
+Version: 0.3
+Requires-Dist: splort (==4)
+Provides-Extra: baz
+Requires-Dist: quux (>=1.1); extra == 'baz'
+""")
+
+ def tearDown(self):
+ shutil.rmtree(self.tmpdir)
+