Coder Social home page Coder Social logo

microsoft / azure-devops-python-api Goto Github PK

View Code? Open in Web Editor NEW
544.0 41.0 182.0 5.28 MB

Azure DevOps Python API

Home Page: https://docs.microsoft.com/azure/devops/integrate/index?view=azure-devops

License: MIT License

Python 99.95% Batchfile 0.03% PowerShell 0.01% Shell 0.01%
vsts api azure devops azuredevops python microsoft rest rest-client

azure-devops-python-api's Introduction

Python package Python

Azure DevOps Python API

This repository contains Python APIs for interacting with and managing Azure DevOps. These APIs power the Azure DevOps Extension for Azure CLI. To learn more about the Azure DevOps Extension for Azure CLI, visit the Microsoft/azure-devops-cli-extension repo.

Install

pip install azure-devops

Get started

To use the API, establish a connection using a personal access token and the URL to your Azure DevOps organization. Then get a client from the connection and make API calls.

from azure.devops.connection import Connection
from msrest.authentication import BasicAuthentication
import pprint

# Fill in with your personal access token and org URL
personal_access_token = 'YOURPAT'
organization_url = 'https://dev.azure.com/YOURORG'

# Create a connection to the org
credentials = BasicAuthentication('', personal_access_token)
connection = Connection(base_url=organization_url, creds=credentials)

# Get a client (the "core" client provides access to projects, teams, etc)
core_client = connection.clients.get_core_client()

# Get the first page of projects
get_projects_response = core_client.get_projects()
index = 0
while get_projects_response is not None:
    for project in get_projects_response.value:
        pprint.pprint("[" + str(index) + "] " + project.name)
        index += 1
    if get_projects_response.continuation_token is not None and get_projects_response.continuation_token != "":
        # Get the next page of projects
        get_projects_response = core_client.get_projects(continuation_token=get_projects_response.continuation_token)
    else:
        # All projects have been retrieved
        get_projects_response = None

API documentation

This Python library provides a thin wrapper around the Azure DevOps REST APIs. See the Azure DevOps REST API reference for details on calling different APIs.

Samples

Learn how to call different APIs by viewing the samples in the Microsoft/azure-devops-python-samples repo.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

azure-devops-python-api's People

Contributors

gauravsaralms avatar mariusvniekerk avatar microsoft-github-policy-service[bot] avatar microsoftopensource avatar msftgits avatar nechvatalp avatar sirpownzalot avatar tedchamb avatar tonybaloney avatar vbossica avatar willsmythe avatar wnjenkin avatar zarenner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

azure-devops-python-api's Issues

Wrapper Documentation Quality

The documentation surrounding this wrapper is poor. The example identifies how to list a set of projects and it works. Great! But what other functions exist? The documentation indicates to use the REST API as a guide as the wrapper is "thin". However, the REST API documentation does not match the wrapper organization.

In python, the "get_projects" call happens by:

  1. Establishing a connection
  2. Getting a client with a magic client identifier string ('vsts.core.v4_0.core_client.CoreClient') to indicate "core" as the API section
  3. Calling "get_projects()" through that client.

In the REST API, the call happens by a GET call to "https://dev.azure.com/{organization}/_apis/projects?api-version=5.0-preview.3"
To find this call, one needs to navigate to: core->projects->list

Why is this poor documentation?

  • The use of magic identifiers is not intuitive or documented. One has to grep code to figure out why such a string would be used.
  • "magic string".get_projects() does not intuitively map to either "projects" or core->projects->list. This means that one cannot know how to make a call through the python wrapper by looking at the API documentation.

What can be done about this?

We can display a list of methods on clients using the signature function from inspect:

	for method_name in method_list:
		if not method_name.startswith('_'):
			method = getattr(core_client, method_name)
			print(method_name + str(signature(method)))

This turns up the following:

add_user_agent(user_agent)
create_connected_service(connected_service_creation_data, project_id)
create_identity_mru(mru_data, mru_name)
create_or_update_proxy(proxy)
create_team(team, project_id)
delete_proxy(proxy_url, site=None)
delete_team(project_id, team_id)
get_connected_service_details(project_id, name)
get_connected_services(project_id, kind=None)
get_identity_mru(mru_name)
get_process_by_id(process_id)
get_processes()
get_project(project_id, include_capabilities=None, include_history=None)
get_project_collection(collection_id)
get_project_collections(top=None, skip=None)
get_project_history_entries(min_revision=None)
get_project_properties(project_id, keys=None)
get_projects(state_filter=None, top=None, skip=None, continuation_token=None)
get_proxies(proxy_url=None)
get_team(project_id, team_id)
get_team_members(project_id, team_id, top=None, skip=None)
get_teams(project_id, top=None, skip=None)
queue_create_project(project_to_create)
queue_delete_project(project_id)
set_project_properties(project_id, patch_document)
update_identity_mru(mru_data, mru_name)
update_project(project_update, project_id)
update_team(team_data, project_id, team_id)

OK, great, now we know the actual names of the functions and their parameters as callable. This is good because they differ from those listed in the API documentation.

Now what about all the other magic strings? Where do I find them?

I didn't really know where to find them, so I cloned a copy of the source and dug through it.

grep -R "CoreClient" .

Turns up the following results

./README.md:core_client = connection.get_client('vsts.core.v4_0.core_client.CoreClient')
./vsts/vsts/core/v4_0/core_client.py:class CoreClient(VssClient):
./vsts/vsts/core/v4_0/core_client.py:        super(CoreClient, self).__init__(base_url, creds)
./vsts/vsts/core/v4_1/core_client.py:class CoreClient(VssClient):
./vsts/vsts/core/v4_1/core_client.py:        super(CoreClient, self).__init__(base_url, creds)

OK, so now we know that folders in the vsts/vsts folder match up with the REST API, we also can start to see the pattern: vsts/API_section/API_version/snake_case_api_section_file/PascalCaseAPISectionClass

We can also see a correlation to the magic string: 'vsts.core.v4_0.core_client.CoreClient' is just using dots instead of slashes.

BUT! that was far more work than somebody that wants to use this package should have to go through. There should be a document which automatically gets built on commit which provides an MD of the clients and the functions available in each client. There should also be an explanation of the magic strings and why they are the way they are.

Even something as simple as the following would help:
generate_docs.1.py.zip

How to use GitClientBase.get_commit_diffs method (v4_0)

I'm trying to use GitClientBase.get_commit_diffs method (v4_0) as follows:

diifs=git_client.get_commit_diffs(
    repository_id=repo_id, 
    project=proj_id,
    diff_common_commit=None,
    top=None, 
    skip=None, 
    base_version_descriptor=GitBaseVersionDescriptor(version=src_commit_id), 
    target_version_descriptor=GitTargetVersionDescriptor(version=dst_commit_id)
)

