Anonymous avatar Anonymous committed d885b2d

Added basic support for dist-info's, some pep8-compliance changes

Comments (0)

Files changed (1)

 # attribute is present to decide wether to reinstall the package
 _distribute = True
 
+
+__all__ = [
+    # Basic resource access and distribution/entry point discovery
+    'require', 'run_script', 'get_provider', 'get_distribution',
+    'load_entry_point', 'get_entry_map', 'get_entry_info', 'iter_entry_points',
+    'resource_string', 'resource_stream', 'resource_filename',
+    'resource_listdir', 'resource_exists', 'resource_isdir',
+
+    # Environmental control
+    'declare_namespace', 'working_set', 'add_activation_listener',
+    'find_distributions', 'set_extraction_path', 'cleanup_resources',
+    'get_default_cache',
+
+    # Primary implementation classes
+    'Environment', 'WorkingSet', 'ResourceManager',
+    'Distribution', 'Requirement', 'EntryPoint',
+
+    # Exceptions
+    'ResolutionError', 'VersionConflict', 'DistributionNotFound',
+    'UnknownExtra', 'ExtractionError',
+
+    # Parsing functions and string utilities
+    'parse_requirements', 'parse_version', 'safe_name', 'safe_version',
+    'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections',
+    'safe_extra', 'to_filename',
+
+    # filesystem utilities
+    'ensure_directory', 'normalize_path',
+
+    # Distribution "precedence" constants
+    'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST',
+
+    # "Provider" interfaces, implementations, and registration/lookup APIs
+    'IMetadataProvider', 'IResourceProvider', 'FileMetadata',
+    'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider',
+    'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider',
+    'register_finder', 'register_namespace_handler', 'register_loader_type',
+    'fixup_namespace_packages', 'get_importer',
+
+    # Deprecated/backward compatibility only
+    'run_main', 'AvailableDistributions',
+]
+
+
 def _bypass_ensure_directory(name, mode=0777):
     # Sandbox-bypassing version of ensure_directory()
     dirname, filename = split(name)
         mkdir(dirname, mode)
 
 
-
-
-
-
-
-
 def get_supported_platform():
     """Return this platform's maximum compatible version.
 
     If this condition occurs for any other platform with a version in its
     platform strings, this function should be extended accordingly.
     """
-    plat = get_build_platform(); m = macosVersionString.match(plat)
+    plat = get_build_platform()
+    m = macosVersionString.match(plat)
+
     if m is not None and sys.platform == "darwin":
         try:
             plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3))
     return plat
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-__all__ = [
-    # Basic resource access and distribution/entry point discovery
-    'require', 'run_script', 'get_provider',  'get_distribution',
-    'load_entry_point', 'get_entry_map', 'get_entry_info', 'iter_entry_points',
-    'resource_string', 'resource_stream', 'resource_filename',
-    'resource_listdir', 'resource_exists', 'resource_isdir',
-
-    # Environmental control
-    'declare_namespace', 'working_set', 'add_activation_listener',
-    'find_distributions', 'set_extraction_path', 'cleanup_resources',
-    'get_default_cache',
-
-    # Primary implementation classes
-    'Environment', 'WorkingSet', 'ResourceManager',
-    'Distribution', 'Requirement', 'EntryPoint',
-
-    # Exceptions
-    'ResolutionError','VersionConflict','DistributionNotFound','UnknownExtra',
-    'ExtractionError',
-
-    # Parsing functions and string utilities
-    'parse_requirements', 'parse_version', 'safe_name', 'safe_version',
-    'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections',
-    'safe_extra', 'to_filename',
-
-    # filesystem utilities
-    'ensure_directory', 'normalize_path',
-
-    # Distribution "precedence" constants
-    'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST',
-
-    # "Provider" interfaces, implementations, and registration/lookup APIs
-    'IMetadataProvider', 'IResourceProvider', 'FileMetadata',
-    'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider',
-    'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider',
-    'register_finder', 'register_namespace_handler', 'register_loader_type',
-    'fixup_namespace_packages', 'get_importer',
-
-    # Deprecated/backward compatibility only
-    'run_main', 'AvailableDistributions',
-]
 class ResolutionError(Exception):
     """Abstract base for dependency resolution errors"""
+
     def __repr__(self):
-        return self.__class__.__name__+repr(self.args)
+        return self.__class__.__name__ + repr(self.args)
+
 
 class VersionConflict(ResolutionError):
     """An already-installed version conflicts with the requested version"""
 
+
 class DistributionNotFound(ResolutionError):
     """A requested distribution was not found"""
 
+
 class UnknownExtra(ResolutionError):
     """Distribution doesn't have an "extra feature" of the given name"""
+
+
 _provider_factories = {}
 
 PY_MAJOR = sys.version[:3]
