检查函数是否使用特定的关键字参数 [英] Check if a function uses a specific keyword argument

查看:61
本文介绍了检查函数是否使用特定的关键字参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的装饰器:

I've got a decorator like this:

def auth(func):
    def dec(self, *args):
        user = Auth.auth(self.server.parse_params(), self.server.client_address)
        // snip...
        if user is None:
            raise NoSuchUserError
        func(self, *args, user=user)
    return dec

效果很好,现在我可以编写如下函数:

That works great, now I can write functions like this:

@auth
def serve_account(self, user=None):
    return json.dumps(user)

但是有时候我有一些函数根本不读取 user 参数,我只是想让装饰者处理未经身份验证的用户.以此为例:

But sometimes I've got functions where I don't actually read the user parameter at all, I just want the decorator to take care of unauthenticated users. Take this as an example:

@auth
def serve_status(self, user=None):
    // I get the status here but I don't use the user parameter.
    return json.dumps(status)

现在,我的IDE和我的静态代码分析服务一直在na不休:

Now my IDE and my static code analysis service keep nagging about it:

未使用的参数用户"

Unused argument 'user'

这也可能使不知道装饰器中发生了什么的人感到困惑:

It might also confuse people who don't know what's going on in the decorator:

TypeError: serve_status() got an unexpected keyword argument 'user'

我无法删除该参数,否则一旦装饰器调用该函数,我将收到运行时错误.

I can't remove the parameter, otherwise I'll get a runtime error once the function gets called by the decorator.

如果函数在参数列表中没有该参数,是否可以在装饰器中省略该参数?(除了创建第二个装饰器,例如 @auth_but_dont_pass_the_user ))

Is there any way I can omit the parameter in the decorator if the function doesn't have it in the argument list? (Apart from creating a second decorator like @auth_but_dont_pass_the_user)

推荐答案

您可以解析到正在调用的函数的源,并检查 user 变量使用了多少次(如果更大)大于1,则可以使用变量 user :

You can parse to source of the function being called and check how many times the user variable is being used, if it is greater than 1 then you can call that function with the variable user:

import ast
import inspect


def is_variable_used(func, variable):
    source = inspect.getsource(func).split('\n', 1)[1]  # Split to drop the decorator part
    return sum(node.id == variable for node in ast.walk(ast.parse(source))
               if isinstance(node, ast.Name)) > 1


def auth(func):
    def dec(self, *args):
        if is_variable_used(func, 'user'):
            print 'Calling {func_name} with user.'.format(func_name=func.__name__)
            return func(self, user=100)
        else:
            print 'Calling {func_name} without user.'.format(func_name=func.__name__)
            return func(self)
    return dec


@auth
def func1_with_user(foo, user=None):
    return 10 + user

@auth
def func2_with_user(foo, user=None):
    a = 10 + foo
    b = a + foo
    c = a + b + user
    return a + b + c

@auth
def func1_without_user(foo, user=None):
    pass

@auth
def func2_without_user(foo, user=None):
    return 10 + foo


print func1_with_user(10)
print func2_with_user(20)
print func1_without_user(100)
print func2_without_user(200)

输出:

>>> !python so.py
Calling func1_with_user with user.
110
Calling func2_with_user with user.
260
Calling func1_without_user without user.
None
Calling func2_without_user without user.
210

这篇关于检查函数是否使用特定的关键字参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