Merge remote-tracking branch 'origin/master'

This commit is contained in:
Jonathan LaCour
2011-09-02 16:26:24 -04:00
11 changed files with 120 additions and 3 deletions

View File

@@ -9,6 +9,7 @@ from mimetypes import guess_type, add_type
from formencode import htmlfill, Invalid, variabledecode
from formencode.schema import merge_dicts
from paste.recursive import ForwardRequestException
from urlparse import urlsplit, urlunsplit
try:
from simplejson import loads
@@ -69,7 +70,7 @@ def abort(status_code=None, detail='', headers=None, comment=None, **kw):
raise exc.status_map[status_code](detail=detail, headers=headers, comment=comment, **kw)
def redirect(location, internal=False, code=None, headers={}):
def redirect(location=None, internal=False, code=None, headers={}, add_slash=False):
'''
Perform a redirect, either internal or external. An internal redirect
performs the redirect server-side, while the external redirect utilizes
@@ -81,6 +82,16 @@ def redirect(location, internal=False, code=None, headers={}):
:param headers: Any HTTP headers to send with the response, as a dictionary.
'''
new_env = request.environ.copy()
if add_slash:
if location is None:
split_url = list(urlsplit(state.request.url))
new_proto = new_env.get('HTTP_X_FORWARDED_PROTO', split_url[0])
split_url[0] = new_proto
location = urlunsplit(split_url)
location = location.rstrip('/') + '/'
if not headers:
headers = {}
if internal:
if code is not None:
raise ValueError('Cannot specify a code for internal redirects')
@@ -210,7 +221,7 @@ class Pecan(object):
'POST data when redirected. Please update your code '\
'to POST to '%s/' or set force_canonical to False" % \
(request.pecan['routing_path'], request.pecan['routing_path'])
raise exc.HTTPFound(add_slash=True)
redirect(code=302, add_slash=True)
return e.controller, e.remainder
def determine_hooks(self, controller=None):

View File

@@ -546,10 +546,11 @@ class TestBase(TestCase):
@expose()
def permanent(self):
redirect('/testing', code=301)
@expose()
def testing(self):
return 'it worked!'
app = TestApp(make_app(RootController(), debug=True))
r = app.get('/')
@@ -569,6 +570,29 @@ class TestBase(TestCase):
r = r.follow()
assert r.status_int == 200
assert r.body == 'it worked!'
def test_x_forward_proto(self):
class ChildController(object):
@expose()
def index(self):
redirect('/testing')
class RootController(object):
@expose()
def index(self):
redirect('/testing')
@expose()
def testing(self):
return 'it worked!'
child = ChildController()
app = TestApp(make_app(RootController(), debug=True))
response = app.get('/child', extra_environ=dict(HTTP_X_FORWARDED_PROTO='https'))
##non-canonical url will redirect, so we won't get a 301
assert response.status_int == 302
##should add trailing / and changes location to https
assert response.location == 'https://localhost/child/'
assert response.environ['HTTP_X_FORWARDED_PROTO'] == 'https'
def test_streaming_response(self):
import StringIO

View File

@@ -0,0 +1,3 @@
def setup_app(config):
assert config.foo.sample_key == True
return 'DEPLOYED!'

View File

@@ -0,0 +1,9 @@
import sample_app
app = {
'modules': [sample_app]
}
foo = {
'sample_key': True
}

View File

@@ -0,0 +1,9 @@
import sample_app_missing
app = {
'modules': [sample_app_missing]
}
foo = {
'sample_key': True
}

61
tests/test_deploy.py Normal file
View File

@@ -0,0 +1,61 @@
from pecan.deploy import deploy
from unittest import TestCase
import pytest
import os
import sys
class TestDeploy(TestCase):
def setUp(self):
test_config_d = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps')
if test_config_d not in sys.path:
sys.path.append(test_config_d)
def test_module_lookup(self):
"""
1. A config file has:
app { 'modules': [valid_module] }
2. The module, `valid_module` has an app.py that defines a `def setup.py`
"""
test_config_file = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps', 'sample_app_config.py')
assert deploy(test_config_file) == 'DEPLOYED!'
def test_module_lookup_find_best_match(self):
"""
1. A config file has:
app { 'modules': [invalid_module, valid_module] }
2. The module, `valid_module` has an app.py that defines a `def setup_app`
"""
test_config_file = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps', 'sample_app_config.py')
assert deploy(test_config_file) == 'DEPLOYED!'
def test_missing_app_file_lookup(self):
"""
1. A config file has:
app { 'modules': [valid_module] }
2. The module has no `app.py` file.
"""
test_config_file = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps', 'sample_app_config_missing.py')
self.assertRaisesRegexp(
Exception,
'No app.setup_app found in any of the configured app.modules',
deploy,
test_config_file
)
def test_missing_setup_app(self):
"""
1. A config file has:
app { 'modules': [valid_module] }
2. The module, `valid_module` has an `app.py` that contains no `def setup_app`
"""
test_config_file = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps', 'sample_app_config_missing_app.py')
self.assertRaisesRegexp(
Exception,
'No app.setup_app found in any of the configured app.modules',
deploy,
test_config_file
)