Commit 9159d6d8 authored by PJ Eby's avatar PJ Eby

Fix a problem with inconsistent quoting of "extras", reported by Ian

Bicking on the distutils-sig.

--HG--
branch : setuptools
extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041253
parent 88c77fe9
......@@ -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)
......
......@@ -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
......
......@@ -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")),),
......
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