I specify repository_id, project_id and IDs for two commits from the repository. But the method returns something different which looks like a recent commit in the repo.

What I do wrong?

No module named "vsts.core.v4_0.core_client on Azure Automation

Hi,
I am trying to use vsts installed from pip in an Azure Automation python 2 runbook.
The funfact is, msrest is installed on a machine which runs the runbook but vsts is not. So I apply a horrific hack executing
subprocess.call([sys.executable, "-u", "-m", "pip", "install", "vsts", "--no-deps"])
which actually installs this module:
Downloading https://files.pythonhosted.org/packages/8d/f0/97266a8d2f321285829ef13f3236b842e76fd7f58775e4873a99fff8faaf/vsts-0.1.9.tar.gz (819kB)

So far good.

I get to the part of getting the client:

from vsts.vss_connection import VssConnection
from msrest.authentication import BasicTokenAuthentication
vsts_instance = get_config(key="vsts_instance")
vsts_token = get_config(key="VstsAuthToken")
client_version = get_config(key="client_version")
credentials = BasicTokenAuthentication(token={"access_token": vsts_token})
connection = VssConnection(base_url=vsts_instance, creds=credentials)
core_client = connection.get_client(client_type=client_version)

The last line raises the following exception:

ImportError('No module named "vsts.core.v4_0.core_client',)
Traceback (most recent call last):
  File "C:\Temp\eqtl2m0n.xsn\881221a4-9ba3-4c4b-8ba0-61bcced3f6ea", line 112, in <module>
    core_client = connection.get_client(client_type=client_version)
  File "C:\Python27\lib\site-packages\vsts\vss_connection.py", line 34, in get_client
    client_class = self._get_class(client_type)
  File "C:\Python27\lib\site-packages\vsts\vss_connection.py", line 42, in _get_class
    imported = __import__(module_name)
ImportError: No module named "vsts.core.v4_0.core_client

Even funnier thing is, I was able to get past the import magic performed in vss_connection with the very same config parameters while testing on my machine locally (but fail due to authorization, however that's another problem, not this scope).

I am yet to do a recursive printing of the contents of the installed vsts module but I feel something deeper is the issue. Can you throw me some pointers, please?

What should I provide as the team_context ? def get_backlogs(self, team_context):

Hello,

Would be possible to help?. I'm trying to understand where Team Context comes from. For example the function in the vsts-python-api/vsts/vsts/work/v4_1/work_client.py

What should I provide as the team_context ?

def get_backlogs(self, team_context):
"""GetBacklogs.
[Preview API] List all backlog levels
:param :class: <work.v4_1.models.TeamContext> team_context: The team context for the operation
:rtype: [BacklogLevelConfiguration]
"""
Thank you in advance, this is a very nice SDK. @tedchamb , @vbossica

AttributeError: 'TeamContext' object has no attribute 'projectId'

Consider the following cut-down code:

from vsts.work.v4_1.models.team_context import TeamContext
work_client = connection.get_client('vsts.work.v4_1.work_client.WorkClient')

_project_id = <GUID>
_team_id = <GUID>

team = TeamContext(project_id=_project_id, team_id=_team_id)
work_client.get_backlogs(team_context=team)

WorkClient methods (and others) that take a TeamContext class do the following:

if team_context is not None:
    if team_context.projectId:
        project = team_context.project_id

..which results in the AttributeError in title; it should be checking team_context.project_id instead.

Or am I missing something? Cheers!

Get test cases appears to return None

Using test client and the get test cases function, see sample code below. I am always getting None, yet if I manually create the URL with the ids, it appears I get valid results.

        credentials = BasicAuthentication(TEST_TOKEN_USER, TEST_TOKEN_VALUE)
        connection = VssConnection(base_url=TEST_SITE, creds=credentials)
        test_client = connection.get_client('vsts.test.v4_1.test_client.TestClient')

        plans = test_client.get_plans(TEST_PROJECT)
        for plan in plans:
            print(plan.id, plan.name)
            plancounts[plan.name] = 0
            suites = test_client.get_test_suites_for_plan(TEST_PROJECT, plan.id)
            for suite in suites:
                print("\t" + suite.name)
                cases = test_client.get_test_cases(suite.project.id, plan.id, suite.id)

Add support to latest msrest package

I'm getting error when importing the VssConnection, with latest msrest package.

It seems like this change broke it.

They moved the ClientRequest class from the msrest.pipeline module to msrest.universal_http

image

More info:

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-9b33f98d18ad> in <module>()
----> 1 from vsts.vss_connection import VssConnection
      2 # from msrest.authentication import BasicAuthentication
      3 # import pprint
      4 
      5 # Fill in with your personal access token and org URL

/opt/conda/lib/python3.6/site-packages/vsts/vss_connection.py in <module>()
      9 from ._file_cache import RESOURCE_CACHE as RESOURCE_FILE_CACHE
     10 from .exceptions import VstsClientRequestError
---> 11 from .location.v4_0.location_client import LocationClient
     12 from .vss_client_configuration import VssClientConfiguration
     13 

/opt/conda/lib/python3.6/site-packages/vsts/location/v4_0/location_client.py in <module>()
      8 
      9 from msrest import Serializer, Deserializer
---> 10 from ...vss_client import VssClient
     11 from . import models
     12 

/opt/conda/lib/python3.6/site-packages/vsts/vss_client.py in <module>()
     13 from msrest import Deserializer, Serializer
     14 from msrest.exceptions import DeserializationError, SerializationError
---> 15 from msrest.pipeline import ClientRequest
     16 from msrest.service_client import ServiceClient
     17 from .exceptions import VstsAuthenticationError, VstsClientRequestError, VstsServiceError

ImportError: cannot import name 'ClientRequest'

Documentation is non-existent

I attempted to use this for more than a non-trivial case, and it turned out to be extremely difficult due to the lack of documentation. It's possible, but difficult. There are API calls which fail for no apparent reason, and without documentation, I'm left debugging the library code to figure out what went wrong.

get_artifact_content_zip returns metadata rather than contents

As described in the subject.

I've managed to get this to work by cloning the entire method, setting self.config.additional_headers['Accept'] = 'application/zip', adding query_parameters['$format'] = 'zip' and changing the return statement to return response.content. I'd hesitate to call this a solution more than a workaround, but I have no idea what would be a better solution.

GitClientBase.get_changes method returns error (v4.0)

I get error โ€œUnable to deserialize to object: type, AttributeError: type object 'ChangeCountDictionary' has no attribute '_validation'โ€ while using get_changes method of a git client (version 4.0). Everything the rest works well.

GitClient class raises a serialization error when creating a repo

I'm trying to create a repo with the create_repository method in GitClient class. But it raises the following exception. I have tried to follow back the error and it seems to me that it is generated from the serialization.py script when it's trying to serialize the body (line 445 and on). Maybe there is some problem in data_type argument (which is passed from git_client_base.py as content = self._serialize.body(git_repository_to_create, 'GitRepositoryCreateOptions')) consumed by the body serialization method. This is the transcript of the error:

Traceback (most recent call last):
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 1020, in __call__
    found_value = key_extractor(attr, attr_desc, data)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 907, in rest_key_case_insensitive_extractor
    return attribute_key_case_insensitive_extractor(key, None, working_data)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 930, in attribute_key_case_insensitive_extractor
    return data.get(found_key)
AttributeError: 'str' object has no attribute 'get'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 470, in body
    data = deserializer(data_type, data)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 1030, in __call__
    raise_with_traceback(DeserializationError, msg, err)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/exceptions.py", line 45, in raise_with_traceback
    raise error.with_traceback(exc_traceback)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 1020, in __call__
    found_value = key_extractor(attr, attr_desc, data)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 907, in rest_key_case_insensitive_extractor
    return attribute_key_case_insensitive_extractor(key, None, working_data)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 930, in attribute_key_case_insensitive_extractor
    return data.get(found_key)
msrest.exceptions.DeserializationError: Unable to deserialize to object: type, AttributeError: 'str' object has no attribute 'get'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "src/__main__.py", line 71, in <module>
    main()
  File "src/__main__.py", line 67, in main
    _res_repo_creation = vsts.create_git_repo(repo_name)
  File "src/lib/vsts.py", line 25, in create_git_repo
    return self.git_client.create_repository(repo_name, self.project_id)
  File "[omitted]/venv/lib/python3.6/site-packages/vsts/git/v4_1/git_client_base.py", line 2761, in create_repository
    content = self._serialize.body(git_repository_to_create, 'GitRepositoryCreateOptions')
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 473, in body
    SerializationError, "Unable to build a model: "+str(err), err)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/exceptions.py", line 45, in raise_with_traceback
    raise error.with_traceback(exc_traceback)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 470, in body
    data = deserializer(data_type, data)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 1030, in __call__
    raise_with_traceback(DeserializationError, msg, err)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/exceptions.py", line 45, in raise_with_traceback
    raise error.with_traceback(exc_traceback)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 1020, in __call__
    found_value = key_extractor(attr, attr_desc, data)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 907, in rest_key_case_insensitive_extractor
    return attribute_key_case_insensitive_extractor(key, None, working_data)
  File "[omitted]/venv/lib/python3.6/site-packages/msrest/serialization.py", line 930, in attribute_key_case_insensitive_extractor
    return data.get(found_key)
