Skip to content

Instantly share code, notes, and snippets.

@mckabi
Last active December 18, 2015 13:39
Show Gist options
  • Save mckabi/5791988 to your computer and use it in GitHub Desktop.
Save mckabi/5791988 to your computer and use it in GitHub Desktop.
The decorator 'foo' works fine in flask 0.9, but it does not work in 0.10.1. http://flask.pocoo.org/snippets/18/ is also same result.
Traceback (most recent call last):
File "./hello.py", line 31, in <module>
def hello(name=None):
File "./hello.py", line 15, in deco
@wraps(f)
File "/Users/mckabi/Documents/Sandbox/flask_ex/env/lib/python2.7/site-packages/flask/app.py", line 1013, in decorator
self.add_url_rule(rule, endpoint, f, **options)
File "/Users/mckabi/Documents/Sandbox/flask_ex/env/lib/python2.7/site-packages/flask/app.py", line 62, in wrapper_func
return f(self, *args, **kwargs)
File "/Users/mckabi/Documents/Sandbox/flask_ex/env/lib/python2.7/site-packages/flask/app.py", line 984, in add_url_rule
'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: hello
def foo(current_app, url, postfix='blah blah', *args, **kwargs):
def deco(f):
@current_app.route(url, defaults=kwargs.pop('defaults', {}), *args, **kwargs)
@wraps(f)
def decorated_func(*args, **kwargs):
sys.stdout.write('... in decorated_func, foo({0!r}) with {1!r}\n'.format(f, postfix))
sys.stdout.flush()
return f(*args, **kwargs)
decorated_func._orig = f
return decorated_func
return deco
@foo(app, '/hello', 'first foo')
@foo(app, '/hello/<name>', 'second foo')
def hello(name=None):
return {'name': name}
@mckabi
Copy link
Author

mckabi commented Jun 16, 2013

My solution is:

def bind_renderer(renderer=None):
    def wrapper(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            result = f(*args, **kwargs)
            if isinstance(result, (Response, BaseResponse)):
                return result
            if renderer is None or not callable(renderer):
                return result
            try:
                return renderer()(result)
            except TypeError:
                return renderer(result)
        return decorated_function
    return wrapper


@app.route('/hello')
@app.route('/hello/<name>')
@bind_renderer(render_json)
def hello(name=None):
    return {'name': name}

I think this solution is close to the flask style.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment