summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pyramid/compat.py17
-rw-r--r--src/pyramid/config/testing.py4
-rw-r--r--src/pyramid/config/views.py4
-rw-r--r--src/pyramid/scripts/pviews.py2
-rw-r--r--src/pyramid/static.py2
-rw-r--r--src/pyramid/traversal.py19
-rw-r--r--src/pyramid/urldispatch.py13
-rw-r--r--src/pyramid/view.py4
-rw-r--r--tests/test_config/test_testing.py14
-rw-r--r--tests/test_config/test_views.py6
-rw-r--r--tests/test_scripts/dummy.py5
-rw-r--r--tests/test_scripts/test_pviews.py18
-rw-r--r--tests/test_url.py1
-rw-r--r--tests/test_urldispatch.py44
14 files changed, 78 insertions, 75 deletions
diff --git a/src/pyramid/compat.py b/src/pyramid/compat.py
index 10d3c4998..30fc10395 100644
--- a/src/pyramid/compat.py
+++ b/src/pyramid/compat.py
@@ -1,7 +1,4 @@
-import inspect
import platform
-import sys
-import types
WIN = platform.system() == 'Windows'
@@ -47,17 +44,3 @@ def native_(s, encoding='latin-1', errors='strict'):
if isinstance(s, str):
return s
return str(s, encoding, errors)
-
-
-# see PEP 3333 for why we encode WSGI PATH_INFO to latin-1 before
-# decoding it to utf-8
-def decode_path_info(path):
- return path.encode('latin-1').decode('utf-8')
-
-
-# see PEP 3333 for why we decode the path to latin-1
-from urllib.parse import unquote_to_bytes
-
-
-def unquote_bytes_to_wsgi(bytestring):
- return unquote_to_bytes(bytestring).decode('latin-1')
diff --git a/src/pyramid/config/testing.py b/src/pyramid/config/testing.py
index bba5054e6..9c998840a 100644
--- a/src/pyramid/config/testing.py
+++ b/src/pyramid/config/testing.py
@@ -9,7 +9,7 @@ from pyramid.interfaces import (
from pyramid.renderers import RendererHelper
-from pyramid.traversal import decode_path_info, split_path_info
+from pyramid.traversal import split_path_info
from pyramid.config.actions import action_method
@@ -95,7 +95,7 @@ class TestingConfiguratorMixin(object):
self.context = context
def __call__(self, request):
- path = decode_path_info(request.environ['PATH_INFO'])
+ path = request.path_info
ob = resources[path]
traversed = split_path_info(path)
return {
diff --git a/src/pyramid/config/views.py b/src/pyramid/config/views.py
index 484c0d754..412e30304 100644
--- a/src/pyramid/config/views.py
+++ b/src/pyramid/config/views.py
@@ -2192,9 +2192,7 @@ class StaticURLInfo(object):
parsed = urlparse(url)
if not parsed.scheme:
url = urlunparse(
- parsed._replace(
- scheme=request.environ['wsgi.url_scheme']
- )
+ parsed._replace(scheme=request.scheme)
)
subpath = quote(subpath)
result = urljoin(url, subpath)
diff --git a/src/pyramid/scripts/pviews.py b/src/pyramid/scripts/pviews.py
index 891dc4709..d2a4bfa40 100644
--- a/src/pyramid/scripts/pviews.py
+++ b/src/pyramid/scripts/pviews.py
@@ -70,7 +70,7 @@ class PViewsCommand(object):
def _find_multi_routes(self, mapper, request):
infos = []
- path = request.environ['PATH_INFO']
+ path = request.path_info
# find all routes that match path, regardless of predicates
for route in mapper.get_routes():
match = route.match(path)
diff --git a/src/pyramid/static.py b/src/pyramid/static.py
index b300df9ee..e3561e93e 100644
--- a/src/pyramid/static.py
+++ b/src/pyramid/static.py
@@ -88,7 +88,7 @@ class static_view(object):
if self.use_subpath:
path_tuple = request.subpath
else:
- path_tuple = traversal_path_info(request.environ['PATH_INFO'])
+ path_tuple = traversal_path_info(request.path_info)
path = _secure_path(path_tuple)
if path is None:
diff --git a/src/pyramid/traversal.py b/src/pyramid/traversal.py
index 429b12e23..e846881f3 100644
--- a/src/pyramid/traversal.py
+++ b/src/pyramid/traversal.py
@@ -1,4 +1,6 @@
from functools import lru_cache
+from urllib.parse import unquote_to_bytes
+
from zope.interface import implementer
from zope.interface.interfaces import IInterface
@@ -9,12 +11,7 @@ from pyramid.interfaces import (
VH_ROOT_KEY,
)
-from pyramid.compat import (
- native_,
- ascii_native_,
- decode_path_info,
- unquote_bytes_to_wsgi,
-)
+from pyramid.compat import native_, ascii_native_
from pyramid.encode import url_quote
from pyramid.exceptions import URLDecodeError
@@ -543,6 +540,16 @@ def split_path_info(path):
return tuple(clean)
+# see PEP 3333 for why we encode to latin-1 then decode to utf-8
+def decode_path_info(path):
+ return path.encode('latin-1').decode('utf-8')
+
+
+# see PEP 3333 for why we decode the path to latin-1
+def unquote_bytes_to_wsgi(bytestring):
+ return unquote_to_bytes(bytestring).decode('latin-1')
+
+
_segment_cache = {}
diff --git a/src/pyramid/urldispatch.py b/src/pyramid/urldispatch.py
index 6d25b2dd5..6348ae7e2 100644
--- a/src/pyramid/urldispatch.py
+++ b/src/pyramid/urldispatch.py
@@ -3,7 +3,7 @@ from zope.interface import implementer
from pyramid.interfaces import IRoutesMapper, IRoute
-from pyramid.compat import native_, text_, decode_path_info
+from pyramid.compat import text_
from pyramid.exceptions import URLDecodeError
@@ -75,10 +75,9 @@ class RoutesMapper(object):
return self.routes[name].generate(kw)
def __call__(self, request):
- environ = request.environ
try:
# empty if mounted under a path in mod_wsgi, for example
- path = decode_path_info(environ['PATH_INFO'] or '/')
+ path = request.path_info or '/'
except KeyError:
path = '/'
except UnicodeDecodeError as e:
@@ -202,14 +201,10 @@ def _compile_route(route):
return None
d = {}
for k, v in m.groupdict().items():
- # k and v will be Unicode 2.6.4 and lower doesnt accept unicode
- # kwargs as **kw, so we explicitly cast the keys to native
- # strings in case someone wants to pass the result as **kw
- nk = native_(k, 'ascii')
if k == remainder:
- d[nk] = split_path_info(v)
+ d[k] = split_path_info(v)
else:
- d[nk] = v
+ d[k] = v
return d
gen = ''.join(gen)
diff --git a/src/pyramid/view.py b/src/pyramid/view.py
index 9e85d7281..944ad93ea 100644
--- a/src/pyramid/view.py
+++ b/src/pyramid/view.py
@@ -15,8 +15,6 @@ from pyramid.interfaces import (
IExceptionViewClassifier,
)
-from pyramid.compat import decode_path_info
-
from pyramid.exceptions import ConfigurationError, PredicateMismatch
from pyramid.httpexceptions import (
@@ -305,7 +303,7 @@ class AppendSlashNotFoundViewFactory(object):
self.redirect_class = redirect_class
def __call__(self, context, request):
- path = decode_path_info(request.environ['PATH_INFO'] or '/')
+ path = request.path_info
registry = request.registry
mapper = registry.queryUtility(IRoutesMapper)
if mapper is not None and not path.endswith('/'):
diff --git a/tests/test_config/test_testing.py b/tests/test_config/test_testing.py
index ede31e1b6..870bbe9fa 100644
--- a/tests/test_config/test_testing.py
+++ b/tests/test_config/test_testing.py
@@ -69,23 +69,27 @@ class TestingConfiguratorMixinTests(unittest.TestCase):
config = self._makeOne(autocommit=True)
config.testing_resources(resources)
adapter = config.registry.getAdapter(None, ITraverser)
- result = adapter(DummyRequest({'PATH_INFO': '/ob1'}))
+ request = DummyRequest()
+ request.path_info = '/ob1'
+ result = adapter(request)
self.assertEqual(result['context'], ob1)
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], (text_('ob1'),))
self.assertEqual(result['virtual_root'], ob1)
self.assertEqual(result['virtual_root_path'], ())
- result = adapter(DummyRequest({'PATH_INFO': '/ob2'}))
+ request = DummyRequest()
+ request.path_info = '/ob2'
+ result = adapter(request)
self.assertEqual(result['context'], ob2)
self.assertEqual(result['view_name'], '')
self.assertEqual(result['subpath'], ())
self.assertEqual(result['traversed'], (text_('ob2'),))
self.assertEqual(result['virtual_root'], ob2)
self.assertEqual(result['virtual_root_path'], ())
- self.assertRaises(
- KeyError, adapter, DummyRequest({'PATH_INFO': '/ob3'})
- )
+ request = DummyRequest()
+ request.path_info = '/ob3'
+ self.assertRaises(KeyError, adapter, request)
try:
config.begin()
self.assertEqual(find_resource(None, '/ob1'), ob1)
diff --git a/tests/test_config/test_views.py b/tests/test_config/test_views.py
index d530542b7..e25ee881e 100644
--- a/tests/test_config/test_views.py
+++ b/tests/test_config/test_views.py
@@ -1357,6 +1357,7 @@ class TestViewsConfigurationMixin(unittest.TestCase):
request_method='POST',
)
request = self._makeRequest(config)
+ request.path_info = '/'
request.method = 'POST'
request.params = {}
router = Router(config.registry)
@@ -1412,6 +1413,7 @@ class TestViewsConfigurationMixin(unittest.TestCase):
request_method='POST',
)
request = self._makeRequest(config)
+ request.path_info = '/'
request.method = 'POST'
request.params = {}
router = Router(config.registry)
@@ -2722,7 +2724,7 @@ class TestViewsConfigurationMixin(unittest.TestCase):
view, renderer=null_renderer, append_slash=True
)
request = self._makeRequest(config)
- request.environ['PATH_INFO'] = '/foo'
+ request.path_info = '/foo'
request.query_string = 'a=1&b=2'
request.path = '/scriptname/foo'
view = self._getViewCallable(
@@ -2751,7 +2753,7 @@ class TestViewsConfigurationMixin(unittest.TestCase):
view, renderer=null_renderer, append_slash=HTTPMovedPermanently
)
request = self._makeRequest(config)
- request.environ['PATH_INFO'] = '/foo'
+ request.path_info = '/foo'
request.query_string = 'a=1&b=2'
request.path = '/scriptname/foo'
view = self._getViewCallable(
diff --git a/tests/test_scripts/dummy.py b/tests/test_scripts/dummy.py
index 8e340f645..bb3475d39 100644
--- a/tests/test_scripts/dummy.py
+++ b/tests/test_scripts/dummy.py
@@ -81,8 +81,11 @@ class DummyRoute(object):
class DummyRequest:
application_url = 'http://example.com:5432'
script_name = ''
+ path_info = '/'
- def __init__(self, environ):
+ def __init__(self, environ=None):
+ if environ is None:
+ environ = {}
self.environ = environ
self.matchdict = {}
diff --git a/tests/test_scripts/test_pviews.py b/tests/test_scripts/test_pviews.py
index 0b26a9cf3..c8d29113f 100644
--- a/tests/test_scripts/test_pviews.py
+++ b/tests/test_scripts/test_pviews.py
@@ -53,7 +53,8 @@ class TestPViewsCommand(unittest.TestCase):
class View1(object):
pass
- request = dummy.DummyRequest({'PATH_INFO': '/a'})
+ request = dummy.DummyRequest()
+ request.path_info = '/a'
root = DefaultRootFactory(request)
root_iface = providedBy(root)
registry.registerAdapter(
@@ -78,7 +79,8 @@ class TestPViewsCommand(unittest.TestCase):
def view1(): # pragma: no cover
pass
- request = dummy.DummyRequest({'PATH_INFO': '/a'})
+ request = dummy.DummyRequest()
+ request.path_info = '/a'
root = DefaultRootFactory(request)
root_iface = providedBy(root)
registry.registerAdapter(
@@ -105,7 +107,8 @@ class TestPViewsCommand(unittest.TestCase):
class View1(object):
pass
- request = dummy.DummyRequest({'PATH_INFO': '/a'})
+ request = dummy.DummyRequest()
+ request.path_info = '/a'
root = DefaultRootFactory(request)
root_iface = providedBy(root)
view = View1()
@@ -267,7 +270,8 @@ class TestPViewsCommand(unittest.TestCase):
dummy.DummyRoute('b', '/a', factory=factory, matchdict={}),
]
mapper = dummy.DummyMapper(*routes)
- request = dummy.DummyRequest({'PATH_INFO': '/a'})
+ request = dummy.DummyRequest()
+ request.path_info = '/a'
result = command._find_multi_routes(mapper, request)
self.assertEqual(
result,
@@ -288,7 +292,8 @@ class TestPViewsCommand(unittest.TestCase):
dummy.DummyRoute('b', '/a', factory=factory, matchdict={}),
]
mapper = dummy.DummyMapper(*routes)
- request = dummy.DummyRequest({'PATH_INFO': '/a'})
+ request = dummy.DummyRequest()
+ request.path_info = '/a'
result = command._find_multi_routes(mapper, request)
self.assertEqual(result, [{'match': {}, 'route': routes[1]}])
@@ -303,7 +308,8 @@ class TestPViewsCommand(unittest.TestCase):
dummy.DummyRoute('b', '/a', factory=factory),
]
mapper = dummy.DummyMapper(*routes)
- request = dummy.DummyRequest({'PATH_INFO': '/a'})
+ request = dummy.DummyRequest()
+ request.path_info = '/a'
result = command._find_multi_routes(mapper, request)
self.assertEqual(result, [])
diff --git a/tests/test_url.py b/tests/test_url.py
index 94a0a61c9..a852f3301 100644
--- a/tests/test_url.py
+++ b/tests/test_url.py
@@ -25,6 +25,7 @@ class TestURLMethodsMixin(unittest.TestCase):
def __init__(self, environ):
self.environ = environ
+ self.scheme = environ.get('wsgi.url_scheme', 'http')
request = Request(environ)
request.registry = self.config.registry
diff --git a/tests/test_urldispatch.py b/tests/test_urldispatch.py
index b50e86b99..9296a50e1 100644
--- a/tests/test_urldispatch.py
+++ b/tests/test_urldispatch.py
@@ -59,9 +59,7 @@ class RoutesMapperTests(unittest.TestCase):
def _getRequest(self, **kw):
from pyramid.threadlocal import get_current_registry
- environ = {'SERVER_NAME': 'localhost', 'wsgi.url_scheme': 'http'}
- environ.update(kw)
- request = DummyRequest(environ)
+ request = DummyRequest(**kw)
reg = get_current_registry()
request.registry = reg
return request
@@ -83,7 +81,7 @@ class RoutesMapperTests(unittest.TestCase):
def test_no_route_matches(self):
mapper = self._makeOne()
- request = self._getRequest(PATH_INFO='/')
+ request = self._getRequest(path_info='/')
result = mapper(request)
self.assertEqual(result['match'], None)
self.assertEqual(result['route'], None)
@@ -130,16 +128,22 @@ class RoutesMapperTests(unittest.TestCase):
def test___call__pathinfo_cant_be_decoded(self):
from pyramid.exceptions import URLDecodeError
+ from pyramid.threadlocal import get_current_registry
+
+ class DummyRequest:
+ @property
+ def path_info(self):
+ return b'\xff\xfe\xe6\x00'.decode('utf-8')
mapper = self._makeOne()
- path_info = b'\xff\xfe\xe6\x00'.decode('latin-1')
- request = self._getRequest(PATH_INFO=path_info)
+ request = DummyRequest()
+ request.registry = get_current_registry()
self.assertRaises(URLDecodeError, mapper, request)
def test___call__route_matches(self):
mapper = self._makeOne()
mapper.connect('foo', 'archives/:action/:article')
- request = self._getRequest(PATH_INFO='/archives/action1/article1')
+ request = self._getRequest(path_info='/archives/action1/article1')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['foo'])
self.assertEqual(result['match']['action'], 'action1')
@@ -150,7 +154,7 @@ class RoutesMapperTests(unittest.TestCase):
mapper.connect(
'foo', 'archives/:action/:article', predicates=[lambda *arg: True]
)
- request = self._getRequest(PATH_INFO='/archives/action1/article1')
+ request = self._getRequest(path_info='/archives/action1/article1')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['foo'])
self.assertEqual(result['match']['action'], 'action1')
@@ -164,7 +168,7 @@ class RoutesMapperTests(unittest.TestCase):
predicates=[lambda *arg: True, lambda *arg: False],
)
mapper.connect('bar', 'archives/:action/:article')
- request = self._getRequest(PATH_INFO='/archives/action1/article1')
+ request = self._getRequest(path_info='/archives/action1/article1')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['bar'])
self.assertEqual(result['match']['action'], 'action1')
@@ -179,7 +183,7 @@ class RoutesMapperTests(unittest.TestCase):
return True
mapper.connect('foo', 'archives/:action/article1', predicates=[pred])
- request = self._getRequest(PATH_INFO='/archives/action1/article1')
+ request = self._getRequest(path_info='/archives/action1/article1')
mapper(request)
def test_cc_bug(self):
@@ -191,13 +195,13 @@ class RoutesMapperTests(unittest.TestCase):
'juri', 'licenses/:license_code/:license_version/:jurisdiction'
)
- request = self._getRequest(PATH_INFO='/licenses/1/v2/rdf')
+ request = self._getRequest(path_info='/licenses/1/v2/rdf')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['rdf'])
self.assertEqual(result['match']['license_code'], '1')
self.assertEqual(result['match']['license_version'], 'v2')
- request = self._getRequest(PATH_INFO='/licenses/1/v2/usa')
+ request = self._getRequest(path_info='/licenses/1/v2/usa')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['juri'])
self.assertEqual(result['match']['license_code'], '1')
@@ -207,7 +211,7 @@ class RoutesMapperTests(unittest.TestCase):
def test___call__root_route_matches(self):
mapper = self._makeOne()
mapper.connect('root', '')
- request = self._getRequest(PATH_INFO='/')
+ request = self._getRequest(path_info='/')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['root'])
self.assertEqual(result['match'], {})
@@ -215,7 +219,7 @@ class RoutesMapperTests(unittest.TestCase):
def test___call__root_route_matches2(self):
mapper = self._makeOne()
mapper.connect('root', '/')
- request = self._getRequest(PATH_INFO='/')
+ request = self._getRequest(path_info='/')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['root'])
self.assertEqual(result['match'], {})
@@ -223,7 +227,7 @@ class RoutesMapperTests(unittest.TestCase):
def test___call__root_route_when_path_info_empty(self):
mapper = self._makeOne()
mapper.connect('root', '/')
- request = self._getRequest(PATH_INFO='')
+ request = self._getRequest(path_info='')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['root'])
self.assertEqual(result['match'], {})
@@ -231,7 +235,7 @@ class RoutesMapperTests(unittest.TestCase):
def test___call__root_route_when_path_info_notempty(self):
mapper = self._makeOne()
mapper.connect('root', '/')
- request = self._getRequest(PATH_INFO='/')
+ request = self._getRequest(path_info='/')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['root'])
self.assertEqual(result['match'], {})
@@ -239,7 +243,7 @@ class RoutesMapperTests(unittest.TestCase):
def test___call__no_path_info(self):
mapper = self._makeOne()
mapper.connect('root', '/')
- request = self._getRequest()
+ request = self._getRequest(path_info='')
result = mapper(request)
self.assertEqual(result['route'], mapper.routes['root'])
self.assertEqual(result['match'], {})
@@ -643,8 +647,10 @@ class DummyContext(object):
class DummyRequest(object):
- def __init__(self, environ):
- self.environ = environ
+ scheme = 'http'
+
+ def __init__(self, **kw):
+ self.__dict__.update(kw)
class DummyRoute(object):