msrest.exceptions.SerializationError: Unable to build a model: Unable to deserialize to object: type, AttributeError: 'str' object has no attribute 'get', DeserializationError: Unable to deserialize to object: type, AttributeError: 'str' object has no attribute 'get'

get_storage_key function is under graph client and should be under identity client?

The get_storage_key function has
location_id='eb85f8cc-f0f6-4264-a5b1-ffe2e4d4801f'
when calling the function via a graph client (where the code is located) it returns a location error
grph_client.get_storage_key(usrDave.descriptor)
ValueError: API resource location eb85f8cc-f0f6-4264-a5b1-ffe2e4d4801f is not registered on https://aiz-alm.visualstudio.com.

-----------------Test w/ each client ------------------------

type(grph_client)
<class 'vsts.graph.v4_1.graph_client.GraphClient'>
type(id_client)
<class 'vsts.identity.v4_1.identity_client.IdentityClient'>

location_id='eb85f8cc-f0f6-4264-a5b1-ffe2e4d4801f'
grph_client._get_resource_location(location_id)

returns None

id_client._get_resource_location(location_id).dict
{'additional_properties': {}, 'id': 'eb85f8cc-f0f6-4264-a5b1-ffe2e4d4801f', 'area': 'Graph', 'resource_name': 'StorageKeys', 'route_template': '_apis/{area}/{resource}/{subjectDescriptor}', 'resource_version': 1, 'min_version': 3.2, 'max_version': 5.0, 'released_version': '0.0'}

ImportError: No module named vss_connection

How to reproduce

  1. I have executed 'pip install vsts' - see [A]
  2. I have written the code to display the projects list [B]
  3. I execute 'python vsts.py'

I am not interested by any other solution such as "run vsts-cli" :-)

An ERROR is generated:

c:\VSTS>python vsts.py
Traceback (most recent call last):
File "vsts.py", line 1, in
from vsts.vss_connection import VssConnection
File "c:\VSTS\vsts.py", line 1, in
from vsts.vss_connection import VssConnection
ImportError: No module named vss_connection

[B] list projects

https://github.com/Microsoft/vsts-python-api

[A] pip install vsts

c:\VSTS>pip install vsts
Requirement already satisfied: vsts in c:\python27\lib\site-packages
Requirement already satisfied: msrest>=0.4.5 in c:\python27\lib\site-packages (from vsts)
Requirement already satisfied: isodate>=0.6.0 in c:\python27\lib\site-packages (from msrest>=0.4.5->vsts)
Requirement already satisfied: requests-oauthlib>=0.5.0 in c:\python27\lib\site-packages (from msrest>=0.4.5->vsts)
Requirement already satisfied: requests~=2.14 in c:\python27\lib\site-packages (from msrest>=0.4.5->vsts)
Requirement already satisfied: certifi>=2017.4.17 in c:\python27\lib\site-packages (from msrest>=0.4.5->vsts)
Requirement already satisfied: enum34>=1.0.4; python_version < "3.4" in c:\python27\lib\site-packages\enum34-1.0.4-py2.7
.egg (from msrest>=0.4.5->vsts)
Requirement already satisfied: six in c:\python27\lib\site-packages (from isodate>=0.6.0->msrest>=0.4.5->vsts)
Requirement already satisfied: oauthlib>=0.6.2 in c:\python27\lib\site-packages (from requests-oauthlib>=0.5.0->msrest>=
0.4.5->vsts)
Requirement already satisfied: idna<2.7,>=2.5 in c:\python27\lib\site-packages (from requests~=2.14->msrest>=0.4.5->vsts
)
Requirement already satisfied: urllib3<1.23,>=1.21.1 in c:\python27\lib\site-packages (from requests~=2.14->msrest>=0.4.
5->vsts)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in c:\python27\lib\site-packages (from requests~=2.14->msrest>=0.4.
5->vsts)

DeserializationError: Cannot deserialize content-type: application/octet-stream

Hi,

I am calling get_attachment_content as below

wiql_results = wit_client.query_by_wiql(wiql, top=1).work_items
if wiql_results:
  work_items = (
    wit_client.get_work_item(int(res.id), expand='Relations') for res in wiql_results
  )
  for work_item in work_items:
    for relation in work_item.relations:
      if relation.rel == 'AttachedFile':
        wit_client.get_attachment_content(relation.url.split('/')[-1])

And getting this error message
Can anybody help?

