summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt17
-rw-r--r--TODO.txt3
-rw-r--r--docs/conf.py2
-rw-r--r--docs/narr/environment.rst63
-rw-r--r--pyramid/request.py52
-rw-r--r--pyramid/static.py43
-rw-r--r--pyramid/tests/test_integration.py20
-rw-r--r--pyramid/tests/test_request.py67
-rw-r--r--pyramid/tests/test_static.py9
-rw-r--r--pyramid/tests/test_wsgi.py48
-rw-r--r--pyramid/tests/wsgiapp2app/__init__.py17
-rw-r--r--pyramid/wsgi.py40
-rw-r--r--setup.py2
13 files changed, 273 insertions, 110 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 5f08606be..c0108ff3a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -25,6 +25,10 @@ Documentation
``pyramid.config.Configurator.set_view_mapper`` and refer to it within
Hooks chapter section named "Using a View Mapper".
+- Added section to the "Environment Variables and ``.ini`` File Settings"
+ chapter in the narrative documentation section entitled "Adding a Custom
+ Setting".
+
Features
--------
@@ -136,6 +140,13 @@ Bug Fixes
- Redirects issued by a static view did not take into account any existing
``SCRIPT_NAME`` (such as one set by a url mapping composite). Now they do.
+- The ``pyramid.wsgi.wsgiapp2`` decorator did not take into account the
+ ``SCRIPT_NAME`` in the origin request.
+
+- The ``pyramid.wsgi.wsgiapp2`` decorator effectively only worked when it
+ decorated a view found via traversal; it ignored the ``PATH_INFO`` that was
+ part of a url-dispatch-matched view.
+
Deprecations
------------
@@ -169,6 +180,12 @@ Behavior Changes
renderer changes the content type (to ``application/json`` or
``text/plain`` for JSON and string renderers respectively).
+- The ``pyramid.wsgi.wsgiapp2`` now uses a slightly different method of
+ figuring out how to "fix" ``SCRIPT_NAME`` and ``PATH_INFO`` for the
+ downstream application. As a result, those values may differ slightly from
+ the perspective of the downstream application (for example, ``SCRIPT_NAME``
+ will now never possess a trailing slash).
+
Dependencies
------------
diff --git a/TODO.txt b/TODO.txt
index eccfb34ed..ac915955c 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -89,9 +89,6 @@ Nice-to-Have
action = '^foo$'
mypackage.views.MyView.foo_GET
-- Raise an exception when a value in response_headerlist is not a
- string or decide to encode.
-
- Update App engine chapter with less creaky directions.
- Add functionality that mocks the behavior of ``repoze.browserid``.
diff --git a/docs/conf.py b/docs/conf.py
index a987106d4..a610351ff 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -93,7 +93,7 @@ copyright = '%s, Agendaless Consulting' % datetime.datetime.now().year
# other places throughout the built documents.
#
# The short X.Y version.
-version = '1.0'
+version = '1.1a0'
# The full version, including alpha/beta/rc tags.
release = version
diff --git a/docs/narr/environment.rst b/docs/narr/environment.rst
index 7b7946aae..8c299f3a3 100644
--- a/docs/narr/environment.rst
+++ b/docs/narr/environment.rst
@@ -381,3 +381,66 @@ around in overridden asset directories. ``reload_assets`` makes the system
*very slow* when templates are in use. Never set ``reload_assets`` to
``True`` on a production system.
+Adding A Custom Setting
+-----------------------
+
+From time to time, you may need to add a custom setting to your application.
+Here's how:
+
+- If you're using an ``.ini`` file, change the ``.ini`` file, adding the
+ setting to the ``[app:foo]`` section representing your Pyramid application.
+ For example:
+
+ .. code-block:: ini
+
+ [app:myapp]
+ # .. other settings
+ debug_frobnosticator = True
+
+- In the ``main()`` function that represents the place that your Pyramid WSGI
+ application is created, anticipate that you'll be getting this key/value
+ pair as a setting and do any type conversion necessary.
+
+ If you've done any type conversion of your custom value, reset the
+ converted values into the ``settings`` dictionary *before* you pass the
+ dictionary as ``settings`` to the :term:`Configurator`. For example:
+
+ .. code-block:: python
+
+ def main(global_config, **settings):
+ # ...
+ from pyramid.settings import asbool
+ debug_frobnosticator = asbool(settings.get(
+ 'debug_frobnosticator', 'false'))
+ settings['debug_frobnosticator'] = debug_frobnosticator
+ config = Configurator(settings=settings)
+
+ .. note:: It's especially important that you mutate the ``settings``
+ dictionary with the converted version of the variable *before* passing
+ it to the Configurator: the configurator makes a *copy* of ``settings``,
+ it doesn't use the one you pass directly.
+
+- In the runtime code that you need to access the new settings value, find
+ the value in the ``registry.settings`` dictionary and use it. In
+ :term:`view` code (or any other code that has access to the request), the
+ easiest way to do this is via ``request.registry.settings``. For example:
+
+ .. code-block:: python
+
+ registry = request.registry.settings
+ debug_frobnosticator = settings['debug_frobnosticator']
+
+ If you wish to use the value in code that does not have access to the
+ request and you wish to use the value, you'll need to use the
+ :func:`pyramid.threadlocal.get_current_registry` API to obtain the current
+ registry, then ask for its ``settings`` attribute. For example:
+
+ .. code-block:: python
+
+ registry = pyramid.threadlocal.get_current_registry()
+ settings = registry.settings
+ debug_frobnosticator = settings['debug_frobnosticator']
+
+
+
+
diff --git a/pyramid/request.py b/pyramid/request.py
index 9d2b9344b..0fe8b9379 100644
--- a/pyramid/request.py
+++ b/pyramid/request.py
@@ -10,6 +10,7 @@ from pyramid.interfaces import IResponseFactory
from pyramid.exceptions import ConfigurationError
from pyramid.decorator import reify
from pyramid.response import Response
+from pyramid.traversal import quote_path_segment
from pyramid.url import resource_url
from pyramid.url import route_url
from pyramid.url import static_url
@@ -393,3 +394,54 @@ def add_global_response_headers(request, headerlist):
response.headerlist.append((k, v))
request.add_response_callback(add_headers)
+def call_app_with_subpath_as_path_info(request, app):
+ # Copy the request. Use the source request's subpath (if it exists) as
+ # the new request's PATH_INFO. Set the request copy's SCRIPT_NAME to the
+ # prefix before the subpath. Call the application with the new request
+ # and return a response.
+ #
+ # Postconditions:
+ # - SCRIPT_NAME and PATH_INFO are empty or start with /
+ # - At least one of SCRIPT_NAME or PATH_INFO are set.
+ # - SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should
+ # be '/').
+
+ environ = request.environ
+ script_name = environ.get('SCRIPT_NAME', '')
+ path_info = environ.get('PATH_INFO', '/')
+ subpath = list(getattr(request, 'subpath', ()))
+
+ new_script_name = ''
+
+ # compute new_path_info
+ new_path_info = '/' + '/'.join([x.encode('utf-8') for x in subpath])
+
+ if new_path_info != '/': # don't want a sole double-slash
+ if path_info != '/': # if orig path_info is '/', we're already done
+ if path_info.endswith('/'):
+ # readd trailing slash stripped by subpath (traversal)
+ # conversion
+ new_path_info += '/'
+
+ # compute new_script_name
+ workback = (script_name + path_info).split('/')
+
+ tmp = []
+ while workback:
+ if tmp == subpath:
+ break
+ el = workback.pop()
+ if el:
+ tmp.insert(0, el.decode('utf-8'))
+
+ # strip all trailing slashes from workback to avoid appending undue slashes
+ # to end of script_name
+ while workback and (workback[-1] == ''):
+ workback = workback[:-1]
+
+ new_script_name = '/'.join(workback)
+
+ new_request = request.copy()
+ new_request.environ['SCRIPT_NAME'] = new_script_name
+ new_request.environ['PATH_INFO'] = new_path_info
+ return new_request.get_response(app)
diff --git a/pyramid/static.py b/pyramid/static.py
index 9e53c034a..ec7b4cb00 100644
--- a/pyramid/static.py
+++ b/pyramid/static.py
@@ -13,6 +13,7 @@ from zope.interface import implements
from pyramid.asset import resolve_asset_spec
from pyramid.interfaces import IStaticURLInfo
from pyramid.path import caller_package
+from pyramid.request import call_app_with_subpath_as_path_info
from pyramid.url import route_url
class PackageURLParser(StaticURLParser):
@@ -221,44 +222,4 @@ class static_view(object):
self.app = app
def __call__(self, context, request):
- # Point PATH_INFO to the static file/dir path; point SCRIPT_NAME
- # to the prefix before it.
-
- # Postconditions:
- # - SCRIPT_NAME and PATH_INFO are empty or start with /
- # - At least one of SCRIPT_NAME or PATH_INFO are set.
- # - SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should
- # be '/').
-
- request_copy = request.copy()
- script_name = request_copy.environ.get('SCRIPT_NAME', '')
- path_info = request_copy.environ.get('PATH_INFO', '/')
-
- new_script_name = script_name
- new_path_info = path_info
-
- subpath = list(request.subpath)
-
- if subpath:
- # compute new_path_info
- new_path_info = '/' + '/'.join(subpath)
- if path_info.endswith('/'):
- # readd trailing slash stripped by subpath (traversal)
- # conversion
- new_path_info += '/'
-
- # compute new_script_name
- tmp = []
- workback = (script_name + path_info).split('/')
- while workback:
- el = workback.pop()
- if el:
- tmp.insert(0, el)
- if tmp == subpath:
- new_script_name = '/'.join(workback)
- break
-
- request_copy.environ['SCRIPT_NAME'] = new_script_name
- request_copy.environ['PATH_INFO'] = new_path_info
-
- return request_copy.get_response(self.app)
+ return call_app_with_subpath_as_path_info(request, self.app)
diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py
index 1f9484279..dd77d3aec 100644
--- a/pyramid/tests/test_integration.py
+++ b/pyramid/tests/test_integration.py
@@ -104,7 +104,7 @@ class TestStaticApp(unittest.TestCase):
from webob import Request
context = DummyContext()
from StringIO import StringIO
- request = Request({'PATH_INFO':'',
+ request = Request({'PATH_INFO':'/static',
'SCRIPT_NAME':'/script_name',
'SERVER_NAME':'localhost',
'SERVER_PORT':'80',
@@ -112,7 +112,7 @@ class TestStaticApp(unittest.TestCase):
'wsgi.version':(1,0),
'wsgi.url_scheme':'http',
'wsgi.input':StringIO()})
- request.subpath = ['static']
+ request.subpath = ('static',)
result = staticapp(context, request)
self.assertEqual(result.status, '301 Moved Permanently')
self.assertEqual(result.location,
@@ -390,6 +390,22 @@ class SelfScanAppTest(unittest.TestCase):
res = self.testapp.get('/two', status=200)
self.assertTrue('two' in res.body)
+class WSGIApp2AppTest(unittest.TestCase):
+ def setUp(self):
+ from pyramid.tests.wsgiapp2app import main
+ config = main()
+ app = config.make_wsgi_app()
+ from webtest import TestApp
+ self.testapp = TestApp(app)
+ self.config = config
+
+ def tearDown(self):
+ self.config.end()
+
+ def test_hello(self):
+ res = self.testapp.get('/hello', status=200)
+ self.assertTrue('Hello' in res.body)
+
class DummyContext(object):
pass
diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py
index 66a451220..60d59ece6 100644
--- a/pyramid/tests/test_request.py
+++ b/pyramid/tests/test_request.py
@@ -325,6 +325,66 @@ class Test_add_global_response_headers(unittest.TestCase):
request.response_callbacks[0](None, response)
self.assertEqual(response.headerlist, [('c', 1)] )
+class Test_call_app_with_subpath_as_path_info(unittest.TestCase):
+ def _callFUT(self, request, app):
+ from pyramid.request import call_app_with_subpath_as_path_info
+ return call_app_with_subpath_as_path_info(request, app)
+
+ def test_it_all_request_and_environment_data_missing(self):
+ request = DummyRequest({})
+ response = self._callFUT(request, 'app')
+ self.assertTrue(request.copied)
+ self.assertEqual(response, 'app')
+ self.assertEqual(request.environ['SCRIPT_NAME'], '')
+ self.assertEqual(request.environ['PATH_INFO'], '/')
+
+ def test_it_with_subpath_and_path_info(self):
+ request = DummyRequest({'PATH_INFO':'/hello'})
+ request.subpath = ('hello',)
+ response = self._callFUT(request, 'app')
+ self.assertTrue(request.copied)
+ self.assertEqual(response, 'app')
+ self.assertEqual(request.environ['SCRIPT_NAME'], '')
+ self.assertEqual(request.environ['PATH_INFO'], '/hello')
+
+ def test_it_with_subpath_and_path_info_path_info_endswith_slash(self):
+ request = DummyRequest({'PATH_INFO':'/hello/'})
+ request.subpath = ('hello',)
+ response = self._callFUT(request, 'app')
+ self.assertTrue(request.copied)
+ self.assertEqual(response, 'app')
+ self.assertEqual(request.environ['SCRIPT_NAME'], '')
+ self.assertEqual(request.environ['PATH_INFO'], '/hello/')
+
+ def test_it_with_subpath_and_path_info_extra_script_name(self):
+ request = DummyRequest({'PATH_INFO':'/hello', 'SCRIPT_NAME':'/script'})
+ request.subpath = ('hello',)
+ response = self._callFUT(request, 'app')
+ self.assertTrue(request.copied)
+ self.assertEqual(response, 'app')
+ self.assertEqual(request.environ['SCRIPT_NAME'], '/script')
+ self.assertEqual(request.environ['PATH_INFO'], '/hello')
+
+ def test_it_with_extra_slashes_in_path_info(self):
+ request = DummyRequest({'PATH_INFO':'//hello/',
+ 'SCRIPT_NAME':'/script'})
+ request.subpath = ('hello',)
+ response = self._callFUT(request, 'app')
+ self.assertTrue(request.copied)
+ self.assertEqual(response, 'app')
+ self.assertEqual(request.environ['SCRIPT_NAME'], '/script')
+ self.assertEqual(request.environ['PATH_INFO'], '/hello/')
+
+ def test_subpath_path_info_and_script_name_have_utf8(self):
+ la = 'La Pe\xc3\xb1a'
+ request = DummyRequest({'PATH_INFO':'/'+la, 'SCRIPT_NAME':'/'+la})
+ request.subpath = (unicode(la, 'utf-8'), )
+ response = self._callFUT(request, 'app')
+ self.assertTrue(request.copied)
+ self.assertEqual(response, 'app')
+ self.assertEqual(request.environ['SCRIPT_NAME'], '/' + la)
+ self.assertEqual(request.environ['PATH_INFO'], '/' + la)
+
class DummyRequest:
def __init__(self, environ=None):
if environ is None:
@@ -334,6 +394,13 @@ class DummyRequest:
def add_response_callback(self, callback):
self.response_callbacks = [callback]
+ def get_response(self, app):
+ return app
+
+ def copy(self):
+ self.copied = True
+ return self
+
class DummyResponse:
def __init__(self):
self.headerlist = []
diff --git a/pyramid/tests/test_static.py b/pyramid/tests/test_static.py
index 43e80098e..e7506628a 100644
--- a/pyramid/tests/test_static.py
+++ b/pyramid/tests/test_static.py
@@ -268,8 +268,9 @@ class Test_static_view(unittest.TestCase):
SCRIPT_NAME='/script_name')
view(context, request)
self.assertEqual(request.copied, True)
- self.assertEqual(request.environ['PATH_INFO'], '/path_info')
- self.assertEqual(request.environ['SCRIPT_NAME'], '/script_name')
+ self.assertEqual(request.environ['PATH_INFO'], '/')
+ self.assertEqual(request.environ['SCRIPT_NAME'],
+ '/script_name/path_info')
def test_with_subpath_path_info_ends_with_slash(self):
view = self._makeOne('fixtures', package_name='another')
@@ -295,7 +296,7 @@ class Test_static_view(unittest.TestCase):
self.assertEqual(request.environ['SCRIPT_NAME'],
'/scriptname/path_info')
- def test_with_subpath_new_script_name_fixes_trailing_double_slashes(self):
+ def test_with_subpath_new_script_name_fixes_trailing_slashes(self):
view = self._makeOne('fixtures', package_name='another')
context = DummyContext()
request = DummyRequest()
@@ -304,7 +305,7 @@ class Test_static_view(unittest.TestCase):
view(context, request)
self.assertEqual(request.copied, True)
self.assertEqual(request.environ['PATH_INFO'], '/sub/path/')
- self.assertEqual(request.environ['SCRIPT_NAME'], '/path_info/')
+ self.assertEqual(request.environ['SCRIPT_NAME'], '/path_info')
class TestStaticURLInfo(unittest.TestCase):
def _getTargetClass(self):
diff --git a/pyramid/tests/test_wsgi.py b/pyramid/tests/test_wsgi.py
index f63667352..06bcf1cb2 100644
--- a/pyramid/tests/test_wsgi.py
+++ b/pyramid/tests/test_wsgi.py
@@ -20,11 +20,9 @@ class WSGIApp2Tests(unittest.TestCase):
def test_decorator_with_subpath_and_view_name(self):
context = DummyContext()
request = DummyRequest()
- request.traversed = ['a', 'b']
- request.virtual_root_path = ['a']
- request.subpath = ['subpath']
- request.view_name = 'view_name'
- request.environ = {'SCRIPT_NAME':'/foo'}
+ request.subpath = ('subpath',)
+ request.environ = {'SCRIPT_NAME':'/foo',
+ 'PATH_INFO':'/b/view_name/subpath'}
decorator = self._callFUT(dummyapp)
response = decorator(context, request)
self.assertEqual(response, dummyapp)
@@ -34,11 +32,8 @@ class WSGIApp2Tests(unittest.TestCase):
def test_decorator_with_subpath_no_view_name(self):
context = DummyContext()
request = DummyRequest()
- request.traversed = ['a', 'b']
- request.virtual_root_path = ['a']
- request.subpath = ['subpath']
- request.view_name = ''
- request.environ = {'SCRIPT_NAME':'/foo'}
+ request.subpath = ('subpath',)
+ request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/b/subpath'}
decorator = self._callFUT(dummyapp)
response = decorator(context, request)
self.assertEqual(response, dummyapp)
@@ -48,11 +43,8 @@ class WSGIApp2Tests(unittest.TestCase):
def test_decorator_no_subpath_with_view_name(self):
context = DummyContext()
request = DummyRequest()
- request.traversed = ['a', 'b']
- request.virtual_root_path = ['a']
- request.subpath = []
- request.view_name = 'view_name'
- request.environ = {'SCRIPT_NAME':'/foo'}
+ request.subpath = ()
+ request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/b/view_name'}
decorator = self._callFUT(dummyapp)
response = decorator(context, request)
self.assertEqual(response, dummyapp)
@@ -62,11 +54,8 @@ class WSGIApp2Tests(unittest.TestCase):
def test_decorator_traversed_empty_with_view_name(self):
context = DummyContext()
request = DummyRequest()
- request.traversed = []
- request.virtual_root_path = []
- request.subpath = []
- request.view_name = 'view_name'
- request.environ = {'SCRIPT_NAME':'/foo'}
+ request.subpath = ()
+ request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/view_name'}
decorator = self._callFUT(dummyapp)
response = decorator(context, request)
self.assertEqual(response, dummyapp)
@@ -76,11 +65,8 @@ class WSGIApp2Tests(unittest.TestCase):
def test_decorator_traversed_empty_no_view_name(self):
context = DummyContext()
request = DummyRequest()
- request.traversed = []
- request.virtual_root_path = []
- request.subpath = []
- request.view_name = ''
- request.environ = {'SCRIPT_NAME':'/foo'}
+ request.subpath = ()
+ request.environ = {'SCRIPT_NAME':'/foo', 'PATH_INFO':'/'}
decorator = self._callFUT(dummyapp)
response = decorator(context, request)
self.assertEqual(response, dummyapp)
@@ -90,11 +76,8 @@ class WSGIApp2Tests(unittest.TestCase):
def test_decorator_traversed_empty_no_view_name_no_script_name(self):
context = DummyContext()
request = DummyRequest()
- request.traversed = []
- request.virtual_root_path = []
- request.subpath = []
- request.view_name = ''
- request.environ = {'SCRIPT_NAME':''}
+ request.subpath = ()
+ request.environ = {'SCRIPT_NAME':'', 'PATH_INFO':'/'}
decorator = self._callFUT(dummyapp)
response = decorator(context, request)
self.assertEqual(response, dummyapp)
@@ -110,3 +93,8 @@ class DummyContext:
class DummyRequest:
def get_response(self, application):
return application
+
+ def copy(self):
+ self.copied = True
+ return self
+
diff --git a/pyramid/tests/wsgiapp2app/__init__.py b/pyramid/tests/wsgiapp2app/__init__.py
new file mode 100644
index 000000000..0880556ef
--- /dev/null
+++ b/pyramid/tests/wsgiapp2app/__init__.py
@@ -0,0 +1,17 @@
+from pyramid.view import view_config
+from pyramid.wsgi import wsgiapp2
+
+@view_config(name='hello', renderer='string')
+@wsgiapp2
+def hello(environ, start_response):
+ assert environ['PATH_INFO'] == '/'
+ assert environ['SCRIPT_NAME'] == '/hello'
+ response_headers = [('Content-Type', 'text/plain')]
+ start_response('200 OK', response_headers)
+ return ['Hello!']
+
+def main():
+ from pyramid.config import Configurator
+ c = Configurator()
+ c.scan()
+ return c
diff --git a/pyramid/wsgi.py b/pyramid/wsgi.py
index e988a000e..e4c61ff63 100644
--- a/pyramid/wsgi.py
+++ b/pyramid/wsgi.py
@@ -1,5 +1,5 @@
from pyramid.compat import wraps
-from pyramid.traversal import quote_path_segment
+from pyramid.request import call_app_with_subpath_as_path_info
def wsgiapp(wrapped):
""" Decorator to turn a WSGI application into a :app:`Pyramid`
@@ -31,7 +31,7 @@ def wsgiapp(wrapped):
"""
def decorator(context, request):
return request.get_response(wrapped)
- return wraps(wrapped)(decorator) # grokkability
+ return wraps(wrapped)(decorator)
def wsgiapp2(wrapped):
""" Decorator to turn a WSGI application into a :app:`Pyramid`
@@ -56,31 +56,15 @@ def wsgiapp2(wrapped):
config.add_view(hello_world, name='hello_world.txt')
The ``wsgiapp2`` decorator will convert the result of the WSGI
- application to a Response and return it to :app:`Pyramid` as if
- the WSGI app were a :app:`Pyramid` view. The ``SCRIPT_NAME``
- and ``PATH_INFO`` values present in the WSGI environment are fixed
- up before the application is invoked. """
+ application to a Response and return it to :app:`Pyramid` as if the WSGI
+ app were a :app:`Pyramid` view. The ``SCRIPT_NAME`` and ``PATH_INFO``
+ values present in the WSGI environment are fixed up before the
+ application is invoked. In particular, a new WSGI environment is
+ generated, and the :term:`subpath` of the request passed to ``wsgiapp2``
+ is used as the new request's ``PATH_INFO`` and everything preceding the
+ subpath is used as the ``SCRIPT_NAME``. The new environment is passed to
+ the downstream WSGI application."""
def decorator(context, request):
- traversed = request.traversed
- vroot_path = request.virtual_root_path
- if not vroot_path:
- vroot_path = ()
- view_name = request.view_name
- subpath = request.subpath
- if not subpath:
- subpath = ()
- script_tuple = traversed[len(vroot_path):]
- script_list = [ quote_path_segment(name) for name in script_tuple ]
- if view_name:
- script_list.append(quote_path_segment(view_name))
- script_name = '/' + '/'.join(script_list)
- path_list = [ quote_path_segment(name) for name in subpath ]
- path_info = '/' + '/'.join(path_list)
- request.environ['PATH_INFO'] = path_info
- script_name = request.environ['SCRIPT_NAME'] + script_name
- if script_name.endswith('/'):
- script_name = script_name[:-1]
- request.environ['SCRIPT_NAME'] = script_name
- return request.get_response(wrapped)
- return wraps(wrapped)(decorator) # grokkability
+ return call_app_with_subpath_as_path_info(request, wrapped)
+ return wraps(wrapped)(decorator)
diff --git a/setup.py b/setup.py
index ac9db9ab7..5208f58a1 100644
--- a/setup.py
+++ b/setup.py
@@ -53,7 +53,7 @@ if sys.version_info[:2] < (2, 6):
install_requires.append('simplejson')
setup(name='pyramid',
- version='1.0',
+ version='1.1a0',
description=('The Pyramid web application development framework, a '
'Pylons project'),
long_description=README + '\n\n' + CHANGES,