Merging pecan-env into master
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -17,3 +17,4 @@ pip-log.txt
 | 
			
		||||
# Unit test / coverage reports
 | 
			
		||||
.coverage
 | 
			
		||||
.tox
 | 
			
		||||
htmlcov
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,6 @@ def proxy(key):
 | 
			
		||||
    class ObjectProxy(object):
 | 
			
		||||
        def __getattr__(self, attr):
 | 
			
		||||
            obj = getattr(state, key)
 | 
			
		||||
            if attr == 'validation_errors':
 | 
			
		||||
                return getattr(obj, attr, {})
 | 
			
		||||
            return getattr(obj, attr)
 | 
			
		||||
        def __setattr__(self, attr, value):
 | 
			
		||||
            obj = getattr(state, key)
 | 
			
		||||
@@ -50,9 +48,10 @@ def override_template(template, content_type=None):
 | 
			
		||||
    :param content_type: a valid MIME type to use for the response.
 | 
			
		||||
    '''
 | 
			
		||||
    
 | 
			
		||||
    request.override_template = template
 | 
			
		||||
    request.pecan['override_template'] = template
 | 
			
		||||
    if content_type:
 | 
			
		||||
        request.override_content_type = content_type 
 | 
			
		||||
        request.pecan['override_content_type'] = content_type 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def abort(status_code=None, detail='', headers=None, comment=None):
 | 
			
		||||
    '''
 | 
			
		||||
@@ -98,9 +97,7 @@ def error_for(field):
 | 
			
		||||
    :param field: The name of the field to get the error for.
 | 
			
		||||
    '''
 | 
			
		||||
    
 | 
			
		||||
    if not request.validation_errors:
 | 
			
		||||
        return ''
 | 
			
		||||
    return request.validation_errors.get(field, '')
 | 
			
		||||
    return request.pecan['validation_errors'].get(field, '')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def static(name, value):
 | 
			
		||||
@@ -129,16 +126,7 @@ def render(template, namespace):
 | 
			
		||||
    :param namespace: The namespace to use for rendering the template, as a dictionary.
 | 
			
		||||
    '''
 | 
			
		||||
    
 | 
			
		||||
    renderer = state.app.renderers.get(state.app.default_renderer, state.app.template_path)
 | 
			
		||||
    if template == 'json':
 | 
			
		||||
        renderer = state.app.renderers.get('json', state.app.template_path)
 | 
			
		||||
    else:
 | 
			
		||||
        namespace['error_for'] = error_for
 | 
			
		||||
        namespace['static'] = static
 | 
			
		||||
    if ':' in template:
 | 
			
		||||
        renderer = state.app.renderers.get(template.split(':')[0], state.app.template_path)
 | 
			
		||||
        template = template.split(':')[1]
 | 
			
		||||
    return renderer.render(template, namespace)
 | 
			
		||||
    return state.app.render(template, namespace)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ValidationException(ForwardRequestException):
 | 
			
		||||
@@ -156,10 +144,10 @@ class ValidationException(ForwardRequestException):
 | 
			
		||||
            location = cfg['error_handler']
 | 
			
		||||
            if callable(location):
 | 
			
		||||
                location = location()
 | 
			
		||||
        merge_dicts(request.validation_errors, errors)
 | 
			
		||||
        merge_dicts(request.pecan['validation_errors'], errors)
 | 
			
		||||
        if 'pecan.params' not in request.environ:
 | 
			
		||||
            request.environ['pecan.params'] = dict(request.str_params)
 | 
			
		||||
        request.environ['pecan.validation_errors'] = request.validation_errors
 | 
			
		||||
        request.environ['pecan.validation_errors'] = request.pecan['validation_errors']
 | 
			
		||||
        if cfg.get('htmlfill') is not None:
 | 
			
		||||
            request.environ['pecan.htmlfill'] = cfg['htmlfill']
 | 
			
		||||
        request.environ['REQUEST_METHOD'] = 'GET'
 | 
			
		||||
@@ -214,7 +202,11 @@ class Pecan(object):
 | 
			
		||||
        except NonCanonicalPath, e:
 | 
			
		||||
            if self.force_canonical and not _cfg(e.controller).get('accept_noncanonical', False):
 | 
			
		||||
                if request.method == 'POST':
 | 
			
		||||
                    raise RuntimeError, "You have POSTed to a URL '%s' which requires a slash.  Most browsers will not maintain POST data when redirected.  Please update your code to POST to '%s/' or set force_canonical to False" % (request.routing_path, request.routing_path)
 | 
			
		||||
                    raise RuntimeError, "You have POSTed to a URL '%s' which '\
 | 
			
		||||
                        'requires a slash. Most browsers will not maintain '\
 | 
			
		||||
                        '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)
 | 
			
		||||
            return e.controller, e.remainder
 | 
			
		||||
    
 | 
			
		||||
@@ -265,9 +257,9 @@ class Pecan(object):
 | 
			
		||||
            args.append(im_self)
 | 
			
		||||
        
 | 
			
		||||
        # grab the routing args from nested REST controllers
 | 
			
		||||
        if hasattr(request, 'routing_args'):
 | 
			
		||||
            remainder = request.routing_args + list(remainder)
 | 
			
		||||
            delattr(request, 'routing_args')
 | 
			
		||||
        if 'routing_args' in request.pecan:
 | 
			
		||||
            remainder = request.pecan['routing_args'] + list(remainder)
 | 
			
		||||
            del request.pecan['routing_args']
 | 
			
		||||
        
 | 
			
		||||
        # handle positional arguments
 | 
			
		||||
        if valid_args and remainder:
 | 
			
		||||