DeserializationError: Cannot deserialize content-type: application/octet-stream
---------------------------------------------------------------------------
DeserializationError                      Traceback (most recent call last)
<command-586803586106076> in <module>()
     34     for relation in work_item.relations:
     35       if relation.rel == 'AttachedFile':
---> 36         wit_client.get_attachment_content(relation.url.split('/')[-1], file_name='a', download=False)
     37 

/databricks/python/lib/python3.5/site-packages/vsts/work_item_tracking/v4_1/work_item_tracking_client.py in get_attachment_content(self, id, project, file_name, download)
    109                               route_values=route_values,
    110                               query_parameters=query_parameters)
--> 111         return self._deserialize('object', response)
    112 
    113     def get_attachment_zip(self, id, project=None, file_name=None, download=None):

/databricks/python/lib/python3.5/site-packages/msrest/serialization.py in __call__(self, target_obj, response_data, content_type)
   1225         :return: Deserialized object.
   1226         """
-> 1227         data = self._unpack_content(response_data, content_type)
   1228         return self._deserialize(target_obj, data)
   1229 

/databricks/python/lib/python3.5/site-packages/msrest/serialization.py in _unpack_content(raw_data, content_type)
   1375             return RawDeserializer.deserialize_from_http_generics(
   1376                 raw_data.text,
-> 1377                 raw_data.headers
   1378             )
   1379 

/databricks/python/lib/python3.5/site-packages/msrest/pipeline/universal.py in deserialize_from_http_generics(cls, body_bytes, headers)
    210 
    211         if body_bytes:
--> 212             return cls.deserialize_from_text(body_bytes, content_type)
    213         return None
    214 

/databricks/python/lib/python3.5/site-packages/msrest/pipeline/universal.py in deserialize_from_text(cls, data, content_type)
    187                 _LOGGER.critical("Wasn't XML not JSON, failing")
    188                 raise_with_traceback(DeserializationError, "XML is invalid")
--> 189         raise DeserializationError("Cannot deserialize content-type: {}".format(content_type))
    190 
    191     @classmethod

DeserializationError: Cannot deserialize content-type: application/octet-stream

how to get a team's iterations?

Hi, here I want to get a team's iterations using vsts-python-api to make velocity-like chart? But I couldn't find the API... (I am using TFS) Maybe it has been existed.. I guess.

Sample code snippet

Hi ,
Thanks to excellent api.

Provided example - how to get team_projects using basic authentication is good.
But is not enough for beginners.

Could you please provide more code snippets for
--> How to navigate from team project to TestPlan and its test runs
--> How to update test run outcome/results

Basically - we are looking for
--> Find test plan
--> Find latest Test run
--> Update test run results w.r.t Functional Test cases executed in our regression test suite in jenkins ( this is Python Robot selenium Framework for Functional Test case automation )

Please provide documentation/example code snippets or any pointers.

Looking forward for your favorable reply.

Regards,
LnT

Request to add Service Endpoint

I'd like to see the Service Endpoint REST API added to this library (https://docs.microsoft.com/en-us/rest/api/vsts/serviceendpoint/endpoints?view=vsts-rest-4.1). It would help when programmatically creating endpoints.

Could you also explain how the APIs are generated? I'm guessing they're autogenerated from OpenAPI/Swagger definitions. I didn't find anything in the scripts directory that shows how to generate the code. Any pointers there would be helpful.

Thanks,

Brandon Richins

Pip install only contains <0.1.1 beta versions

Hello,

I've been using the 0.1.0b2 of the API, however, as 0.1.1 brings more advanced support for artifacts/file_container I was wondering if it were possible to publish the updated version to pip so that I can easily install it via pip automation.

Thanks!

Exception with get_release method

I am getting below error while trying to get a release.

Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1023, in call
value = self.deserialize_data(raw_value, attr_desc['type'])
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1178, in deserialize_data
obj_type = self.dependencies[data_type]
KeyError: 'number'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/karan/PycharmProjects/vsts-automation/v2/sample.py", line 17, in
release_ = client.get_release(project='myproject',release_id=123)
File "/usr/local/lib/python3.5/dist-packages/vsts/release/v4_1/release_client.py", line 628, in get_release
return self._deserialize('Release', response)
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1023, in call
value = self.deserialize_data(raw_value, attr_desc['type'])
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1176, in deserialize_data
return self.deserialize_type[iter_type](data, data_type[1:-1])
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1203, in deserialize_iter
return [self.deserialize_data(a, iter_type) for a in attr]
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1203, in
return [self.deserialize_data(a, iter_type) for a in attr]
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1187, in deserialize_data
return self(obj_type, data)
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1027, in call
raise_with_traceback(DeserializationError, msg, err)
File "/usr/local/lib/python3.5/dist-packages/msrest/exceptions.py", line 45, in raise_with_traceback
raise error.with_traceback(exc_traceback)
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1023, in call
value = self.deserialize_data(raw_value, attr_desc['type'])
File "/usr/local/lib/python3.5/dist-packages/msrest/serialization.py", line 1178, in deserialize_data
obj_type = self.dependencies[data_type]
msrest.exceptions.DeserializationError: Unable to deserialize to object: type, KeyError: 'number'

Below are the python package version i am trying to use.
pip3 list | grep 'msrest|vsts'
msrest 0.4.28
vsts 0.1.3

Mismatch between TeamContext and query_by_wiql and query_by_wiql

Both WorkItemTrackingClient.query_by_wiql() and WorkItemTrackingClient.query_by_wiql() take in TeamContext as a parameter but are accessing fields that don't exist on TeamContext but similar fields exist. For example instead of team_id which exists on the TeamContext it tries to use teamId. The same is true for project_id. I would submit a PR to fix it but the auto-generation warning at the top of the file scares me away.

How to add Attachment to Test Steps?

I would like to add attachments to some of the steps of my Test Cases like I can do in the Web Interface.

This is how I want my step to look like:

Step with attachment

... and when you run it, that would look like this:
enter image description here

However, I have not been able to find where this information is stored.

This is the JSON data for the WorkItem of my Test Case

{
id: 224,
rev: 2,
fields: {
    System.AreaPath: "GM_sandbox\GM-Toto",
    System.TeamProject: "GM_sandbox",
    System.IterationPath: "GM_sandbox",
    System.WorkItemType: "Test Case",
    System.State: "Design",
    System.Reason: "New",
    System.AssignedTo: "Jeff",
    System.CreatedDate: "2019-01-03T01:43:09.743Z",
    System.CreatedBy: "Jeff",
    System.ChangedDate: "2019-01-03T02:12:07.15Z",
    System.ChangedBy: "Jeff",
    System.Title: "Titi",
    Microsoft.VSTS.Common.StateChangeDate: "2019-01-03T01:43:09.743Z",
    Microsoft.VSTS.Common.ActivatedDate: "2019-01-03T01:43:09.743Z",
    Microsoft.VSTS.Common.ActivatedBy: "Jeff",
    Microsoft.VSTS.Common.Priority: 2,
    Microsoft.VSTS.TCM.AutomationStatus: "Not Automated",
    Microsoft.VSTS.TCM.Steps: "<steps id="0" last="2"><step id="2" type="ValidateStep"><parameterizedString isformatted="true">&lt;DIV&gt;&lt;P&gt;Click on the rainbow button&lt;/P&gt;&lt;/DIV&gt;</parameterizedString><parameterizedString isformatted="true">&lt;P&gt;Screen becomes Blue (see picture)&lt;/P&gt;</parameterizedString><description/></step></steps>"
},
_links: {
    self: {
        href: "https://my_server.com:8443/tfs/PRODUCT/23d89bd4-8547-4be3-aa73-13a30866f176/_apis/wit/workItems/224"
    },
    workItemUpdates: {
        href: "https://my_server.com:8443/tfs/PRODUCT/_apis/wit/workItems/224/updates"
    },
    workItemRevisions: {
        href: "https://my_server.com:8443/tfs/PRODUCT/_apis/wit/workItems/224/revisions"
    },
    workItemHistory: {
        href: "https://my_server.com:8443/tfs/PRODUCT/_apis/wit/workItems/224/history"
    },
    html: {
        href: "https://my_server.com:8443/tfs/PRODUCTi.aspx?pcguid=4107d6a2-eaaa-40b9-9a8d-f8fdbb31d4b7&id=224"
    },
    workItemType: {
        href: "https://my_server.com:8443/tfs/PRODUCT/23d89bd4-8547-4be3-aa73-13a30866f176/_apis/wit/workItemTypes/Test%20Case"
    },
    fields: {
        href: "https://my_server.com:8443/tfs/PRODUCT/23d89bd4-8547-4be3-aa73-13a30866f176/_apis/wit/fields"
    }
},
url: "https://my_server.com:8443/tfs/PRODUCT/23d89bd4-8547-4be3-aa73-13a30866f176/_apis/wit/workItems/224"
}

Any idea on where this information is stored?

And, if possible, could anyone tell me how to add an attachment from a file and link it to the test step?

Thanks a lot

GitClientBase.get_item_text always returns the file metadata

To retrieve the content of a file, it is mandatory to send the 'text/plain' Accept header, otherwise the file metadata is always returned.

There are two issues:

  1. the VSSClient._send hard codes application/json as Accept header
  2. the generated GitClientBase.get_item_text must somehow pass text/plain as Accept header

Example for using the "create_attachment" function?

I have tried using the path to a file as the upload_stream as well as opening the file to use the contents.

Using the path returns an ID and URL but they lead to a null (File does not exist) exception.

Using the contents of the file result in "'utf8' codec can't decode byte 0xff in position 0: invalid start byte".

Class WorkItemExpand is missing

Class WorkItemExpand, referenced in WorkItemTrackingClient is missing from the code base.

But using a str instead of a WorkItemExpand instance works. So either the generated code doesn't contain all the classes, or the generated documentation is misleading.

How does this work?

Hi,

I have tried to use the library but cannot see how. If I do import vsts the module does not seem to contain any methods I can call.
Could you add a small snippet to the readme? Just to get people started. Right now I am writing my own code to communicate with VSTS over RESTful, but would really like to use this library insted.

Thanks

create test run does not populate teststatistics field

2018-07-12 06:55:54.32: root : DEBUG Route template: {project}/_apis/test/{resource}/{runId}
2018-07-12 06:55:54.36: root : DEBUG Api version '4.1'
2018-07-12 06:55:54.38: root : DEBUG POST https://REDACTED/THEPROJECT/_apis/test/Runs
2018-07-12 06:55:54.40: root : DEBUG Request content: {'runStatistics': [{'count': 1, 'state': 'Completed', 'outcome': 'Failed'}], 'isAutomated': True, 'name': 'MyTest'}
2018-07-12 06:55:54.43: msrest.pipeline: DEBUG Configuring request: timeout=100, verify=True, cert=None
2018-07-12 06:55:54.45: msrest.pipeline: DEBUG Configuring proxies: ''
2018-07-12 06:55:54.46: msrest.pipeline: DEBUG Evaluate proxies against ENV settings: True
2018-07-12 06:55:54.49: msrest.pipeline: DEBUG Configuring redirects: allow=True, max=30
2018-07-12 06:55:54.49: msrest.pipeline: DEBUG Configuring retry: max_retries=3, backoff_factor=0.8, max_backoff=90
2018-07-12 06:55:54.59: urllib3.connectionpool: DEBUG Starting new HTTPS connection (1): REDACTED
2018-07-12 06:55:54.361: urllib3.connectionpool: DEBUG https://REDACTED:443 "POST /THEPROJECT/_apis/test/Runs HTTP/1.1" 200 443
2018-07-12 06:55:54.378: root : DEBUG Response content: {"id":74094,"name":"MyTest","url":"https://REDACTED/THEPROJECT/_apis/test/Runs/74094","isAutomated":true,"iteration":"THEPROJECT","owner":{"displayName":null,"id":"00000000-0000-0000-0000-000000000000"},"project":{"id":"493b23e6-f63f-4c56-9c2a-4d09eec371e8","name":"THEPROJECT"},"state":"Unspecified","totalTests":0,"incompleteTests":0,"notApplicableTests":0,"passedTests":0,"unanalyzedTests":0,"revision":2,"webAccessUrl":"https://REDACTED/THEPROJECT/_TestManagement/Runs#runId=74094&_a=runCharts"}
{'comment': None, 'substate': None, 'release_environment_uri': None, 'last_updated_date': None, 'owner': <vsts.test.v4_1.models.identity_ref.IdentityRef object at 0x0516C110>, 'unanalyzed_tests': 0, 'post_process_state': None, 'id': 74094, 'custom_fields': None, 'project': <vsts.test.v4_1.models.shallow_reference.ShallowReference object at 0x0516C310>, 'passed_tests': 0, 'is_automated': True, 'build_configuration': None, 'state': u'Unspecified', 'total_tests': 0, 'additional_properties': {}, 'build': None, 'dtl_environment_creation_details': None, 'due_date': None, 'release_uri': None, 'completed_date': None, 'test_environment': None, 'incomplete_tests': 0, 'last_updated_by': None, 'plan': None, 'phase': None, 'started_date': None, 'run_statistics': None, 'test_message_log_id': None, 'name': u'MyTest', 'drop_location': None, 'dtl_environment': None, 'dtl_aut_environment': None, 'url': u'https://REDACTED/THEPROJECT/_apis/test/Runs/74094', 'test_settings': None, 'error_message': None, 'iteration': u'THEPROJECT', 'controller': None, 'web_access_url': u'https://REDACTED/THEPROJECT/_TestManagement/Runs#runId=74094&_a=runCharts', 'filter': None, 'not_applicable_tests': 0, 'created_date': None, 'release': None, 'revision': 2}

Unable to deserialize to object: type, KeyError: 'DayOfWeek'

All API related calls for team settings (e.g., get_team_settings() and update_team_settings() seem to fail with Unable to deserialize to object: type, KeyError: 'DayOfWeek'.

Client side I am using vsts 0.1.21, and server side I am on Azure DevOps Server 2019 RC1

Here is some sample debug output:

DEBUG:vsts.vss_client:Route template: {project}/{team}/_apis/{area}/{resource}
DEBUG:vsts.vss_client:Api version '4.1'
DEBUG:vsts.vss_client:GET https://devops.acme.com/tfs/Team%20Inheritance%20Test/6fc0f768-5a54-4e35-bfbd-9676efd75e5e/Platform/_apis/work/teamsettings
DEBUG:vsts.vss_client:Request content: None
DEBUG:msrest.universal_http:Configuring redirects: allow=True, max=30
DEBUG:msrest.universal_http:Configuring request: timeout=100, verify=True, cert=None
DEBUG:msrest.universal_http:Configuring proxies: ''
DEBUG:msrest.universal_http:Evaluate proxies against ENV settings: True
DEBUG:urllib3.connectionpool:https://devops.acme.com:443 "GET /tfs/Team%20Inheritance%20Test/6fc0f768-5a54-4e35-bfbd-9676efd75e5e/Platform/_apis/work/teamsettings HTTP/1.1" 200 564
DEBUG:vsts.vss_client:Response content: b'{"backlogIteration":{"id":"00000000-0000-0000-0000-000000000000"},"bugsBehavior":"asTasks","workingDays":["monday","tuesday","wednesday","thursday","friday"],"backlogVisibilities":{"Microsoft.FeatureCategory":true,"Microsoft.EpicCategory":false,"Microsoft.RequirementCategory":true},"defaultIteration":null,"defaultIterationMacro":"@currentIteration","url":"https://devops.acme.com/tfs/Team Inheritance Test/6fc0f768-5a54-4e35-bfbd-9676efd75e5e/b54a7d18-6edb-44b8-9771-d931faeb5c86/_apis/work/teamsettings","_links":{"self":{"href":"https://devops.soroco.com/tfs/Team Inheritance Test/6fc0f768-5a54-4e35-bfbd-9676efd75e5e/b54a7d18-6edb-44b8-9771-d931faeb5c86/_apis/work/teamsettings"},"project":{"href":"https://devops.soroco.com/tfs/Team Inheritance Test/_apis/projects/6fc0f768-5a54-4e35-bfbd-9676efd75e5e"},"team":{"href":"https://devops.soroco.com/tfs/Team Inheritance Test/_apis/projects/6fc0f768-5a54-4e35-bfbd-9676efd75e5e/teams/b54a7d18-6edb-44b8-9771-d931faeb5c86"},"teamIterations":{"href":"https://devops.soroco.com/tfs/Team Inheritance Test/6fc0f768-5a54-4e35-bfbd-9676efd75e5e/b54a7d18-6edb-44b8-9771-d931faeb5c86/_apis/work/teamsettings/iterations"},"teamFieldValues":{"href":"https://devops.soroco.com/tfs/Team Inheritance Test/6fc0f768-5a54-4e35-bfbd-9676efd75e5e/b54a7d18-6edb-44b8-9771-d931faeb5c86/_apis/work/teamsettings/teamfieldvalues"}}}'
DEBUG:msrest.exceptions:Unable to deserialize to object: type, KeyError: 'DayOfWeek'
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
c:\python36\lib\site-packages\msrest\serialization.py in _deserialize(self, target_obj, data)
   1293 
-> 1294                 value = self.deserialize_data(raw_value, attr_desc['type'])
   1295                 d_attrs[attr] = value

c:\python36\lib\site-packages\msrest\serialization.py in deserialize_data(self, data, data_type)
   1446             if iter_type in self.deserialize_type:
-> 1447                 return self.deserialize_type[iter_type](data, data_type[1:-1])
   1448 

c:\python36\lib\site-packages\msrest\serialization.py in deserialize_iter(self, attr, iter_type)
   1477             ))
-> 1478         return [self.deserialize_data(a, iter_type) for a in attr]
   1479 

c:\python36\lib\site-packages\msrest\serialization.py in <listcomp>(.0)
   1477             ))
-> 1478         return [self.deserialize_data(a, iter_type) for a in attr]
   1479 

c:\python36\lib\site-packages\msrest\serialization.py in deserialize_data(self, data, data_type)
   1448 
-> 1449             obj_type = self.dependencies[data_type]
   1450             if issubclass(obj_type, Enum):

KeyError: 'DayOfWeek'

During handling of the above exception, another exception occurred:

DeserializationError                      Traceback (most recent call last)
<ipython-input-16-6b5197c3a80a> in <module>
----> 1 work_client.get_team_settings(TeamContext(project_id=project_id, team="Platform"))

c:\python36\lib\site-packages\vsts\work\v4_1\work_client.py in get_team_settings(self, team_context)
   1307                               version='4.1',
   1308                               route_values=route_values)
-> 1309         return self._deserialize('TeamSetting', response)
   1310 
   1311     def update_team_settings(self, team_settings_patch, team_context):

c:\python36\lib\site-packages\msrest\serialization.py in __call__(self, target_obj, response_data, content_type)
   1226         """
   1227         data = self._unpack_content(response_data, content_type)