-EGG_DIST    = 3
+EGG_DIST = 3
 BINARY_DIST = 2
 SOURCE_DIST = 1
 CHECKOUT_DIST = 0
 DEVELOP_DIST = -1
 
+
 def register_loader_type(loader_type, provider_factory):
     """Register `provider_factory` to make providers for `loader_type`
 
     """
     _provider_factories[loader_type] = provider_factory
 
+
 def get_provider(moduleOrReq):
     """Return an IResourceProvider for the named module or requirement"""
-    if isinstance(moduleOrReq,Requirement):
+    if isinstance(moduleOrReq, Requirement):
         return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
     try:
         module = sys.modules[moduleOrReq]
     loader = getattr(module, '__loader__', None)
     return _find_adapter(_provider_factories, loader)(module)
 
+
 def _macosx_vers(_cache=[]):
     if not _cache:
         import platform
         _cache.append(version.split('.'))
     return _cache[0]
 
+
 def _macosx_arch(machine):
-    return {'PowerPC':'ppc', 'Power_Macintosh':'ppc'}.get(machine,machine)
+    return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine)
+
 
 def get_build_platform():
     """Return this platform's string for platform-specific distributions
             pass
     return plat
 
+
 macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)")
 darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)")
 get_platform = get_build_platform   # XXX backward compat
 
-def compatible_platforms(provided,required):
+
+def compatible_platforms(provided, required):
     """Can code for the `provided` platform run on the `required` platform?
 
     Returns true if either platform is ``None``, or the platforms are equal.
 
     XXX Needs compatibility checks for Linux and other unixy OSes.
     """
-    if provided is None or required is None or provided==required:
+    if provided is None or required is None or provided == required:
         return True     # easy case
 
     # Mac OS X special cases
             return False
 
 
-
         # is the required OS major update >= the provided one?
         if int(provMac.group(2)) > int(reqMac.group(2)):
             return False
 
 run_main = run_script   # backward compatibility
 
+
 def get_distribution(dist):
     """Return a current distribution object for a Requirement or string"""
-    if isinstance(dist,basestring): dist = Requirement.parse(dist)
-    if isinstance(dist,Requirement): dist = get_provider(dist)
-    if not isinstance(dist,Distribution):
+    if isinstance(dist, basestring): dist = Requirement.parse(dist)
+    if isinstance(dist, Requirement): dist = get_provider(dist)
+    if not isinstance(dist, Distribution):
         raise TypeError("Expected string, Requirement, or Distribution", dist)
     return dist
 
+
 def load_entry_point(dist, group, name):
     """Return `name` entry point of `group` for `dist` or raise ImportError"""
     return get_distribution(dist).load_entry_point(group, name)
 
+
 def get_entry_map(dist, group=None):
     """Return the entry point map for `group`, or the full entry map"""
     return get_distribution(dist).get_entry_map(group)
 
+
 def get_entry_info(dist, group, name):
     """Return the EntryPoint object for `group`+`name`, or ``None``"""
     return get_distribution(dist).get_entry_info(group, name)
         """Execute the named script in the supplied namespace dictionary"""
 
 
-
-
-
-
-
-
-
-
 class IResourceProvider(IMetadataProvider):
     """An object that provides access to package resources"""
 
         """List of resource names in the directory (like ``os.listdir()``)"""
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
 class WorkingSet(object):
     """A collection of active distributions on sys.path (or a similar list)"""
 
         for entry in entries:
             self.add_entry(entry)
 
-
     def add_entry(self, entry):
         """Add a path item to ``.entries``, finding any distributions on it
 
         for dist in find_distributions(entry, True):
             self.add(dist, entry, False)
 
-
-    def __contains__(self,dist):
+    def __contains__(self, dist):
         """True if `dist` is the active distribution for its project"""
         return self.by_key.get(dist.key) == dist
 
-
-
-
-
     def find(self, req):
         """Find a distribution matching requirement `req`
 
         """
         dist = self.by_key.get(req.key)
         if dist is not None and dist not in req:
-            raise VersionConflict(dist,req)     # XXX add more info
+            raise VersionConflict(dist, req)     # XXX add more info
         else:
             return dist
 
         ns['__name__'] = name
         self.require(requires)[0].run_script(script_name, ns)
 
