首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何编写装饰器并返回经过身份验证的对象

如何编写装饰器并返回经过身份验证的对象
EN

Stack Overflow用户
提问于 2016-01-20 21:09:51
回答 1查看 609关注 0票数 1

我正在编写自动化脚本,以便通过Jira python库向jira添加一些bug。

我在一个文件中有我的用户名和密码,我想确保每次调用一个函数(它添加/修改一个bug)都经过身份验证。

基本上我想写个装潢师。但是这个装饰器将返回一个jira对象,该对象将由每个函数使用。下面是我要写的函数。

代码语言:javascript
复制
def return_authed_jira():
    options = {'server': 'https://jira.xxxxyyzzz.com'}
    authed_jira = JIRA(options,  basic_auth=('my_uname', my_passwd))
    return authed_jira

有什么办法可以用装饰师来做吗。再说一遍,我知道我可以用不同的方式去做而不用装饰,但是我想用一个装饰师来做。

我试着自己写,但是我看到的大多数例子都没有返回一个对象。

这就是我尝试过的。

代码语言:javascript
复制
def authenticate(func):

    def authenticate_and_call(*args, **kwargs):

        options = {'server': 'https://jira.xxxxxxx.com', 'verify': False}
        jira = JIRA(options)
        if not jira.current_user() == 'uname':
            options = {'server': 'https://jira.xxxxxx.com', 'verify': False}
            jira = JIRA(options, basic_auth=('uname', passwd))
            args.append(jira)
        return func(*args, **kwargs)
    return authenticate_and_call

在这里,我试图附加jira对象,但这不起作用。

这是我想要的。将jira对象添加到args并不能使函数很容易访问。这类似于登录装饰器,如果您试图访问一个需要用户登录的页面,您可以将装饰器添加到为该页面服务的函数中。

代码语言:javascript
复制
@authenticate
def create_new_jira_bug(jira_fields):

    new_issue = jira.create_issue(jira_fields)
    print new_issue.id

下面是Blckknght回答了这个问题并做了一些修改后的新代码。

代码语言:javascript
复制
def authenticate(func):

    def authenticate_and_call(*args, **kwargs):

        options = {'server': 'https://jira.xyz.com', 'verify': False}
        jira = JIRA(options)
        if not jira.current_user() == 'uname':
            options = {'server': 'https://jira.xyz.com', 'verify': False}
            jira = JIRA(options, basic_auth=(uname, password))
        return func(*args, jira=jira, **kwargs)
    return authenticate_and_call

@authenticate
def list_projects():

    my_issue = jira.issue('MYKEY-1289')
    print (my_issue.raw.get('fields'))

list_projects()

下面是当我没有将jira添加到list_projects函数时所遇到的错误

代码语言:javascript
复制
Traceback (most recent call last):
  File "C:/testjira.py", line 44, in <module>
    list_projects()
  File "C:testjira.py", line 33, in authenticate_and_call
    return func(*args, jira=jira, **kwargs)
TypeError: list_projects() takes no arguments (1 given)

我的问题是,我必须将jira对象传递给调用修饰器的函数,否则我会得到这个错误。有什么替代办法吗?下面的代码可以很好地工作。我试图得到一个解释,为什么在定义函数时必须传递对象,而在调用函数时不需要传递该对象。

代码语言:javascript
复制
@authenticate
def list_projects(jira):

    my_issue = jira.issue('MYKEY-1289')
    print (my_issue.raw.get('fields'))

list_projects()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-20 22:02:31

您不能appendargs,因为它是元组,而不是列表。要添加一个值,您需要使用连接的值创建一个新的元组:

代码语言:javascript
复制
args = args + (jira,)

注意(jira,)末尾的逗号,必须使它成为一个1元组,而不是一个简单的圆括号表达式。

您还需要设置要修饰的函数,以期待jira参数:

代码语言:javascript
复制
@authenticate
def create_new_jira_bug(jira_fields, jira): # expects jira arg from decorator
    new_issue = jira.create_issue(jira_fields)
    print new_issue.id

请注意,我没有为jira提供默认值。当前的代码只是在某些时候将jira参数添加到args中,如果jira是必需的参数,则jira将无法工作。从装潢师那里传进来也许更有意义。

在装饰器的调用中添加关键字参数可能更自然,而不是添加额外的位置参数。这将需要您正在修饰的所有函数为装饰器传入的jira对象使用相同的名称,但它不会干扰它们对其他关键字参数的处理。将位置参数添加到现有的末尾(正如您当前所做的那样)可能会使用关键字参数中断调用。下面是使用关键字的装饰器的样子:

代码语言:javascript
复制
def authenticate(func):
    def authenticate_and_call(*args, **kwargs):
        options = {'server': 'https://jira.xxxxxxx.com', 'verify': False}

        jira = JIRA(options)
        if not jira.current_user() == 'uname':
            jira = JIRA(options, basic_auth=('uname', passwd))

        return func(*args, jira=jira, **kwargs)

    return authenticate_and_call

这将与上面的函数一起工作,但它不会干扰以下调用:

代码语言:javascript
复制
 create_new_jira_bug(jira_fields={"foo": "bar"})
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34910582

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档