-> 1228         return self._deserialize(target_obj, data)
   1229 
   1230     def _deserialize(self, target_obj, data):

c:\python36\lib\site-packages\msrest\serialization.py in _deserialize(self, target_obj, data)
   1296         except (AttributeError, TypeError, KeyError) as err:
   1297             msg = "Unable to deserialize to object: " + class_name
-> 1298             raise_with_traceback(DeserializationError, msg, err)
   1299         else:
   1300             additional_properties = self._build_additional_properties(attributes, data)

c:\python36\lib\site-packages\msrest\exceptions.py in raise_with_traceback(exception, message, *args, **kwargs)
     49     error = exception(exc_msg, *args, **kwargs)
     50     try:
---> 51         raise error.with_traceback(exc_traceback)
     52     except AttributeError:
     53         error.__traceback__ = exc_traceback

c:\python36\lib\site-packages\msrest\serialization.py in _deserialize(self, target_obj, data)
   1292                         raw_value = found_value
   1293 
-> 1294                 value = self.deserialize_data(raw_value, attr_desc['type'])
   1295                 d_attrs[attr] = value
   1296         except (AttributeError, TypeError, KeyError) as err:

c:\python36\lib\site-packages\msrest\serialization.py in deserialize_data(self, data, data_type)
   1445             iter_type = data_type[0] + data_type[-1]
   1446             if iter_type in self.deserialize_type:
