From ab19ea8a5372ac83c6f7a7d75d1ecca5ed2b025e Mon Sep 17 00:00:00 2001 From: Daniel Nouri Date: Mon, 28 Feb 2011 16:13:47 +0100 Subject: 'pyramid.url.resource_url' no longer quotes '@' in '*elements'. See http://groups.google.com/group/pylons-discuss/browse_thread/thread/ebb8e0196858a48 --- pyramid/tests/test_url.py | 8 ++++++++ pyramid/traversal.py | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py index 3c70e9028..e13fbbb91 100644 --- a/pyramid/tests/test_url.py +++ b/pyramid/tests/test_url.py @@ -49,6 +49,14 @@ class ResourceURLTests(unittest.TestCase): self.assertEqual(result, 'http://example.com/context/La%20Pe%C3%B1a') + def test_at_sign_in_element_names(self): + request = _makeRequest() + self._registerContextURL(request.registry) + context = DummyContext() + result = self._callFUT(context, request, '@@myview') + self.assertEqual(result, + 'http://example.com/context/@@myview') + def test_element_names_url_quoted(self): request = _makeRequest() self._registerContextURL(request.registry) diff --git a/pyramid/traversal.py b/pyramid/traversal.py index 0953ef313..03137330a 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -509,6 +509,7 @@ def traversal_path(path): return tuple(clean) _segment_cache = {} +path_safe = ':@&+$,' def quote_path_segment(segment): """ Return a quoted representation of a 'path segment' (such as @@ -540,9 +541,9 @@ def quote_path_segment(segment): return _segment_cache[segment] except KeyError: if segment.__class__ is unicode: # isinstance slighly slower (~15%) - result = url_quote(segment.encode('utf-8')) + result = url_quote(segment.encode('utf-8'), path_safe) else: - result = url_quote(str(segment)) + result = url_quote(str(segment), path_safe) # we don't need a lock to mutate _segment_cache, as the below # will generate exactly one Python bytecode (STORE_SUBSCR) _segment_cache[segment] = result -- cgit v1.2.3 From 8cf91a73beb31df98617fbe5ce98bdd0c0180ab7 Mon Sep 17 00:00:00 2001 From: Daniel Nouri Date: Mon, 28 Feb 2011 19:20:21 +0100 Subject: Do not quote characters ':@&+$,' in '*elements' passed to route_path and resource_url. We're deliberately using these safe characters only with '*elements' instead of the whole path since that would break existing apps that persist quoted paths of resources. See https://github.com/dnouri/pyramid/commit/ab19ea8a5372ac83c6f7a7d75d1ecca5ed2b025e#commitcomment-285947 --- pyramid/traversal.py | 15 +++++++++------ pyramid/url.py | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pyramid/traversal.py b/pyramid/traversal.py index 03137330a..c69892854 100644 --- a/pyramid/traversal.py +++ b/pyramid/traversal.py @@ -509,9 +509,8 @@ def traversal_path(path): return tuple(clean) _segment_cache = {} -path_safe = ':@&+$,' -def quote_path_segment(segment): +def quote_path_segment(segment, safe=''): """ Return a quoted representation of a 'path segment' (such as the string ``__name__`` attribute of a resource) as a string. If the ``segment`` passed in is a unicode object, it is converted to a @@ -522,6 +521,10 @@ def quote_path_segment(segment): raised. The return value of ``quote_path_segment`` is always a string, never Unicode. + You may pass a string of characters that need not be encoded as + the ``safe`` argument to this function. This corresponds to the + ``safe`` argument to :mod:`urllib.quote`. + .. note:: The return value for each segment passed to this function is cached in a module-scope dictionary for speed: the cached version is returned when possible @@ -538,15 +541,15 @@ def quote_path_segment(segment): # unicode value) as the key, so we can look it up later without # needing to reencode or re-url-quote it try: - return _segment_cache[segment] + return _segment_cache[(segment, safe)] except KeyError: if segment.__class__ is unicode: # isinstance slighly slower (~15%) - result = url_quote(segment.encode('utf-8'), path_safe) + result = url_quote(segment.encode('utf-8'), safe) else: - result = url_quote(str(segment), path_safe) + result = url_quote(str(segment), safe) # we don't need a lock to mutate _segment_cache, as the below # will generate exactly one Python bytecode (STORE_SUBSCR) - _segment_cache[segment] = result + _segment_cache[(segment, safe)] = result return result class ResourceTreeTraverser(object): diff --git a/pyramid/url.py b/pyramid/url.py index cb60684e2..ebf0402d8 100644 --- a/pyramid/url.py +++ b/pyramid/url.py @@ -432,4 +432,4 @@ def current_route_url(request, *elements, **kw): @lru_cache(1000) def _join_elements(elements): - return '/'.join([quote_path_segment(s) for s in elements]) + return '/'.join([quote_path_segment(s, safe=':@&+$,') for s in elements]) -- cgit v1.2.3