Daniel Holth avatar Daniel Holth committed 0c805a7

find .dist-info distributions as well

Comments (0)

Files changed (1)

 
 import sys, os, zipimport, time, re, imp, types
 from urlparse import urlparse, urlunparse
+from email.parser import Parser
 
 try:
     frozenset
             # 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
 
 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
     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
         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)
 
     extras = property(extras)
 
 
+class DistInfoDistribution(Distribution):
+    """Wrap an actual or potential sys.path entry w/metadata, .dist-info style"""
+    PKG_INFO = 'METADATA'
+
+    @property
+    def _parsed_pkg_info(self):
+        """Parse and cache metadata"""
+        try:
+            return self._pkg_info
+        except AttributeError:
+            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:
+            dm = self.__dep_map = {None: []}
+            # Including condition expressions
+            # XXX parse condition expressions, extras
+            reqs = self._parsed_pkg_info.get_all('Requires-Dist')
+#            extras = self._parsed_pkg_info.get_all('Provides-Extra') or []
+#            for extra,reqs in split_sections(self._get_metadata(name)):
+#                if extra: extra = safe_extra(extra)
+            dm.setdefault(None,[]).extend(parse_requirements(reqs))
+            return dm
+
+    def requires(self,extras=()):
+        """List of Requirements needed for this distro if `extras` are used"""
+        dm = self._dep_map
+        deps = []
+        deps.extend(dm.get(None,()))
+        for ext in extras:
+            try:
+                deps.extend(dm[safe_extra(ext)])
+            except KeyError:
+                raise UnknownExtra(
+                    "%s has no such extra feature %r" % (self, ext)
+                )
+        return deps
+
+
+_distributionImpl = {'.egg': Distribution,
+                     '.egg-info': Distribution,
+                     '.dist-info': DistInfoDistribution }
+
+
 def issue_warning(*args,**kw):
     level = 1
     g = globals()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.