Fixed #8726 -- When doing reverse URL resolving, make sure we're consistently

dealing with unicode strings throughout by promoting up from UTF-8 as necessary.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@8777 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-08-31 22:47:25 +00:00
parent ab13303ea4
commit 7838493b9e
3 changed files with 23 additions and 18 deletions

View File

@ -228,12 +228,14 @@ class RegexURLResolver(object):
if args: if args:
if len(args) != len(params): if len(args) != len(params):
continue continue
candidate = result % dict(zip(params, args)) unicode_args = [force_unicode(val) for val in args]
candidate = result % dict(zip(params, unicode_args))
else: else:
if set(kwargs.keys()) != set(params): if set(kwargs.keys()) != set(params):
continue continue
candidate = result % kwargs unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()])
if re.search('^%s' % pattern, candidate, re.UNICODE): candidate = result % unicode_kwargs
if re.search(u'^%s' % pattern, candidate, re.UNICODE):
return candidate return candidate
raise NoReverseMatch("Reverse for '%s' with arguments '%s' and keyword " raise NoReverseMatch("Reverse for '%s' with arguments '%s' and keyword "
"arguments '%s' not found." % (lookup_view, args, kwargs)) "arguments '%s' not found." % (lookup_view, args, kwargs))

View File

@ -13,12 +13,12 @@ ESCAPE_MAPPINGS = {
"A": None, "A": None,
"b": None, "b": None,
"B": None, "B": None,
"d": '0', "d": u"0",
"D": "x", "D": u"x",
"s": " ", "s": u" ",
"S": "x", "S": u"x",
"w": "x", "w": u"x",
"W": "!", "W": u"!",
"Z": None, "Z": None,
} }
@ -77,7 +77,7 @@ def normalize(pattern):
try: try:
ch, escaped = pattern_iter.next() ch, escaped = pattern_iter.next()
except StopIteration: except StopIteration:
return zip([''], [[]]) return zip([u''], [[]])
try: try:
while True: while True:
@ -85,7 +85,7 @@ def normalize(pattern):
result.append(ch) result.append(ch)
elif ch == '.': elif ch == '.':
# Replace "any character" with an arbitrary representative. # Replace "any character" with an arbitrary representative.
result.append("x") result.append(u"x")
elif ch == '|': elif ch == '|':
# FIXME: One day we'll should do this, but not in 1.0. # FIXME: One day we'll should do this, but not in 1.0.
raise NotImplementedError raise NotImplementedError
@ -117,7 +117,7 @@ def normalize(pattern):
# A positional group # A positional group
name = "_%d" % num_args name = "_%d" % num_args
num_args += 1 num_args += 1
result.append(Group((("%%(%s)s" % name), name))) result.append(Group(((u"%%(%s)s" % name), name)))
walk_to_end(ch, pattern_iter) walk_to_end(ch, pattern_iter)
else: else:
ch, escaped = pattern_iter.next() ch, escaped = pattern_iter.next()
@ -144,7 +144,7 @@ def normalize(pattern):
name.append(ch) name.append(ch)
ch, escaped = pattern_iter.next() ch, escaped = pattern_iter.next()
param = ''.join(name) param = ''.join(name)
result.append(Group((("%%(%s)s" % param), param))) result.append(Group(((u"%%(%s)s" % param), param)))
walk_to_end(ch, pattern_iter) walk_to_end(ch, pattern_iter)
elif ch in "*?+{": elif ch in "*?+{":
# Quanitifers affect the previous item in the result list. # Quanitifers affect the previous item in the result list.
@ -180,7 +180,7 @@ def normalize(pattern):
pass pass
except NotImplementedError: except NotImplementedError:
# A case of using the disjunctive form. No results for you! # A case of using the disjunctive form. No results for you!
return zip([''], [[]]) return zip([u''], [[]])
return zip(*flatten_result(result)) return zip(*flatten_result(result))
@ -279,20 +279,20 @@ def flatten_result(source):
Each of the two lists will be of the same length. Each of the two lists will be of the same length.
""" """
if source is None: if source is None:
return [''], [[]] return [u''], [[]]
if isinstance(source, Group): if isinstance(source, Group):
if source[1] is None: if source[1] is None:
params = [] params = []
else: else:
params = [source[1]] params = [source[1]]
return [source[0]], [params] return [source[0]], [params]
result = [''] result = [u'']
result_args = [[]] result_args = [[]]
pos = last = 0 pos = last = 0
for pos, elt in enumerate(source): for pos, elt in enumerate(source):
if isinstance(elt, basestring): if isinstance(elt, basestring):
continue continue
piece = ''.join(source[last:pos]) piece = u''.join(source[last:pos])
if isinstance(elt, Group): if isinstance(elt, Group):
piece += elt[0] piece += elt[0]
param = elt[1] param = elt[1]
@ -320,7 +320,7 @@ def flatten_result(source):
result = new_result result = new_result
result_args = new_args result_args = new_args
if pos >= last: if pos >= last:
piece = ''.join(source[last:]) piece = u''.join(source[last:])
for i in range(len(result)): for i in range(len(result)):
result[i] += piece result[i] += piece
return result, result_args return result, result_args

View File

@ -194,6 +194,7 @@ class Templates(unittest.TestCase):
output = self.render(test_template, vals) output = self.render(test_template, vals)
except Exception, e: except Exception, e:
if e.__class__ != result: if e.__class__ != result:
raise
failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s" % (invalid_str, name, e.__class__, e)) failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s" % (invalid_str, name, e.__class__, e))
continue continue
if output != result: if output != result:
@ -899,6 +900,8 @@ class Templates(unittest.TestCase):
'url05': (u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 'url05': (u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url06': (u'{% url метка_оператора_2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 'url06': (u'{% url метка_оператора_2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url07': (u'{% url regressiontests.templates.views.client2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'), 'url07': (u'{% url regressiontests.templates.views.client2 tag=v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url08': (u'{% url метка_оператора v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
'url09': (u'{% url метка_оператора_2 tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
# Failures # Failures
'url-fail01': ('{% url %}', {}, template.TemplateSyntaxError), 'url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),