From 12b19b5147262a65c34d8857242dd91dc02301c7 Mon Sep 17 00:00:00 2001 From: Gonchik Tsymzhitov Date: Thu, 3 Oct 2019 19:57:20 +0300 Subject: [PATCH 1/9] A new Tempo method --- atlassian/bitbucket.py | 4 +++- atlassian/confluence.py | 14 ++++++++++++++ atlassian/jira.py | 26 +++++++++++++++++++++----- requirements.txt | 4 ++-- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/atlassian/bitbucket.py b/atlassian/bitbucket.py index 1dd7df5ac..c0f014518 100644 --- a/atlassian/bitbucket.py +++ b/atlassian/bitbucket.py @@ -527,7 +527,7 @@ def delete_branch(self, project, repository, name, end_point): data = {"name": str(name), "endPoint": str(end_point)} return self.delete(url, data=data) - def get_pull_requests(self, project, repository, state='OPEN', order='newest', limit=100, start=0): + def get_pull_requests(self, project, repository, state='OPEN', order='newest', limit=100, start=0, at=None): """ Get pull requests :param project: @@ -550,6 +550,8 @@ def get_pull_requests(self, project, repository, state='OPEN', order='newest', l params['start'] = start if order: params['order'] = order + if at: + params['at'] = at response = self.get(url, params=params) if 'values' not in response: return [] diff --git a/atlassian/confluence.py b/atlassian/confluence.py index 5a70a68fc..118b68fb4 100644 --- a/atlassian/confluence.py +++ b/atlassian/confluence.py @@ -1295,3 +1295,17 @@ def avatar_set_default_for_user(self, user_key): """ url = 'rest/user-profile/1.0/{}/avatar/default'.format(user_key) return self.get(url) + + def add_user_to_group(self, username, group_name): + """ + Add given user to a group + + :param username: str + :param group_name: str + :return: Current state of the group + """ + url = 'rest/api/2/group/user' + params = {'groupname': group_name} + data = {'name': username} + + return self.post(url, params=params, data=data) \ No newline at end of file diff --git a/atlassian/jira.py b/atlassian/jira.py index efa399e94..4a84781b1 100644 --- a/atlassian/jira.py +++ b/atlassian/jira.py @@ -386,8 +386,9 @@ def add_version(self, project_key, project_id, version, is_archived=False, is_re :is_released: :return: """ - payload = {'name': version, 'archived': is_archived, 'released': is_released, 'project': project_key, 'projectId': project_id} - return self.post("rest/api/2/version", data = payload) + payload = {'name': version, 'archived': is_archived, 'released': is_released, 'project': project_key, + 'projectId': project_id} + return self.post("rest/api/2/version", data=payload) def get_project_roles(self, project_key): """ @@ -1044,7 +1045,7 @@ def set_issue_status_by_transition_id(self, issue_key, transition_id): def get_issue_status(self, issue_key): url = 'rest/api/2/issue/{issue_key}?fields=status'.format(issue_key=issue_key) - return (self.get(url) or {}).get('fields').get('status').get('name') + return (((self.get(url) or {}).get('fields') or {}).get('status') or {}).get('name') or {} def get_issue_status_id(self, issue_key): url = 'rest/api/2/issue/{issue_key}?fields=status'.format(issue_key=issue_key) @@ -1711,12 +1712,12 @@ def tempo_timesheets_get_worklogs(self, date_from=None, date_to=None, username=N def tempo_timesheets_write_worklog(self, worker, started, time_spend_in_seconds, issue_id, comment=None): """ - - :param comment: + Log work for user :param worker: :param started: :param time_spend_in_seconds: :param issue_id: + :param comment: :return: """ data = {"worker": worker, @@ -1728,6 +1729,21 @@ def tempo_timesheets_write_worklog(self, worker, started, time_spend_in_seconds, url = 'rest/tempo-timesheets/4/worklogs/' return self.post(url, data=data) + def tempo_timesheets_approval_worklog_report(self, user_key, period_start_date): + """ + Return timesheets for approval + :param user_key: + :param period_start_date: + :return: + """ + url = "rest/tempo-timesheets/4/timesheet-approval/current" + params = {} + if period_start_date: + params['periodStartDate'] = period_start_date + if user_key: + params['userKey'] = user_key + return self.get(url, params=params) + def tempo_get_links_to_project(self, project_id): """ Gets all links to a specific project diff --git a/requirements.txt b/requirements.txt index 34fe49703..2ad9cd06c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,5 +2,5 @@ six requests oauthlib requests_oauthlib -kerberos; platform_system != 'Windows' -kerberos-sspi; platform_system == 'Windows' +kerberos ; platform_system != 'Windows' +kerberos-sspi ; platform_system == 'Windows' \ No newline at end of file From 81932839013d18bd7a843dabc4009c3de68ce4ea Mon Sep 17 00:00:00 2001 From: Gonchik Tsymzhitov Date: Thu, 3 Oct 2019 20:08:40 +0300 Subject: [PATCH 2/9] Tempo: add team member --- atlassian/jira.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/atlassian/jira.py b/atlassian/jira.py index af8f3bbab..a6b70aab1 100644 --- a/atlassian/jira.py +++ b/atlassian/jira.py @@ -1720,6 +1720,13 @@ def tempo_get_default_link_to_project(self, project_id): url = 'rest/tempo-accounts/1/link/project/{}/default/'.format(project_id) return self.get(url) + def tempo_teams_get_all_teams(self, expand=None): + url = "rest/tempo-teams/2/team" + params = {} + if expand: + params['expand'] = expand + return self.get(url, params=params) + def tempo_teams_add_member(self, team_id, member_key): """ Add team member @@ -1727,12 +1734,37 @@ def tempo_teams_add_member(self, team_id, member_key): :param member_key: :return: """ - url = 'rest/tempo-teams/2/team/{}/member/'.format(team_id) - data = {"member": {"key": member_key, "type": "USER"}, + data = {"member": {"key": str(member_key), "type": "USER"}, "membership": { "availability": "100", "role": {"id": 1} }} + return self.tempo_teams_add_member_raw(team_id, member_data=data) + + def tempo_teams_add_membership(self, team_id, member_id): + """ + Add team member + :param team_id: + :param member_id: + :return: + """ + data = {"teamMemberId": member_id, + "teamId": team_id, + "availability": "100", + "role": {"id": 1} + } + url = "rest/tempo-teams/2/team/{}/member/{}/membership".format(team_id, member_id) + return self.post(url, data=data) + + def tempo_teams_add_member_raw(self, team_id, member_data): + """ + Add team member + :param team_id: + :param member_data: + :return: + """ + url = 'rest/tempo-teams/2/team/{}/member/'.format(team_id) + data = member_data return self.post(url, data=data) def tempo_teams_get_members(self, team_id): From 16beefa11183eafb606380d150bec45e18ddfb5c Mon Sep 17 00:00:00 2001 From: Gonchik Tsymzhitov Date: Fri, 4 Oct 2019 12:55:49 +0300 Subject: [PATCH 3/9] Bugfix --- atlassian/confluence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atlassian/confluence.py b/atlassian/confluence.py index 118b68fb4..f372c62ac 100644 --- a/atlassian/confluence.py +++ b/atlassian/confluence.py @@ -1266,7 +1266,7 @@ def team_calendar_events(self, sub_calendar_id, start, end, user_time_zone_id=No if start: params['start'] = start if end: - params['start'] = end + params['end'] = end return self.get(url, params=params) def get_mobile_parameters(self, username): From fd0cf22c5b2fe72a9c997bfd46dcd5c56834c4cc Mon Sep 17 00:00:00 2001 From: Gonchik Tsymzhitov Date: Thu, 24 Oct 2019 00:51:26 +0300 Subject: [PATCH 4/9] Set workload method --- atlassian/jira.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/atlassian/jira.py b/atlassian/jira.py index 075bc2313..0dbb8ae73 100644 --- a/atlassian/jira.py +++ b/atlassian/jira.py @@ -1657,6 +1657,17 @@ def tempo_workload_scheme_get_members(self, scheme_id): url = 'rest/tempo-core/1/workloadscheme/users/{}'.format(scheme_id) return self.get(url) + def tempo_workload_scheme_set_member(self, scheme_id, member): + """ + Provide a workload scheme members + :param member: user name of user + :param scheme_id: + :return: + """ + url = 'rest/tempo-core/1/workloadscheme/user/{}'.format(member) + data = {'id': scheme_id} + return self.put(url, data=data) + def tempo_timesheets_get_configuration(self): """ Provide the configs of timesheets From f190a274da54a83c8b1f7e4de76209bc2ae0747a Mon Sep 17 00:00:00 2001 From: Gonchik Tsymzhitov Date: Thu, 24 Oct 2019 00:52:20 +0300 Subject: [PATCH 5/9] Bump version --- atlassian/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atlassian/VERSION b/atlassian/VERSION index 850e74240..63e799cf4 100644 --- a/atlassian/VERSION +++ b/atlassian/VERSION @@ -1 +1 @@ -1.14.0 +1.14.1 From 359c1ee4ceb9b26573245405674376e7cf5bc581 Mon Sep 17 00:00:00 2001 From: Gonchik Tsymzhitov Date: Mon, 28 Oct 2019 22:16:55 +0300 Subject: [PATCH 6/9] Organize the imports --- atlassian/VERSION | 2 +- atlassian/__init__.py | 12 ++++++------ atlassian/bamboo.py | 2 ++ atlassian/bitbucket.py | 1 + atlassian/confluence.py | 8 +++++--- atlassian/crowd.py | 1 + atlassian/jira.py | 2 ++ atlassian/jira8.py | 1 + atlassian/marketplace.py | 1 + atlassian/portfolio.py | 1 + atlassian/request_utils.py | 1 + atlassian/rest_client.py | 4 +++- atlassian/service_desk.py | 1 + 13 files changed, 26 insertions(+), 11 deletions(-) diff --git a/atlassian/VERSION b/atlassian/VERSION index 63e799cf4..a4cc55716 100644 --- a/atlassian/VERSION +++ b/atlassian/VERSION @@ -1 +1 @@ -1.14.1 +1.14.2 diff --git a/atlassian/__init__.py b/atlassian/__init__.py index 2c6308697..cf793bbdc 100644 --- a/atlassian/__init__.py +++ b/atlassian/__init__.py @@ -1,13 +1,13 @@ -from .confluence import Confluence -from .jira import Jira +from .bamboo import Bamboo from .bitbucket import Bitbucket from .bitbucket import Bitbucket as Stash -from .portfolio import Portfolio -from .bamboo import Bamboo +from .confluence import Confluence from .crowd import Crowd -from .service_desk import ServiceDesk -from .marketplace import MarketPlace +from .jira import Jira from .jira8 import Jira8 +from .marketplace import MarketPlace +from .portfolio import Portfolio +from .service_desk import ServiceDesk __all__ = [ 'Confluence', diff --git a/atlassian/bamboo.py b/atlassian/bamboo.py index 8a40153b9..2189ea088 100755 --- a/atlassian/bamboo.py +++ b/atlassian/bamboo.py @@ -1,6 +1,8 @@ # coding=utf-8 import logging + from requests.exceptions import HTTPError + from .rest_client import AtlassianRestAPI log = logging.getLogger(__name__) diff --git a/atlassian/bitbucket.py b/atlassian/bitbucket.py index 89418a115..896ac737e 100644 --- a/atlassian/bitbucket.py +++ b/atlassian/bitbucket.py @@ -1,5 +1,6 @@ # coding=utf-8 import logging + from .rest_client import AtlassianRestAPI log = logging.getLogger(__name__) diff --git a/atlassian/confluence.py b/atlassian/confluence.py index 60fd5bab8..9a44b5233 100644 --- a/atlassian/confluence.py +++ b/atlassian/confluence.py @@ -1,11 +1,13 @@ # coding=utf-8 -from atlassian import utils -from .rest_client import AtlassianRestAPI -from requests import HTTPError import logging import os import time +from requests import HTTPError + +from atlassian import utils +from .rest_client import AtlassianRestAPI + log = logging.getLogger(__name__) diff --git a/atlassian/crowd.py b/atlassian/crowd.py index 0f3583a48..e7b2f91fa 100644 --- a/atlassian/crowd.py +++ b/atlassian/crowd.py @@ -1,5 +1,6 @@ # coding=utf-8 import logging + from .rest_client import AtlassianRestAPI log = logging.getLogger(__name__) diff --git a/atlassian/jira.py b/atlassian/jira.py index 14d7808b3..ce0972fb8 100644 --- a/atlassian/jira.py +++ b/atlassian/jira.py @@ -1,6 +1,8 @@ # coding=utf-8 import logging + from requests.exceptions import HTTPError + from .rest_client import AtlassianRestAPI log = logging.getLogger(__name__) diff --git a/atlassian/jira8.py b/atlassian/jira8.py index 87bd538f7..960592678 100644 --- a/atlassian/jira8.py +++ b/atlassian/jira8.py @@ -1,5 +1,6 @@ # coding=utf-8 import logging + from .rest_client import AtlassianRestAPI log = logging.getLogger(__name__) diff --git a/atlassian/marketplace.py b/atlassian/marketplace.py index 47b70cb56..0f983e1b9 100644 --- a/atlassian/marketplace.py +++ b/atlassian/marketplace.py @@ -1,5 +1,6 @@ # coding=utf-8 import logging + from .rest_client import AtlassianRestAPI log = logging.getLogger(__name__) diff --git a/atlassian/portfolio.py b/atlassian/portfolio.py index 4907be073..a1f127db5 100644 --- a/atlassian/portfolio.py +++ b/atlassian/portfolio.py @@ -1,5 +1,6 @@ # coding=utf-8 import logging + from .rest_client import AtlassianRestAPI log = logging.getLogger(__name__) diff --git a/atlassian/request_utils.py b/atlassian/request_utils.py index e968fa404..f1e4027cb 100644 --- a/atlassian/request_utils.py +++ b/atlassian/request_utils.py @@ -1,4 +1,5 @@ import logging + from six import PY3 diff --git a/atlassian/rest_client.py b/atlassian/rest_client.py index a44dd11af..3761ed9eb 100644 --- a/atlassian/rest_client.py +++ b/atlassian/rest_client.py @@ -1,10 +1,12 @@ # coding=utf-8 import json import logging -from six.moves.urllib.parse import urlencode + import requests from oauthlib.oauth1 import SIGNATURE_RSA from requests_oauthlib import OAuth1 +from six.moves.urllib.parse import urlencode + from atlassian.request_utils import get_default_logger log = get_default_logger(__name__) diff --git a/atlassian/service_desk.py b/atlassian/service_desk.py index 56046b833..a7b30df79 100644 --- a/atlassian/service_desk.py +++ b/atlassian/service_desk.py @@ -1,5 +1,6 @@ # coding=utf-8 import logging + from .rest_client import AtlassianRestAPI log = logging.getLogger(__name__) From 0e4e922d6e8bcbe0b02180b9f85b42a7a724f2dd Mon Sep 17 00:00:00 2001 From: Gonchik Tsymzhitov Date: Mon, 28 Oct 2019 22:20:50 +0300 Subject: [PATCH 7/9] Polish --- atlassian/bamboo.py | 2 ++ atlassian/bitbucket.py | 16 +++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/atlassian/bamboo.py b/atlassian/bamboo.py index 2189ea088..41db89577 100755 --- a/atlassian/bamboo.py +++ b/atlassian/bamboo.py @@ -198,6 +198,7 @@ def get_vcs_branches(self, plan_key, max_results=25): """ Get all vcs names for the current plan :param plan_key: str TST-BLD + :param max_results :return: """ resource = 'plan/{plan_key}/vcsBranches'.format(plan_key=plan_key) @@ -304,6 +305,7 @@ def build_result(self, build_key, expand=None, include_all_states=False): using stages.stage.results.result. All expand parameters should contain results.result prefix. :param build_key: Should be in the form XX-YY[-ZZ]-99, that is, the last token should be an integer representing the build number + :param include_all_states """ try: int(build_key.split('-')[-1]) diff --git a/atlassian/bitbucket.py b/atlassian/bitbucket.py index 896ac737e..5f42aef86 100644 --- a/atlassian/bitbucket.py +++ b/atlassian/bitbucket.py @@ -561,7 +561,8 @@ def get_pull_request_settings(self, project, repository): :param repository: :return: """ - url = 'rest/api/1.0/projects/{project}/repos/{repository}/settings/pull-requests'.format(project=project,repository=repository) + url = 'rest/api/1.0/projects/{project}/repos/{repository}/settings/pull-requests'.format(project=project, + repository=repository) return self.get(url) def set_pull_request_settings(self, project, repository, data): @@ -572,7 +573,8 @@ def set_pull_request_settings(self, project, repository, data): :param data: json body :return: """ - url = 'rest/api/1.0/projects/{project}/repos/{repository}/settings/pull-requests'.format(project=project,repository=repository) + url = 'rest/api/1.0/projects/{project}/repos/{repository}/settings/pull-requests'.format(project=project, + repository=repository) return self.post(url, data=data) def get_pull_requests(self, project, repository, state='OPEN', order='newest', limit=100, start=0, at=None): @@ -1075,7 +1077,7 @@ def get_branches_permissions(self, project, repository=None, start=0, limit=25): :param limit: :return: """ - if repository != None: + if repository is not None: url = 'rest/branch-permissions/2.0/projects/{project}/repos/{repository}/restrictions'.format( project=project, repository=repository) @@ -1099,12 +1101,12 @@ def all_branches_permissions(self, project, repository=None): """ start = 0 branches_permissions = [] - response = self.get_branches_permissions(project=project, repository=repository, start=start) - branches_permissions += response.get('values') + response = self.get_branches_permissions(project=project, repository=repository, start=start) + branches_permissions += response.get('values') while not response.get('isLastPage'): start = response.get('nextPageStart') - response = self.get_branches_permissions(project=project, repository=repository, start=start) - branches_permissions += response.get('values') + response = self.get_branches_permissions(project=project, repository=repository, start=start) + branches_permissions += response.get('values') return branches_permissions def reindex(self): From 1fbfcc9744704744cb77b2178e81f95acfa467f2 Mon Sep 17 00:00:00 2001 From: Gonchik Tsymzhitov Date: Wed, 13 Nov 2019 20:50:19 +0700 Subject: [PATCH 8/9] Bump version --- atlassian/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atlassian/VERSION b/atlassian/VERSION index a4cc55716..cf28a128f 100644 --- a/atlassian/VERSION +++ b/atlassian/VERSION @@ -1 +1 @@ -1.14.2 +2.14.3 From 91bf3025ffbc7d61a613530d1a0c2bf4e2213101 Mon Sep 17 00:00:00 2001 From: Gonchik Tsymzhitov Date: Wed, 13 Nov 2019 21:09:31 +0700 Subject: [PATCH 9/9] Add LFS info fetcher --- atlassian/bitbucket.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/atlassian/bitbucket.py b/atlassian/bitbucket.py index 5f42aef86..638c6ef24 100644 --- a/atlassian/bitbucket.py +++ b/atlassian/bitbucket.py @@ -1408,3 +1408,9 @@ def create_code_insights_report(self, project_key, repository_slug, commit_id, r data = {"title": report_title} data.update(report_params) return self.put(url, data=data) + + def get_lfs_repo_status(self, project_key, repo): + url = 'rest/git-lfs/git-lfs/admin/projects/{projectKey}/repos/{repositorySlug}/enabled'.format( + projectKey=project_key, + repositorySlug=repo) + return self.get(url)