Reputation: 1538
I have 4 string variables like this:
a = 'a long string'
b = 'a longer string'
c = 'a path (with a single slash \)'
d = 'another path (with a single slash \)'
I am supposed to be adding this to a variable, which is a list of dictionaries. Something like this:
var = [
{
"op": "add",
"path": "/fields/System.Title",
"from": null,
"value": a
},
{
"op": "add",
"path": "/fields/System.Description",
"from": null,
"value": b
},
{
"op": "add",
"path": "/fields/System.AreaPath",
"from": null,
"value": c
},
{
"op": "add",
"path": "/fields/System.State",
"from": null,
"value": "New"
},
{
"op": "add",
"path": "/fields/System.IterationPath",
"from": null,
"value": d
}
]
FYI, var[3] does not take the variables I created. Only var[0], var[1], var[2] and var[4]
All this works fine. As you may have guessed by now, this is my payload for a POST operation that I am supposed to be sending (it's actually to create a work item in my Azure DevOps organization with the above parameters). Please note, the from in var only accepts null.
When I use POSTMAN to send the above request, it works (except I am not passing the variables in the body, but actually the hard coded values). When I do the same using Python, on VSCode, I am always thrown a 203, which is essentially an incorrect/incomprehensible payload. I am not able to get this working.
This is essentially the code (please assume the variables):
url = f'https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/${workitemtype}?api-version=6.0'
header = {'Content-Type': 'application/json-patch+json', 'Authorization': f'Basic {PAT}'}
request = requests.post(url = url, json = var, headers = header)
I've tried everything I can think of:
request = requests.post(url = url, **data = json.dumps(var)**, headers = header)
,
request = requests.post(url = url, **data = json.loads(var)**, headers = header)
,
request = requests.post(url = url, **data = json.loads(str(var))**, headers = header)
-> this because loads(var) was throwing TypeError: the JSON object must be str, bytes or bytearray, not list
I also tried to include the entire var variable as a docstring - but the problem with that is that I need to pass the variables (a, b, c and d) into it, and docstrings cannot accept them.
How may I overcome this?
I have a feeling that it's the null that's causing this issue, but I could be wrong.
Upvotes: 0
Views: 631
Reputation: 30313
I tested with your code, and i failed to pass the authorization if i defined the Authorization in the request headers. I fixed it by passing the PAT to the auth
parameter in requests.post
method. I made a little to your code. And it worked fine for me. See below:
import requests
if __name__ == '__main__':
a = 'a longer string'
b = 'a longer string'
c = 'project\area'
d = 'project\iteration'
var = [
{
"op": "add",
"path": "/fields/System.Title",
"from": None,
"value": a
},
{
"op": "add",
"path": "/fields/System.Description",
"from": None,
"value": b
},
{
"op": "add",
"path": "/fields/System.AreaPath",
"from": None,
"value": c
},
{
"op": "add",
"path": "/fields/System.State",
"from": None,
"value": "New"
},
{
"op": "add",
"path": "/fields/System.IterationPath",
"from": None,
"value": d
}
]
pat = "Personal access token"
url = 'https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/$Task?api-version=6.1-preview.3'
header = {'Content-Type': 'application/json-patch+json'}
request = requests.post(url = url, json = var, headers = header, auth=("", pat))
However you can also check out azure-devops-python-api. See below example code to create a work item.
from azure.devops.connection import Connection
from msrest.authentication import BasicAuthentication
from azure.devops.v5_1.work_item_tracking.models import JsonPatchOperation
def _create_patch_operation(op, path, value):
patch_operation = JsonPatchOperation()
patch_operation.op = op
patch_operation.path = path
patch_operation.value = value
return patch_operation
def _create_work_item_field_patch_operation(op, field, value):
path = '/fields/{field}'.format(field=field)
return _create_patch_operation(op=op, path=path, value=value)
if __name__=='__main__':
a = 'a longer string'
b = 'a longer string'
c = 'project\area'
d = 'project\iteration'
# Fill in with your personal access token and org URL
personal_access_token = 'PAT'
organization_url = 'https://dev.azure.com/{org}/'
# Create a connection to the org
credentials = BasicAuthentication('', personal_access_token)
connection = Connection(base_url=organization_url, creds=credentials)
# Get a client
wit_client = connection.clients.get_work_item_tracking_client()
patch_document=[]
patch_document.append(_create_work_item_field_patch_operation('add', 'System.Title', a))
patch_document.append(_create_work_item_field_patch_operation('add', 'System.Description', b))
patch_document.append(_create_work_item_field_patch_operation('add', 'System.AreaPath', c))
wit_client.create_work_item(patch_document, "Project", 'Task')
Upvotes: 1