diff options
| author | Chris McDonough <chrism@plope.com> | 2011-09-24 03:56:29 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-09-24 03:56:29 -0400 |
| commit | a84e17d716774ac1bab5f6a0edf422e21eef96c9 (patch) | |
| tree | a966fbd443c3e57ea6c153f76c6748893930f5a7 | |
| parent | 2e409a88b60be27f8868c95f0fff806fb6cdc155 (diff) | |
| download | pyramid-a84e17d716774ac1bab5f6a0edf422e21eef96c9.tar.gz pyramid-a84e17d716774ac1bab5f6a0edf422e21eef96c9.tar.bz2 pyramid-a84e17d716774ac1bab5f6a0edf422e21eef96c9.zip | |
slog
| -rw-r--r-- | pyramid/compat.py | 4 | ||||
| -rw-r--r-- | pyramid/encode.py | 84 | ||||
| -rw-r--r-- | pyramid/testing.py | 35 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_views.py | 13 | ||||
| -rw-r--r-- | pyramid/tests/test_encode.py | 39 | ||||
| -rw-r--r-- | pyramid/tests/test_httpexceptions.py | 2 | ||||
| -rw-r--r-- | pyramid/tests/test_paster.py | 7 | ||||
| -rw-r--r-- | pyramid/tests/test_scaffolds.py | 2 | ||||
| -rw-r--r-- | pyramid/tests/test_traversal.py | 21 | ||||
| -rw-r--r-- | pyramid/tests/test_url.py | 24 | ||||
| -rw-r--r-- | pyramid/urldispatch.py | 4 |
11 files changed, 100 insertions, 135 deletions
diff --git a/pyramid/compat.py b/pyramid/compat.py index d83205c87..ecb661ce9 100644 --- a/pyramid/compat.py +++ b/pyramid/compat.py @@ -64,13 +64,15 @@ try: # pragma: no cover from urllib import parse urlparse = parse from urllib.parse import quote as url_quote + from urllib.parse import quote_plus as url_quote_plus from urllib.parse import unquote as url_unquote - url_unquote_text = url_unquote from urllib.parse import urlencode as url_encode from urllib.request import urlopen as url_open + url_unquote_text = url_unquote except ImportError: import urlparse from urllib import quote as url_quote + from urllib import quote_plus as url_quote_plus from urllib import unquote as url_unquote from urllib import urlencode as url_encode from urllib2 import urlopen as url_open diff --git a/pyramid/encode.py b/pyramid/encode.py index ee574a0eb..a259d1414 100644 --- a/pyramid/encode.py +++ b/pyramid/encode.py @@ -1,62 +1,11 @@ -import re - from pyramid.compat import text_type -from pyramid.compat import native_ +from pyramid.compat import binary_type from pyramid.compat import is_nonstr_iter +from pyramid.compat import url_quote as _url_quote +from pyramid.compat import url_quote_plus as quote_plus # bw compat api (dnr) -always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' - 'abcdefghijklmnopqrstuvwxyz' - '0123456789' '_.-') -_safemaps = {} -_must_quote = {} - -def url_quote(s, safe=''): - """quote('abc def') -> 'abc%20def' - - Each part of a URL, e.g. the path info, the query, etc., has a - different set of reserved characters that must be quoted. - - RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists - the following reserved characters:: - - reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | - "$" | "," - - Each of these characters is reserved in some component of a URL, - but not necessarily in all of them. - - Unlike the default version of this function in the Python stdlib, by - default, the url_quote function is intended for quoting individual path - segments instead of an already composed path that might have ``/`` - characters in it. Thus, it *will* encode any ``/`` character it finds in a - string unless ``/`` is marked as 'safe'. It is also slightly faster than - the stdlib version. - """ - cachekey = (safe, always_safe) - try: - safe_map = _safemaps[cachekey] - if not _must_quote[cachekey].search(s): - return s - except KeyError: - safe += always_safe - _must_quote[cachekey] = re.compile(r'[^%s]' % safe) - safe_map = {} - for i in range(256): - c = chr(i) - if c in safe: - safe_map[c] = c - else: - safe_map[c] = '%%%02X' % i - _safemaps[cachekey] = safe_map - res = map(safe_map.__getitem__, s) - return ''.join(res) - -def quote_plus(s, safe=''): - """ Version of stdlib quote_plus which uses faster url_quote """ - if ' ' in s: - s = url_quote(s, safe + ' ') - return s.replace(' ', '+') - return url_quote(s, safe) +def url_quote(s, safe=''): # bw compat api + return _url_quote(s, safe=safe) def urlencode(query, doseq=True): """ @@ -92,21 +41,26 @@ def urlencode(query, doseq=True): prefix = '' for (k, v) in query: - if k.__class__ is text_type: - k = native_(k, 'utf-8') - k = quote_plus(str(k)) + k = _enc(k) + if is_nonstr_iter(v): for x in v: - if x.__class__ is text_type: - x = native_(x, 'utf-8') - x = quote_plus(str(x)) + x = _enc(x) result += '%s%s=%s' % (prefix, k, x) prefix = '&' else: - if v.__class__ is text_type: - v = native_(v, 'utf-8') - v = quote_plus(str(v)) + v = _enc(v) result += '%s%s=%s' % (prefix, k, v) + prefix = '&' return result + +def _enc(val): + cls = val.__class__ + if cls is text_type: + val = val.encode('utf-8') + elif cls is not binary_type: + val = str(val).encode('utf-8') + return quote_plus(val) + diff --git a/pyramid/testing.py b/pyramid/testing.py index 862d31459..89cd39a1b 100644 --- a/pyramid/testing.py +++ b/pyramid/testing.py @@ -14,6 +14,9 @@ from pyramid.interfaces import IView from pyramid.interfaces import IViewClassifier from pyramid.interfaces import ISession +from pyramid.compat import PY3 +from pyramid.compat import PYPY +from pyramid.compat import class_types from pyramid.config import Configurator from pyramid.decorator import reify from pyramid.httpexceptions import HTTPForbidden @@ -896,21 +899,25 @@ class MockTemplate(object): return self.response def skip_on(*platforms): + skip = False + for platform in platforms: + if skip_on.os_name.startswith(platform): + skip = True + if platform == 'pypy' and PYPY: # pragma: no cover + skip = True + if platform == 'py3' and PY3: # pragma: no cover + skip = True def decorator(func): - def wrapper(*args, **kw): - for platform in platforms: - if skip_on.os_name.startswith(platform): - return - if platform == 'pypy' and skip_on.pypy: # pragma: no cover + if isinstance(func, class_types): + if skip: return None + else: return func + else: + def wrapper(*args, **kw): + if skip: return - return func(*args, **kw) - wrapper.__name__ = func.__name__ - wrapper.__doc__ = func.__doc__ - return wrapper + return func(*args, **kw) + wrapper.__name__ = func.__name__ + wrapper.__doc__ = func.__doc__ + return wrapper return decorator skip_on.os_name = os.name # for testing -try: # pragma: no cover - import __pypy__ - skip_on.pypy = True -except ImportError: - skip_on.pypy = False diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 141b60e87..9f2ff9b6f 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -5,6 +5,7 @@ from pyramid.tests.test_config import IDummy from pyramid.tests.test_config import dummy_view +from pyramid.compat import im_func from pyramid.exceptions import ConfigurationError from pyramid.exceptions import ConfigurationExecutionError from pyramid.exceptions import ConfigurationConflictError @@ -3245,12 +3246,12 @@ class Test_preserve_view_attrs(unittest.TestCase): self.assertTrue(view1.__doc__ is view2.__doc__) self.assertTrue(view1.__module__ is view2.__module__) self.assertTrue(view1.__name__ is view2.__name__) - self.assertTrue(view1.__call_permissive__.im_func is - view2.__call_permissive__.im_func) - self.assertTrue(view1.__permitted__.im_func is - view2.__permitted__.im_func) - self.assertTrue(view1.__predicated__.im_func is - view2.__predicated__.im_func) + self.assertTrue(getattr(view1.__call_permissive__, im_func) is + getattr(view2.__call_permissive__, im_func)) + self.assertTrue(getattr(view1.__permitted__, im_func) is + getattr(view2.__permitted__, im_func)) + self.assertTrue(getattr(view1.__predicated__, im_func) is + getattr(view2.__predicated__, im_func)) class TestStaticURLInfo(unittest.TestCase): diff --git a/pyramid/tests/test_encode.py b/pyramid/tests/test_encode.py index 738efeea2..ccc8f16e3 100644 --- a/pyramid/tests/test_encode.py +++ b/pyramid/tests/test_encode.py @@ -1,5 +1,6 @@ import unittest from pyramid.compat import text_ +from pyramid.compat import native_ class UrlEncodeTests(unittest.TestCase): def _callFUT(self, query, doseq=False): @@ -11,17 +12,17 @@ class UrlEncodeTests(unittest.TestCase): self.assertEqual(result, 'a=1&b=2') def test_unicode_key(self): - la = text_('LaPe\xc3\xb1a', 'utf-8') + la = text_(b'LaPe\xc3\xb1a', 'utf-8') result = self._callFUT([(la, 1), ('b',2)]) self.assertEqual(result, 'LaPe%C3%B1a=1&b=2') def test_unicode_val_single(self): - la = text_('LaPe\xc3\xb1a', 'utf-8') + la = text_(b'LaPe\xc3\xb1a', 'utf-8') result = self._callFUT([('a', la), ('b',2)]) self.assertEqual(result, 'a=LaPe%C3%B1a&b=2') def test_unicode_val_multiple(self): - la = [text_('LaPe\xc3\xb1a', 'utf-8')] * 2 + la = [text_(b'LaPe\xc3\xb1a', 'utf-8')] * 2 result = self._callFUT([('a', la), ('b',2)], doseq=True) self.assertEqual(result, 'a=LaPe%C3%B1a&a=LaPe%C3%B1a&b=2') @@ -30,6 +31,10 @@ class UrlEncodeTests(unittest.TestCase): result = self._callFUT([('a', s)], doseq=True) self.assertEqual(result, 'a=1&a=2') + def test_with_spaces(self): + result = self._callFUT([('a', '123 456')], doseq=True) + self.assertEqual(result, 'a=123+456') + def test_dict(self): result = self._callFUT({'a':1}) self.assertEqual(result, 'a=1') @@ -39,29 +44,17 @@ class URLQuoteTests(unittest.TestCase): from pyramid.encode import url_quote return url_quote(val, safe) - def test_it_default(self): - la = 'La/Pe\xc3\xb1a' + def test_it_bytes(self): + la = b'La/Pe\xc3\xb1a' result = self._callFUT(la) self.assertEqual(result, 'La%2FPe%C3%B1a') - def test_it_with_safe(self): - la = 'La/Pe\xc3\xb1a' - result = self._callFUT(la, '/') - self.assertEqual(result, 'La/Pe%C3%B1a') - -class TestQuotePlus(unittest.TestCase): - def _callFUT(self, val, safe=''): - from pyramid.encode import quote_plus - return quote_plus(val, safe) - - def test_it_default(self): - la = 'La Pe\xc3\xb1a' + def test_it_native(self): + la = native_(b'La/Pe\xc3\xb1a', 'utf-8') result = self._callFUT(la) - self.assertEqual(result, 'La+Pe%C3%B1a') - + self.assertEqual(result, 'La%2FPe%C3%B1a') + def test_it_with_safe(self): - la = 'La /Pe\xc3\xb1a' + la = b'La/Pe\xc3\xb1a' result = self._callFUT(la, '/') - self.assertEqual(result, 'La+/Pe%C3%B1a') - - + self.assertEqual(result, 'La/Pe%C3%B1a') diff --git a/pyramid/tests/test_httpexceptions.py b/pyramid/tests/test_httpexceptions.py index 6bc7fbb30..927d27733 100644 --- a/pyramid/tests/test_httpexceptions.py +++ b/pyramid/tests/test_httpexceptions.py @@ -277,7 +277,7 @@ class TestRenderAllExceptionsWithoutArguments(unittest.TestCase): exc.content_type = content_type result = list(exc(environ, start_response))[0] if exc.empty_body: - self.assertEqual(result, '') + self.assertEqual(result, b'') else: self.assertTrue(bytes_(exc.status) in result) L.append(result) diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py index f46aca49d..a697b5691 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -1,5 +1,7 @@ import unittest +from pyramid.testing import skip_on +@skip_on('py3') class TestPShellCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.paster import PShellCommand @@ -246,6 +248,7 @@ class TestPShellCommand(unittest.TestCase): self.assertTrue(self.bootstrap.closer.called) self.assertTrue(shell.help) +@skip_on('py3') class TestPRoutesCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.paster import PRoutesCommand @@ -372,6 +375,7 @@ class TestPRoutesCommand(unittest.TestCase): result = command._get_mapper(registry) self.assertEqual(result.__class__, RoutesMapper) +@skip_on('py3') class TestPViewsCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.paster import PViewsCommand @@ -824,6 +828,7 @@ class TestPViewsCommand(unittest.TestCase): self.assertEqual(L[8], ' pyramid.tests.test_paster.view.call') self.assertEqual(L[9], ' view predicates (predicate = x)') +@skip_on('py3') class TestGetApp(unittest.TestCase): def _callFUT(self, config_file, section_name, loadapp): from pyramid.paster import get_app @@ -859,6 +864,7 @@ class TestGetApp(unittest.TestCase): self.assertEqual(loadapp.relative_to, os.getcwd()) self.assertEqual(result, app) +@skip_on('py3') class TestBootstrap(unittest.TestCase): def _callFUT(self, config_uri, request=None): from pyramid.paster import bootstrap @@ -898,6 +904,7 @@ class TestBootstrap(unittest.TestCase): self.assertEqual(result['root'], self.root) self.assert_('closer' in result) +@skip_on('py3') class TestPTweensCommand(unittest.TestCase): def _getTargetClass(self): from pyramid.paster import PTweensCommand diff --git a/pyramid/tests/test_scaffolds.py b/pyramid/tests/test_scaffolds.py index ed2c5a993..265e20c3b 100644 --- a/pyramid/tests/test_scaffolds.py +++ b/pyramid/tests/test_scaffolds.py @@ -1,5 +1,7 @@ import unittest +from pyramid.testing import skip_on +@skip_on('py3') class TestPyramidTemplate(unittest.TestCase): def _getTargetClass(self): from pyramid.scaffolds import PyramidTemplate diff --git a/pyramid/tests/test_traversal.py b/pyramid/tests/test_traversal.py index cd48d0268..07f7515eb 100644 --- a/pyramid/tests/test_traversal.py +++ b/pyramid/tests/test_traversal.py @@ -4,6 +4,7 @@ from pyramid.testing import cleanUp from pyramid.compat import text_ from pyramid.compat import native_ from pyramid.compat import text_type +from pyramid.compat import url_quote class TraversalPathTests(unittest.TestCase): def _callFUT(self, path): @@ -42,18 +43,16 @@ class TraversalPathTests(unittest.TestCase): self.assertEqual(result2, (text_('foo'), text_('bar'))) def test_utf8(self): - import urllib - la = 'La Pe\xc3\xb1a' - encoded = urllib.quote(la) + la = b'La Pe\xc3\xb1a' + encoded = url_quote(la) decoded = text_(la, 'utf-8') path = '/'.join([encoded, encoded]) self.assertEqual(self._callFUT(path), (decoded, decoded)) def test_utf16(self): from pyramid.exceptions import URLDecodeError - import urllib - la = text_('La Pe\xc3\xb1a', 'utf-8').encode('utf-16') - encoded = urllib.quote(la) + la = text_(b'La Pe\xc3\xb1a', 'utf-8').encode('utf-16') + encoded = url_quote(la) path = '/'.join([encoded, encoded]) self.assertRaises(URLDecodeError, self._callFUT, path) @@ -67,7 +66,7 @@ class TraversalPathTests(unittest.TestCase): self.assertEqual(self._callFUT(path), (text_('abc'),)) def test_unicode_undecodeable_to_ascii(self): - path = text_('/La Pe\xc3\xb1a', 'utf-8') + path = text_(b'/La Pe\xc3\xb1a', 'utf-8') self.assertRaises(UnicodeEncodeError, self._callFUT, path) class ResourceTreeTraverserTests(unittest.TestCase): @@ -604,7 +603,7 @@ class FindResourceTests(unittest.TestCase): root = DummyContext(unprintable) unprintable.__parent__ = root unprintable.__name__ = text_( - '/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8') + b'/\xe6\xb5\x81\xe8\xa1\x8c\xe8\xb6\x8b\xe5\x8a\xbf', 'utf-8') root.__parent__ = None root.__name__ = None traverser = ResourceTreeTraverser @@ -757,7 +756,7 @@ class QuotePathSegmentTests(unittest.TestCase): return quote_path_segment(s) def test_unicode(self): - la = text_('/La Pe\xc3\xb1a', 'utf-8') + la = text_(b'/La Pe\xc3\xb1a', 'utf-8') result = self._callFUT(la) self.assertEqual(result, '%2FLa%20Pe%C3%B1a') @@ -774,7 +773,7 @@ class QuotePathSegmentTests(unittest.TestCase): def test_long(self): from pyramid.compat import long import sys - s = long(sys.maxint + 1) + s = long(sys.maxsize + 1) result = self._callFUT(s) expected = str(s) self.assertEqual(result, expected) @@ -847,7 +846,7 @@ class TraversalContextURLTests(unittest.TestCase): root.__name__ = None one = DummyContext() one.__parent__ = root - one.__name__ = text_('La Pe\xc3\xb1a', 'utf-8') + one.__name__ = text_(b'La Pe\xc3\xb1a', 'utf-8') two = DummyContext() two.__parent__ = one two.__name__ = 'La Pe\xc3\xb1a' diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py index 22eacd758..aa6fa30dd 100644 --- a/pyramid/tests/test_url.py +++ b/pyramid/tests/test_url.py @@ -49,7 +49,7 @@ class TestURLMethodsMixin(unittest.TestCase): def test_resource_url_unicode_in_element_names(self): request = self._makeOne() self._registerContextURL(request.registry) - uc = text_('La Pe\xc3\xb1a', 'utf-8') + uc = text_(b'La Pe\xc3\xb1a', 'utf-8') context = DummyContext() result = request.resource_url(context, uc) self.assertEqual(result, @@ -74,7 +74,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() self._registerContextURL(request.registry) context = DummyContext() - uc = text_('La Pe\xc3\xb1a', 'utf-8') + uc = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, 'a', query={'a':uc}) self.assertEqual(result, 'http://example.com/context/a?a=La+Pe%C3%B1a') @@ -83,9 +83,9 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() self._registerContextURL(request.registry) context = DummyContext() - uc = text_('La Pe\xc3\xb1a', 'utf-8') + uc = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, 'a', query=[('a', 'hi there'), - ('b', uc)]) + ('b', uc)]) self.assertEqual(result, 'http://example.com/context/a?a=hi+there&b=La+Pe%C3%B1a') @@ -118,7 +118,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() self._registerContextURL(request.registry) context = DummyContext() - uc = text_('La Pe\xc3\xb1a', 'utf-8') + uc = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.resource_url(context, anchor=uc) self.assertEqual(result, 'http://example.com/context/#La Pe\xc3\xb1a') @@ -173,7 +173,7 @@ class TestURLMethodsMixin(unittest.TestCase): mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_url('flub', a=1, b=2, c=3, _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, 'http://example.com:5432/1/2/3?a=1#foo') @@ -191,7 +191,7 @@ class TestURLMethodsMixin(unittest.TestCase): request = self._makeOne() mapper = DummyRoutesMapper(route=DummyRoute('/1/2/3')) request.registry.registerUtility(mapper, IRoutesMapper) - anchor = text_('La Pe\xc3\xb1a', 'utf-8') + anchor = text_(b'La Pe\xc3\xb1a', 'utf-8') result = request.route_url('flub', _anchor=anchor) self.assertEqual(result, 'http://example.com:5432/1/2/3#La Pe\xc3\xb1a') @@ -282,7 +282,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_url('extra1', 'extra2', _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') @@ -295,7 +295,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.matchdict = {} request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_url('extra1', 'extra2', _query={'a':1}, - _anchor=text_("foo"), + _anchor=text_(b"foo"), _route_name='bar') self.assertEqual(result, 'http://example.com:5432/1/2/3/extra1/extra2?a=1#foo') @@ -310,7 +310,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.script_name = '/script_name' request.registry.registerUtility(mapper, IRoutesMapper) result = request.current_route_path('extra1', 'extra2', _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, '/script_name/1/2/3/extra1/extra2?a=1#foo') def test_route_path_with_elements(self): @@ -321,7 +321,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.script_name = '' result = request.route_path('flub', 'extra1', 'extra2', a=1, b=2, c=3, _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, '/1/2/3/extra1/extra2?a=1#foo') def test_route_path_with_script_name(self): @@ -332,7 +332,7 @@ class TestURLMethodsMixin(unittest.TestCase): request.registry.registerUtility(mapper, IRoutesMapper) result = request.route_path('flub', 'extra1', 'extra2', a=1, b=2, c=3, _query={'a':1}, - _anchor=text_("foo")) + _anchor=text_(b"foo")) self.assertEqual(result, '/foo/1/2/3/extra1/extra2?a=1#foo') def test_static_url_staticurlinfo_notfound(self): diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index 696b69f89..b11bcefcb 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -8,7 +8,7 @@ from pyramid.compat import url_unquote_text from pyramid.compat import native_ from pyramid.compat import text_type from pyramid.compat import is_nonstr_iter -from pyramid.encode import url_quote +from pyramid.compat import url_quote from pyramid.exceptions import URLDecodeError from pyramid.traversal import traversal_path from pyramid.traversal import quote_path_segment @@ -163,7 +163,7 @@ def _compile_route(route): v = '/'.join([quote_path_segment(x) for x in v]) elif k != star: try: - v = url_quote(v) + v = url_quote(v, safe='') except TypeError: pass newdict[k] = v |