-> 1447                 return self.deserialize_type[iter_type](data, data_type[1:-1])
   1448 
   1449             obj_type = self.dependencies[data_type]

c:\python36\lib\site-packages\msrest\serialization.py in deserialize_iter(self, attr, iter_type)
   1476                 type(attr)
   1477             ))
-> 1478         return [self.deserialize_data(a, iter_type) for a in attr]
   1479 
   1480     def deserialize_dict(self, attr, dict_type):

c:\python36\lib\site-packages\msrest\serialization.py in <listcomp>(.0)
   1476                 type(attr)
   1477             ))
-> 1478         return [self.deserialize_data(a, iter_type) for a in attr]
   1479 
   1480     def deserialize_dict(self, attr, dict_type):

c:\python36\lib\site-packages\msrest\serialization.py in deserialize_data(self, data, data_type)
   1447                 return self.deserialize_type[iter_type](data, data_type[1:-1])
   1448 
-> 1449             obj_type = self.dependencies[data_type]
   1450             if issubclass(obj_type, Enum):
   1451                 if isinstance(data, ET.Element):

DeserializationError: Unable to deserialize to object: type, KeyError: 'DayOfWeek'

Not able to create relationships between work items

I am trying to create relationships between work items using the work item client API. This relationship seems to be tracked as a high-level /relations property path. I can't seem to find support for setting these relationships in the API. If I try to force it via a JsonPatchOperation I get:

