[Python-checkins] python/nondist/sandbox/setuptools pkg_resources.py, 1.11, 1.12

pje@users.sourceforge.net pje at users.sourceforge.net
Sun May 22 21:40:24 CEST 2005


Update of /cvsroot/python/python/nondist/sandbox/setuptools
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13209

Modified Files:
	pkg_resources.py 
Log Message:
Distribution metadata parsing: distribution objects can now extract their
version from PKG-INFO and their dependencies from depends.txt, including
optional dependencies.


Index: pkg_resources.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- pkg_resources.py	22 May 2005 18:16:59 -0000	1.11
+++ pkg_resources.py	22 May 2005 19:40:22 -0000	1.12
@@ -14,23 +14,19 @@
 method.
 """
 __all__ = [
-    'register_loader_type', 'get_provider', 'IResourceProvider',
+    'register_loader_type', 'get_provider', 'IResourceProvider', 
     'ResourceManager', 'AvailableDistributions', 'require', 'resource_string',
     'resource_stream', 'resource_filename', 'set_extraction_path',
     'cleanup_resources', 'parse_requirements', 'parse_version',
-    'compatible_platforms', 'get_platform',
+    'compatible_platforms', 'get_platform', 'IMetadataProvider',
     'ResolutionError', 'VersionConflict', 'DistributionNotFound',
-    'Distribution', 'Requirement', # 'glob_resources'
+    'InvalidOption', 'Distribution', 'Requirement', 'yield_lines',
+    'split_sections', # 'glob_resources'
 ]
 
 import sys, os, zipimport, time, re
 
-def _sort_dists(dists):
-    tmp = [(dist.version,dist) for dist in dists]
-    tmp.sort()
-    dists[::-1] = [d for v,d in tmp]
-
-class ResolutionError(ImportError):
+class ResolutionError(Exception):
     """Abstract base for dependency resolution errors"""
 
 class VersionConflict(ResolutionError):
@@ -39,6 +35,10 @@
 class DistributionNotFound(ResolutionError):
     """A requested distribution was not found"""
 
+class InvalidOption(ResolutionError):
+    """Invalid or unrecognized option name for a distribution"""
+
+
 _provider_factories = {}
 
 def register_loader_type(loader_type, provider_factory):
@@ -80,7 +80,22 @@
     return False
 
 
-class IResourceProvider:
+class IMetadataProvider:
+
+    def has_metadata(name):
+        """Does the package's distribution contain the named metadata?"""
+
+    def get_metadata(name):
+        """The named metadata resource as a string"""
+
+    def get_metadata_lines(name):
+        """Yield named metadata resource as list of non-blank non-comment lines
+
+       Leading and trailing whitespace is stripped from each line, and lines
+       with ``#`` as the first non-blank character are omitted.
+       """
+
+class IResourceProvider(IMetadataProvider):
 
     """An object that provides access to package resources"""
 
@@ -102,25 +117,10 @@
     def has_resource(resource_name):
         """Does the package contain the named resource?"""
 
-    def has_metadata(name):
-        """Does the package's distribution contain the named metadata?"""
-
-    def get_metadata(name):
-        """The named metadata resource as a string"""
-
-    def get_metadata_lines(name):
-        """Yield named metadata resource as list of non-blank non-comment lines
-
-       Leading and trailing whitespace is stripped from each line, and lines
-       with ``#`` as the first non-blank character are omitted.
-       """
-
     # XXX list_resources?  glob_resources?
 
 
 
-
-
 class AvailableDistributions(object):
     """Searchable snapshot of distributions on a search path"""
 
@@ -417,7 +417,6 @@
     XXX This doesn't work yet, because:
 
         * get_distro_source() isn't implemented
-        * Distribution.depends() isn't implemented
         * Distribution.install_on() isn't implemented
         * Requirement.options isn't implemented
         * AvailableDistributions.resolve() is untested
@@ -449,6 +448,7 @@
 
 
 
+
 class DefaultProvider:
     """Provides access to package resources in the filesystem"""
 
@@ -746,11 +746,12 @@
         if name:
             self.name = name.replace('_','-')
         if version:
-            self.version = version.replace('_','-')
+            self._version = version.replace('_','-')
 
         self.py_version = py_version
         self.platform = platform
         self.path = path_str
+        self.metadata = metadata
 
     def installed_on(self,path=None):
         """Is this distro installed on `path`? (defaults to ``sys.path``)"""
@@ -776,7 +777,6 @@
 
 
 
-
     # These properties have to be lazy so that we don't have to load any
     # metadata until/unless it's actually needed.  (i.e., some distributions
     # may not know their name or version without loading PKG-INFO)
@@ -800,17 +800,58 @@
 
     parsed_version = property(parsed_version)
 
+    #@property
+    def version(self):
+        try:
+            return self._version
+        except AttributeError:
+            for line in self.metadata.get_metadata_lines('PKG-INFO'):
+                if line.lower().startswith('version:'):
+                    self._version = line.split(':',1)[1].strip()
+                    return self._version
+            else:
+                raise AttributeError(
+                    "Missing Version: header in PKG-INFO", self
+                )
+    version = property(version)
 
 
 
 
+    #@property
+    def _dep_map(self):
+        try:
+            return self.__dep_map
+        except AttributeError:
+            dm = self.__dep_map = {None: []}
+            if self.metadata.has_metadata('depends.txt'):
+                for section,contents in split_sections(
+                    self.metadata.get_metadata_lines('depends.txt')
+                ):
+                    dm[section] = list(parse_requirements(contents))
+            return dm
 
+    _dep_map = property(_dep_map)
 
+    def depends(self,options=()):
+        """List of Requirements needed for this distro if `options` are used"""
+        dm = self._dep_map
+        deps = []
+        deps.extend(dm.get(None,()))
 
+        for opt in options:
+            try:
+                deps.extend(dm[opt.lower()])
+            except KeyError:
+                raise InvalidOption("No such option", self, opt)
+        return deps
 
 
 
-
+def _sort_dists(dists):
+    tmp = [(dist.version,dist) for dist in dists]
+    tmp.sort()
+    dists[::-1] = [d for v,d in tmp]
 
 
 
@@ -941,6 +982,33 @@
         os.makedirs(dirname)
 
 
+def split_sections(s):
+    """Split a string or iterable thereof into (section,content) pairs
+
+    Each ``section`` is a lowercase version of the section header ("[section]")
+    and each ``content`` is a list of stripped lines excluding blank lines and
+    comment-only lines.  If there are any such lines before the first section
+    header, they're returned in a first ``section`` of ``None``.
+    """
+    section = None
+    content = []
+    for line in yield_lines(s):
+        if line.startswith("["):
+            if line.endswith("]"):
+                if content:
+                    yield section, content
+                section = line[1:-1].strip().lower()
+                content = []
+            else:
+                raise ValueError("Invalid section heading", line)
+        else:
+            content.append(line)
+
+    # wrap up last segment
+    if content:
+        yield section, content
+
+
 # Set up global resource manager
 
 _manager = ResourceManager()
@@ -952,3 +1020,6 @@
 _initialize(globals())
 
 
+
+
+



More information about the Python-checkins mailing list