PyRal 获取附件
PyRal getAttachment
我有一个相当简单的用例,但我不理解我收到的错误消息。
我正在使用请求和 pyral 模块,pyral (http://pyral.readthedocs.io/en/latest/interface.html#) 实际上只是 Rally Restful api 的包装器。我的目标是从 Rally(CA 产品)UserStory 获取文件(附件)并将其存储到本地文件系统。
对于上下文,这是我的环境设置(验证 Rally 并创建一个对象)。我显然已经删除了身份验证信息。
from pyral import Rally, rallyWorkset
options = [arg for arg in sys.argv[1:] if arg.startswith('--')]
args = [arg for arg in sys.argv[1:] if arg not in options]
server, user, password, apikey, workspace, project = rallyWorkset(options)
rally = Rally(server='rally1.rallydev.com',
user='**********', password='***********',
apikey="**************",
workspace='**************', project='**************',
server_ping=False)
之后我得到了一个用户故事的响应对象(参见 US845 的查询),我这样做只是为了简化问题。
r = rally.get('UserStory', fetch = True, projectScopeDown=True, query = 'FormattedID = US845')
然后我使用内置迭代器从 RallyRESTResponse 对象中获取用户故事。
us = r.next()
从那里感觉我应该能够轻松地使用接受工件 (us) 和文件名(附件名称)的 getAttachment() 方法。我可以使用 getAttachmentNames(us) 来 return 附件名称列表。当我尝试
之类的东西时,问题就出现了
attachment_names = rally.getAttachmentNames(us) #get attachments for this UserStory
attachment_file = rally.getAttachment(us, attachment_names[0]) #Try to get the first attachment
return像这样的错误
Traceback (most recent call last):
File "<ipython-input-81-a4a342a59c5a>", line 1, in <module>
attachment_file = rally.getAttachment(us, attachment_names[0])
File "C:\Miniconda3\lib\site-packages\pyral\restapi.py", line 1700, in getAttachment
att.Content = base64.decodebytes(att_content.Content) # maybe further txfm to Unicode ?
File "C:\Miniconda3\lib\base64.py", line 552, in decodebytes
_input_type_check(s)
File "C:\Miniconda3\lib\base64.py", line 520, in _input_type_check
raise TypeError(msg) from err
TypeError: expected bytes-like object, not str
如果我尝试使用
,我会收到类似的错误
test_obj = rally.getAttachments(us)
其中 return 是这样的错误:
Traceback (most recent call last):
File "<ipython-input-82-06a8cd525177>", line 1, in <module>
rally.getAttachments(us)
File "C:\Miniconda3\lib\site-packages\pyral\restapi.py", line 1721, in getAttachments
attachments = [self.getAttachment(artifact, attachment_name) for attachment_name in attachment_names]
File "C:\Miniconda3\lib\site-packages\pyral\restapi.py", line 1721, in <listcomp>
attachments = [self.getAttachment(artifact, attachment_name) for attachment_name in attachment_names]
File "C:\Miniconda3\lib\site-packages\pyral\restapi.py", line 1700, in getAttachment
att.Content = base64.decodebytes(att_content.Content) # maybe further txfm to Unicode ?
File "C:\Miniconda3\lib\base64.py", line 552, in decodebytes
_input_type_check(s)
File "C:\Miniconda3\lib\base64.py", line 520, in _input_type_check
raise TypeError(msg) from err
TypeError: expected bytes-like object, not str
看来我从根本上误解了此方法所需的参数?以前有没有人能够成功地做到这一点?对于它的价值,我可以毫无问题地将 addAttachment() 方法与与上述类似的工作流程一起使用。我试过使用 bytes() 方法将文件名(字符串)转换为 utf-8,但这没有帮助。
我也在 pyral 源代码中查看了这个示例,但我在尝试执行它时收到完全相同的错误。
https://github.com/klehman-rally/pyral/blob/master/examples/get_attachments.py
看起来像是 restapi.py 脚本中的问题 - base64 库中没有 decodebytes 方法:
att.Content = base64.decodebytes(att_content.Content)
所有可用方法的描述如下:
RFC 3548: Base16, Base32, Base64 Data Encodings
因此,解决方法是用 restapi.py 中的 base64.b64decode
替换 decodebytes。至少,它对我有用。
例如位置 Mac OS X:
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pyral/restapi.py
我已使用以下代码获取所有附件,因为 getAttachments 未按预期工作。它将在当前目录中创建一个同名文件。
import sys
import string
import base64
from pyral import rallyWorkset, Rally,RallyRESTResponse
rally = Rally(server, user=USER_NAME, password=PASSWORD, workspace=workspace, project=project)
criterion = 'FormattedID = US57844'
response = rally.get('HierarchicalRequirement', query=criterion, order="FormattedID",pagesize=200, limit=400, projectScopeDown=True)
artifact = response.next()
context, augments = rally.contextHelper.identifyContext()
for att in artifact.Attachments:
resp = rally._getResourceByOID(context, 'AttachmentContent', att.Content.oid, project=None)
if resp.status_code not in [200, 201, 202]:
break
res = RallyRESTResponse(rally.session, context, "AttachmentContent.x", resp, "full", 1)
if res.errors or res.resultCount != 1:
print("breaking the for loop")
att_content = res.next()
cont = att_content.Content
x = base64.b64decode(cont)
output = open(att.Name, 'wb')
output.write(x)
我有一个相当简单的用例,但我不理解我收到的错误消息。
我正在使用请求和 pyral 模块,pyral (http://pyral.readthedocs.io/en/latest/interface.html#) 实际上只是 Rally Restful api 的包装器。我的目标是从 Rally(CA 产品)UserStory 获取文件(附件)并将其存储到本地文件系统。
对于上下文,这是我的环境设置(验证 Rally 并创建一个对象)。我显然已经删除了身份验证信息。
from pyral import Rally, rallyWorkset
options = [arg for arg in sys.argv[1:] if arg.startswith('--')]
args = [arg for arg in sys.argv[1:] if arg not in options]
server, user, password, apikey, workspace, project = rallyWorkset(options)
rally = Rally(server='rally1.rallydev.com',
user='**********', password='***********',
apikey="**************",
workspace='**************', project='**************',
server_ping=False)
之后我得到了一个用户故事的响应对象(参见 US845 的查询),我这样做只是为了简化问题。
r = rally.get('UserStory', fetch = True, projectScopeDown=True, query = 'FormattedID = US845')
然后我使用内置迭代器从 RallyRESTResponse 对象中获取用户故事。
us = r.next()
从那里感觉我应该能够轻松地使用接受工件 (us) 和文件名(附件名称)的 getAttachment() 方法。我可以使用 getAttachmentNames(us) 来 return 附件名称列表。当我尝试
之类的东西时,问题就出现了attachment_names = rally.getAttachmentNames(us) #get attachments for this UserStory
attachment_file = rally.getAttachment(us, attachment_names[0]) #Try to get the first attachment
return像这样的错误
Traceback (most recent call last):
File "<ipython-input-81-a4a342a59c5a>", line 1, in <module>
attachment_file = rally.getAttachment(us, attachment_names[0])
File "C:\Miniconda3\lib\site-packages\pyral\restapi.py", line 1700, in getAttachment
att.Content = base64.decodebytes(att_content.Content) # maybe further txfm to Unicode ?
File "C:\Miniconda3\lib\base64.py", line 552, in decodebytes
_input_type_check(s)
File "C:\Miniconda3\lib\base64.py", line 520, in _input_type_check
raise TypeError(msg) from err
TypeError: expected bytes-like object, not str
如果我尝试使用
,我会收到类似的错误test_obj = rally.getAttachments(us)
其中 return 是这样的错误:
Traceback (most recent call last):
File "<ipython-input-82-06a8cd525177>", line 1, in <module>
rally.getAttachments(us)
File "C:\Miniconda3\lib\site-packages\pyral\restapi.py", line 1721, in getAttachments
attachments = [self.getAttachment(artifact, attachment_name) for attachment_name in attachment_names]
File "C:\Miniconda3\lib\site-packages\pyral\restapi.py", line 1721, in <listcomp>
attachments = [self.getAttachment(artifact, attachment_name) for attachment_name in attachment_names]
File "C:\Miniconda3\lib\site-packages\pyral\restapi.py", line 1700, in getAttachment
att.Content = base64.decodebytes(att_content.Content) # maybe further txfm to Unicode ?
File "C:\Miniconda3\lib\base64.py", line 552, in decodebytes
_input_type_check(s)
File "C:\Miniconda3\lib\base64.py", line 520, in _input_type_check
raise TypeError(msg) from err
TypeError: expected bytes-like object, not str
看来我从根本上误解了此方法所需的参数?以前有没有人能够成功地做到这一点?对于它的价值,我可以毫无问题地将 addAttachment() 方法与与上述类似的工作流程一起使用。我试过使用 bytes() 方法将文件名(字符串)转换为 utf-8,但这没有帮助。
我也在 pyral 源代码中查看了这个示例,但我在尝试执行它时收到完全相同的错误。
https://github.com/klehman-rally/pyral/blob/master/examples/get_attachments.py
看起来像是 restapi.py 脚本中的问题 - base64 库中没有 decodebytes 方法:
att.Content = base64.decodebytes(att_content.Content)
所有可用方法的描述如下:
RFC 3548: Base16, Base32, Base64 Data Encodings
因此,解决方法是用 restapi.py 中的 base64.b64decode
替换 decodebytes。至少,它对我有用。
例如位置 Mac OS X:
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pyral/restapi.py
我已使用以下代码获取所有附件,因为 getAttachments 未按预期工作。它将在当前目录中创建一个同名文件。
import sys
import string
import base64
from pyral import rallyWorkset, Rally,RallyRESTResponse
rally = Rally(server, user=USER_NAME, password=PASSWORD, workspace=workspace, project=project)
criterion = 'FormattedID = US57844'
response = rally.get('HierarchicalRequirement', query=criterion, order="FormattedID",pagesize=200, limit=400, projectScopeDown=True)
artifact = response.next()
context, augments = rally.contextHelper.identifyContext()
for att in artifact.Attachments:
resp = rally._getResourceByOID(context, 'AttachmentContent', att.Content.oid, project=None)
if resp.status_code not in [200, 201, 202]:
break
res = RallyRESTResponse(rally.session, context, "AttachmentContent.x", resp, "full", 1)
if res.errors or res.resultCount != 1:
print("breaking the for loop")
att_content = res.next()
cont = att_content.Content
x = base64.b64decode(cont)
output = open(att.Name, 'wb')
output.write(x)