Skip to content

add support for returning continuationToken for methods using IPagedList pattern #258

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@

# Shell scripts
*.sh eol=lf

# Python
*.py eol=lf
20 changes: 15 additions & 5 deletions azure-devops/azure/devops/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,23 +124,26 @@ def _create_request_message(self, http_method, location_id, route_values=None,
route_values = {}
route_values['area'] = location.area
route_values['resource'] = location.resource_name
url = self._transform_route_template(location.route_template, route_values)
route_template = self._remove_optional_route_parameters(location.route_template,
route_values)
logger.debug('Route template: %s', location.route_template)
url = self._client.format_url(route_template, **route_values)
import pprint
pprint.pprint("url=" + url)
request = ClientRequest(method=http_method, url=self._client.format_url(url))
if query_parameters:
request.format_parameters(query_parameters)
return request

@staticmethod
def _transform_route_template(route_template, route_values):
def _remove_optional_route_parameters(route_template, route_values):
new_template = ''
route_template = route_template.replace('{*', '{')
for path_segment in route_template.split('/'):
if (len(path_segment) <= 2 or not path_segment[0] == '{'
or not path_segment[len(path_segment) - 1] == '}'):
or not path_segment[len(path_segment) - 1] == '}'
or path_segment[1:len(path_segment) - 1] in route_values):
new_template = new_template + '/' + path_segment
elif path_segment[1:len(path_segment) - 1] in route_values:
new_template = new_template + '/' + route_values[path_segment[1:len(path_segment) - 1]]
return new_template

def _get_resource_location(self, location_id):
Expand Down Expand Up @@ -270,11 +273,18 @@ def _handle_error(self, request, response):
raise AzureDevOpsClientRequestError(full_message_format.format(error_message=error_message,
status_code=response.status_code))

def _get_continuation_token(self, response):
if self._continuation_token_header_key in response.headers:
return response.headers[self._continuation_token_header_key]
else:
return None

@staticmethod
def _normalize_url(url):
return url.rstrip('/').lower()

_locations_cache = {}
_continuation_token_header_key = 'X-MS-ContinuationToken'
_session_header_key = 'X-TFS-Session'
_session_data = {_session_header_key: str(uuid.uuid4())}

