diff options
| author | Chris McDonough <chrism@plope.com> | 2011-02-09 02:32:29 -0500 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-02-09 02:32:29 -0500 |
| commit | 9595236d4f1212323dbf06670a80e6a4fb7c8fcf (patch) | |
| tree | cd4582e995790a95635e2f07c61a994548f60d7f | |
| parent | e8e655fecd4b45be571c3da3e5d1a0351353ab61 (diff) | |
| download | pyramid-9595236d4f1212323dbf06670a80e6a4fb7c8fcf.tar.gz pyramid-9595236d4f1212323dbf06670a80e6a4fb7c8fcf.tar.bz2 pyramid-9595236d4f1212323dbf06670a80e6a4fb7c8fcf.zip | |
- URL pattern markers used in URL dispatch are permitted to specify a custom
regex. For example, the pattern ``/{foo:\d+}`` means to match ``/12345``
(foo==12345 in the match dictionary) but not ``/abc``. However, custom
regexes in a pattern marker which used squiggly brackets did not work. For
example, ``/{foo:\d{4}}`` would fail to match ``/1234`` and
``/{foo:\d{1,2}}`` would fail to match ``/1`` or ``/11``. One level of
inner squiggly brackets is now recognized so that the prior two patterns
given as examples now work. See also
https://github.com/Pylons/pyramid/issues/#issue/123.
Closes #123
| -rw-r--r-- | CHANGES.txt | 16 | ||||
| -rw-r--r-- | pyramid/tests/test_urldispatch.py | 16 | ||||
| -rw-r--r-- | pyramid/urldispatch.py | 10 |
3 files changed, 40 insertions, 2 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index ffafe1b7d..34e8cd7b6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,19 @@ +Next release +============ + +Bug Fixes +--------- + +- URL pattern markers used in URL dispatch are permitted to specify a custom + regex. For example, the pattern ``/{foo:\d+}`` means to match ``/12345`` + (foo==12345 in the match dictionary) but not ``/abc``. However, custom + regexes in a pattern marker which used squiggly brackets did not work. For + example, ``/{foo:\d{4}}`` would fail to match ``/1234`` and + ``/{foo:\d{1,2}}`` would fail to match ``/1`` or ``/11``. One level of + inner squiggly brackets is now recognized so that the prior two patterns + given as examples now work. See also + https://github.com/Pylons/pyramid/issues/#issue/123. + 1.0 (2011-01-30) ================ diff --git a/pyramid/tests/test_urldispatch.py b/pyramid/tests/test_urldispatch.py index a452fdb97..eca4603a3 100644 --- a/pyramid/tests/test_urldispatch.py +++ b/pyramid/tests/test_urldispatch.py @@ -268,7 +268,21 @@ class TestCompileRoute(unittest.TestCase): self.assertEqual(matcher('/foo/baz/biz/buz.bar'), {'baz':'baz', 'buz':'buz', 'bar':'bar'}) self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) - self.assertEqual(generator({'baz':1, 'buz':2, 'bar': 'html'}), '/foo/1/biz/2.html') + self.assertEqual(generator({'baz':1, 'buz':2, 'bar': 'html'}), + '/foo/1/biz/2.html') + + def test_custom_regex_with_embedded_squigglies(self): + matcher, generator = self._callFUT('/{buz:\d{4}}') + self.assertEqual(matcher('/2001'), {'buz':'2001'}) + self.assertEqual(matcher('/200'), None) + self.assertEqual(generator({'buz':2001}), '/2001') + + def test_custom_regex_with_embedded_squigglies2(self): + matcher, generator = self._callFUT('/{buz:\d{3,4}}') + self.assertEqual(matcher('/2001'), {'buz':'2001'}) + self.assertEqual(matcher('/200'), {'buz':'200'}) + self.assertEqual(matcher('/20'), None) + self.assertEqual(generator({'buz':2001}), '/2001') class TestCompileRouteMatchFunctional(unittest.TestCase): def matches(self, pattern, path, expected): diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index 5d1e53947..57ca8ff83 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -76,7 +76,13 @@ class RoutesMapper(object): # stolen from bobo and modified old_route_re = re.compile(r'(\:[a-zA-Z]\w*)') star_in_brackets = re.compile(r'\{[^\}]*\*\w*[^\}]*\}') -route_re = re.compile(r'(\{[a-zA-Z][^\}]*\})') +# The torturous nature of the regex named ``route_re`` below is due to the +# fact that we need to support at least one level of "inner" squigglies +# inside the expr of a {name:expr} pattern. This regex used to be just +# (\{[a-zA-Z][^\}]*\}) but that choked when supplied with e.g. {foo:\d{4}}. +# Thanks to Zart for the regex help. +route_re = re.compile(r'(\{[a-zA-Z](?:\{[^\}]*\}|[^\{\}]*)*\})') + def update_pattern(matchobj): name = matchobj.group(0) return '{%s}' % name[1:] @@ -103,6 +109,8 @@ def _compile_route(route): name = name[1:-1] if ':' in name: name, reg = name.split(':') + reg = reg.replace(r'\{', '{') + reg = reg.replace(r'\}', '}') else: reg = '[^/]+' gen.append('%%(%s)s' % name) |