@@ -304,6 +296,18 @@ class Pecan(object):
 | 
			
		||||
        
 | 
			
		||||
        return args, kwargs
 | 
			
		||||
    
 | 
			
		||||
    def render(self, template, namespace):
 | 
			
		||||
        renderer = self.renderers.get(self.default_renderer, self.template_path)
 | 
			
		||||
        if template == 'json':
 | 
			
		||||
            renderer = self.renderers.get('json', self.template_path)
 | 
			
		||||
        else:
 | 
			
		||||
            namespace['error_for'] = error_for
 | 
			
		||||
            namespace['static'] = static
 | 
			
		||||
        if ':' in template:
 | 
			
		||||
            renderer = self.renderers.get(template.split(':')[0], self.template_path)
 | 
			
		||||
            template = template.split(':')[1]
 | 
			
		||||
        return renderer.render(template, namespace)
 | 
			
		||||
    
 | 
			
		||||
    def validate(self, schema, params, json=False, error_handler=None, 
 | 
			
		||||
                 htmlfill=None, variable_decode=None):
 | 
			
		||||
        '''
 | 
			
		||||
@@ -318,7 +322,6 @@ class Pecan(object):
 | 
			
		||||
        :param variable_decode: Indicates whether or not to decode variables when using htmlfill.
 | 
			
		||||
        '''
 | 
			
		||||
        
 | 
			
		||||
        request.validation_errors = {}
 | 
			
		||||
        try:
 | 
			
		||||
            to_validate = params
 | 
			
		||||
            if json:
 | 
			
		||||
@@ -331,7 +334,7 @@ class Pecan(object):
 | 
			
		||||
            if variable_decode is not None:
 | 
			
		||||
                kwargs['encode_variables'] = True
 | 
			
		||||
                kwargs.update(variable_decode)
 | 
			
		||||
            request.validation_errors = e.unpack_errors(**kwargs)
 | 
			
		||||
            request.pecan['validation_errors'] = e.unpack_errors(**kwargs)
 | 
			
		||||
            if error_handler is not None:
 | 
			
		||||
                raise ValidationException()
 | 
			
		||||
        if json:
 | 
			
		||||
@@ -347,21 +350,20 @@ class Pecan(object):
 | 
			
		||||
        state.hooks = self.determine_hooks()
 | 
			
		||||
        
 | 
			
		||||
        # store the routing path to allow hooks to modify it
 | 
			
		||||
        request.routing_path = request.path
 | 
			
		||||
        request.pecan['routing_path'] = request.path
 | 
			
		||||
 | 
			
		||||
        # handle "on_route" hooks
 | 
			
		||||
        self.handle_hooks('on_route', state)
 | 
			
		||||
        
 | 
			
		||||
        # lookup the controller, respecting content-type as requested
 | 
			
		||||
        # by the file extension on the URI
 | 
			
		||||
        path = request.routing_path
 | 
			
		||||
        path = request.pecan['routing_path']
 | 
			
		||||
 | 
			
		||||
        if state.content_type is None and '.' in path.split('/')[-1]:
 | 
			
		||||
        if not request.pecan['content_type'] and '.' in path.split('/')[-1]:
 | 
			
		||||
            path, extension = splitext(path)
 | 
			
		||||
 | 
			
		||||
            request.extension = extension
 | 
			
		||||
            request.pecan['extension'] = extension
 | 
			
		||||
            # preface with a letter to ensure compat for 2.5
 | 
			
		||||
            state.content_type = guess_type('x' + extension)[0]
 | 
			
		||||
            request.pecan['content_type'] = guess_type('x' + extension)[0]
 | 
			
		||||
 | 
			
		||||
        controller, remainder = self.route(self.root, path)
 | 
			
		||||
        cfg = _cfg(controller)
 | 
			
		||||
@@ -381,8 +383,11 @@ class Pecan(object):
 | 
			
		||||
        state.controller = controller
 | 
			
		||||
    
 | 
			
		||||
        # if unsure ask the controller for the default content type 
 | 
			
		||||
        if state.content_type is None:
 | 
			
		||||
            state.content_type = cfg.get('content_type', 'text/html')
 | 
			
		||||
        if not request.pecan['content_type']:
 | 
			
		||||
            request.pecan['content_type'] = cfg.get('content_type', 'text/html')
 | 
			
		||||
        elif cfg.get('content_type') is not None and \
 | 
			
		||||
            request.pecan['content_type'] not in cfg.get('content_types', {}):
 | 
			
		||||
            raise exc.HTTPNotFound
 | 
			
		||||
        
 | 
			
		||||
        # get a sorted list of hooks, by priority
 | 
			
		||||
        state.hooks = self.determine_hooks(controller)
 | 
			
		||||
