test_strings = (
'/favicon.ico',
'index.html',
- '\x00\x01\\000',
'Hello, World!',
'!$@#%;',
)
for string in test_strings:
self.assertEqual(string, re_unescape(re.escape(string)))
+
+ def test_re_unescape_raises_error_on_invalid_input(self):
+ with self.assertRaises(ValueError):
+ re_unescape('\\d')
+ with self.assertRaises(ValueError):
+ re_unescape('\\b')
+ with self.assertRaises(ValueError):
+ re_unescape('\\Z')
return None
-_re_unescape_split_pattern = re.compile(r'(\\[^0])')
-# re.escape('\x00') is a special case
+_alphanum = frozenset(
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
+
+def _re_unescape_replacement(match):
+ group = match.group(1)
+ if group[0] in _alphanum:
+ raise ValueError("cannot unescape '\\\\%s'" % group[0])
+ return group
+
+_re_unescape_pattern = re.compile(r'\\(.)', re.DOTALL)
def re_unescape(s):
'''
unescape a string escaped by ``re.escape()``
'''
- parts = []
- for i, splited in enumerate(_re_unescape_split_pattern.split(s)):
- if i % 2:
- parts.append(splited[1])
- else:
- parts.append(splited.replace(r'\000', '\000'))
- return ''.join(parts)
+ return _re_unescape_pattern.sub(_re_unescape_replacement, s)
class Configurable(object):
if paren_loc >= 0:
pieces.append('%s' + fragment[paren_loc + 1:])
else:
+ try:
+ unescaped_fragment = re_unescape(fragment)
+ except ValueError as exc:
+ raise ValueError(exc.args[0] + '; invalid url: %r' % pattern)
pieces.append(re_unescape(fragment))
return (''.join(pieces), self.regex.groups)