summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pyramid/tests/test_traversal.py12
-rw-r--r--pyramid/traversal.py7
-rw-r--r--pyramid/url.py7
-rw-r--r--pyramid/urldispatch.py3
4 files changed, 22 insertions, 7 deletions
diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py
index 0decd04d6..5fc878a32 100644
--- a/pyramid/tests/test_traversal.py
+++ b/pyramid/tests/test_traversal.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import unittest
import warnings
@@ -839,7 +840,7 @@ class QuotePathSegmentTests(unittest.TestCase):
def test_string(self):
s = '/ hello!'
result = self._callFUT(s)
- self.assertEqual(result, '%2F%20hello%21')
+ self.assertEqual(result, '%2F%20hello!')
def test_int(self):
s = 12345
@@ -1299,6 +1300,15 @@ class Test__join_path_tuple(unittest.TestCase):
result = self._callFUT(('x',))
self.assertEqual(result, 'x')
+ def test_segments_with_unsafes(self):
+ safe_segments = tuple(u"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$&'()*+,;=:@")
+ result = self._callFUT(safe_segments)
+ self.assertEqual(result, u'/'.join(safe_segments))
+ unsafe_segments = tuple(chr(i) for i in range(0x20, 0x80) if not chr(i) in safe_segments) + (u'あ',)
+ result = self._callFUT(unsafe_segments)
+ self.assertEqual(result, u'/'.join(''.join('%%%02X' % (ord(c) if isinstance(c, str) else c) for c in unsafe_segment.encode('utf-8')) for unsafe_segment in unsafe_segments))
+
+
def make_traverser(result):
class DummyTraverser(object):
def __init__(self, context):
diff --git a/pyramid/traversal.py b/pyramid/traversal.py
index 963a76bb5..1ca52692a 100644
--- a/pyramid/traversal.py
+++ b/pyramid/traversal.py
@@ -35,6 +35,9 @@ with warnings.catch_warnings():
warnings.filterwarnings('ignore')
from pyramid.interfaces import IContextURL
+PATH_SEGMENT_SAFE = "~!$&'()*+,;=:@" # from webob
+PATH_SAFE = PATH_SEGMENT_SAFE + "/"
+
empty = text_('')
def find_root(resource):
@@ -577,7 +580,7 @@ the ``safe`` argument to this function. This corresponds to the
if PY2:
# special-case on Python 2 for speed? unchecked
- def quote_path_segment(segment, safe=''):
+ def quote_path_segment(segment, safe=PATH_SEGMENT_SAFE):
""" %s """ % quote_path_segment_doc
# The bit of this code that deals with ``_segment_cache`` is an
# optimization: we cache all the computation of URL path segments
@@ -596,7 +599,7 @@ if PY2:
_segment_cache[(segment, safe)] = result
return result
else:
- def quote_path_segment(segment, safe=''):
+ def quote_path_segment(segment, safe=PATH_SEGMENT_SAFE):
""" %s """ % quote_path_segment_doc
# The bit of this code that deals with ``_segment_cache`` is an
# optimization: we cache all the computation of URL path segments
diff --git a/pyramid/url.py b/pyramid/url.py
index fd62f0057..0214d35ad 100644
--- a/pyramid/url.py
+++ b/pyramid/url.py
@@ -25,10 +25,11 @@ from pyramid.threadlocal import get_current_registry
from pyramid.traversal import (
ResourceURL,
quote_path_segment,
+ PATH_SAFE,
+ PATH_SEGMENT_SAFE,
)
-PATH_SAFE = '/:@&+$,' # from webob
-QUERY_SAFE = '/?:@!$&\'()*+,;=' # RFC 3986
+QUERY_SAFE = "/?:@!$&'()*+,;=" # RFC 3986
ANCHOR_SAFE = QUERY_SAFE
def parse_url_overrides(kw):
@@ -947,4 +948,4 @@ def current_route_path(request, *elements, **kw):
@lru_cache(1000)
def _join_elements(elements):
- return '/'.join([quote_path_segment(s, safe=':@&+$,') for s in elements])
+ return '/'.join([quote_path_segment(s, safe=PATH_SEGMENT_SAFE) for s in elements])
diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py
index 0f7dd1490..a61071845 100644
--- a/pyramid/urldispatch.py
+++ b/pyramid/urldispatch.py
@@ -22,6 +22,7 @@ from pyramid.exceptions import URLDecodeError
from pyramid.traversal import (
quote_path_segment,
split_path_info,
+ PATH_SAFE,
)
_marker = object()
@@ -209,7 +210,7 @@ def _compile_route(route):
gen = ''.join(gen)
def q(v):
- return quote_path_segment(v, safe='/:@&+$,')
+ return quote_path_segment(v, safe=PATH_SAFE)
def generator(dict):
newdict = {}