Commit 7e5b8c11 authored by Jason R. Coombs's avatar Jason R. Coombs

Merged in dholth/distribute (pull request #11)

--HG--
branch : distribute
extra : rebase_source : 1598139e29770c9ef7cdcfbe8e64145c9e13b330
parents 0e304af1 c62d8121
......@@ -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()
......
"""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)
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