-
-
     def __iter__(self):
         """Yield distributions for non-duplicate projects in the working set
 
         for item in self.entries:
             for key in self.entry_keys[item]:
                 if key not in seen:
-                    seen[key]=1
+                    seen[key] = 1
                     yield self.by_key[key]
 
     def add(self, dist, entry=None, insert=True):
 
         if entry is None:
             entry = dist.location
-        keys = self.entry_keys.setdefault(entry,[])
-        keys2 = self.entry_keys.setdefault(dist.location,[])
+        keys = self.entry_keys.setdefault(entry, [])
+        keys2 = self.entry_keys.setdefault(dist.location, [])
         if dist.key in self.by_key:
             return      # ignore hidden distros
 
                         env = Environment(self.entries)
                     dist = best[req.key] = env.best_match(req, self, installer)
                     if dist is None:
-                        raise DistributionNotFound(req)  # XXX put more info here
+                        raise DistributionNotFound(req) # XXX put more info
                 to_activate.append(dist)
             if dist not in req:
                 # Oops, the "best" so far conflicts with a dependency
-                raise VersionConflict(dist,req) # XXX put more info here
+                raise VersionConflict(dist, req) # XXX put more info here
             requirements.extend(dist.requires(req.extras)[::-1])
             processed[req] = True
 
         return to_activate    # return list of distros to activate
 
     def find_plugins(self,
-        plugin_env, full_env=None, installer=None, fallback=True
-    ):
+        plugin_env, full_env=None, installer=None, fallback=True):
         """Find all activatable distributions in `plugin_env`
 
         Example usage::
                 try:
                     resolvees = shadow_set.resolve(req, env, installer)
 
-                except ResolutionError,v:
+                except ResolutionError, v:
                     error_info[dist] = v    # save error info
                     if fallback:
                         continue    # try the next older version of project
 
         return distributions, error_info
 
-
-
-
-
     def require(self, *requirements):
         """Ensure that distributions matching `requirements` are activated
 
 
         return needed
 
-
     def subscribe(self, callback):
         """Invoke `callback` for all distributions (including existing ones)"""
         if callback in self.callbacks:
         for dist in self:
             callback(dist)
 
-
     def _added_new(self, dist):
         for callback in self.callbacks:
             callback(dist)
 
 
-
-
-
-
-
-
-
-
-
 class Environment(object):
     """Searchable snapshot of distributions on a search path"""
 
-    def __init__(self, search_path=None, platform=get_supported_platform(), python=PY_MAJOR):
+    def __init__(self, search_path=None, platform=get_supported_platform(),
+                 python=PY_MAJOR):
         """Snapshot distributions available on a search path
 
         Any distributions found on `search_path` are added to the environment.
         is returned.
         """
         return (self.python is None or dist.py_version is None
-            or dist.py_version==self.python) \
-           and compatible_platforms(dist.platform,self.platform)
+            or dist.py_version == self.python) \
+           and compatible_platforms(dist.platform, self.platform)
 
     def remove(self, dist):
         """Remove `dist` from the environment"""
                 if dist.key in self._cache:
                     _sort_dists(self._cache[dist.key])
 
-
     def best_match(self, req, working_set, installer=None):
         """Find distribution best matching `req` and usable on `working_set`
 
         for key in self._distmap.keys():
             if self[key]: yield key
 
-
-
-
     def __iadd__(self, other):
         """In-place addition of a distribution or environment"""
-        if isinstance(other,Distribution):
+        if isinstance(other, Distribution):
             self.add(other)
-        elif isinstance(other,Environment):
+        elif isinstance(other, Environment):
             for project in other:
                 for dist in other[project]:
                     self.add(dist)
     """
 
 
-
-
 class ResourceManager:
     """Manage resource extraction and packages"""
     extraction_path = None
         raise err
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
     def get_cache_path(self, archive_name, names=()):
         """Return absolute location in cache for `archive_name` and `names`
 
         return target_path
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     def postprocess(self, tempname, filename):
         """Perform any platform-specific postprocessing of `tempname`
 
             os.chmod(tempname, mode)
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     def set_extraction_path(self, path):
         """Set the base path where resources will be extracted to, if needed.
 
         # XXX
 
 
-
 def get_default_cache():
     """Determine the default cache location
 
     """
     return name.replace('-','_')
 
-
-
-
-
-
-
-
 class NullProvider:
     """Try to implement resources and metadata for arbitrary PEP 302 loaders"""
 
             "Can't perform this operation for loaders without 'get_data()'"
         )
 
+
 register_loader_type(object, NullProvider)
 
 
             path, base = os.path.split(path)
 
 
-
-
-
-
 class DefaultProvider(EggProvider):
     """Provides access to package resources in the filesystem"""
 
         finally:
             stream.close()
 
+
 register_loader_type(type(None), DefaultProvider)
 
 
 empty_provider = EmptyProvider()
 
 
