我正在编写自动化脚本,通过jira python库向Jira添加一些bug。
我在一个文件中有我的用户名和密码,我想确保每次调用一个函数(添加/修改一个bug)都会被验证。
基本上我想写一个装饰器。但是这个装饰器将返回一个jira对象,每个函数都应该使用它。以下是我要写的函数。
def return_authed_jira():
options = {'server': 'https://jira.xxxxyyzzz.com'}
authed_jira = JIRA(options, basic_auth=('my_uname', my_passwd))
return authed_jira
有没有办法可以使用装饰器来做到这一点。再说一遍,我知道如果不使用装饰器我可以做到不同,但我想用装饰器做这件事。
我自己尝试过编写它,但我见过的大多数示例都没有返回对象。
这就是我的尝试。
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不会使函数轻松访问。这与登录装饰器类似,如果您尝试访问需要用户登录的页面,则将装饰器添加到服务页面的功能中。
@authenticate
def create_new_jira_bug(jira_fields):
new_issue = jira.create_issue(jira_fields)
print new_issue.id
以下是Blckknght
回答问题并做出一些修改后的新代码。
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函数时得到的错误
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对象传递给调用装饰器之前的函数,否则我会收到此错误。有替代方案吗?它可以正常使用下面的代码。我试图得到一个解释,为什么我必须在定义函数时传递对象,当我在调用函数时不必传递该对象。
@authenticate
def list_projects(jira):
my_issue = jira.issue('MYKEY-1289')
print (my_issue.raw.get('fields'))
list_projects()
答案 0 :(得分:1)
你不能append
到args
,因为它是一个元组,而不是一个列表。要添加值,您需要创建一个值为concatenated的新元组:
args = args + (jira,)
注意(jira,)
末尾的逗号,必须使它成为1元组,而不是简单的括号表达式。
您还需要设置要装饰的函数以期望jira
参数:
@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
对象使用相同的名称,但它不会干扰它们对其他关键字参数的处理。将位置参数添加到现有的末尾(正如您当前所做的那样)可能会使用关键字参数来中断调用。以下是使用关键字的装饰器的外观:
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
这将适用于上述功能,但不会干扰如下调用:
create_new_jira_bug(jira_fields={"foo": "bar"})