summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkg_resources.py58
-rwxr-xr-xpkg_resources.txt15
-rw-r--r--setuptools/tests/test_resources.py4
3 files changed, 46 insertions, 31 deletions
diff --git a/pkg_resources.py b/pkg_resources.py
index 371ef20d..a2147d6d 100644
--- a/pkg_resources.py
+++ b/pkg_resources.py
@@ -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)
diff --git a/pkg_resources.txt b/pkg_resources.txt
index 254051cc..31e411bf 100755
--- a/pkg_resources.txt
+++ b/pkg_resources.txt
@@ -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.
diff --git a/setuptools/tests/test_resources.py b/setuptools/tests/test_resources.py
index 723bd730..076dd53e 100644
--- a/setuptools/tests/test_resources.py
+++ b/setuptools/tests/test_resources.py
@@ -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