-
-
 class ZipProvider(EggProvider):
     """Resource support for zips and eggs"""
 
 register_loader_type(zipimport.zipimporter, ZipProvider)
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 class FileMetadata(EmptyProvider):
     """Metadata handler for standalone PKG-INFO files
 
         return yield_lines(self.get_metadata(name))
 
 
-
-
-
-
-
-
-
-
-
-
-
-
+class DistInfoMetadata(EmptyProvider):
+    """Provides a metadata proxy for dist-info distributions.
+       Works in a similar manner to :class:`PathMetadata`."""
+
+    def __init__(self,path):
+        self.path = path
+
+    def has_metadata(self,name):
+        return name in ('PKG-INFO', 'requires.txt')
+
+    def get_metadata(self,name):
+        f = open(os.path.join(self.path, 'METADATA'),'rU')
+        metadata = f.read()
+        f.close()
+        
+        if name=='PKG-INFO':    
+            return metadata
+        elif name=='requires.txt':
+            reqs = []
+            for line in metadata.splitlines():
+                line = line.strip()
+                req = None
+                if line.startswith('Requires:'):
+                    req = line.split('Requires:', 1)[1].strip()
+                elif line.startswith('Requires-Dist:'):
+                    req = line.split('Requires-Dist:', 1)[1].strip()
+                if req:
+                    req = req.replace('(', '')
+                    req = req.replace(')', '')
+                    reqs.append(req)
+            return '\n'.join(reqs)
+        else:
+            raise KeyError()
+
+    def get_metadata_lines(self,name):
+        return yield_lines(self.get_metadata(name))
 
 
 class PathMetadata(DefaultProvider):
         return mod
 
 
-
-
 def get_importer(path_item):
     """Retrieve a PEP 302 "importer" for the given path item
 
     del ImpLoader, ImpImporter
 
 
-
-
-
-
 _distribution_finders = {}
 
 def register_finder(importer_type, distribution_finder):
                     path_item, os.path.join(path_item,'EGG-INFO')
                 )
             )
+        elif path_item.lower().endswith('.dist-info'):
+            yield Distribution.from_filename(
+                path_item, metadata=DistInfoMetadata(path_item)
+            )
         else:
             # scan for .egg and .egg-info in directory
             for entry in os.listdir(path_item):
                         for item in find_distributions(os.path.join(path_item,line.rstrip())):
                             yield item
                         break
+                elif lower.endswith('.dist-info'):
+                    fullpath = os.path.join(path_item, entry)
+                    if os.path.isdir(fullpath):
+                        metadata = DistInfoMetadata(fullpath)
+                        yield Distribution.from_location(fullpath, entry, metadata)
+                    
+                    
 register_finder(ImpWrapper,find_on_path)
 
 _namespace_handlers = {}
             working_set.resolve(self.dist.requires(self.extras),env,installer))
 
 
-
     #@classmethod
     def parse(cls, src, dist=None):
         """Parse a single entry point from string `src`
 
     parse = classmethod(parse)
 
-
-
-
-
-
-
-
     #@classmethod
     def parse_group(cls, group, lines, dist=None):
         """Parse an entry point group"""
     parse_map = classmethod(parse_map)
 
 
-
-
-
-
 class Distribution(object):
     """Wrap an actual or potential sys.path entry w/metadata"""
     def __init__(self,
     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 ('.egg','.egg-info'):
             match = EGG_NAME(basename)
             if match:
                 project_name, version, py_version, platform = match.group(
                     'name','ver','pyver','plat'
                 )
+        elif ext.lower() == '.dist-info':
+            try:
+                project_name, version = basename.rsplit('-', 1)
+            except ValueError:
+                pass
+
         return cls(
             location, metadata, project_name=project_name, version=version,
             py_version=py_version, platform=platform, **kw
         )
+
     from_location = classmethod(from_location)
 
     hashcmp = property(
                 )
     version = property(version)
 
-
-
-
     #@property
     def _dep_map(self):
         try:
         """Return the EntryPoint object for `group`+`name`, or ``None``"""
         return self.get_entry_map(group).get(name)
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
     def insert_on(self, path, loc = None):
         """Insert self.location in path before its nearest parent directory"""
 
-        loc = loc or self.location
+        if self.location.endswith('.dist-info'):
+            loc = loc or self.location[:-10] # trim off .dist-info
+        else:
+            loc = loc or self.location
         if not loc:
             return
 
         return
 
 
-
     def check_version_conflict(self):
         if self.key=='distribute':
             return      # ignore the inevitable setuptools self-conflicts  :(
         kw.setdefault('metadata', self._provider)
         return self.__class__(**kw)
 
-
-
-
     #@property
     def extras(self):
         return [dep for dep in self._dep_map if dep]
     warn(stacklevel = level+1, *args, **kw)
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 def parse_requirements(strs):
     """Yield ``Requirement`` objects for each specification in `strs`
 
     dists[::-1] = [d for hc,d in tmp]
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 class Requirement:
     def __init__(self, project_name, specs, extras):
         """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!"""
 
     parse = staticmethod(parse)
 
+
 state_machine = {
     #       =><
     '<' :  '--T',
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.