@@ -402,7 +407,7 @@ class Pecan(object):
 | 
			
		||||
                        variable_decode=cfg.get('variable_decode')
 | 
			
		||||
                    )
 | 
			
		||||
        elif 'pecan.validation_errors' in request.environ:
 | 
			
		||||
            request.validation_errors = request.environ.pop('pecan.validation_errors')
 | 
			
		||||
            request.pecan['validation_errors'] = request.environ.pop('pecan.validation_errors')
 | 
			
		||||
        
 | 
			
		||||
        # fetch the arguments for the controller
 | 
			
		||||
        args, kwargs = self.get_args(
 | 
			
		||||
@@ -423,17 +428,17 @@ class Pecan(object):
 | 
			
		||||
        raw_namespace = result
 | 
			
		||||
 | 
			
		||||
        # pull the template out based upon content type and handle overrides
 | 
			
		||||
        template = cfg.get('content_types', {}).get(state.content_type)
 | 
			
		||||
        template = cfg.get('content_types', {}).get(request.pecan['content_type'])
 | 
			
		||||
 | 
			
		||||
        # check if for controller override of template
 | 
			
		||||
        template = getattr(request, 'override_template', template)
 | 
			
		||||
        state.content_type = getattr(request, 'override_content_type', state.content_type)
 | 
			
		||||
        template = request.pecan.get('override_template', template)
 | 
			
		||||
        request.pecan['content_type'] = request.pecan.get('override_content_type', request.pecan['content_type'])
 | 
			
		||||
 | 
			
		||||
        # if there is a template, render it
 | 
			
		||||
        if template:
 | 
			
		||||
            if template == 'json':
 | 
			
		||||
                state.content_type = 'application/json'
 | 
			
		||||
            result = render(template, result)
 | 
			
		||||
                request.pecan['content_type'] = 'application/json'
 | 
			
		||||
            result = self.render(template, result)
 | 
			
		||||
        
 | 
			
		||||
        # pass the response through htmlfill (items are popped out of the 
 | 
			
		||||
        # environment even if htmlfill won't run for proper cleanup)
 | 
			
		||||
@@ -442,8 +447,8 @@ class Pecan(object):
 | 
			
		||||
            _htmlfill = request.environ.pop('pecan.htmlfill')
 | 
			
		||||
        if 'pecan.params' in request.environ:
 | 
			
		||||
            params = request.environ.pop('pecan.params')
 | 
			
		||||
        if request.validation_errors and _htmlfill is not None and state.content_type == 'text/html':
 | 
			
		||||
            errors = getattr(request, 'validation_errors', {})
 | 
			
		||||
        if request.pecan['validation_errors'] and _htmlfill is not None and request.pecan['content_type'] == 'text/html':
 | 
			
		||||
            errors = request.pecan['validation_errors']
 | 
			
		||||
            result = htmlfill.render(result, defaults=params, errors=errors, **_htmlfill)
 | 
			
		||||
        
 | 
			
		||||
        # If we are in a test request put the namespace where it can be
 | 
			
		||||
@@ -461,8 +466,8 @@ class Pecan(object):
 | 
			
		||||
            response.body = result
 | 
			
		||||
        
 | 
			
		||||
        # set the content type
 | 
			
		||||
        if state.content_type:
 | 
			
		||||
            response.content_type = state.content_type
 | 
			
		||||
        if request.pecan['content_type']:
 | 
			
		||||
            response.content_type = request.pecan['content_type']
 | 
			
		||||
    
 | 
			
		||||
    def __call__(self, environ, start_response):
 | 
			
		||||
        '''
 | 
			
		||||
@@ -471,15 +476,15 @@ class Pecan(object):
 | 
			
		||||
        
 | 
			
		||||
        # create the request and response object
 | 
			
		||||
        state.request      = Request(environ)
 | 
			
		||||
        state.content_type = None
 | 
			
		||||
        state.response     = Response()
 | 
			
		||||
        state.hooks        = []
 | 
			
		||||
        state.app          = self
 | 
			
		||||
        
 | 
			
		||||
        # handle the request
 | 
			
		||||
        try:
 | 
			
		||||
            # add context to the request 
 | 
			
		||||
            # add context and environment to the request 
 | 
			
		||||
            state.request.context = {}
 | 
			
		||||
            state.request.pecan = dict(content_type=None, validation_errors={})
 | 
			
		||||
 | 
			
		||||
            self.handle_request()
 | 
			
		||||
        except Exception, e:
 | 
			
		||||
@@ -502,7 +507,6 @@ class Pecan(object):
 | 
			
		||||
            return state.response(environ, start_response)
 | 
			
		||||
        finally:        
 | 
			
		||||
            # clean up state
 | 
			
		||||
            del state.content_type
 | 
			
		||||
            del state.hooks
 | 
			
		||||
            del state.request
 | 
			
		||||
            del state.response
 | 
			
		||||
 
 | 
			
		||||
@@ -49,9 +49,12 @@ class GenericJSON(JSONEncoder):
 | 
			
		||||
                    props[key] = getattr(obj, key)
 | 
			
		||||
            return props
 | 
			
		||||
        elif isinstance(obj, ResultProxy):
 | 
			
		||||
            return dict(rows=list(obj), count=obj.rowcount)
 | 
			
		||||
            props = dict(rows=list(obj), count=obj.rowcount)
 | 
			
		||||
            if props['count'] < 0:
 | 
			
		||||
                props['count'] = len(props['rows'])
 | 
			
		||||
            return props
 | 
			
		||||
        elif isinstance(obj, RowProxy):
 | 
			
		||||
            return dict(rows=dict(obj), count=1)
 | 
			
		||||
            return dict(obj)
 | 
			
		||||
        elif isinstance(obj, (MultiDict, UnicodeMultiDict)):
 | 
			
		||||
            return obj.mixed()
 | 
			
		||||
        else:
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ class RestController(object):
 | 
			
		||||
        
 | 
			
		||||
        # get the args to figure out how much to chop off
 | 
			
		||||
        args = getargspec(getattr(self, method))
 | 
			
		||||
        fixed_args = len(args[0][1:]) - len(getattr(request, 'routing_args', []))
 | 
			
		||||
        fixed_args = len(args[0][1:]) - len(request.pecan.get('routing_args', []))
 | 
			
		||||
        var_args = args[1]
 | 
			
		||||
        
 | 
			
		||||
        # attempt to locate a sub-controller
 | 
			
		||||
@@ -166,7 +166,4 @@ class RestController(object):
 | 
			
		||||
    _handle_put = _handle_post
 | 
			
		||||
    
 | 
			
		||||
    def _set_routing_args(self, args):
 | 
			
		||||
        if hasattr(request, 'routing_args'):
 | 
			
		||||
            request.routing_args.extend(args)
 | 
			
		||||
        else:
 | 
			
		||||
            setattr(request, 'routing_args', args)
 | 
			
		||||
        request.pecan.setdefault('routing_args', []).extend(args)
 | 
			
		||||
 
 | 
			
		||||
@@ -11,9 +11,9 @@ class SampleForm(Schema):
 | 
			
		||||
class RootController(object):
 | 
			
		||||
    @expose('index.html')
 | 
			
		||||
    def index(self, name='', age=''):
 | 
			
		||||
        return dict(errors=request.validation_errors, name=name, age=age)
 | 
			
		||||
        return dict(errors=request.pecan['validation_errors'], name=name, age=age)
 | 
			
		||||
    
 | 
			
		||||
    @expose('success.html', schema=SampleForm(), error_handler='index')
 | 
			
		||||
    @expose('success.html', schema=SampleForm(), error_handler='/index')
 | 
			
		||||
    def handle_form(self, name, age):
 | 
			
		||||
        return dict(name=name, age=age)
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ from paste.recursive import ForwardRequestException
 | 
			
		||||
from unittest import TestCase
 | 
			
		||||
from webtest import TestApp
 | 
			
		||||
 | 
			
		||||
from pecan import Pecan, expose, request, response, redirect, abort, make_app, override_template
 | 
			
		||||
from pecan import Pecan, expose, request, response, redirect, abort, make_app, override_template, render
 | 
			
		||||
from pecan.templating import _builtin_renderers as builtin_renderers, error_formatters
 | 
			
		||||
from pecan.decorators import accept_noncanonical
 | 
			
		||||
 | 
			
		||||
@@ -438,6 +438,10 @@ class TestBase(TestCase):
 | 
			
		||||
            def internal(self):
 | 
			
		||||
                redirect('/testing', internal=True)
 | 
			
		||||
            
 | 
			
		||||
            @expose()
 | 
			
		||||
            def bad_internal(self):
 | 
			
		||||
                redirect('/testing', internal=True, code=301)
 | 
			
		||||
            
 | 
			
		||||
            @expose()
 | 
			
		||||
            def permanent(self):
 | 
			
		||||
                redirect('/testing', code=301)
 | 
			
		||||
@@ -446,14 +450,18 @@ class TestBase(TestCase):
 | 
			
		||||
            def testing(self):
 | 
			
		||||
                return 'it worked!'
 | 
			
		||||
        
 | 
			
		||||
        app = TestApp(Pecan(RootController()))
 | 
			
		||||
        app = TestApp(make_app(RootController(), debug=True))
 | 
			
		||||
        r = app.get('/')
 | 
			
		||||
        assert r.status_int == 302
 | 
			
		||||
        r = r.follow()
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert r.body == 'it worked!'
 | 
			
		||||
        
 | 
			
		||||
        self.assertRaises(ForwardRequestException, app.get, '/internal')
 | 
			
		||||
        r = app.get('/internal')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert r.body == 'it worked!'
 | 
			
		||||
        
 | 
			
		||||
        self.assertRaises(ValueError, app.get, '/bad_internal')
 | 
			
		||||
        
 | 
			
		||||
        r = app.get('/permanent')
 | 
			
		||||
        assert r.status_int == 301
 | 
			
		||||
@@ -511,10 +519,10 @@ class TestBase(TestCase):
 | 
			
		||||
        Test extension splits
 | 
			
		||||
        """
 | 
			
		||||
        class RootController(object):
 | 
			
		||||
            @expose()
 | 
			
		||||
            @expose(content_type=None)
 | 
			
		||||
            def _default(self, *args):
 | 
			
		||||
                from pecan.core import request
 | 
			
		||||
                return request.extension
 | 
			
		||||
                return request.pecan['extension']
 | 
			
		||||
 | 
			
		||||
        app = TestApp(Pecan(RootController()))
 | 
			
		||||
        r = app.get('/index.html')
 | 
			
		||||
@@ -545,6 +553,117 @@ class TestBase(TestCase):
 | 
			
		||||
        app = make_app(RootController(), wrap_app=wrap, debug=True)
 | 
			
		||||
        assert len(wrapped_apps) == 1
 | 
			
		||||
    
 | 
			
		||||
    def test_bad_content_type(self):
 | 
			
		||||
        class RootController(object):
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self):
 | 
			
		||||
                return '/'
 | 
			
		||||
    
 | 
			
		||||
        app = TestApp(Pecan(RootController()))
 | 
			
		||||
        r = app.get('/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert r.body == '/'
 | 
			
		||||
        
 | 
			
		||||
        r = app.get('/index.html', expect_errors=True)
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert r.body == '/'
 | 
			
		||||
 | 
			
		||||
        r = app.get('/index.txt', expect_errors=True)
 | 
			
		||||
        assert r.status_int == 404
 | 
			
		||||
 | 
			
		||||
    def test_canonical_index(self):
 | 
			
		||||
        class ArgSubController(object):
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self, arg):
 | 
			
		||||
                return arg
 | 
			
		||||
        class AcceptController(object):
 | 
			
		||||
            @accept_noncanonical
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self):
 | 
			
		||||
                return 'accept'
 | 
			
		||||
        class SubController(object):
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self):
 | 
			
		||||
                return 'subindex'
 | 
			
		||||
        class RootController(object):
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self):
 | 
			
		||||
                return 'index'
 | 
			
		||||
 | 
			
		||||
            sub = SubController()
 | 
			
		||||
            arg = ArgSubController()
 | 
			
		||||
            accept = AcceptController()
 | 
			
		||||
 | 
			
		||||
        app = TestApp(Pecan(RootController()))
 | 
			
		||||
 | 
			
		||||
        r = app.get('/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'index' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/index')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'index' in r.body
 | 
			
		||||
        
 | 
			
		||||
        # for broken clients
 | 
			
		||||
        r = app.get('', status=302)
 | 
			
		||||
        assert r.status_int == 302
 | 
			
		||||
 | 
			
		||||
        r = app.get('/sub/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'subindex' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/sub', status=302)
 | 
			
		||||
        assert r.status_int == 302
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            r = app.post('/sub', dict(foo=1))
 | 
			
		||||
            raise Exception, "Post should fail"
 | 
			
		||||
        except Exception, e:
 | 
			
		||||
            assert isinstance(e, RuntimeError)
 | 
			
		||||
 | 
			
		||||
        r = app.get('/arg/index/foo')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert r.body == 'foo'
 | 
			
		||||
 | 
			
		||||
        r = app.get('/accept/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'accept' == r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/accept')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'accept' == r.body
 | 
			
		||||
 | 
			
		||||
        app = TestApp(Pecan(RootController(), force_canonical=False))
 | 
			
		||||
        r = app.get('/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'index' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/sub')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'subindex' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.post('/sub', dict(foo=1))
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'subindex' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/sub/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'subindex' in r.body
 | 
			
		||||
    
 | 
			
		||||
    def test_proxy(self):
 | 
			
		||||
        class RootController(object):
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self):
 | 
			
		||||
                request.testing = True
 | 
			
		||||
                assert request.testing == True
 | 
			
		||||
                del request.testing
 | 
			
		||||
                assert hasattr(request, 'testing') == False
 | 
			
		||||
                return '/'
 | 
			
		||||
        
 | 
			
		||||
        app = TestApp(make_app(RootController(), debug=True))
 | 
			
		||||
        r = app.get('/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestEngines(object):
 | 
			
		||||
    
 | 
			
		||||
@@ -652,88 +771,18 @@ class TestEngines(object):
 | 
			
		||||
        assert 'Override' in r.body 
 | 
			
		||||
        assert r.content_type == 'text/plain'
 | 
			
		||||
 | 
			
		||||
    def test_canonical_index(self):
 | 
			
		||||
        class ArgSubController(object):
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self, arg):
 | 
			
		||||
                return arg
 | 
			
		||||
        class AcceptController(object):
 | 
			
		||||
            @accept_noncanonical
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self):
 | 
			
		||||
                return 'accept'
 | 
			
		||||
        class SubController(object):
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self):
 | 
			
		||||
                return 'subindex'
 | 
			
		||||
    def test_render(self):
 | 
			
		||||
        
 | 
			
		||||
        #if 'mako' not in builtin_renderers:
 | 
			
		||||
        #    return
 | 
			
		||||
        
 | 
			
		||||
        class RootController(object):
 | 
			
		||||
            @expose()
 | 
			
		||||
            def index(self):
 | 
			
		||||
                return 'index'
 | 
			
		||||
 | 
			
		||||
            sub = SubController()
 | 
			
		||||
            arg = ArgSubController()
 | 
			
		||||
            accept = AcceptController()
 | 
			
		||||
 | 
			
		||||
        app = TestApp(Pecan(RootController()))
 | 
			
		||||
            def index(self, name='Jonathan'):
 | 
			
		||||
                return render('mako.html', dict(name=name))
 | 
			
		||||
                return dict(name=name)
 | 
			
		||||
        
 | 
			
		||||
        app = TestApp(Pecan(RootController(), template_path=self.template_path))
 | 
			
		||||
        r = app.get('/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'index' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/index')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'index' in r.body
 | 
			
		||||
        
 | 
			
		||||
        # for broken clients
 | 
			
		||||
        r = app.get('', status=302)
 | 
			
		||||
        assert r.status_int == 302
 | 
			
		||||
 | 
			
		||||
        r = app.get('/sub/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'subindex' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/sub', status=302)
 | 
			
		||||
        assert r.status_int == 302
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            r = app.post('/sub', dict(foo=1))
 | 
			
		||||
            raise Exception, "Post should fail"
 | 
			
		||||
        except Exception, e:
 | 
			
		||||
            assert isinstance(e, RuntimeError)
 | 
			
		||||
 | 
			
		||||
        r = app.get('/arg/index/foo')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert r.body == 'foo'
 | 
			
		||||
 | 
			
		||||
        r = app.get('/accept/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'accept' == r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/accept')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'accept' == r.body
 | 
			
		||||
 | 
			
		||||
        app = TestApp(Pecan(RootController(), force_canonical=False))
 | 
			
		||||
        r = app.get('/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'index' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/sub')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'subindex' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.post('/sub', dict(foo=1))
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'subindex' in r.body
 | 
			
		||||
 | 
			
		||||
        r = app.get('/sub/')
 | 
			
		||||
        assert r.status_int == 200
 | 
			
		||||
        assert 'subindex' in r.body
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        assert "<h1>Hello, Jonathan!</h1>" in r.body
 | 
			
		||||
 
 | 
			
		||||
@@ -125,3 +125,7 @@ class TestConf(TestCase):
 | 
			
		||||
            conf = configuration.Config({'a':1})
 | 
			
		||||
            self.assertEqual(['a'], dir(conf))
 | 
			
		||||
 | 
			
		||||
    def test_config_bad_key(self):
 | 
			
		||||
        conf = configuration.Config({'a': 1})
 | 
			
		||||
        assert conf.a == 1
 | 
			
		||||
        self.assertRaises(AttributeError, getattr, conf, 'b')
 | 
			
		||||
 
 | 
			
		||||
@@ -696,7 +696,7 @@ class TestHooks(object):
 | 
			
		||||
                            password_confirm,
 | 
			
		||||
                            age):
 | 
			
		||||
                run_hook.append('inside')
 | 
			
		||||
                return str(len(request.validation_errors) > 0)
 | 
			
		||||
                return str(len(request.pecan['validation_errors']) > 0)
 | 
			
		||||
            
 | 
			
		||||
            @expose(schema=RegistrationSchema(), error_handler='/errors')
 | 
			
		||||
            def with_handler(self, first_name, 
 | 
			
		||||
@@ -707,7 +707,7 @@ class TestHooks(object):
 | 
			
		||||
                            password_confirm,
 | 
			
		||||
                            age):
 | 
			
		||||
                run_hook.append('inside')
 | 
			
		||||
                return str(len(request.validation_errors) > 0)
 | 
			
		||||
                return str(len(request.pecan['validation_errors']) > 0)
 | 
			
		||||
        
 | 
			
		||||
        # test that the hooks get properly run with no validation errors        
 | 
			
		||||
        app = TestApp(make_app(RootController(), hooks=[SimpleHook()]))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,20 @@
 | 
			
		||||
from datetime           import datetime, date
 | 
			
		||||
from decimal            import Decimal
 | 
			
		||||
from datetime              import datetime, date
 | 
			
		||||
from decimal               import Decimal
 | 
			
		||||
try:
 | 
			
		||||
    from simplejson     import loads
 | 
			
		||||
    from simplejson        import loads
 | 
			
		||||
except:
 | 
			
		||||
    from json           import loads
 | 
			
		||||
from unittest           import TestCase
 | 
			
		||||
    from json              import loads
 | 
			
		||||
try:
 | 
			
		||||
    from sqlalchemy        import orm, schema, types
 | 
			
		||||
    from sqlalchemy.engine import create_engine
 | 
			
		||||
except ImportError:
 | 
			
		||||
    create_engine = None
 | 
			
		||||
from unittest              import TestCase
 | 
			
		||||
 | 
			
		||||
from pecan.jsonify      import jsonify, encode
 | 
			
		||||
from pecan              import Pecan, expose, request
 | 
			
		||||
from webtest            import TestApp
 | 
			
		||||
from webob.multidict    import MultiDict, UnicodeMultiDict
 | 
			
		||||
from pecan.jsonify         import jsonify, encode, ResultProxy, RowProxy
 | 
			
		||||
from pecan                 import Pecan, expose, request
 | 
			
		||||
from webtest               import TestApp
 | 
			
		||||
from webob.multidict       import MultiDict, UnicodeMultiDict
 | 
			
		||||
 | 
			
		||||
def make_person():
 | 
			
		||||
    class Person(object):
 | 
			
		||||
@@ -106,3 +111,93 @@ class TestJsonifyGenericEncoder(TestCase):
 | 
			
		||||
        class Foo(object): pass
 | 
			
		||||
 | 
			
		||||
        self.assertRaises(TypeError, encode, Foo())
 | 
			
		||||
 | 
			
		||||
class TestJsonifySQLAlchemyGenericEncoder(TestCase):
 | 
			
		||||
    
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        if not create_engine:
 | 
			
		||||
            self.create_fake_proxies()
 | 
			
		||||
        else:
 | 
			
		||||
            self.create_sa_proxies()
 | 
			
		||||
    
 | 
			
		||||
    def create_fake_proxies(self):
 | 
			
		||||
        
 | 
			
		||||
        # create a fake SA object
 | 
			
		||||
        class FakeSAObject(object):
 | 
			
		||||
            def __init__(self):
 | 
			
		||||
                self._sa_class_manager = object()
 | 
			
		||||
                self._sa_instance_state = 'awesome'
 | 
			
		||||
                self.id = 1
 | 
			
		||||
                self.first_name = 'Jonathan'
 | 
			
		||||
                self.last_name = 'LaCour'
 | 
			
		||||
        
 | 
			
		||||
        # create a fake result proxy
 | 
			
		||||
        class FakeResultProxy(ResultProxy):
 | 
			
		||||
            def __init__(self):
 | 
			
		||||
                self.rowcount = -1
 | 
			
		||||
                self.rows = []
 | 
			
		||||
            def __iter__(self):
 | 
			
		||||
                return iter(self.rows)
 | 
			
		||||
            def append(self, row):
 | 
			
		||||
                self.rows.append(row)
 | 
			
		||||
        
 | 
			
		||||
        # create a fake row proxy
 | 
			
		||||
        class FakeRowProxy(RowProxy):
 | 
			
		||||
            def __init__(self, arg=None):
 | 
			
		||||
                self.row = dict(arg)
 | 
			
		||||
            def __getitem__(self, key):
 | 
			
		||||
                return self.row.__getitem__(key)
 | 
			
		||||
            def keys(self):
 | 
			
		||||
                return self.row.keys()
 | 
			
		||||
        
 | 
			
		||||
        # get the SA objects
 | 
			
		||||
        self.sa_object = FakeSAObject()
 | 
			
		||||
        self.result_proxy = FakeResultProxy()
 | 
			
		||||
        self.result_proxy.append(FakeRowProxy([('id', 1), ('first_name', 'Jonathan'), ('last_name', 'LaCour')]))
 | 
			
		||||
        self.result_proxy.append(FakeRowProxy([('id', 2), ('first_name', 'Yoann'), ('last_name', 'Roman')]))
 | 
			
		||||
        self.row_proxy = FakeRowProxy([('id', 1), ('first_name', 'Jonathan'), ('last_name', 'LaCour')])
 | 
			
		||||
        
 | 
			
		||||
    def create_sa_proxies(self):
 | 
			
		||||
        
 | 
			
		||||
        # create the table and mapper
 | 
			
		||||
        metadata = schema.MetaData()
 | 
			
		||||
        user_table = schema.Table('user', metadata, 
 | 
			
		||||
            schema.Column('id', types.Integer, primary_key=True),
 | 
			
		||||
            schema.Column('first_name', types.Unicode(25)),
 | 
			
		||||
            schema.Column('last_name', types.Unicode(25)))
 | 
			
		||||
        class User(object):
 | 
			
		||||
            pass
 | 
			
		||||
        orm.mapper(User, user_table)
 | 
			
		||||
        
 | 
			
		||||
        # create the session
 | 
			
		||||
        engine = create_engine('sqlite:///:memory:')
 | 
			
		||||
        metadata.bind = engine
 | 
			
		||||
        metadata.create_all()
 | 
			
		||||
        session = orm.sessionmaker(bind=engine)()
 | 
			
		||||
        
 | 
			
		||||
        # add some dummy data
 | 
			
		||||
        user_table.insert().execute([
 | 
			
		||||
            {'first_name': u'Jonathan', 'last_name': u'LaCour'},
 | 
			
		||||
            {'first_name': u'Yoann', 'last_name': u'Roman'}
 | 
			
		||||
        ])
 | 
			
		||||
        
 | 
			
		||||
        # get the SA objects
 | 
			
		||||
        self.sa_object = session.query(User).first()
 | 
			
		||||
        select = user_table.select()
 | 
			
		||||
        self.result_proxy = select.execute()
 | 
			
		||||
        self.row_proxy = select.execute().fetchone()
 | 
			
		||||
    
 | 
			
		||||
    def test_sa_object(self):
 | 
			
		||||
        result = encode(self.sa_object)
 | 
			
		||||
        assert loads(result) == {'id': 1, 'first_name': 'Jonathan', 'last_name': 'LaCour'}
 | 
			
		||||
    
 | 
			
		||||
    def test_result_proxy(self):
 | 
			
		||||
        result = encode(self.result_proxy)
 | 
			
		||||
        assert loads(result) == {'count': 2, 'rows': [
 | 
			
		||||
            {'id': 1, 'first_name': 'Jonathan', 'last_name': 'LaCour'},
 | 
			
		||||
            {'id': 2, 'first_name': 'Yoann', 'last_name': 'Roman'}
 | 
			
		||||
        ]}
 | 
			
		||||
    
 | 
			
		||||
    def test_row_proxy(self):
 | 
			
		||||
        result = encode(self.row_proxy)
 | 
			
		||||
        assert loads(result) == {'id': 1, 'first_name': 'Jonathan', 'last_name': 'LaCour'}
 | 
			
		||||
 
 | 
			
		||||
@@ -95,7 +95,7 @@ class TestValidation(object):
 | 
			
		||||
 | 
			
		||||
            @expose()
 | 
			
		||||
            def errors(self, *args, **kwargs):
 | 
			
		||||
                assert len(request.validation_errors) > 0
 | 
			
		||||
                assert len(request.pecan['validation_errors']) > 0
 | 
			
		||||
                return 'There was an error!'
 | 
			
		||||
            
 | 
			
		||||
            @expose(schema=RegistrationSchema())
 | 
			
		||||
@@ -106,7 +106,7 @@ class TestValidation(object):
 | 
			
		||||
                            password,
 | 
			
		||||
                            password_confirm,
 | 
			
		||||
                            age):
 | 
			
		||||
                assert len(request.validation_errors) > 0
 | 
			
		||||
                assert len(request.pecan['validation_errors']) > 0
 | 
			
		||||
                return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
            @expose(schema=RegistrationSchema(), error_handler='/errors')
 | 
			
		||||
@@ -117,17 +117,17 @@ class TestValidation(object):
 | 
			
		||||
                            password,
 | 
			
		||||
                            password_confirm,
 | 
			
		||||
                            age):
 | 
			
		||||
                assert len(request.validation_errors) > 0
 | 
			
		||||
                assert len(request.pecan['validation_errors']) > 0
 | 
			
		||||
                return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
            @expose(json_schema=RegistrationSchema())
 | 
			
		||||
            def json(self, data):
 | 
			
		||||
                assert len(request.validation_errors) > 0
 | 
			
		||||
                assert len(request.pecan['validation_errors']) > 0
 | 
			
		||||
                return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
            @expose(json_schema=RegistrationSchema(), error_handler='/errors')
 | 
			
		||||
            def json_with_handler(self, data):
 | 
			
		||||
                assert len(request.validation_errors) > 0
 | 
			
		||||
                assert len(request.pecan['validation_errors']) > 0
 | 
			
		||||
                return 'Success!'
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
@@ -193,13 +193,13 @@ class TestValidation(object):
 | 
			
		||||
            
 | 
			
		||||
            @expose()
 | 
			
		||||
            def errors(self, *args, **kwargs):
 | 
			
		||||
                return 'Error with %s!' % ', '.join(request.validation_errors.keys())
 | 
			
		||||
                return 'Error with %s!' % ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
            
 | 
			
		||||
            @expose(schema=ColorSchema(), 
 | 
			
		||||
                    variable_decode=True)
 | 
			
		||||
            def index(self, **kwargs):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
@@ -207,16 +207,16 @@ class TestValidation(object):
 | 
			
		||||
                    error_handler='/errors', 
 | 
			
		||||
                    variable_decode=True)
 | 
			
		||||
            def with_handler(self, **kwargs):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
            @expose(json_schema=ColorSchema(), 
 | 
			
		||||
                    variable_decode=True)
 | 
			
		||||
            def json(self, data):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
@@ -224,16 +224,16 @@ class TestValidation(object):
 | 
			
		||||
                    error_handler='/errors', 
 | 
			
		||||
                    variable_decode=True)
 | 
			
		||||
            def json_with_handler(self, data):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
            @expose(schema=ColorSchema(),
 | 
			
		||||
                    variable_decode=dict())
 | 
			
		||||
            def custom(self, **kwargs):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
@@ -241,16 +241,16 @@ class TestValidation(object):
 | 
			
		||||
                    error_handler='/errors',
 | 
			
		||||
                    variable_decode=dict())
 | 
			
		||||
            def custom_with_handler(self, **kwargs):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
            @expose(json_schema=ColorSchema(),
 | 
			
		||||
                    variable_decode=dict())
 | 
			
		||||
            def custom_json(self, data):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
 | 
			
		||||
@@ -258,16 +258,16 @@ class TestValidation(object):
 | 
			
		||||
                    error_handler='/errors',
 | 
			
		||||
                    variable_decode=dict())
 | 
			
		||||
            def custom_json_with_handler(self, data):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
 | 
			
		||||
            @expose(schema=ColorSchema(),
 | 
			
		||||
                    variable_decode=dict(dict_char='-', list_char='.'))
 | 
			
		||||
            def alternate(self, **kwargs):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
@@ -275,16 +275,16 @@ class TestValidation(object):
 | 
			
		||||
                    error_handler='/errors',
 | 
			
		||||
                    variable_decode=dict(dict_char='-', list_char='.'))
 | 
			
		||||
            def alternate_with_handler(self, **kwargs):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
            
 | 
			
		||||
            @expose(json_schema=ColorSchema(),
 | 
			
		||||
                    variable_decode=dict(dict_char='-', list_char='.'))
 | 
			
		||||
            def alternate_json(self, data):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
 | 
			
		||||
@@ -292,8 +292,8 @@ class TestValidation(object):
 | 
			
		||||
                    error_handler='/errors',
 | 
			
		||||
                    variable_decode=dict(dict_char='-', list_char='.'))
 | 
			
		||||
            def alternate_json_with_handler(self, data):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return ', '.join(request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return ', '.join(request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return 'Success!'
 | 
			
		||||
        
 | 
			
		||||
@@ -507,7 +507,7 @@ class TestValidation(object):
 | 
			
		||||
                    schema=ColorSchema(), 
 | 
			
		||||
                    variable_decode=True)
 | 
			
		||||
            def index(self, **kwargs):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return dict()
 | 
			
		||||
                else:
 | 
			
		||||
                    return dict(data=kwargs)
 | 
			
		||||
@@ -542,8 +542,8 @@ class TestValidation(object):
 | 
			
		||||
                    schema=NameSchema(),
 | 
			
		||||
                    htmlfill=dict(auto_insert_errors=True))
 | 
			
		||||
            def json(self, **kwargs):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                    return dict(error_with=request.validation_errors.keys())
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return dict(error_with=request.pecan['validation_errors'].keys())
 | 
			
		||||
                else:
 | 
			
		||||
                    return kwargs
 | 
			
		||||
        
 | 
			
		||||
@@ -639,7 +639,7 @@ class TestValidation(object):
 | 
			
		||||
            @expose(template='mako:form_login.html',
 | 
			
		||||
                    schema=LoginSchema())
 | 
			
		||||
            def index(self, **kwargs):
 | 
			
		||||
                if request.validation_errors:
 | 
			
		||||
                if request.pecan['validation_errors']:
 | 
			
		||||
                    return dict()
 | 
			
		||||
                else:
 | 
			
		||||
                    return dict(data=kwargs)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user