diff options
| -rw-r--r-- | pkg_resources.py | 58 | ||||
| -rwxr-xr-x | pkg_resources.txt | 15 | ||||
| -rw-r--r-- | setuptools/tests/test_resources.py | 4 |
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 |
