Python装饰器内部调用了错误的函数

标签 python twisted decorator

我们已经实现了一个扭曲的 web api。

为了处理身份验证,我们使用了一个装饰器来包装一些路由。

@requires_auth(roles=[Roles.Admin])
def get_secret_stuff(request):
    return 42

requires_auth 包装器实现如下。

def requires_auth(roles):
    def wrap(f):
        def wrapped_f(request, *args, **kwargs):
            # If the user is authenticated then...
            return f(request, *args, **kwargs)
        return wrapped_f
    return wrap

问题是如果这个装饰器有多个路由,那么调用 它们中的任何一个都会导致调用要装饰的最新路由。

这显然不是我想要的并且违背了我对装饰器应该如何工作的理解。 我在代码中添加了一些打印语句来尝试找出答案:

def requires_auth(roles):
    def wrap(f):
        print(f) # This shows that the decorator is being called correctly once per each
                 # route that is decorated
        def wrapped_f(request, *args, **kwargs):
            # If the user is authenticated then...
            return f(request, *args, **kwargs)
        return wrapped_f
    return wrap

万一它很重要,我正在为其中一些路由使用 twisted 的 inlineCallbacks,并为所有这些路由使用 twisted web 的 @app.route(url, methods) 装饰器。

感谢您的阅读:)

编辑: 我删除了构造函数的默认参数,因为有人告诉我这是个坏主意:)

编辑:这是一个说明问题的最小示例:

from klein import Klein
import json
app = Klein()

def requires_auth(roles):
    def wrap(f):
        print('inside the first clojure with f=%s' % str(f))
        def wrapped_f(request, *args, **kwargs):
            print('inside the second closure with f=%s' % str(f))
            return f(request, *args, **kwargs)
        return wrapped_f
    return wrap

@app.route('/thing_a')
@requires_auth(roles=['user'])
def get_a(request):
    return json.dumps({'thing A': 'hello'})

@app.route('/thing_b')
@requires_auth(roles=['admin'])
def get_b(request):
    return json.dumps({'thing B': 'goodbye'})

app.run('0.0.0.0', 8080)

转到路由 '/thing_a' 会得到来自 route_b 的 json

最佳答案

试试这个:

from functools import wraps

def require_auth(roles=(Roles.USER,), *args, **kwargs):

    def call(f, *args, **kwargs):
        return f(*args, **kwargs)

    def deco(f):
        @wraps(f)
        def wrapped_f(request, *a, **kw):
            # do your authentication here
            return call(f, request, *a, **kw)

        return wrapped_f

    return deco

关于Python装饰器内部调用了错误的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18832601/

相关文章:

python - 在 Google App Engine 中存储评论的有效方法?

decorator - 在 NestJS 中,如何在自定义方法装饰器中获取执行上下文或请求实例?

python - 无法写入 Twisted FTP 服务器

reactjs - ES7 中的类装饰器

java - 热插拔装修?

Python tkinter网格布局问题

java - 特定的 IDE,用于特定的事物

python - 我可以在docker上分发python应用程序吗?

python - Django 发出 IPC 信号

logging - 扭曲的日志级别开关