A few minor tweaks:
* Only require simplejson if we need to. * Improve upon parameter validation. * Add a redirect utility function. * Remove some print statements.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
from paste.urlparser import StaticURLParser
|
from paste.urlparser import StaticURLParser
|
||||||
from paste.cascade import Cascade
|
from paste.cascade import Cascade
|
||||||
|
|
||||||
from pecan import Pecan, request, response, override_template
|
from pecan import Pecan, request, response, override_template, redirect
|
||||||
from decorators import expose
|
from decorators import expose
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@@ -1,10 +1,18 @@
|
|||||||
|
from inspect import getargspec
|
||||||
|
|
||||||
def expose(template=None, content_type='text/html'):
|
def expose(template=None, content_type='text/html'):
|
||||||
if template == 'json': content_type = 'application/json'
|
if template == 'json': content_type = 'application/json'
|
||||||
def decorate(f):
|
def decorate(f):
|
||||||
|
# flag the method as exposed
|
||||||
f.exposed = True
|
f.exposed = True
|
||||||
|
|
||||||
|
# set a "pecan" attribute, where we will store details
|
||||||
if not hasattr(f, 'pecan'): f.pecan = {}
|
if not hasattr(f, 'pecan'): f.pecan = {}
|
||||||
f.pecan['content_type'] = content_type
|
f.pecan['content_type'] = content_type
|
||||||
f.pecan.setdefault('template', []).append(template)
|
f.pecan.setdefault('template', []).append(template)
|
||||||
f.pecan.setdefault('content_types', {})[content_type] = template
|
f.pecan.setdefault('content_types', {})[content_type] = template
|
||||||
|
|
||||||
|
# store the arguments for this controller method
|
||||||
|
f.pecan['argspec'] = getargspec(f)
|
||||||
return f
|
return f
|
||||||
return decorate
|
return decorate
|
@@ -28,6 +28,10 @@ def override_template(template):
|
|||||||
request.override_template = template
|
request.override_template = template
|
||||||
|
|
||||||
|
|
||||||
|
def redirect(location):
|
||||||
|
raise exc.HTTPFound(location=location)
|
||||||
|
|
||||||
|
|
||||||
class Pecan(object):
|
class Pecan(object):
|
||||||
def __init__(self, root,
|
def __init__(self, root,
|
||||||
renderers = renderers,
|
renderers = renderers,
|
||||||
@@ -70,6 +74,13 @@ class Pecan(object):
|
|||||||
for hook in state.hooks:
|
for hook in state.hooks:
|
||||||
getattr(hook, hook_type)(*args)
|
getattr(hook, hook_type)(*args)
|
||||||
|
|
||||||
|
def get_validated_params(self, all_params, argspec):
|
||||||
|
valid_params = dict()
|
||||||
|
for param_name, param_value in all_params.iteritems():
|
||||||
|
if param_name in argspec.args:
|
||||||
|
valid_params[param_name] = param_value
|
||||||
|
return valid_params
|
||||||
|
|
||||||
def handle_request(self):
|
def handle_request(self):
|
||||||
# lookup the controller, respecting content-type as requested
|
# lookup the controller, respecting content-type as requested
|
||||||
# by the file extension on the URI
|
# by the file extension on the URI
|
||||||
@@ -94,7 +105,11 @@ class Pecan(object):
|
|||||||
self.handle_hooks('before', state)
|
self.handle_hooks('before', state)
|
||||||
|
|
||||||
# get the result from the controller, properly handling wrap hooks
|
# get the result from the controller, properly handling wrap hooks
|
||||||
result = controller(**dict(state.request.str_params))
|
params = self.get_validated_params(
|
||||||
|
dict(state.request.str_params),
|
||||||
|
controller.pecan['argspec']
|
||||||
|
)
|
||||||
|
result = controller(**params)
|
||||||
|
|
||||||
# pull the template out based upon content type and handle overrides
|
# pull the template out based upon content type and handle overrides
|
||||||
template = controller.pecan.get('content_types', {}).get(content_type)
|
template = controller.pecan.get('content_types', {}).get(content_type)
|
||||||
|
@@ -35,10 +35,6 @@ class JsonRenderer(object):
|
|||||||
def render(self, template_path, namespace):
|
def render(self, template_path, namespace):
|
||||||
from jsonify import encode
|
from jsonify import encode
|
||||||
result = encode(namespace)
|
result = encode(namespace)
|
||||||
print '*' * 80
|
|
||||||
print result
|
|
||||||
print type(result)
|
|
||||||
print '*' * 80
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
39
setup.py
39
setup.py
@@ -17,10 +17,34 @@ class PyTest(Command):
|
|||||||
py.cmdline.pytest(py.std.sys.argv[2:])
|
py.cmdline.pytest(py.std.sys.argv[2:])
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# determine requirements
|
||||||
|
#
|
||||||
|
requirements = [
|
||||||
|
"WebOb >= 0.9.8",
|
||||||
|
"simplegeneric >= 0.7",
|
||||||
|
"Genshi >= 0.6",
|
||||||
|
"Kajiki >= 0.2.2",
|
||||||
|
"Mako >= 0.3",
|
||||||
|
"py >= 1.3.4",
|
||||||
|
"WebTest >= 1.2.2",
|
||||||
|
"Paste >= 1.7.5.1",
|
||||||
|
"PasteScript >= 1.7.3"
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
import json
|
||||||
|
except:
|
||||||
|
requirements.append("simplejson >= 2.1.1")
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# call setup
|
||||||
|
#
|
||||||
setup(
|
setup(
|
||||||
name = 'pecan',
|
name = 'pecan',
|
||||||
version = version,
|
version = version,
|
||||||
description = "A WSGI object-dispatching web framework, in the spirit of TurboGears, only much much smaller, with many fewer dependancies.",
|
description = "A WSGI object-dispatching web framework, in the spirit of TurboGears, only much much smaller, with many fewer dependencies.",
|
||||||
long_description = None,
|
long_description = None,
|
||||||
classifiers = [],
|
classifiers = [],
|
||||||
keywords = '',
|
keywords = '',
|
||||||
@@ -32,18 +56,7 @@ setup(
|
|||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
zip_safe = True,
|
zip_safe = True,
|
||||||
cmdclass = {'test': PyTest},
|
cmdclass = {'test': PyTest},
|
||||||
install_requires=[
|
install_requires = requirements,
|
||||||
"WebOb >= 0.9.8",
|
|
||||||
"simplegeneric >= 0.7",
|
|
||||||
"Genshi >= 0.6",
|
|
||||||
"Kajiki >= 0.2.2",
|
|
||||||
"Mako >= 0.3",
|
|
||||||
"py >= 1.3.4",
|
|
||||||
"WebTest >= 1.2.2",
|
|
||||||
"Paste >= 1.7.5.1",
|
|
||||||
"simplejson >= 2.1.1",
|
|
||||||
"PasteScript >= 1.7.3"
|
|
||||||
],
|
|
||||||
entry_points = """
|
entry_points = """
|
||||||
[paste.paster_create_template]
|
[paste.paster_create_template]
|
||||||
pecan-base = templates:NewProjectTemplate
|
pecan-base = templates:NewProjectTemplate
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
from pecan import Pecan, expose, request, response
|
from pecan import Pecan, expose, request, response, redirect
|
||||||
from webtest import TestApp
|
from webtest import TestApp
|
||||||
|
|
||||||
class TestBase(object):
|
class TestBase(object):
|
||||||
@@ -161,3 +161,35 @@ class TestEngines(object):
|
|||||||
assert r.status_int == 200
|
assert r.status_int == 200
|
||||||
result = dict(loads(r.body))
|
result = dict(loads(r.body))
|
||||||
assert result == expected_result
|
assert result == expected_result
|
||||||
|
|
||||||
|
def test_controller_parameters(self):
|
||||||
|
class RootController(object):
|
||||||
|
@expose('json')
|
||||||
|
def index(self, argument=None):
|
||||||
|
assert argument == 'value'
|
||||||
|
|
||||||
|
# arguments should get passed appropriately
|
||||||
|
app = TestApp(Pecan(RootController()))
|
||||||
|
r = app.get('/?argument=value')
|
||||||
|
assert r.status_int == 200
|
||||||
|
|
||||||
|
# extra arguments get stripped off
|
||||||
|
r = app.get('/?argument=value&extra=not')
|
||||||
|
assert r.status_int == 200
|
||||||
|
|
||||||
|
def test_redirect(self):
|
||||||
|
class RootController(object):
|
||||||
|
@expose()
|
||||||
|
def index(self):
|
||||||
|
redirect('/testing')
|
||||||
|
|
||||||
|
@expose()
|
||||||
|
def testing(self):
|
||||||
|
return 'it worked!'
|
||||||
|
|
||||||
|
app = TestApp(Pecan(RootController()))
|
||||||
|
r = app.get('/')
|
||||||
|
assert r.status_int == 302
|
||||||
|
r = r.follow()
|
||||||
|
assert r.status_int == 200
|
||||||
|
assert r.body == 'it worked!'
|
Reference in New Issue
Block a user