Commit 6402ec9b authored by PJ Eby's avatar PJ Eby

Added support for ``.egg-info`` files or directories with version/platform

information embedded in the filename, so that system packagers have the
option of including ``PKG-INFO`` files to indicate the presence of a
system-installed egg, without needing to use ``.egg`` directories, zipfiles,
or ``.pth`` manipulation.

--HG--
branch : setuptools
extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041615
parent 969bfb31
......@@ -70,7 +70,7 @@ __all__ = [
'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST',
# "Provider" interfaces, implementations, and registration/lookup APIs
'IMetadataProvider', 'IResourceProvider',
'IMetadataProvider', 'IResourceProvider', 'FileMetadata',
'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider',
'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider',
'register_finder', 'register_namespace_handler', 'register_loader_type',
......@@ -1155,31 +1155,31 @@ class ZipProvider(EggProvider):
register_loader_type(zipimport.zipimporter, ZipProvider)
class FileMetadata(EmptyProvider):
"""Metadata handler for standalone PKG-INFO files
Usage::
metadata = FileMetadata("/path/to/PKG-INFO")
This provider rejects all data and metadata requests except for PKG-INFO,
which is treated as existing, and will be the contents of the file at
the provided location.
"""
def __init__(self,path):
self.path = path
def has_metadata(self,name):
return name=='PKG-INFO'
def get_metadata(self,name):
if name=='PKG-INFO':
return open(self.path,'rU').read()
raise KeyError("No metadata except PKG-INFO is available")
def get_metadata_lines(self,name):
return yield_lines(self.get_metadata(name))
......@@ -1373,13 +1373,14 @@ def find_on_path(importer, path_item, only=False):
lower = entry.lower()
if lower.endswith('.egg-info'):
fullpath = os.path.join(path_item, entry)
if os.path.isdir(fullpath):
# development egg
metadata = None
if os.path.isdir(fullpath):
# egg-info directory, allow getting metadata
metadata = PathMetadata(path_item, fullpath)
dist_name = os.path.splitext(entry)[0]
yield Distribution(
path_item, metadata, project_name=dist_name
)
else:
metadata = FileMetadata(fullpath)
yield Distribution.from_location(path_item,entry,metadata)
elif not only and lower.endswith('.egg'):
for dist in find_distributions(os.path.join(path_item, entry)):
yield dist
......@@ -1391,7 +1392,6 @@ def find_on_path(importer, path_item, only=False):
register_finder(ImpWrapper,find_on_path)
_namespace_handlers = {}
_namespace_packages = {}
......@@ -1739,7 +1739,7 @@ class Distribution(object):
def from_location(cls,location,basename,metadata=None):
project_name, version, py_version, platform = [None]*4
basename, ext = os.path.splitext(basename)
if ext.lower()==".egg":
if ext.lower() in (".egg",".egg-info"):
match = EGG_NAME(basename)
if match:
project_name, version, py_version, platform = match.group(
......@@ -1754,13 +1754,13 @@ class Distribution(object):
hashcmp = property(
lambda self: (
getattr(self,'parsed_version',()), self.precedence, self.key,
-len(self.location), self.location, self.py_version, self.platform
-len(self.location or ''), self.location, self.py_version,
self.platform
)
)
def __cmp__(self, other): return cmp(self.hashcmp, other)
def __hash__(self): return hash(self.hashcmp)
# 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)
......
......@@ -1282,6 +1282,7 @@ where appropriate. Their inheritance tree looks like this::
ZipProvider
EggMetadata
EmptyProvider
FileMetadata
``NullProvider``
......@@ -1326,6 +1327,14 @@ where appropriate. Their inheritance tree looks like this::
itself is a ".egg"). It can also be a combination, such as a zipfile egg
that also contains other eggs.
``FileMetadata(path_to_pkg_info)``
Create an ``IResourceProvider`` that provides exactly one metadata
resource: ``PKG-INFO``. The supplied path should be a distutils PKG-INFO
file. This is basically the same as an ``EmptyProvider``, except that
requests for ``PKG-INFO`` will be answered using the contents of the
designated file. (This provider is used to wrap ``.egg-info`` files
installed by vendor-supplied system packages.)
Utility Functions
=================
......@@ -1503,6 +1512,12 @@ Release Notes/Change History
unless absolutely necessary. Warn about skipping invalid/unfinished eggs
when building an Environment.
* Added support for ``.egg-info`` files or directories with version/platform
information embedded in the filename, so that system packagers have the
option of including ``PKG-INFO`` files to indicate the presence of a
system-installed egg, without needing to use ``.egg`` directories, zipfiles,
or ``.pth`` manipulation.
0.6a8
* Fixed a problem with ``WorkingSet.resolve()`` that prevented version
conflicts from being detected at runtime.
......
......@@ -94,6 +94,8 @@ class DistroTests(TestCase):
def testDistroParse(self):
d = Distribution.from_filename("FooPkg-1.3_1-py2.4-win32.egg")
self.checkFooPkg(d)
d = Distribution.from_filename("FooPkg-1.3_1-py2.4-win32.egg-info")
self.checkFooPkg(d)
def testDistroMetadata(self):
d = Distribution(
......@@ -119,8 +121,6 @@ class DistroTests(TestCase):
self.checkRequires(self.distRequires(v), v)
def testResolve(self):
ad = Environment([]); ws = WorkingSet([])
# Resolving no requirements -> nothing to install
......
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