VstsServiceError: Work item patch does not support patching the top level property at path /relations.

How can I create relations via the API?

Connecting to team instance using PAT gives error

Running following code:

team_instance='https://devdiv.visualstudio.com'
credentials = BasicTokenAuthentication(vsts_pat)
connection = VssConnection(base_url=team_instance, creds=credentials)
core_client =  #connection.get_client('vsts.core.v4_0.core_client.CoreClient')

Gives following error:


TypeError Traceback (most recent call last)
/anaconda/envs/py35/lib/python3.5/site-packages/msrest/service_client.py in send(self, request, headers, content, **config)
234 try:
--> 235 session = self.creds.signed_session(self._session)
236 except TypeError: # Credentials does not support session injection

/anaconda/envs/py35/lib/python3.5/site-packages/msrest/authentication.py in signed_session(self, session)
110 session = super(BasicTokenAuthentication, self).signed_session(session)
--> 111 header = "{} {}".format(self.scheme, self.token['access_token'])
112 session.headers['Authorization'] = header

TypeError: string indices must be integers

During handling of the above exception, another exception occurred:

TypeError Traceback (most recent call last)
in ()
5 credentials = BasicTokenAuthentication(vsts_pat)
6 connection = VssConnection(base_url=team_instance, creds=credentials)
----> 7 core_client = connection.get_client('vsts.core.v4_1.core_client.CoreClient')

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/vss_connection.py in get_client(self, client_type)
33 if client_type not in self._client_cache:
34 client_class = self._get_class(client_type)
---> 35 self._client_cache[client_type] = self._get_client_instance(client_class)
36 return self._client_cache[client_type]
37

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/vss_connection.py in _get_client_instance(self, client_class)
46
47 def _get_client_instance(self, client_class):
---> 48 url = self._get_url_for_client_instance(client_class)
49 client = client_class(url, self._creds)
50 client.add_user_agent(self._addition_user_agent)

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/vss_connection.py in _get_url_for_client_instance(self, client_class)
56 return self.base_url
57 else:
---> 58 resource_areas = self._get_resource_areas()
59 if resource_areas is None:
60 raise VstsClientRequestError(('Failed to retrieve resource areas '

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/vss_connection.py in _get_resource_areas(self, force)
86 elif not force:
87 logging.debug('File cache miss for resources on: %s', location_client.normalized_url)
---> 88 self._resource_areas = location_client.get_resource_areas()
89 if self._resource_areas is None:
90 # For OnPrem environments we get an empty collection wrapper.

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/location/v4_0/location_client.py in get_resource_areas(self)
70 location_id='e81700f7-3be2-46de-8624-2eb35882fcaa',
71 version='4.0-preview.1',
---> 72 returns_collection=True)
73 return self._deserialize('[ResourceAreaInfo]', response)
74

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/vss_client.py in _send(self, http_method, location_id, version, route_values, query_parameters, content, media_type, returns_collection)
66 location_id=location_id,
67 route_values=route_values,
---> 68 query_parameters=query_parameters)
69 negotiated_version = self._negotiate_request_version(
70 self._get_resource_location(location_id),

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/vss_client.py in _create_request_message(self, http_method, location_id, route_values, query_parameters)
103 def _create_request_message(self, http_method, location_id, route_values=None,
104 query_parameters=None):
--> 105 location = self._get_resource_location(location_id)
106 if location is None:
107 raise ValueError('API resource location ' + location_id + ' is not registered on '

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/vss_client.py in _get_resource_location(self, location_id)
135 def _get_resource_location(self, location_id):
136 if self.config.base_url not in VssClient._locations_cache:
--> 137 VssClient._locations_cache[self.config.base_url] = self._get_resource_locations(all_host_types=False)
138 for location in VssClient._locations_cache[self.config.base_url]:
139 if location.id == location_id:

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/vss_client.py in _get_resource_locations(self, all_host_types)
171 if self._suppress_fedauth_redirect:
172 headers['X-TFS-FedAuthRedirect'] = 'Suppress'
--> 173 response = self._send_request(request, headers=headers)
174 wrapper = self._base_deserialize('VssJsonCollectionWrapper', response)
175 if wrapper is None:

/anaconda/envs/py35/lib/python3.5/site-packages/vsts/vss_client.py in _send_request(self, request, headers, content, **operation_config)
54 logging.debug('Request content: %s', content)
55 response = self._client.send(request=request, headers=headers,
---> 56 content=content, **operation_config)
57 logging.debug('Response content: %s', response.content)
58 if response.status_code < 200 or response.status_code >= 300:

/anaconda/envs/py35/lib/python3.5/site-packages/msrest/service_client.py in send(self, request, headers, content, **config)
235 session = self.creds.signed_session(self._session)
236 except TypeError: # Credentials does not support session injection
--> 237 session = self.creds.signed_session()
238 if self._session is not None:
239 _LOGGER.warning("Your credentials class does not support session injection. Performance will not be at the maximum.")

/anaconda/envs/py35/lib/python3.5/site-packages/msrest/authentication.py in signed_session(self, session)
109 """
110 session = super(BasicTokenAuthentication, self).signed_session(session)
--> 111 header = "{} {}".format(self.scheme, self.token['access_token'])
112 session.headers['Authorization'] = header
113 return session

TypeError: string indices must be integers

get_client breaks when using new msrest v0.6.3 as a dependency.

With msrest v0.6.3 it breaks as follows.

The following code used to work with v0.6.2:

    credentials = BasicAuthentication('', personal_access_token)
    connection = VssConnection(base_url=organization_url, creds=credentials)
    git_client = connection.get_client('vsts.git.v4_1.git_client.GitClient')

Now with msrest v0.6.3 the third line throws this exception:

Traceback (most recent call last):
- File "/var/task/lambda_function.py", line 31, in go
- git_client = connection.get_client('vsts.git.v4_1.git_client.GitClient')
- File "/opt/lib/vsts/vss_connection.py", line 37, in get_client
- self._client_cache[client_type] = self._get_client_instance(client_class)
- File "/opt/lib/vsts/vss_connection.py", line 50, in _get_client_instance
- url = self._get_url_for_client_instance(client_class)
- File "/opt/lib/vsts/vss_connection.py", line 60, in _get_url_for_client_instance
- resource_areas = self._get_resource_areas()
- File "/opt/lib/vsts/vss_connection.py", line 90, in _get_resource_areas
- self._resource_areas = location_client.get_resource_areas()
- File "/opt/lib/vsts/location/v4_0/location_client.py", line 71, in get_resource_areas
- version='4.0-preview.1')
- File "/opt/lib/vsts/vss_client.py", line 71, in _send
- query_parameters=query_parameters)
- File "/opt/lib/vsts/vss_client.py", line 110, in _create_request_message
- location = self._get_resource_location(location_id)
- File "/opt/lib/vsts/vss_client.py", line 140, in _get_resource_location
- VssClient._locations_cache[self.config.base_url] = self._get_resource_locations(all_host_types=False)
- File "/opt/lib/vsts/vss_client.py", line 176, in _get_resource_locations
- response = self._send_request(request, headers=headers)
- File "/opt/lib/vsts/vss_client.py", line 63, in _send_request
- self._handle_error(request, response)
- File "/opt/lib/vsts/vss_client.py", line 238, in _handle_error
- raise VstsServiceError(wrapped_exception)
vsts.exceptions.VstsServiceError: TF400813: The user '' is not authorized to access this resource.

I am installing packages using pip, with a requirements.txt file with just one line:

vsts

Workaround: Change requirements.txt file to the following:

msrest==0.6.2
vsts

Work module not found

Hello, I have a VssConnection and I have been able to get most clients from it except I am having trouble with the work client. I'm using the following code to get the client:
work_client = connection.get_client('vsts.work.v4_0.work_client.WorkClient')

And the error I'm getting is:
ModuleNotFoundError: No module named 'vsts.work'

Can you please tell me how to initialize a work client?

Proxy support

I am behind a proxy and so far have not been able to figure out how proxy details can be defined. Can you please give me an example of how to define proxy setting and proxy certificate?

update_release_definition wiping queue details

I am trying to clone an environment, apparently the queue details are getting wiped off when i perform a release definition update.

I tried just getting the release definition and performing an update without modifying the object, its wiping off the queue details.

image

Could you please help.

I am using 0.1.4 vsts and below the client class

client = get_connection(team_collection).get_client('vsts.release.v4_1.release_client.ReleaseClient')

Creation of new release definition fails when a release trigger is defined.

When creating a new release definition which contains a release trigger (no matter which type), the process fails with the following error:

vsts.exceptions.VstsServiceError: Invalid data is passed for artifact source trigger object.

Trigger definition:

"triggers": [
        {
            "artifactAlias": "_CI",
            "triggerConditions": [],
            "triggerType": 1
        }
    ]

It seems only the trigger type is being passed to the VSTS REST API and other properties are being stripped out.

When removing the trigger definition from the new release definition, the creation works successfully.

Function `query_test_runs` limited to a time range of 7 days

I am exploring the different ways to retrieve Test Results and I tried the function query_test_runs.

Is it normal that the delta between start and end date is limited to 7 days.

In my case, I had the following code:

from datetime import datetime, timedelta
from vsts.vss_connection import VssConnection
...
test_client = connection.get_client("vsts.test.v4_1.test_client.TestClient")

end_date = datetime.today()
start_date = end_date - timedelta(days=8)
plan_ids = [functional_tp]
for run in test_client.query_test_runs(my_project, start_date, end_date):
    for res in test_client.get_test_results(my_project, run.id):
        tc = res.test_case

which returned the following Traceback:

Traceback (most recent call last):
  File "c:\SVN\Scripts\Playground\TFS\test_TFS.py", line 93, in <module>
    for run in test_client.query_test_runs(my_project, start_date, end_date):
  File "C:\Python36\lib\site-packages\vsts\test\v4_1\test_client.py", line 1608, in query_test_runs
    returns_collection=True)
  File "C:\Python36\lib\site-packages\vsts\vss_client.py", line 96, in _send
    response = self._send_request(request=request, headers=headers, content=content)
  File "C:\Python36\lib\site-packages\vsts\vss_client.py", line 63, in _send_request
    self._handle_error(request, response)
  File "C:\Python36\lib\site-packages\vsts\vss_client.py", line 243, in _handle_error
    raise VstsServiceError(wrapped_exception)
vsts.exceptions.VstsServiceError: Date Range should be within 7 days

Documentation for adding a task (and subtasks) to VSTS

Nice work on the new library! I've been able to install and run it successfully. Now I'm jsut scratching my head wondering how to actually add tasks in VSTS using this. Will you be adding documentation on this soon? Would I be able to get a hint (I tried searching through the source code but got lost with over 200 hits to the phrase 'task')?

get_pull_request_iteration_changes only return change_tracking_id

I try to use get_pull_request_iteration_changes to get files that are change in this iteration as shown here.

I copy and paste the desired output from the documentation below.
{
"changeEntries": [
{
"changeTrackingId": 1,
"changeId": 1,
"item": {
"objectId": "e21e56d119ae81fb4ffebc4fefc6351f5b5ef888",
"path": "/new_feature.cpp"
},
"changeType": "add"
},
{
"changeTrackingId": 2,
"changeId": 2,
"item": {
"objectId": "5ec0f71ffb8b47bd4c0117f624647963e021f3d2",
"path": "/new_feature.h"
},
"changeType": "add"
}
]
}

However, when I use get_pull_request_iteration_changes, I can only see changeTrackingId. I wonder if what is the proper way to get above schema, particular the path of the item.

client.get_pull_request_iteration_changes(repo_id, pull_request_id, 2, compare_to=1).as_dict()
{'change_entries': [{'change_tracking_id': 1}, {'change_tracking_id': 4}]}

How approve a pending release?

Hi,

I'm trying making a simple approve with my code, but isn't working.

(...)
client.update_release_approval(approval='{ "status": "approved", "comments": "Good to go!"}', project="projectX", approval_id=3321)

I believe that my approval is wrong, how I create than?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.