aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkg_resources.py98
-rw-r--r--setuptools/tests/test_resources.py83
2 files changed, 168 insertions, 13 deletions
diff --git a/pkg_resources.py b/pkg_resources.py
index 5fd6362a..d4b1f27b 100644
--- a/pkg_resources.py
+++ b/pkg_resources.py
@@ -17,7 +17,8 @@ __all__ = [
'register_loader_type', 'get_provider', 'IResourceProvider',
'ResourceManager', 'iter_distributions', 'require', 'resource_string',
'resource_stream', 'resource_filename', 'set_extraction_path',
- 'cleanup_resources', 'parse_requirements', 'parse_version'# 'glob_resources'
+ 'cleanup_resources', 'parse_requirements', 'parse_version',
+ 'Distribution', # 'glob_resources'
]
import sys, os, zipimport, time, re
@@ -38,7 +39,6 @@ def get_provider(moduleName):
loader = getattr(module, '__loader__', None)
return _find_adapter(_provider_factories, loader)(module)
-
class IResourceProvider:
"""An object that provides access to package resources"""
@@ -508,6 +508,12 @@ DISTRO = re.compile(r"\s*(\w+)").match # Distribution name
VERSION = re.compile(r"\s*(<=?|>=?|==|!=)\s*((\w|\.)+)").match # version info
COMMA = re.compile(r"\s*,").match # comma between items
+EGG_NAME = re.compile(
+ r"(?P<name>[^-]+)"
+ r"( -(?P<ver>[^-]+) (-py(?P<pyver>[^-]+) (-(?P<plat>.+))? )? )?",
+ re.VERBOSE | re.IGNORECASE
+).match
+
component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE)
replace = {'pre':'c', 'preview':'c','-':'final-','rc':'c'}.get
@@ -525,12 +531,6 @@ def _parse_version_parts(s):
-
-
-
-
-
-
def parse_version(s):
"""Convert a version string to a sortable key
@@ -572,6 +572,88 @@ def parse_version(s):
+class Distribution(object):
+ """Wrap an actual or potential sys.path entry w/metadata"""
+
+ def __init__(self,
+ path_str, metadata=None, name=None, version=None,
+ py_version=sys.version[:3]
+ ):
+ if name:
+ self.name = name
+ if version:
+ self.version = version
+
+ self.py_version = py_version
+ self.path = path_str
+ self.normalized_path = os.path.normpath(os.path.normcase(path_str))
+
+ def installed_on(self,path=None):
+ """Is this distro installed on `path`? (defaults to ``sys.path``)"""
+ if path is None:
+ path = sys.path
+ if self.path in path or self.normalized_path in path:
+ return True
+ for item in path:
+ normalized = os.path.normpath(os.path.normcase(item))
+ if normalized == self.normalized_path:
+ return True
+ return False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #@classmethod
+ def from_filename(cls,filename,metadata=None):
+ name,version,py_version,platform = [None]*4
+ basename,ext = os.path.splitext(os.path.basename(filename))
+ if ext.lower()==".egg":
+ match = EGG_NAME(basename)
+ if match:
+ name,version,py_version,platform = match.group(
+ 'name','ver','pyver','plat'
+ )
+ if version and '_' in version:
+ version = version.replace('_','-')
+ return cls(
+ filename,metadata,name=name,version=version,py_version=py_version
+ )
+ from_filename = classmethod(from_filename)
+
+ # 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)
+
+ #@property
+ def key(self):
+ try:
+ return self._key
+ except AttributeError:
+ self._key = key = self.name.lower()
+ return key
+ key = property(key)
+
+ #@property
+ def parsed_version(self):
+ try:
+ return self._parsed_version
+ except AttributeError:
+ self._parsed_version = pv = parse_version(self.version)
+ return pv
+
+ parsed_version = property(parsed_version)
+
+
def parse_requirements(strs):
"""Yield ``Requirement`` objects for each specification in `strs`
diff --git a/setuptools/tests/test_resources.py b/setuptools/tests/test_resources.py
index 8797cda9..7cde4013 100644
--- a/setuptools/tests/test_resources.py
+++ b/setuptools/tests/test_resources.py
@@ -1,13 +1,46 @@
from unittest import TestCase, makeSuite
from pkg_resources import *
-import pkg_resources
+import pkg_resources, sys
class DistroTests(TestCase):
+
def testEmptyiter(self):
# empty path should produce no distributions
self.assertEqual(list(iter_distributions(path=[])), [])
+ def checkFooPkg(self,d):
+ self.assertEqual(d.name, "FooPkg")
+ self.assertEqual(d.key, "foopkg")
+ self.assertEqual(d.version, "1.3-1")
+ self.assertEqual(d.py_version, "2.4")
+ self.assertEqual(d.parsed_version, parse_version("1.3-1"))
+
+ def testDistroBasics(self):
+ d = Distribution(
+ "/some/path",
+ name="FooPkg",version="1.3-1",py_version="2.4"
+ )
+ self.checkFooPkg(d)
+ self.failUnless(d.installed_on(["/some/path"]))
+ self.failIf(d.installed_on([]))
+
+ d = Distribution("/some/path")
+ self.assertEqual(d.py_version, sys.version[:3])
+
+ def testDistroParse(self):
+ d = Distribution.from_filename("FooPkg-1.3_1-py2.4-win32.egg")
+ self.checkFooPkg(d)
+
+
+
+
+
+
+
+
+
class ParseTests(TestCase):
+
def testEmptyParse(self):
self.assertEqual(list(parse_requirements('')), [])
@@ -39,14 +72,22 @@ class ParseTests(TestCase):
+
+
+
+
+
+
+
+
def testVersionOrdering(self):
def c(s1,s2):
p1, p2 = parse_version(s1),parse_version(s2)
self.failUnless(p1<p2, (s1,s2,p1,p2))
c('2.1','2.1.1')
- c('2a1','2b0')
- c('2a1','2.1')
+ c('2a1','2b0')
+ c('2a1','2.1')
c('2.3a1', '2.3')
c('2.1-1', '2.1-2')
c('2.1-1', '2.1.1')
@@ -61,12 +102,30 @@ class ParseTests(TestCase):
c('0.0.4', '0.4.0')
c('0pl1', '0.4pl1')
+ torture ="""
+ 0.80.1-3 0.80.1-2 0.80.1-1 0.79.9999+0.80.0pre4-1
+ 0.79.9999+0.80.0pre2-3 0.79.9999+0.80.0pre2-2
+ 0.77.2-1 0.77.1-1 0.77.0-1
+ """.split()
+
+ for p,v1 in enumerate(torture):
+ for v2 in torture[p+1:]:
+ c(v2,v1)
+
+
+
+
+
+
+
+
+
def testVersionEquality(self):
def c(s1,s2):
p1, p2 = parse_version(s1),parse_version(s2)
self.assertEqual(p1,p2, (s1,s2,p1,p2))
-
+
c('0.4', '0.4.0')
c('0.4.0.0', '0.4.0')
c('0.4.0-0', '0.4-0')
@@ -75,7 +134,21 @@ class ParseTests(TestCase):
c('0.0.0preview1', '0c1')
c('0.0c1', '0rc1')
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+