我一直在编写一些 Python 代码来以编程方式更新 CFD 小部件设置,以显示过去 14、15、16 天等的数据。 但是,当我测试 API 端点 来更新小部件时,Web 界面向我抛出一个错误:
TypeError: e.split is not a function
但是,我发出的API请求得到了成功的返回。 这是代码:
import fazer_requisicoes
import json
import base64
import os
from dotenv import load_dotenv
from pprint import pp
load_dotenv()
token_do_azure = os.environ['AZURE_DEVOPS_PAT']
pat_encoded = base64.b64encode((":" + token_do_azure).encode()).decode()
headers = {
'Content-Type': 'application/json',
'Authorization': f'Basic {pat_encoded}'
}
settings_dict = {
"chartDataSettings": {
"timePeriod": {
"settings": 16
}
}
}
def atualizar_cfd():
organization = r'ACR-AcompanhamentoCliente'
project = r'S565 - Acompanhamento de Clientes'
team = r'S565 - Acompanhamento de Clientes Team'
dashboard_id = r'c80b8254-5432-442e-a0af-c761af863f1e'
widget_id = r'591ecd56-87ed-4dcf-ae65-4c7619a1c79d'
url = f'https://dev.azure.com/{organization}/{project}/{team}/_apis/dashboard/dashboards/{dashboard_id}/widgets/{widget_id}?api-version=7.2-preview.2'
get_req = fazer_requisicoes.fazer_requisicoes("GET", url, headers)
get_req_text = json.loads(get_req.text)
# Assuming the ETag is in the body, otherwise look for it in the headers
current_etag_widget = get_req_text['eTag']
current_etag_dashboard = get_req_text['dashboard']['eTag']
pp(current_etag_widget)
pp(current_etag_dashboard)
url = f'https://dev.azure.com/{organization}/{project}/{team}/_apis/dashboard/dashboards/{dashboard_id}/widgets/{widget_id}?api-version=7.2-preview.2'
req_body = {
"id": widget_id,
"name": "Cumulative Flow Diagram (CFD)",
"eTag": f'{current_etag_widget}',
'position': {'row': 4, 'column': 5},
"size": {
"rowSpan": 2, "columnSpan": 3
},
'settings': settings_dict,
"settingsVersion":
{
"major": 1,
"minor": 0,
"patch": 0
},
"contributionId": "ms.vss-dashboards-web.Microsoft.VisualStudioOnline.Dashboards.CumulativeFlowDiagramWidget",
'dashboard': {'position': -1,
'eTag': f'{current_etag_dashboard}',
'modifiedDate': '0001-01-01T00:00:00',
'lastAccessedDate': '0001-01-01T00:00:00'},
}
req = fazer_requisicoes.fazer_requisicoes("PATCH", url, headers, req_body)
req_text = json.loads(req.text)
req_response = json.dumps(req_text)
pp(req_response)
def main():
atualizar_cfd()
main()
这是 'fazer_requisicoes 函数:
import requests
import time
import urllib3
from requests.exceptions import JSONDecodeError
from pprint import pprint
urllib3.disable_warnings()
session = requests.Session()
contador_timeout = 0
contador_SSL = 0
def fazer_requisicoes(metodo, url, headers, request_body=None):
global contador_timeout
global contador_SSL
while True:
try:
if metodo in ['GET', 'DELETE']:
req = session.request(metodo, url, headers=headers, verify=False)
else:
req = session.request(metodo, url, headers=headers, json=request_body, verify=False)
try:
req.json()
except JSONDecodeError:
print(f'{req.status_code}\n')
pprint(req.text)
print(f"Resposta inválida recebida. Tentando novamente...")
time.sleep(10)
continue
return req
except requests.exceptions.ConnectTimeout as e:
contador_timeout += 1
print(f"Erro de timeout número {contador_timeout}. Tentando novamente...")
time.sleep(10)
except requests.exceptions.SSLError as e:
contador_SSL += 1
print(f"Erro de SSL número {contador_SSL}. Tentando novamente...")
time.sleep(10)
我可以修复它吗?如果是的话,怎么办?
我尝试在设置中使用多行,但它在 Web 界面中引发了另一个错误,即 SyntaxError。
您的问题可能与以下几件事有关:
“
settings
”对象的值是一个json字符串,其中所有双引号("
)都通过斜杠(\
)转义。当传递给 PATCH
API 调用时,还应该使用转义的 json 字符串。
更新“
settings
”对象的值时,似乎需要将整个转义的json字符串与更新的部分一起传递给PATCH
API调用。
下面是我尝试的一个 Python 示例。它可以很好地更新CFD Widget的设置,不会出现任何错误。您可以参考它来更新您的 Python 脚本。
# coding=utf-8
import os
import json
import base64
import requests
organization = '{organization}'
project = '{project}'
team = '{team}'
dashboardId = '{dashboardId}'
widgetId = '{widgetId}'
ado_pat = os.environ['AZURE_DEVOPS_PAT']
b64token = base64.b64encode((":" + ado_pat).encode()).decode()
url = f'https://dev.azure.com/{organization}/{project}/{team}/_apis/dashboard/dashboards/{dashboardId}/widgets/{widgetId}?api-version=7.2-preview.2'
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': f'Basic {b64token}'
}
session = requests.Session()
print("-------------------- CFD Widget befor updating --------------------")
response_get = session.request('GET', url, headers=headers, json=None)
json_object_get = json.loads(response_get.content)
json_format_get = json.dumps(json_object_get, indent=2)
print(json_format_get)
print("-------------------- Updating CFD Widget --------------------")
body_patch = json_object_get
print("The settings before updating is:")
settings = body_patch["settings"]
json_object_settings = json.loads(settings)
json_format_settings = json.dumps(json_object_settings, indent=2)
print(json_format_settings)
print("Update the settings to:")
json_object_settings["chartDataSettings"]["timePeriod"]["settings"] = 20
json_format_settings_updated = json.dumps(json_object_settings, indent=2)
print(json_format_settings_updated)
print("-------------------- CFD Widget after updating --------------------")
body_patch["settings"] = json.dumps(json_object_settings).replace('"', '\"')
response_patch = session.request('PATCH', url, headers=headers, json=body_patch)
json_object_patch = json.loads(response_patch.content)
json_format_patch = json.dumps(json_object_patch, indent=2)
print(json_format_patch)