Expand Down
57 changes: 51 additions & 6 deletions azure-devops/azure/devops/released/build/build_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def get_builds(self, project, definitions=None, queues=None, build_number=None,
:param [int] build_ids: A comma-delimited list that specifies the IDs of builds to retrieve.
:param str repository_id: If specified, filters to builds that built from this repository.
:param str repository_type: If specified, filters to builds that built from repositories of this type.
:rtype: [Build]
:rtype: :class:`<GetBuildsResponseValue>`
"""
route_values = {}
if project is not None:
Expand Down Expand Up @@ -268,7 +268,22 @@ def get_builds(self, project, definitions=None, queues=None, build_number=None,
version='5.1',
route_values=route_values,
query_parameters=query_parameters)
return self._deserialize('[Build]', self._unwrap_collection(response))
response_value = self._deserialize('[Build]', self._unwrap_collection(response))
continuation_token = self._get_continuation_token(response)
return self.GetBuildsResponseValue(response_value, continuation_token)

class GetBuildsResponseValue(object):
def __init__(self, value, continuation_token):
"""
Response for the get_builds method

:param value:
:type value: :class:`<[Build]> <azure.devops.v5_1.build.models.[Build]>`
:param continuation_token: The continuation token to be used to get the next page of results.
:type continuation_token: str
"""
self.value = value
self.continuation_token = continuation_token

def queue_build(self, build, project, ignore_warnings=None, check_in_ticket=None, source_build_id=None):
"""QueueBuild.
Expand Down Expand Up @@ -351,7 +366,7 @@ def get_build_changes(self, project, build_id, continuation_token=None, top=None
:param str continuation_token:
:param int top: The maximum number of changes to return
:param bool include_source_change:
:rtype: [Change]
:rtype: :class:`<GetBuildChangesResponseValue>`
"""
route_values = {}
if project is not None:
Expand All @@ -370,7 +385,22 @@ def get_build_changes(self, project, build_id, continuation_token=None, top=None
version='5.1',
route_values=route_values,
query_parameters=query_parameters)
return self._deserialize('[Change]', self._unwrap_collection(response))
response_value = self._deserialize('[Change]', self._unwrap_collection(response))
continuation_token = self._get_continuation_token(response)
return self.GetBuildChangesResponseValue(response_value, continuation_token)

class GetBuildChangesResponseValue(object):
def __init__(self, value, continuation_token):
"""
Response for the get_build_changes method

:param value:
:type value: :class:`<[Change]> <azure.devops.v5_1.build.models.[Change]>`
:param continuation_token: The continuation token to be used to get the next page of results.
:type continuation_token: str
"""
self.value = value
self.continuation_token = continuation_token

def get_build_controller(self, controller_id):
"""GetBuildController.
Expand Down Expand Up @@ -497,7 +527,7 @@ def get_definitions(self, project, name=None, repository_id=None, repository_typ
:param str task_id_filter: If specified, filters to definitions that use the specified task.
:param int process_type: If specified, filters to definitions with the given process type.
:param str yaml_filename: If specified, filters to YAML definitions that match the given filename.
:rtype: [BuildDefinitionReference]
:rtype: :class:`<GetDefinitionsResponseValue>`
"""
route_values = {}
if project is not None:
Expand Down Expand Up @@ -541,7 +571,22 @@ def get_definitions(self, project, name=None, repository_id=None, repository_typ
version='5.1',
route_values=route_values,
query_parameters=query_parameters)
return self._deserialize('[BuildDefinitionReference]', self._unwrap_collection(response))
response_value = self._deserialize('[BuildDefinitionReference]', self._unwrap_collection(response))
continuation_token = self._get_continuation_token(response)
return self.GetDefinitionsResponseValue(response_value, continuation_token)

class GetDefinitionsResponseValue(object):
def __init__(self, value, continuation_token):
"""
Response for the get_definitions method

:param value:
:type value: :class:`<[BuildDefinitionReference]> <azure.devops.v5_1.build.models.[BuildDefinitionReference]>`
:param continuation_token: The continuation token to be used to get the next page of results.
:type continuation_token: str
"""
self.value = value
self.continuation_token = continuation_token

def restore_definition(self, project, definition_id, deleted):
"""RestoreDefinition.
Expand Down
19 changes: 17 additions & 2 deletions azure-devops/azure/devops/released/core/core_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def get_projects(self, state_filter=None, top=None, skip=None, continuation_toke
:param int skip:
:param str continuation_token:
:param bool get_default_team_image_url:
:rtype: [TeamProjectReference]
:rtype: :class:`<GetProjectsResponseValue>`
"""
query_parameters = {}
if state_filter is not None:
Expand All @@ -157,7 +157,22 @@ def get_projects(self, state_filter=None, top=None, skip=None, continuation_toke
location_id='603fe2ac-9723-48b9-88ad-09305aa6c6e1',
version='5.1',
query_parameters=query_parameters)
return self._deserialize('[TeamProjectReference]', self._unwrap_collection(response))
response_value = self._deserialize('[TeamProjectReference]', self._unwrap_collection(response))
continuation_token = self._get_continuation_token(response)
return self.GetProjectsResponseValue(response_value, continuation_token)

class GetProjectsResponseValue(object):
def __init__(self, value, continuation_token):
"""
Response for the get_projects method

:param value:
:type value: :class:`<[TeamProjectReference]> <azure.devops.v5_1.core.models.[TeamProjectReference]>`
:param continuation_token: The continuation token to be used to get the next page of results.
:type continuation_token: str
"""
self.value = value
self.continuation_token = continuation_token

def queue_create_project(self, project_to_create):
"""QueueCreateProject.
Expand Down
58 changes: 51 additions & 7 deletions azure-devops/azure/devops/released/git/git_client_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -781,13 +781,15 @@ def get_pull_request_iteration_commits(self, repository_id, pull_request_id, ite
query_parameters=query_parameters)
return self._deserialize('[GitCommitRef]', self._unwrap_collection(response))

def get_pull_request_commits(self, repository_id, pull_request_id, project=None):
def get_pull_request_commits(self, repository_id, pull_request_id, project=None, top=None, continuation_token=None):
"""GetPullRequestCommits.
Get the commits for the specified pull request.
:param str repository_id: ID or name of the repository.
:param int pull_request_id: ID of the pull request.
:param str project: Project ID or project name
:rtype: [GitCommitRef]
:param int top: Maximum number of commits to return.
:param str continuation_token: The continuation token used for pagination.
:rtype: :class:`<GetPullRequestCommitsResponseValue>`
"""
route_values = {}
if project is not None:
Expand All @@ -796,11 +798,32 @@ def get_pull_request_commits(self, repository_id, pull_request_id, project=None)
route_values['repositoryId'] = self._serialize.url('repository_id', repository_id, 'str')
if pull_request_id is not None:
route_values['pullRequestId'] = self._serialize.url('pull_request_id', pull_request_id, 'int')
query_parameters = {}
if top is not None:
query_parameters['$top'] = self._serialize.query('top', top, 'int')
if continuation_token is not None:
query_parameters['continuationToken'] = self._serialize.query('continuation_token', continuation_token, 'str')
response = self._send(http_method='GET',
location_id='52823034-34a8-4576-922c-8d8b77e9e4c4',
version='5.1',
route_values=route_values)
return self._deserialize('[GitCommitRef]', self._unwrap_collection(response))
route_values=route_values,
query_parameters=query_parameters)
response_value = self._deserialize('[GitCommitRef]', self._unwrap_collection(response))
continuation_token = self._get_continuation_token(response)
return self.GetPullRequestCommitsResponseValue(response_value, continuation_token)

class GetPullRequestCommitsResponseValue(object):
def __init__(self, value, continuation_token):
"""
Response for the get_pull_request_commits method

:param value:
:type value: :class:`<[GitCommitRef]> <azure.devops.v5_1.git.models.[GitCommitRef]>`
:param continuation_token: The continuation token to be used to get the next page of results.
:type continuation_token: str
"""
self.value = value
self.continuation_token = continuation_token

def get_pull_request_iteration_changes(self, repository_id, pull_request_id, iteration_id, project=None, top=None, skip=None, compare_to=None):
"""GetPullRequestIterationChanges.
Expand Down Expand Up @@ -1601,7 +1624,7 @@ def get_pushes(self, repository_id, project=None, skip=None, top=None, search_cr
query_parameters=query_parameters)
return self._deserialize('[GitPush]', self._unwrap_collection(response))

def get_refs(self, repository_id, project=None, filter=None, include_links=None, include_statuses=None, include_my_branches=None, latest_statuses_only=None, peel_tags=None, filter_contains=None):
def get_refs(self, repository_id, project=None, filter=None, include_links=None, include_statuses=None, include_my_branches=None, latest_statuses_only=None, peel_tags=None, filter_contains=None, top=None, continuation_token=None):
"""GetRefs.
Queries the provided repository for its refs and returns them.
:param str repository_id: The name or ID of the repository.
Expand All @@ -1613,7 +1636,9 @@ def get_refs(self, repository_id, project=None, filter=None, include_links=None,
:param bool latest_statuses_only: [optional] True to include only the tip commit status for each ref. This option requires `includeStatuses` to be true. The default value is false.
:param bool peel_tags: [optional] Annotated tags will populate the PeeledObjectId property. default is false.
:param str filter_contains: [optional] A filter to apply to the refs (contains).
:rtype: [GitRef]
:param int top: [optional] Maximum number of refs to return. It cannot be bigger than 1000. If it is not provided but continuationToken is, top will default to 100.
:param str continuation_token: The continuation token used for pagination.
:rtype: :class:`<GetRefsResponseValue>`
"""
route_values = {}
if project is not None:
Expand All @@ -1635,12 +1660,31 @@ def get_refs(self, repository_id, project=None, filter=None, include_links=None,
query_parameters['peelTags'] = self._serialize.query('peel_tags', peel_tags, 'bool')
if filter_contains is not None:
query_parameters['filterContains'] = self._serialize.query('filter_contains', filter_contains, 'str')
if top is not None:
query_parameters['$top'] = self._serialize.query('top', top, 'int')
if continuation_token is not None:
query_parameters['continuationToken'] = self._serialize.query('continuation_token', continuation_token, 'str')
response = self._send(http_method='GET',
location_id='2d874a60-a811-4f62-9c9f-963a6ea0a55b',
version='5.1',
route_values=route_values,
query_parameters=query_parameters)
return self._deserialize('[GitRef]', self._unwrap_collection(response))
response_value = self._deserialize('[GitRef]', self._unwrap_collection(response))
continuation_token = self._get_continuation_token(response)
return self.GetRefsResponseValue(response_value, continuation_token)

class GetRefsResponseValue(object):
def __init__(self, value, continuation_token):
"""
Response for the get_refs method

:param value:
:type value: :class:`<[GitRef]> <azure.devops.v5_1.git.models.[GitRef]>`
:param continuation_token: The continuation token to be used to get the next page of results.
:type continuation_token: str
"""
self.value = value
self.continuation_token = continuation_token

def update_ref(self, new_ref_info, repository_id, filter, project=None, project_id=None):
"""UpdateRef.
Expand Down
27 changes: 24 additions & 3 deletions azure-devops/azure/devops/released/policy/policy_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,28 +80,49 @@ def get_policy_configuration(self, project, configuration_id):
route_values=route_values)
return self._deserialize('PolicyConfiguration', response)

def get_policy_configurations(self, project, scope=None, policy_type=None):
def get_policy_configurations(self, project, scope=None, top=None, continuation_token=None, policy_type=None):
"""GetPolicyConfigurations.
Get a list of policy configurations in a project.
:param str project: Project ID or project name
:param str scope: [Provided for legacy reasons] The scope on which a subset of policies is defined.
:param int top: Maximum number of policies to return.
:param str continuation_token: The continuation token used for pagination.
:param str policy_type: Filter returned policies to only this type
:rtype: [PolicyConfiguration]
:rtype: :class:`<GetPolicyConfigurationsResponseValue>`
"""
route_values = {}
if project is not None:
route_values['project'] = self._serialize.url('project', project, 'str')
query_parameters = {}
if scope is not None:
query_parameters['scope'] = self._serialize.query('scope', scope, 'str')
if top is not None:
query_parameters['$top'] = self._serialize.query('top', top, 'int')
if continuation_token is not None:
query_parameters['continuationToken'] = self._serialize.query('continuation_token', continuation_token, 'str')
if policy_type is not None:
query_parameters['policyType'] = self._serialize.query('policy_type', policy_type, 'str')
response = self._send(http_method='GET',
location_id='dad91cbe-d183-45f8-9c6e-9c1164472121',
version='5.1',
route_values=route_values,
query_parameters=query_parameters)
return self._deserialize('[PolicyConfiguration]', self._unwrap_collection(response))
response_value = self._deserialize('[PolicyConfiguration]', self._unwrap_collection(response))
continuation_token = self._get_continuation_token(response)
return self.GetPolicyConfigurationsResponseValue(response_value, continuation_token)

class GetPolicyConfigurationsResponseValue(object):
def __init__(self, value, continuation_token):
"""
Response for the get_policy_configurations method

:param value:
:type value: :class:`<[PolicyConfiguration]> <azure.devops.v5_1.policy.models.[PolicyConfiguration]>`
:param continuation_token: The continuation token to be used to get the next page of results.
:type continuation_token: str
"""
self.value = value
self.continuation_token = continuation_token

def update_policy_configuration(self, configuration, project, configuration_id):
"""UpdatePolicyConfiguration.
Expand Down
Loading