diff options
-rw-r--r-- | pkg_resources.py | 30 | ||||
-rwxr-xr-x | pkg_resources.txt | 15 | ||||
-rw-r--r-- | setuptools/tests/test_resources.py | 2 |
3 files changed, 30 insertions, 17 deletions
diff --git a/pkg_resources.py b/pkg_resources.py index 4cb9f957..15dca3c1 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -61,6 +61,7 @@ __all__ = [ # Parsing functions and string utilities 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', + 'safe_extra', # filesystem utilities 'ensure_directory', 'normalize_path', @@ -79,7 +80,6 @@ __all__ = [ 'run_main', 'AvailableDistributions', ] - class ResolutionError(Exception): """Abstract base for dependency resolution errors""" @@ -836,14 +836,14 @@ def safe_version(version): return re.sub('[^A-Za-z0-9.]+', '-', version) +def safe_extra(extra): + """Convert an arbitrary string to a standard 'extra' name - - - - - - - + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + """ + return re.sub('[^A-Za-z0-9]+', '_', extra).lower() + @@ -1606,9 +1606,7 @@ class EntryPoint(object): self.name = name self.module_name = module_name self.attrs = tuple(attrs) - self.extras = Requirement.parse( - ("x[%s]" % ','.join(extras)).lower() - ).extras + self.extras = Requirement.parse(("x[%s]" % ','.join(extras))).extras self.dist = dist def __str__(self): @@ -1638,6 +1636,8 @@ class EntryPoint(object): map(working_set.add, 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` @@ -1810,7 +1810,7 @@ class Distribution(object): dm = self.__dep_map = {None: []} for name in 'requires.txt', 'depends.txt': for extra,reqs in split_sections(self._get_metadata(name)): - if extra: extra = extra.lower() + if extra: extra = safe_extra(extra) dm.setdefault(extra,[]).extend(parse_requirements(reqs)) return dm _dep_map = property(_dep_map) @@ -1822,7 +1822,7 @@ class Distribution(object): deps.extend(dm.get(None,())) for ext in extras: try: - deps.extend(dm[ext.lower()]) + deps.extend(dm[safe_extra(ext)]) except KeyError: raise UnknownExtra( "%s has no such extra feature %r" % (self, ext) @@ -2014,10 +2014,10 @@ class Requirement: index = [(parse_version(v),state_machine[op],op,v) for op,v in specs] index.sort() self.specs = [(op,ver) for parsed,trans,op,ver in index] - self.index, self.extras = index, tuple(extras) + self.index, self.extras = index, tuple(map(safe_extra,extras)) self.hashCmp = ( self.key, tuple([(op,parsed) for parsed,trans,op,ver in index]), - ImmutableSet(map(str.lower,extras)) + ImmutableSet(self.extras) ) self.__hash = hash(self.hashCmp) diff --git a/pkg_resources.txt b/pkg_resources.txt index 4540c994..e9e5286d 100755 --- a/pkg_resources.txt +++ b/pkg_resources.txt @@ -522,7 +522,10 @@ Requirements Parsing or indexing. ``extras`` - A tuple of names of "extras" that this requirement calls for. + A tuple of names of "extras" that this requirement calls for. (These will + be all-lowercase and normalized using the ``safe_extra()`` parsing utility + function, so they may not exactly equal the extras the requirement was + created with.) Entry Points @@ -1413,6 +1416,12 @@ Parsing Utilities are generating a filename from this you should replace any "-" characters in the output with underscores. +``safe_extra(extra)`` + Return a "safe" form of an extra's name, suitable for use in a requirement + string or a setup script's ``extras_require`` keyword. This routine is + similar to ``safe_name()`` except that non-alphanumeric runs are replaced + by a single underbar (``_``), and the result is lowercased. + Platform Utilities ------------------ @@ -1479,6 +1488,10 @@ File/Path Utilities Release Notes/Change History ---------------------------- +0.6a3 + * Added ``safe_extra()`` parsing utility routine, and use it for Requirement, + EntryPoint, and Distribution objects' extras handling. + 0.6a1 * Enhanced performance of ``require()`` and related operations when all requirements are already in the working set, and enhanced performance of diff --git a/setuptools/tests/test_resources.py b/setuptools/tests/test_resources.py index ee3de5c5..87648f1c 100644 --- a/setuptools/tests/test_resources.py +++ b/setuptools/tests/test_resources.py @@ -333,7 +333,7 @@ class RequirementsTests(TestCase): self.assertEqual(r1,r2) self.assertEqual(r1,r3) self.assertEqual(r1.extras, ("foo","bar")) - self.assertEqual(r2.extras, ("bar","FOO")) + self.assertEqual(r2.extras, ("bar","foo")) # extras are normalized self.assertEqual(hash(r1), hash(r2)) self.assertEqual( hash(r1), hash(("twisted", ((">=",parse_version("1.2")),), |