0

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.

asked Oct 13, 2020 at 22:58
1
  • 1
    It might be quicker to use a tool like WireShark or Netmon to see the difference between calling it with postman vs calling it with python. Commented Oct 13, 2020 at 23:22

1 Answer 1

1

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')
answered Oct 14, 2020 at 4:52
Sign up to request clarification or add additional context in comments.

1 Comment

Yea, you're right. All i had to do was to pass the bloody auth parameter in the request.post method and not header. Thanks a ton. I wasted a lot of time on this.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.