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