[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