diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f71afad8f..93841931c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,11 +14,11 @@ jobs: run-docker: runs-on: ubuntu-18.04 - + strategy: fail-fast: false matrix: - python-version: ['3.4', '3.5', '3.6', '3.7', '3.8'] + python-version: ['3.4', '3.5', '3.6', '3.7', '3.8', '3.9', '-dev'] steps: - uses: actions/checkout@v2 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 07c6eab2b..000000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: python -python: - - "2.7" - - "3.4" - - "3.5" - - "3.6" - - "3.7" - - "3.8" - - "3.9" - - "3.10-dev" - -matrix: - allow_failures: - - python: "3.10-dev" - -install: pip install tox-travis -before_script: - - .travis/bump_version ./ minor > atlassian/VERSION -script: - - make qa diff --git a/Dockerfile.qa b/Dockerfile.qa index 218b756b5..35e3ed805 100644 --- a/Dockerfile.qa +++ b/Dockerfile.qa @@ -1,10 +1,10 @@ -FROM ubuntu:18.04 +FROM ubuntu:20.04 ARG PYTHON_VERSION RUN \ apt update && \ - apt-get install -y make gcc-5 libkrb5-dev python$PYTHON_VERSION python3-pip && \ + apt-get install -y make gcc-8 libkrb5-dev python$PYTHON_VERSION python3-pip && \ apt-get clean WORKDIR /atlassian-python-api diff --git a/Makefile b/Makefile index 8b02dea55..5fb5642c1 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,8 @@ setup-dev: qa: tox +tox: export PYTHONDONTWRITEBYTECODE := 1 + tox: tox diff --git a/atlassian/bamboo.py b/atlassian/bamboo.py index 57a91fcb1..8a6b986b8 100755 --- a/atlassian/bamboo.py +++ b/atlassian/bamboo.py @@ -66,15 +66,7 @@ def _get_generator( yield response def base_list_call( - self, - resource, - expand, - favourite, - clover_enabled, - max_results, - label=None, - start_index=0, - **kwargs + self, resource, expand, favourite, clover_enabled, max_results, label=None, start_index=0, **kwargs ): flags = [] params = {"max-results": max_results} @@ -101,9 +93,7 @@ def base_list_call( """ Projects & Plans """ - def projects( - self, expand=None, favourite=False, clover_enabled=False, max_results=25 - ): + def projects(self, expand=None, favourite=False, clover_enabled=False, max_results=25): return self.base_list_call( "project", expand=expand, @@ -217,9 +207,7 @@ def enable_plan(self, plan_key): """ Branches """ - def search_branches( - self, plan_key, include_default_branch=True, max_results=25, start=0 - ): + def search_branches(self, plan_key, include_default_branch=True, max_results=25, start=0): params = { "max-result": max_results, "start-index": start, @@ -261,9 +249,7 @@ def get_branch_info(self, plan_key, branch_name): :param branch_name: :return: """ - resource = "plan/{plan_key}/branch/{branch_name}".format( - plan_key=plan_key, branch_name=branch_name - ) + resource = "plan/{plan_key}/branch/{branch_name}".format(plan_key=plan_key, branch_name=branch_name) return self.get(self.resource_url(resource)) def create_branch( @@ -286,9 +272,7 @@ def create_branch( :param cleanup_enabled: bool :return: PUT request """ - resource = "plan/{plan_key}/branch/{branch_name}".format( - plan_key=plan_key, branch_name=branch_name - ) + resource = "plan/{plan_key}/branch/{branch_name}".format(plan_key=plan_key, branch_name=branch_name) params = {} if vcs_branch: params = dict( @@ -350,9 +334,7 @@ def results( """ resource = "result" if project_key and plan_key and job_key and build_number: - resource += "/{}-{}-{}/{}".format( - project_key, plan_key, job_key, build_number - ) + resource += "/{}-{}-{}/{}".format(project_key, plan_key, job_key, build_number) elif project_key and plan_key and build_number: resource += "/{}-{}/{}".format(project_key, plan_key, build_number) elif project_key and plan_key: @@ -489,9 +471,7 @@ def plan_results( include_all_states=include_all_states, ) - def build_result( - self, build_key, expand=None, include_all_states=False, start=0, max_results=25 - ): + def build_result(self, build_key, expand=None, include_all_states=False, start=0, max_results=25): """ Returns details of a specific build result :param expand: expands build result details on request. Possible values are: artifacts, comments, labels, @@ -516,9 +496,7 @@ def build_result( include_all_states=include_all_states, ) except ValueError: - raise ValueError( - 'The key "{}" does not correspond to a build result'.format(build_key) - ) + raise ValueError('The key "{}" does not correspond to a build result'.format(build_key)) def build_latest_result(self, plan_key, expand=None, include_all_states=False): """ @@ -541,11 +519,7 @@ def build_latest_result(self, plan_key, expand=None, include_all_states=False): include_all_states=include_all_states, ) except ValueError: - raise ValueError( - 'The key "{}" does not correspond to the latest build result'.format( - plan_key - ) - ) + raise ValueError('The key "{}" does not correspond to the latest build result'.format(plan_key)) def delete_build_result(self, build_key): """ @@ -557,18 +531,9 @@ def delete_build_result(self, build_key): plan_key = "{}-{}".format(build_key[0], build_key[1]) build_number = build_key[2] params = {"buildKey": plan_key, "buildNumber": build_number} - return self.post( - custom_resource, params=params, headers=self.form_token_headers - ) + return self.post(custom_resource, params=params, headers=self.form_token_headers) - def execute_build( - self, - plan_key, - stage=None, - execute_all_stages=True, - custom_revision=None, - **bamboo_variables - ): + def execute_build(self, plan_key, stage=None, execute_all_stages=True, custom_revision=None, **bamboo_variables): """ Fire build execution for specified plan. !IMPORTANT! NOTE: for some reason, this method always execute all stages @@ -604,9 +569,7 @@ def stop_build(self, plan_key): """ Comments & Labels """ - def comments( - self, project_key, plan_key, build_number, start_index=0, max_results=25 - ): + def comments(self, project_key, plan_key, build_number, start_index=0, max_results=25): resource = "result/{}-{}-{}/comment".format(project_key, plan_key, build_number) params = {"start-index": start_index, "max-results": max_results} return self.get(self.resource_url(resource), params=params) @@ -619,9 +582,7 @@ def create_comment(self, project_key, plan_key, build_number, comment, author=No } return self.post(self.resource_url(resource), data=comment_data) - def labels( - self, project_key, plan_key, build_number, start_index=0, max_results=25 - ): + def labels(self, project_key, plan_key, build_number, start_index=0, max_results=25): resource = "result/{}-{}-{}/label".format(project_key, plan_key, build_number) params = {"start-index": start_index, "max-results": max_results} return self.get(self.resource_url(resource), params=params) @@ -631,9 +592,7 @@ def create_label(self, project_key, plan_key, build_number, label): return self.post(self.resource_url(resource), data={"name": label}) def delete_label(self, project_key, plan_key, build_number, label): - resource = "result/{}-{}-{}/label/{}".format( - project_key, plan_key, build_number, label - ) + resource = "result/{}-{}-{}/label/{}".format(project_key, plan_key, build_number, label) return self.delete(self.resource_url(resource)) def get_projects(self): @@ -667,9 +626,7 @@ def deployment_project(self, project_id): return self.get(self.resource_url(resource)) def deployment_environment_results(self, env_id, expand=None, max_results=25): - resource = "deploy/environment/{environmentId}/results".format( - environmentId=env_id - ) + resource = "deploy/environment/{environmentId}/results".format(environmentId=env_id) params = {"max-result": max_results, "start-index": 0} size = 1 if expand: @@ -686,11 +643,7 @@ def deployment_dashboard(self, project_id=None): Returns the current status of each deployment environment If no project id is provided, returns all projects. """ - resource = ( - "deploy/dashboard/{}".format(project_id) - if project_id - else "deploy/dashboard" - ) + resource = "deploy/dashboard/{}".format(project_id) if project_id else "deploy/dashboard" return self.get(self.resource_url(resource)) """ Users & Groups """ diff --git a/atlassian/bitbucket/__init__.py b/atlassian/bitbucket/__init__.py index 7c4b49af4..9fe2a8cb3 100644 --- a/atlassian/bitbucket/__init__.py +++ b/atlassian/bitbucket/__init__.py @@ -16,9 +16,7 @@ def __init__(self, url, *args, **kwargs): if "cloud" not in kwargs and ("bitbucket.org" in url): kwargs["cloud"] = True if "api_version" not in kwargs: - kwargs["api_version"] = ( - "2.0" if "cloud" in kwargs and kwargs["cloud"] else "1.0" - ) + kwargs["api_version"] = "2.0" if "cloud" in kwargs and kwargs["cloud"] else "1.0" if "cloud" in kwargs: kwargs["api_root"] = "" if "api.bitbucket.org" in url else "api" super(Bitbucket, self).__init__(url, *args, **kwargs) @@ -66,19 +64,13 @@ def all_project_administrators(self): :return: A generator object containing a map with the project_key, project_name and project_administrators """ for project in self.project_list(): - log.info( - "Processing project: {0} - {1}".format( - project.get("key"), project.get("name") - ) - ) + log.info("Processing project: {0} - {1}".format(project.get("key"), project.get("name"))) yield { "project_key": project.get("key"), "project_name": project.get("name"), "project_administrators": [ {"email": x["emailAddress"], "name": x["displayName"]} - for x in self.project_users_with_administrator_permissions( - project["key"] - ) + for x in self.project_users_with_administrator_permissions(project["key"]) ], } @@ -201,9 +193,7 @@ def get_associated_build_statuses(self, commit): :commit: str- commit id :return: """ - url = self.resource_url( - "commits/{commitId}".format(commitId=commit), api_root="rest/build-status" - ) + url = self.resource_url("commits/{commitId}".format(commitId=commit), api_root="rest/build-status") return self.get(url) def _url_announcement_banner(self): @@ -315,9 +305,7 @@ def update_project(self, key, **params): """ data = self.project(key) if "errors" in data: - log.debug( - "Failed to update project: {0}: Unable to read project".format(key) - ) + log.debug("Failed to update project: {0}: Unable to read project".format(key)) return None else: data.update(params) @@ -415,9 +403,7 @@ def project_users_with_administrator_permissions(self, key): :return: List of project administrators """ project_administrators = [ - user["user"] - for user in self.project_users(key) - if user["permission"] == "PROJECT_ADMIN" + user["user"] for user in self.project_users(key) if user["permission"] == "PROJECT_ADMIN" ] for group in self.project_groups_with_administrator_permissions(key): for user in self.group_members(group): @@ -499,9 +485,7 @@ def project_remove_group_permissions(self, project_key, groupname): def _url_project_conditions(self, project_key): return "{}/conditions".format( - self._url_project( - project_key, api_root="rest/default-reviewers", api_version="1.0" - ) + self._url_project(project_key, api_root="rest/default-reviewers", api_version="1.0") ) def get_project_conditions(self, project_key): @@ -518,9 +502,7 @@ def get_project_conditions(self, project_key): def _url_project_condition(self, project_key, id_condition=None): url = "{}/condition".format( - self._url_project( - project_key, api_root="rest/default-reviewers", api_version="1.0" - ) + self._url_project(project_key, api_root="rest/default-reviewers", api_version="1.0") ) if id_condition is not None: url += "/{}".format(id_condition) @@ -617,9 +599,7 @@ def repo_all_list(self, project_key): """ return self.repo_list(project_key, limit=None) - def create_repo( - self, project_key, repository_slug, forkable=False, is_private=True - ): + def create_repo(self, project_key, repository_slug, forkable=False, is_private=True): """Create a new repository. Requires an existing project in which this repository will be created. The only parameters which will be used @@ -667,7 +647,10 @@ def reindex_repo(self, project_key, repository_slug): """ url = "{urlRepo}/sync".format( urlRepo=self._url_repo( - project_key, repository_slug, api_root="rest/indexing", api_version="1.0" + project_key, + repository_slug, + api_root="rest/indexing", + api_version="1.0", ) ) return self.post(url) @@ -682,9 +665,7 @@ def reindex_repo_dev_panel(self, project_key, repository_slug): :param repository_slug: :return: """ - url = "{}/reindex".format( - self._url_repo(project_key, repository_slug, api_root="rest/jira-dev") - ) + url = "{}/reindex".format(self._url_repo(project_key, repository_slug, api_root="rest/jira-dev")) return self.post(url) def get_repo(self, project_key, repository_slug): @@ -820,15 +801,9 @@ def project_groups_with_administrator_permissions(self, key): :param key: :return: """ - return [ - group["group"]["name"] - for group in self.project_groups(key) - if group["permission"] == "PROJECT_ADMIN" - ] + return [group["group"]["name"] for group in self.project_groups(key) if group["permission"] == "PROJECT_ADMIN"] - def repo_grant_group_permissions( - self, project_key, repo_key, groupname, permission - ): + def repo_grant_group_permissions(self, project_key, repo_key, groupname, permission): """ Grant the specified repository permission to an specific group Promote or demote a group's permission level for the specified repository. Available repository permissions are: @@ -850,9 +825,7 @@ def repo_grant_group_permissions( params = {"permission": permission, "name": groupname} return self.put(url, params=params) - def repo_remove_group_permissions( - self, project_key, repo_key, groupname, permission - ): + def repo_remove_group_permissions(self, project_key, repo_key, groupname, permission): """ Revoke all permissions for the specified repository for a group. The authenticated user must have REPO_ADMIN permission for the specified repository @@ -901,9 +874,7 @@ def set_repo_label(self, project_key, repository_slug, label_name): return self.post(url, data=data) def _url_repo_branches(self, project_key, repository_slug, api_root=None): - return "{}/branches".format( - self._url_repo(project_key, repository_slug, api_root=api_root) - ) + return "{}/branches".format(self._url_repo(project_key, repository_slug, api_root=api_root)) def get_branches( self, @@ -946,9 +917,7 @@ def get_branches( return self._get_paged(url, params=params) def _url_repo_default_branche(self, project_key, repository_slug): - return "{}/default".format( - self._url_repo_branches(project_key, repository_slug) - ) + return "{}/default".format(self._url_repo_branches(project_key, repository_slug)) def get_default_branch(self, project_key, repository_slug): """ @@ -974,9 +943,7 @@ def set_default_branch(self, project_key, repository_slug, ref_branch_name): data = {"id": ref_branch_name} return self.put(url, data=data) - def create_branch( - self, project_key, repository_slug, name, start_point, message="" - ): + def create_branch(self, project_key, repository_slug, name, start_point, message=""): """Creates a branch using the information provided in the request. The authenticated user must have REPO_WRITE permission for the context repository to call this resource. @@ -1011,12 +978,10 @@ def delete_branch(self, project_key, repository_slug, name, end_point=None): :param end_point: :return: """ - url = self._url_repo_branches( - project_key, repository_slug, api_root="rest/branch-utils" - ) + url = self._url_repo_branches(project_key, repository_slug, api_root="rest/branch-utils") data = {"name": str(name)} if end_point: - data['endPoint'] = end_point + data["endPoint"] = end_point return self.delete(url, data=data) def _url_repo_tags(self, project_key, repository_slug, api_root=None): @@ -1071,9 +1036,7 @@ def get_project_tags(self, project_key, repository_slug, tag_name): url = self._url_repo_tags(project_key, repository_slug) return self.get(url) - def set_tag( - self, project_key, repository_slug, tag_name, commit_revision, description=None - ): + def set_tag(self, project_key, repository_slug, tag_name, commit_revision, description=None): """ Creates a tag using the information provided in the {@link RestCreateTagRequest request} The authenticated user must have REPO_WRITE permission for the context repository to call this resource. @@ -1103,14 +1066,15 @@ def delete_tag(self, project_key, repository_slug, tag_name): :param tag_name: :return: """ - url = "{}/{}".format(self._url_repo_tags(project_key, repository_slug, api_root="rest/git"), tag_name) + url = "{}/{}".format( + self._url_repo_tags(project_key, repository_slug, api_root="rest/git"), + tag_name, + ) (project_key, repository_slug, tag_name) return self.delete(url) def _url_pull_request_settings(self, project_key, repository_slug): - return "{}/settings/pull-requests".format( - self._url_repo(project_key, repository_slug) - ) + return "{}/settings/pull-requests".format(self._url_repo(project_key, repository_slug)) def get_pull_request_settings(self, project_key, repository_slug): """ @@ -1135,13 +1099,9 @@ def set_pull_request_settings(self, project_key, repository_slug, data): def _url_pull_requests(self, project_key, repository_slug): if Cloud: - return self.resource_url( - "repositories/{}/{}/pullrequests".format(project_key, repository_slug) - ) + return self.resource_url("repositories/{}/{}/pullrequests".format(project_key, repository_slug)) else: - return "{}/pull-requests".format( - self._url_repo(project_key, repository_slug) - ) + return "{}/pull-requests".format(self._url_repo(project_key, repository_slug)) def get_pull_requests( self, @@ -1253,9 +1213,7 @@ def create_pull_request(self, project_key, repository_slug, data): return self.post(url, data=data) def _url_pull_request(self, project_key, repository_slug, pull_request_id): - return "{}/{}".format( - self._url_pull_requests(project_key, repository_slug), pull_request_id - ) + return "{}/{}".format(self._url_pull_requests(project_key, repository_slug), pull_request_id) def get_pull_request(self, project_key, repository_slug, pull_request_id): """ @@ -1277,9 +1235,7 @@ def get_pullrequest(self, *args, **kwargs): """ return self.get_pull_request(*args, **kwargs) - def delete_pull_request( - self, project_key, repository_slug, pull_request_id, pull_request_version - ): + def delete_pull_request(self, project_key, repository_slug, pull_request_id, pull_request_version): """ Delete a pull request. @@ -1293,9 +1249,7 @@ def delete_pull_request( data = {"version": pull_request_version} return self.delete(url, data=data) - def get_pull_requests_activities( - self, project_key, repository_slug, pull_request_id, start=0, limit=None - ): + def get_pull_requests_activities(self, project_key, repository_slug, pull_request_id, start=0, limit=None): """ Get pull requests activities :param project_key: @@ -1304,9 +1258,7 @@ def get_pull_requests_activities( :param start: :return: """ - url = "{}/activities".format( - self._url_pull_request(project_key, repository_slug, pull_request_id) - ) + url = "{}/activities".format(self._url_pull_request(project_key, repository_slug, pull_request_id)) params = {} if start: params["start"] = start @@ -1314,9 +1266,7 @@ def get_pull_requests_activities( params["limit"] = limit return self._get_paged(url, params) - def get_pull_requests_changes( - self, project_key, repository_slug, pull_request_id, start=0, limit=None - ): + def get_pull_requests_changes(self, project_key, repository_slug, pull_request_id, start=0, limit=None): """ Get pull requests changes :param project_key: @@ -1324,9 +1274,7 @@ def get_pull_requests_changes( :param pull_request_id: the ID of the pull request within the repository :return: """ - url = "{}/changes".format( - self._url_pull_request(project_key, repository_slug, pull_request_id) - ) + url = "{}/changes".format(self._url_pull_request(project_key, repository_slug, pull_request_id)) params = {} if start: params["start"] = start @@ -1334,9 +1282,7 @@ def get_pull_requests_changes( params["limit"] = limit return self._get_paged(url, params) - def get_pull_requests_commits( - self, project_key, repository_slug, pull_request_id, start=0, limit=None - ): + def get_pull_requests_commits(self, project_key, repository_slug, pull_request_id, start=0, limit=None): """ Get pull requests commits :param project_key: @@ -1346,9 +1292,7 @@ def get_pull_requests_commits( :limit :return: """ - url = "{}/commits".format( - self._url_pull_request(project_key, repository_slug, pull_request_id) - ) + url = "{}/commits".format(self._url_pull_request(project_key, repository_slug, pull_request_id)) params = {} if start: params["start"] = start @@ -1356,16 +1300,10 @@ def get_pull_requests_commits( params["limit"] = limit return self._get_paged(url, params) - def _url_pull_request_participants( - self, project_key, repository_slug, pull_request_id - ): - return "{}/{}/participants".format( - self._url_pull_requests(project_key, repository_slug), pull_request_id - ) + def _url_pull_request_participants(self, project_key, repository_slug, pull_request_id): + return "{}/{}/participants".format(self._url_pull_requests(project_key, repository_slug), pull_request_id) - def get_pull_requests_participants( - self, project_key, repository_slug, pull_request_id, start=0, limit=None - ): + def get_pull_requests_participants(self, project_key, repository_slug, pull_request_id, start=0, limit=None): """ Get all participants of a pull request :param project_key: @@ -1373,9 +1311,7 @@ def get_pull_requests_participants( :param pull_request_id: :return: """ - url = self._url_pull_request_participants( - project_key, repository_slug, pull_request_id - ) + url = self._url_pull_request_participants(project_key, repository_slug, pull_request_id) params = {} if start: params["start"] = start @@ -1383,9 +1319,7 @@ def get_pull_requests_participants( params["limit"] = limit return self._get_paged(url, params) - def change_reviewed_status( - self, project_key, repository_slug, pull_request_id, status, user_slug - ): + def change_reviewed_status(self, project_key, repository_slug, pull_request_id, status, user_slug): """ Change the current user's status for a pull request. Implicitly adds the user as a participant if they are not already. @@ -1398,9 +1332,7 @@ def change_reviewed_status( :return: """ url = "{}/{}".format( - self._url_pull_request_participants( - project_key, repository_slug, pull_request_id - ), + self._url_pull_request_participants(project_key, repository_slug, pull_request_id), user_slug, ) approved = True if status == "APPROVED" else False @@ -1408,14 +1340,10 @@ def change_reviewed_status( return self.put(url, data) def _url_pull_request_comments(self, project_key, repository_slug, pull_request_id): - url = "{}/comments".format( - self._url_pull_request(project_key, repository_slug, pull_request_id) - ) + url = "{}/comments".format(self._url_pull_request(project_key, repository_slug, pull_request_id)) return url - def add_pull_request_comment( - self, project_key, repository_slug, pull_request_id, text, parent_id=None - ): + def add_pull_request_comment(self, project_key, repository_slug, pull_request_id, text, parent_id=None): """ Add comment into pull request :param project_key: @@ -1426,26 +1354,20 @@ def add_pull_request_comment( :return: """ - url = self._url_pull_request_comments( - project_key, repository_slug, pull_request_id - ) + url = self._url_pull_request_comments(project_key, repository_slug, pull_request_id) body = {"text": text} if parent_id: body["parent"] = {"id": parent_id} return self.post(url, data=body) - def _url_pull_request_comment( - self, project_key, repository_slug, pull_request_id, comment_id - ): + def _url_pull_request_comment(self, project_key, repository_slug, pull_request_id, comment_id): url = "{}/{}".format( self._url_pull_request_comments(project_key, repository_slug, pull_request_id), comment_id, ) return url - def get_pull_request_comment( - self, project_key, repository_slug, pull_request_id, comment_id - ): + def get_pull_request_comment(self, project_key, repository_slug, pull_request_id, comment_id): """ Retrieves a pull request comment. The authenticated user must have REPO_READ permission @@ -1456,9 +1378,7 @@ def get_pull_request_comment( :param comment_id: the ID of the comment to retrieve :return: """ - url = self._url_pull_request_comment( - project_key, repository_slug, pull_request_id, comment_id - ) + url = self._url_pull_request_comment(project_key, repository_slug, pull_request_id, comment_id) return self.get(url) def update_pull_request_comment( @@ -1478,9 +1398,7 @@ def update_pull_request_comment( that must match the server's version of the comment or the update will fail. """ - url = self._url_pull_request_comment( - project_key, repository_slug, pull_request_id, comment_id - ) + url = self._url_pull_request_comment(project_key, repository_slug, pull_request_id, comment_id) data = {"version": comment_version, "text": comment} return self.put(url, data=data) @@ -1512,9 +1430,7 @@ def get_tasks(self, project_key, repository_slug, pull_request_id): """ if Cloud: raise Exception("Not supported in Bitbucket Cloud") - url = "{}/tasks".format( - self._url_pull_request(project_key, repository_slug, pull_request_id) - ) + url = "{}/tasks".format(self._url_pull_request(project_key, repository_slug, pull_request_id)) return self.get(url) def _url_tasks(self): @@ -1584,9 +1500,7 @@ def is_pull_request_can_be_merged(self, project_key, repository_slug, pr_id): :param pr_id: 2341 :return: """ - url = "{}/merge".format( - self._url_pull_request(project_key, repository_slug, pr_id) - ) + url = "{}/merge".format(self._url_pull_request(project_key, repository_slug, pr_id)) return self.get(url) def merge_pull_request(self, project_key, repository_slug, pr_id, pr_version): @@ -1601,9 +1515,7 @@ def merge_pull_request(self, project_key, repository_slug, pr_id, pr_version): :param pr_version: :return: """ - url = "{}/merge".format( - self._url_pull_request(project_key, repository_slug, pr_id) - ) + url = "{}/merge".format(self._url_pull_request(project_key, repository_slug, pr_id)) params = {} if not Cloud: params["version"] = pr_version @@ -1621,9 +1533,7 @@ def reopen_pull_request(self, project_key, repository_slug, pr_id, pr_version): :param pr_version: 12 :return: """ - url = "{}/reopen".format( - self._url_pull_request(project_key, repository_slug, pr_id) - ) + url = "{}/reopen".format(self._url_pull_request(project_key, repository_slug, pr_id)) params = {"version": pr_version} return self.post(url, params=params) @@ -1666,9 +1576,7 @@ def get_diff(self, project_key, repository_slug, path, hash_oldest, hash_newest) :param hash_newest: the target commit (can be a partial/full commit ID or qualified/unqualified ref name) :return: """ - url = "{}/diff/{}".format( - self._url_repo_compare(project_key, repository_slug), path - ) + url = "{}/diff/{}".format(self._url_repo_compare(project_key, repository_slug), path) params = {} if hash_oldest: params["from"] = hash_oldest @@ -1677,7 +1585,9 @@ def get_diff(self, project_key, repository_slug, path, hash_oldest, hash_newest) return (self.get(url, params=params) or {}).get("diffs") def _url_commits(self, project_key, repository_slug, api_root=None, api_version=None): - return "{}/commits".format(self._url_repo(project_key, repository_slug, api_root=api_root, api_version=api_version)) + return "{}/commits".format( + self._url_repo(project_key, repository_slug, api_root=api_root, api_version=api_version) + ) def get_commits( self, @@ -1729,9 +1639,7 @@ def get_commits( params["limit"] = limit return (self.get(url, params=params) or {}).get("values") - def get_changelog( - self, project_key, repository_slug, ref_from, ref_to, start=0, limit=None - ): + def get_changelog(self, project_key, repository_slug, ref_from, ref_to, start=0, limit=None): """ Get change log between 2 refs :param project_key: @@ -1756,7 +1664,8 @@ def get_changelog( def _url_commit(self, project_key, repository_slug, commit_id, api_root=None, api_version=None): return "{}/{}".format( - self._url_commits(project_key, repository_slug, api_root=api_root, api_version=api_version), commit_id + self._url_commits(project_key, repository_slug, api_root=api_root, api_version=api_version), + commit_id, ) def get_commit_info(self, project_key, repository_slug, commit, path=None): @@ -1784,16 +1693,19 @@ def get_pull_requests_contain_commit(self, project_key, repository_slug, commit) url = self._url_commit(project_key, repository_slug, commit) return (self.get(url) or {}).get("values") - def _url_code_insights_report( - self, project_key, repository_slug, commit_id, report_key - ): + def _url_code_insights_report(self, project_key, repository_slug, commit_id, report_key): return "{}/reports/{}".format( - self._url_commit(project_key, repository_slug, commit_id, api_root="rest/insights", api_version="1.0"), report_key + self._url_commit( + project_key, + repository_slug, + commit_id, + api_root="rest/insights", + api_version="1.0", + ), + report_key, ) - def get_code_insights_report( - self, project_key, repository_slug, commit_id, report_key - ): + def get_code_insights_report(self, project_key, repository_slug, commit_id, report_key): """ Retrieve the specified code-insights report. :projectKey: str @@ -1801,14 +1713,10 @@ def get_code_insights_report( :commitId: str :report_key: str """ - url = self._url_code_insights_report( - project_key, repository_slug, commit_id, report_key - ) + url = self._url_code_insights_report(project_key, repository_slug, commit_id, report_key) return self.get(url) - def delete_code_insights_report( - self, project_key, repository_slug, commit_id, report_key - ): + def delete_code_insights_report(self, project_key, repository_slug, commit_id, report_key): """ Delete a report for the given commit. Also deletes any annotations associated with this report. :projectKey: str @@ -1816,19 +1724,11 @@ def delete_code_insights_report( :commitId: str :report_key: str """ - url = self._url_code_insights_report( - project_key, repository_slug, commit_id, report_key - ) + url = self._url_code_insights_report(project_key, repository_slug, commit_id, report_key) return self.delete(url) def create_code_insights_report( - self, - project_key, - repository_slug, - commit_id, - report_key, - report_title, - **report_params + self, project_key, repository_slug, commit_id, report_key, report_title, **report_params ): """ Create a new insight report, or replace the existing one @@ -1844,16 +1744,12 @@ def create_code_insights_report( :report_title: str :report_params: """ - url = self._url_code_insights_report( - project_key, repository_slug, commit_id, report_key - ) + url = self._url_code_insights_report(project_key, repository_slug, commit_id, report_key) data = {"title": report_title} data.update(report_params) return self.put(url, data=data) - def get_file_list( - self, project_key, repository_slug, query=None, start=0, limit=None - ): + def get_file_list(self, project_key, repository_slug, query=None, start=0, limit=None): """ Retrieve a page of files from particular directory of a repository. The search is done recursively, so all files from any sub-directory of the specified directory will be returned. @@ -1875,9 +1771,7 @@ def get_file_list( params["limit"] = limit return self._get_paged(url, params=params) - def get_content_of_file( - self, project_key, repository_slug, filename, at=None, markup=None - ): + def get_content_of_file(self, project_key, repository_slug, filename, at=None, markup=None): """ Retrieve the raw content for a file path at a specified revision. The authenticated user must have REPO_READ permission for the specified repository to call this resource. @@ -1898,13 +1792,9 @@ def get_content_of_file( headers = self.form_token_headers return self.get(url, params=params, not_json_response=True, headers=headers) - def _url_branches_permissions( - self, project_key, permission_id=None, repository_slug=None - ): + def _url_branches_permissions(self, project_key, permission_id=None, repository_slug=None): if repository_slug is None: - base = self._url_project( - project_key, api_root="rest/branch-permissions", api_version="2.0" - ) + base = self._url_project(project_key, api_root="rest/branch-permissions", api_version="2.0") else: base = self._url_repo( project_key, @@ -1913,13 +1803,9 @@ def _url_branches_permissions( api_version="2.0", ) - return "{}/restrictions/{}".format( - base, "" if permission_id is None else str(permission_id) - ) + return "{}/restrictions/{}".format(base, "" if permission_id is None else str(permission_id)) - def get_branches_permissions( - self, project_key, permission_id, repository_slug=None, start=0, limit=25 - ): + def get_branches_permissions(self, project_key, permission_id, repository_slug=None, start=0, limit=25): """ Get branches permissions from a given repo :param project_key: @@ -1929,9 +1815,7 @@ def get_branches_permissions( :param limit: :return: """ - url = self._url_branches_permissions( - project_key, permission_id, repository_slug - ) + url = self._url_branches_permissions(project_key, permission_id, repository_slug) params = {} if limit: params["limit"] = limit @@ -1972,9 +1856,7 @@ def set_branches_permissions( :param limit: :return: """ - url = self._url_branches_permissions( - project_key=project_key, repository_slug=repository_slug - ) + url = self._url_branches_permissions(project_key=project_key, repository_slug=repository_slug) if except_users is None: except_users = [] if except_groups is None: @@ -2004,9 +1886,7 @@ def set_branches_permissions( params = {"start": start, "limit": limit} return self.post(url, data=restriction, params=params, headers=headers) - def delete_branch_permission( - self, project_key, permission_id, repository_slug=None - ): + def delete_branch_permission(self, project_key, permission_id, repository_slug=None): """ Deletes a restriction as specified by a restriction id. The authenticated user must have REPO_ADMIN permission or higher to call this resource. @@ -2016,9 +1896,7 @@ def delete_branch_permission( :param permission_id: :return: """ - url = self._url_branches_permissions( - project_key, permission_id, repository_slug - ) + url = self._url_branches_permissions(project_key, permission_id, repository_slug) return self.delete(url) def get_branch_permission(self, project_key, permission_id, repository_slug=None): @@ -2031,14 +1909,10 @@ def get_branch_permission(self, project_key, permission_id, repository_slug=None :param permission_id: :return: """ - url = self._url_branches_permissions( - project_key, permission_id, repository_slug - ) + url = self._url_branches_permissions(project_key, permission_id, repository_slug) return self.get(url) - def all_branches_permissions( - self, project_key, permission_id, repository_slug=None - ): + def all_branches_permissions(self, project_key, permission_id, repository_slug=None): """ Get branches permissions from a given repo :param project_key: @@ -2046,16 +1920,12 @@ def all_branches_permissions( :param repository_slug: :return: """ - url = self._url_branches_permissions( - project_key, permission_id, repository_slug - ) + url = self._url_branches_permissions(project_key, permission_id, repository_slug) return self._get_paged(url) def _url_branching_model(self, project_key, repository_slug): return self.resource_url( - "{}/branchmodel/configuration".format( - self._url_repo(project_key, repository_slug) - ), + "{}/branchmodel/configuration".format(self._url_repo(project_key, repository_slug)), api_root="rest/branch-utils", api_version="1.0", ) @@ -2117,9 +1987,7 @@ def enable_branching_model(self, project_key, repository_slug): }, ], } - return self.set_branching_model( - project_key, repository_slug, default_model_data - ) + return self.set_branching_model(project_key, repository_slug, default_model_data) def disable_branching_model(self, project_key, repository_slug): """ @@ -2131,13 +1999,9 @@ def disable_branching_model(self, project_key, repository_slug): return self.delete(self._url_branching_model(project_key, repository_slug)) def _url_file(self, project_key, repository_slug, filename): - return "{}/browse/{}".format( - self._url_repo(project_key, repository_slug), filename - ) + return "{}/browse/{}".format(self._url_repo(project_key, repository_slug), filename) - def upload_file( - self, project_key, repository_slug, content, message, branch, filename - ): + def upload_file(self, project_key, repository_slug, content, message, branch, filename): """ Upload new file for given branch. :param project_key: @@ -2189,9 +2053,7 @@ def search_code(self, team, search_query, page=1, limit=10): :search_query: str """ url = self.resource_url("teams/{team}/search/code".format(team=team)) - return self.get( - url, params={"search_query": search_query, "page": page, "pagelen": limit} - ) + return self.get(url, params={"search_query": search_query, "page": page, "pagelen": limit}) def get_lfs_repo_status(self, project_key, repo): url = "rest/git-lfs/git-lfs/admin/projects/{projectKey}/repos/{repositorySlug}/enabled".format( @@ -2202,7 +2064,10 @@ def get_lfs_repo_status(self, project_key, repo): def _url_repo_conditions(self, project_key, repo_key): return "{}/conditions".format( self._url_repo( - project_key, repo_key, api_root="rest/default-reviewers", api_version="1.0" + project_key, + repo_key, + api_root="rest/default-reviewers", + api_version="1.0", ) ) @@ -2261,7 +2126,10 @@ def get_repo_repo_conditions(self, project_key, repo_key): def _url_repo_condition(self, project_key, repo_key, id_condition=None): return "{}/condition/{}".format( self._url_repo( - project_key, repo_key, api_root="rest/default-reviewers", api_version="1.0" + project_key, + repo_key, + api_root="rest/default-reviewers", + api_version="1.0", ), "" if id_condition is None else str(id_condition), ) @@ -2360,9 +2228,7 @@ def get_repositories(self, workspace, role=None, query=None, sort=None): version="2.0.2", reason="Use atlassion.bitbucket.cloud instead of atlassian.bitbucket", ) - def get_pipelines( - self, workspace, repository_slug, number=10, sort_by="-created_on" - ): + def get_pipelines(self, workspace, repository_slug, number=10, sort_by="-created_on"): """ Get information about latest pipelines runs. @@ -2387,9 +2253,7 @@ def get_pipelines( version="2.0.2", reason="Use atlassion.bitbucket.cloud instead of atlassian.bitbucket", ) - def trigger_pipeline( - self, workspace, repository_slug, branch="master", revision=None, name=None - ): + def trigger_pipeline(self, workspace, repository_slug, branch="master", revision=None, name=None): """ Trigger a new pipeline. The following options are possible (1 and 2 trigger the pipeline that the branch is associated with in the Pipelines @@ -2487,9 +2351,7 @@ def get_pipeline_step(self, workspace, repository_slug, pipeline_uuid, step_uuid version="2.0.2", reason="Use atlassion.bitbucket.cloud instead of atlassian.bitbucket", ) - def get_pipeline_step_log( - self, workspace, repository_slug, pipeline_uuid, step_uuid - ): + def get_pipeline_step_log(self, workspace, repository_slug, pipeline_uuid, step_uuid): """ Get log of a step of a pipeline, specified by respective UUIDs. :param pipeline_uuid: Pipeline identifier (with surrounding {}; NOT the build number) @@ -2527,9 +2389,7 @@ def create_issue( Cloud(self.url, **self._new_session_args) .workspaces.get(workspace) .repositories.get(repository_slug) - .issues.create( - title=title, description=description, kind=kind, priority=priority - ) + .issues.create(title=title, description=description, kind=kind, priority=priority) .data ) @@ -2663,9 +2523,7 @@ def add_branch_restriction( version="2.0.2", reason="Use atlassion.bitbucket.cloud instead of atlassian.bitbucket", ) - def get_branch_restrictions( - self, workspace, repository_slug, kind=None, pattern=None, number=10 - ): + def get_branch_restrictions(self, workspace, repository_slug, kind=None, pattern=None, number=10): """ Get all branch permissions. """ diff --git a/atlassian/bitbucket/base.py b/atlassian/bitbucket/base.py index a3012ab81..305c88bed 100644 --- a/atlassian/bitbucket/base.py +++ b/atlassian/bitbucket/base.py @@ -21,9 +21,7 @@ def __init__(self, url, *args, **kwargs): expected_type = kwargs.pop("expected_type") if not self.get_data("type") == expected_type: raise ValueError( - "Expected type of data is [{}], got [{}].".format( - expected_type, self.get_data("type") - ) + "Expected type of data is [{}], got [{}].".format(expected_type, self.get_data("type")) ) if url is None: url = self.get_link("self") diff --git a/atlassian/bitbucket/cloud/__init__.py b/atlassian/bitbucket/cloud/__init__.py index b59f4dcce..dc852e018 100644 --- a/atlassian/bitbucket/cloud/__init__.py +++ b/atlassian/bitbucket/cloud/__init__.py @@ -14,12 +14,8 @@ def __init__(self, url, *args, **kwargs): kwargs["api_version"] = "2.0" url = url.strip("/") + "/{}".format(kwargs["api_version"]) super(Cloud, self).__init__(url, *args, **kwargs) - self.__workspaces = Workspaces( - "{}/workspaces".format(self.url), **self._new_session_args - ) - self.__repositories = Repositories( - "{}/repositories".format(self.url), **self._new_session_args - ) + self.__workspaces = Workspaces("{}/workspaces".format(self.url), **self._new_session_args) + self.__repositories = Repositories("{}/repositories".format(self.url), **self._new_session_args) @property def workspaces(self): diff --git a/atlassian/bitbucket/cloud/base.py b/atlassian/bitbucket/cloud/base.py index 4280aaca7..f6114d2db 100644 --- a/atlassian/bitbucket/cloud/base.py +++ b/atlassian/bitbucket/cloud/base.py @@ -15,9 +15,7 @@ def __init__(self, url, *args, **kwargs): """ super(BitbucketCloudBase, self).__init__(url, *args, **kwargs) - def _get_paged( - self, url, params={}, data=None, flags=None, trailing=None, absolute=False - ): + def _get_paged(self, url, params={}, data=None, flags=None, trailing=None, absolute=False): """ Used to get the paged data :param url: The url to retrieve. diff --git a/atlassian/bitbucket/cloud/repositories/__init__.py b/atlassian/bitbucket/cloud/repositories/__init__.py index 7c0ddb888..45475767e 100644 --- a/atlassian/bitbucket/cloud/repositories/__init__.py +++ b/atlassian/bitbucket/cloud/repositories/__init__.py @@ -109,11 +109,7 @@ def get(self, repository, by="slug"): if r.name == repository: return r else: - ValueError( - "Unknown value '{}' for argument [by], expected 'key' or 'name'".format( - by - ) - ) + ValueError("Unknown value '{}' for argument [by], expected 'key' or 'name'".format(by)) raise Exception("Unknown repository {} '{}'".format(by, repository)) @@ -148,16 +144,10 @@ def get(self, repository, by="slug"): :return: The requested Repository object """ if by not in ("slug", "name"): - ValueError( - "Unknown value '{}' for argument [by], expected 'slug' or 'name'".format( - by - ) - ) + ValueError("Unknown value '{}' for argument [by], expected 'slug' or 'name'".format(by)) for r in self.each(): - if ((by == "slug") and (r.slug == repository)) or ( - (by == "name") and (r.name == repository) - ): + if ((by == "slug") and (r.slug == repository)) or ((by == "name") and (r.name == repository)): return r raise Exception("Unknown repository {} '{}'".format(by, repository)) @@ -165,19 +155,13 @@ def get(self, repository, by="slug"): class Repository(BitbucketCloudBase): def __init__(self, data, *args, **kwargs): - super(Repository, self).__init__( - None, *args, data=data, expected_type="repository", **kwargs - ) + super(Repository, self).__init__(None, *args, data=data, expected_type="repository", **kwargs) self.__branch_restrictions = BranchRestrictions( "{}/branch-restrictions".format(self.url), **self._new_session_args ) - self.__default_reviewers = DefaultReviewers( - "{}/default-reviewers".format(self.url), **self._new_session_args - ) + self.__default_reviewers = DefaultReviewers("{}/default-reviewers".format(self.url), **self._new_session_args) self.__issues = Issues("{}/issues".format(self.url), **self._new_session_args) - self.__pipelines = Pipelines( - "{}/pipelines".format(self.url), **self._new_session_args - ) + self.__pipelines = Pipelines("{}/pipelines".format(self.url), **self._new_session_args) @property def branch_restrictions(self): diff --git a/atlassian/bitbucket/cloud/repositories/branchRestrictions.py b/atlassian/bitbucket/cloud/repositories/branchRestrictions.py index 228ce4e37..62c07dc79 100644 --- a/atlassian/bitbucket/cloud/repositories/branchRestrictions.py +++ b/atlassian/bitbucket/cloud/repositories/branchRestrictions.py @@ -105,9 +105,7 @@ def get(self, id): class BranchRestriction(BitbucketCloudBase): def __init__(self, data, *args, **kwargs): - super(BranchRestriction, self).__init__( - None, *args, data=data, expected_type="branchrestriction", **kwargs - ) + super(BranchRestriction, self).__init__(None, *args, data=data, expected_type="branchrestriction", **kwargs) @property def id(self): @@ -146,9 +144,7 @@ def update(self, **kwargs): Updates an existing branch restriction rule. Fields not present in the request body are ignored. """ - self.__data = super(BranchRestriction, self).put( - self.url, absolute=True, data=kwargs - ) + self.__data = super(BranchRestriction, self).put(self.url, absolute=True, data=kwargs) return self def delete(self): diff --git a/atlassian/bitbucket/cloud/repositories/defaultReviewers.py b/atlassian/bitbucket/cloud/repositories/defaultReviewers.py index 61aa7fa2a..1a4737ea4 100644 --- a/atlassian/bitbucket/cloud/repositories/defaultReviewers.py +++ b/atlassian/bitbucket/cloud/repositories/defaultReviewers.py @@ -72,9 +72,7 @@ def get(self, user): class DefaultReviewer(BitbucketCloudBase): def __init__(self, data, *args, **kwargs): - super(DefaultReviewer, self).__init__( - None, *args, data=data, expected_type="user", **kwargs - ) + super(DefaultReviewer, self).__init__(None, *args, data=data, expected_type="user", **kwargs) @property def display_name(self): diff --git a/atlassian/bitbucket/cloud/repositories/issues.py b/atlassian/bitbucket/cloud/repositories/issues.py index 5d6d21b0e..c2e10ad17 100644 --- a/atlassian/bitbucket/cloud/repositories/issues.py +++ b/atlassian/bitbucket/cloud/repositories/issues.py @@ -65,9 +65,7 @@ def get(self, id): class Issue(BitbucketCloudBase): def __init__(self, data, *args, **kwargs): - super(Issue, self).__init__( - None, *args, data=data, expected_type="issue", **kwargs - ) + super(Issue, self).__init__(None, *args, data=data, expected_type="issue", **kwargs) @property def id(self): diff --git a/atlassian/bitbucket/cloud/repositories/pipelines.py b/atlassian/bitbucket/cloud/repositories/pipelines.py index 7d6e24e7d..0ef0abab5 100644 --- a/atlassian/bitbucket/cloud/repositories/pipelines.py +++ b/atlassian/bitbucket/cloud/repositories/pipelines.py @@ -94,16 +94,12 @@ def trigger(self, branch="master", commit=None, pattern=None, variables=None): class Pipeline(BitbucketCloudBase): def __init__(self, data, *args, **kwargs): - super(Pipeline, self).__init__( - None, *args, data=data, expected_type="pipeline", **kwargs - ) + super(Pipeline, self).__init__(None, *args, data=data, expected_type="pipeline", **kwargs) def _get_object(self, data): if "errors" in data: return - return Step( - "{}/steps/{}".format(self.url, data["uuid"]), data, **self._new_session_args - ) + return Step("{}/steps/{}".format(self.url, data["uuid"]), data, **self._new_session_args) @property def uuid(self): @@ -150,9 +146,7 @@ def step(self, uuid): class Step(BitbucketCloudBase): def __init__(self, url, data, *args, **kwargs): - super(Step, self).__init__( - url, *args, data=data, expected_type="pipeline_step", **kwargs - ) + super(Step, self).__init__(url, *args, data=data, expected_type="pipeline_step", **kwargs) @property def uuid(self): @@ -197,9 +191,7 @@ def log(self, start=None, end=None): the overall size and the byte representation of the requested range. """ headers = {"Accept": "application/octet-stream"} - if ((start is not None) and (end is None)) or ( - (start is None) and (end is not None) - ): + if ((start is not None) and (end is None)) or ((start is None) and (end is not None)): raise ValueError("For a range [start] and [end] are needed.") if start is not None: start = int(start) @@ -207,9 +199,7 @@ def log(self, start=None, end=None): if (start >= 0) and (start < end): headers["Range"] = "bytes={}-{}".format(start, end) else: - raise ValueError( - "Value of [start] must be o or greater and [end] must be greater than [start]." - ) + raise ValueError("Value of [start] must be o or greater and [end] must be greater than [start].") response = None try: diff --git a/atlassian/bitbucket/cloud/workspaces/__init__.py b/atlassian/bitbucket/cloud/workspaces/__init__.py index 9df3c08b6..775a8a773 100644 --- a/atlassian/bitbucket/cloud/workspaces/__init__.py +++ b/atlassian/bitbucket/cloud/workspaces/__init__.py @@ -58,13 +58,9 @@ def get(self, workspace): class Workspace(BitbucketCloudBase): def __init__(self, data, *args, **kwargs): - super(Workspace, self).__init__( - None, *args, data=data, expected_type="workspace", **kwargs - ) + super(Workspace, self).__init__(None, *args, data=data, expected_type="workspace", **kwargs) self.__projects = Projects(self.get_link("projects"), **self._new_session_args) - self.__repositories = WorkspaceRepositories( - self.get_link("repositories"), **self._new_session_args - ) + self.__repositories = WorkspaceRepositories(self.get_link("repositories"), **self._new_session_args) @property def projects(self): diff --git a/atlassian/bitbucket/cloud/workspaces/projects.py b/atlassian/bitbucket/cloud/workspaces/projects.py index c0a834bcc..e879b20ae 100644 --- a/atlassian/bitbucket/cloud/workspaces/projects.py +++ b/atlassian/bitbucket/cloud/workspaces/projects.py @@ -84,27 +84,19 @@ def get(self, project, by="key"): if p.name == project: return p else: - ValueError( - "Unknown value '{}' for argument [by], expected 'key' or 'name'".format( - by - ) - ) + ValueError("Unknown value '{}' for argument [by], expected 'key' or 'name'".format(by)) raise Exception("Unknown project {} '{}'".format(by, project)) class Project(BitbucketCloudBase): def __init__(self, data, *args, **kwargs): - super(Project, self).__init__( - None, *args, data=data, expected_type="project", **kwargs - ) + super(Project, self).__init__(None, *args, data=data, expected_type="project", **kwargs) try: url = self.get_link("repositories") except KeyError: workspace = self.get_data("workspace") - url = '{}/?q=project.key="{}"'.format( - workspace["links"]["self"], workspace["slug"] - ) + url = '{}/?q=project.key="{}"'.format(workspace["links"]["self"], workspace["slug"]) self.__repositories = ProjectRepositories(url, **self._new_session_args) @property diff --git a/atlassian/confluence.py b/atlassian/confluence.py index db8930a46..a2830c5fb 100644 --- a/atlassian/confluence.py +++ b/atlassian/confluence.py @@ -40,30 +40,20 @@ def __init__(self, url, *args, **kwargs): @staticmethod def _create_body(body, representation): if representation not in ["editor", "export_view", "view", "storage", "wiki"]: - raise ValueError( - "Wrong value for representation, it should be either wiki or storage" - ) + raise ValueError("Wrong value for representation, it should be either wiki or storage") return {representation: {"value": body, "representation": representation}} def page_exists(self, space, title): try: if self.get_page_by_title(space, title): - log.info( - 'Page "{title}" already exists in space "{space}"'.format( - space=space, title=title - ) - ) + log.info('Page "{title}" already exists in space "{space}"'.format(space=space, title=title)) return True else: log.info("Page does not exist because did not find by title search") return False except (HTTPError, KeyError, IndexError): - log.info( - 'Page "{title}" does not exist in space "{space}"'.format( - space=space, title=title - ) - ) + log.info('Page "{title}" does not exist in space "{space}"'.format(space=space, title=title)) return False def get_page_child_by_type(self, page_id, type="page", start=None, limit=None): @@ -81,9 +71,7 @@ def get_page_child_by_type(self, page_id, type="page", start=None, limit=None): if limit is not None: params["limit"] = int(limit) - url = "rest/api/content/{page_id}/child/{type}".format( - page_id=page_id, type=type - ) + url = "rest/api/content/{page_id}/child/{type}".format(page_id=page_id, type=type) log.info(url) try: @@ -154,12 +142,9 @@ def get_parent_content_id(self, page_id): """ parent_content_id = None try: - parent_content_id = ( - self.get_page_by_id(page_id=page_id, expand="ancestors").get( - "ancestors" - ) - or {} - )[-1].get("id") or None + parent_content_id = (self.get_page_by_id(page_id=page_id, expand="ancestors").get("ancestors") or {})[ + -1 + ].get("id") or None except Exception as e: log.error(e) return parent_content_id @@ -172,12 +157,9 @@ def get_parent_content_title(self, page_id): """ parent_content_title = None try: - parent_content_title = ( - self.get_page_by_id(page_id=page_id, expand="ancestors").get( - "ancestors" - ) - or {} - )[-1].get("title") or None + parent_content_title = (self.get_page_by_id(page_id=page_id, expand="ancestors").get("ancestors") or {})[ + -1 + ].get("title") or None except Exception as e: log.error(e) return parent_content_title @@ -188,9 +170,7 @@ def get_page_space(self, page_id): :param page_id: content ID :return: """ - return ( - (self.get_page_by_id(page_id, expand="space") or {}).get("space") or {} - ).get("key") + return ((self.get_page_by_id(page_id, expand="space") or {}).get("space") or {}).get("key") def get_pages_by_title(self, space, title, start=0, limit=200, expand=None): """ @@ -248,11 +228,7 @@ def get_page_by_title(self, space, title, start=0, limit=1, expand=None): try: return response.get("results")[0] except (IndexError, TypeError) as e: - log.error( - "Can't find '{title}' page on the {url}!".format( - title=title, url=self.url - ) - ) + log.error("Can't find '{title}' page on the {url}!".format(title=title, url=self.url)) log.debug(e) return None @@ -332,14 +308,14 @@ def get_page_labels(self, page_id, prefix=None, start=None, limit=None): return response def get_page_comments( - self, - content_id, - expand=None, - parent_version=None, - start=0, - limit=25, - location=None, - depth=None, + self, + content_id, + expand=None, + parent_version=None, + start=0, + limit=25, + location=None, + depth=None, ): """ @@ -385,9 +361,7 @@ def get_draft_page_by_id(self, page_id, status="draft"): :param status: :return: """ - url = "rest/api/content/{page_id}?status={status}".format( - page_id=page_id, status=status - ) + url = "rest/api/content/{page_id}?status={status}".format(page_id=page_id, status=status) try: response = self.get(url) @@ -414,9 +388,7 @@ def get_all_pages_by_label(self, label, start=0, limit=50): url = "rest/api/content/search" params = {} if label: - params["cql"] = 'type={type} AND label="{label}"'.format( - type="page", label=label - ) + params["cql"] = 'type={type} AND label="{label}"'.format(type="page", label=label) if start: params["start"] = start if limit: @@ -432,9 +404,7 @@ def get_all_pages_by_label(self, label, start=0, limit=50): return response.get("results") - def get_all_pages_from_space( - self, space, start=0, limit=50, status=None, expand=None, content_type="page" - ): + def get_all_pages_from_space(self, space, start=0, limit=50, status=None, expand=None, content_type="page"): """ Get all pages from space @@ -479,9 +449,7 @@ def get_all_pages_from_space( return response.get("results") - def get_all_pages_from_space_trash( - self, space, start=0, limit=500, status="trashed", content_type="page" - ): + def get_all_pages_from_space_trash(self, space, start=0, limit=500, status="trashed", content_type="page"): """ Get list of pages from trash :param space: @@ -492,9 +460,7 @@ def get_all_pages_from_space_trash( :param content_type: the content type to return. Default value: page. Valid values: page, blogpost. :return: """ - return self.get_all_pages_from_space( - space, start, limit, status, content_type=content_type - ) + return self.get_all_pages_from_space(space, start, limit, status, content_type=content_type) def get_all_draft_pages_from_space(self, space, start=0, limit=500, status="draft"): """ @@ -509,9 +475,7 @@ def get_all_draft_pages_from_space(self, space, start=0, limit=500, status="draf """ return self.get_all_pages_from_space(space, start, limit, status) - def get_all_draft_pages_from_space_through_cql( - self, space, start=0, limit=500, status="draft" - ): + def get_all_draft_pages_from_space_through_cql(self, space, start=0, limit=500, status="draft"): """ Search list of draft pages by space key Use case is cleanup old drafts from Confluence @@ -522,9 +486,7 @@ def get_all_draft_pages_from_space_through_cql( fixed system limits. Default: 500 :return: """ - url = "rest/api/content?cql=space=spaceKey={space} and status={status}".format( - space=space, status=status - ) + url = "rest/api/content?cql=space=spaceKey={space} and status={status}".format(space=space, status=status) params = {} if limit: params["limit"] = limit @@ -638,14 +600,14 @@ def remove_page(self, page_id, status=None, recursive=False): return response def create_page( - self, - space, - title, - body, - parent_id=None, - type="page", - representation="storage", - editor=None, + self, + space, + title, + body, + parent_id=None, + type="page", + representation="storage", + editor=None, ): """ Create page from scratch @@ -658,11 +620,7 @@ def create_page( :param editor: OPTIONAL: v2 to be created in the new editor :return: """ - log.info( - 'Creating {type} "{space}" -> "{title}"'.format( - space=space, title=title, type=type - ) - ) + log.info('Creating {type} "{space}" -> "{title}"'.format(space=space, title=title, type=type)) url = "rest/api/content/" data = { "type": type, @@ -687,9 +645,7 @@ def create_page( return response - def move_page( - self, space_key, page_id, target_id=None, target_title=None, position="append" - ): + def move_page(self, space_key, page_id, target_id=None, target_title=None, position="append"): """ Move page method :param space_key: @@ -845,14 +801,14 @@ def add_comment(self, page_id, text): return response def attach_content( - self, - content, - name, - content_type="application/binary", - page_id=None, - title=None, - space=None, - comment=None, + self, + content, + name, + content_type="application/binary", + page_id=None, + title=None, + space=None, + comment=None, ): """ Attach (upload) a file to a page, if it exists it will update the @@ -872,14 +828,10 @@ def attach_content( :param comment: A comment describing this upload/file :type comment: ``str`` """ - page_id = ( - self.get_page_id(space=space, title=title) if page_id is None else page_id - ) + page_id = self.get_page_id(space=space, title=title) if page_id is None else page_id type = "attachment" if page_id is not None: - comment = ( - comment if comment else "Uploaded {filename}.".format(filename=name) - ) + comment = comment if comment else "Uploaded {filename}.".format(filename=name) data = { "type": type, "fileName": name, @@ -890,9 +842,7 @@ def attach_content( headers = {"X-Atlassian-Token": "nocheck", "Accept": "application/json"} path = "rest/api/content/{page_id}/child/attachment".format(page_id=page_id) # Check if there is already a file with the same name - attachments = self.get( - path=path, headers=headers, params={"filename": name} - ) + attachments = self.get(path=path, headers=headers, params={"filename": name}) if attachments.get("size"): path = path + "/" + attachments["results"][0]["id"] + "/data" @@ -928,14 +878,14 @@ def attach_content( return None def attach_file( - self, - filename, - name=None, - content_type=None, - page_id=None, - title=None, - space=None, - comment=None, + self, + filename, + name=None, + content_type=None, + page_id=None, + title=None, + space=None, + comment=None, ): """ Attach (upload) a file to a page, if it exists it will update the @@ -1000,14 +950,10 @@ def delete_attachment_by_id(self, attachment_id, version): :return: """ return self.delete( - "rest/experimental/content/{id}/version/{versionId}".format( - id=attachment_id, versionId=version - ) + "rest/experimental/content/{id}/version/{versionId}".format(id=attachment_id, versionId=version) ) - def remove_page_attachment_keep_version( - self, page_id, filename, keep_last_versions - ): + def remove_page_attachment_keep_version(self, page_id, filename, keep_last_versions): """ Keep last versions :param filename: @@ -1015,14 +961,12 @@ def remove_page_attachment_keep_version( :param keep_last_versions: :return: """ - attachment = self.get_attachments_from_content( - page_id=page_id, expand="version", filename=filename - ).get("results")[0] + attachment = self.get_attachments_from_content(page_id=page_id, expand="version", filename=filename).get( + "results" + )[0] attachment_versions = self.get_attachment_history(attachment.get("id")) while len(attachment_versions) > keep_last_versions: - remove_version_attachment_number = attachment_versions[ - keep_last_versions - ].get("number") + remove_version_attachment_number = attachment_versions[keep_last_versions].get("number") self.delete_attachment_by_id( attachment_id=attachment.get("id"), version=remove_version_attachment_number, @@ -1033,11 +977,7 @@ def remove_page_attachment_keep_version( ) ) attachment_versions = self.get_attachment_history(attachment.get("id")) - log.info( - "Kept versions {} for {}".format( - keep_last_versions, attachment.get("title") - ) - ) + log.info("Kept versions {} for {}".format(keep_last_versions, attachment.get("title"))) def get_attachment_history(self, attachment_id, limit=200, start=0): """ @@ -1052,9 +992,7 @@ def get_attachment_history(self, attachment_id, limit=200, start=0): return (self.get(url, params=params) or {}).get("results") # @todo prepare more attachments info - def get_attachments_from_content( - self, page_id, start=0, limit=50, expand=None, filename=None, media_type=None - ): + def get_attachments_from_content(self, page_id, start=0, limit=50, expand=None, filename=None, media_type=None): """ Get attachments for page :param page_id: @@ -1133,8 +1071,7 @@ def remove_page_label(self, page_id, label): except HTTPError as e: if e.response.status_code == 403: raise ApiPermissionError( - "The user has view permission, " - "but no edit permission to the content", + "The user has view permission, " "but no edit permission to the content", reason=e, ) if e.response.status_code == 404: @@ -1176,9 +1113,7 @@ def get_content_history_by_version_number(self, content_id, version_number): :param version_number: :return: """ - url = "rest/experimental/content/{0}/version/{1}".format( - content_id, version_number - ) + url = "rest/experimental/content/{0}/version/{1}".format(content_id, version_number) return self.get(url) def remove_content_history(self, page_id, version_number): @@ -1188,9 +1123,7 @@ def remove_content_history(self, page_id, version_number): :param version_number: version number :return: """ - url = "rest/experimental/content/{id}/version/{versionNumber}".format( - id=page_id, versionNumber=version_number - ) + url = "rest/experimental/content/{id}/version/{versionNumber}".format(id=page_id, versionNumber=version_number) self.delete(url) def remove_page_history(self, page_id, version_number): @@ -1209,9 +1142,7 @@ def remove_content_history_in_cloud(self, page_id, version_id): :param version_id: :return: """ - url = "rest/api/content/{id}/version/{versionId}".format( - id=page_id, versionId=version_id - ) + url = "rest/api/content/{id}/version/{versionId}".format(id=page_id, versionId=version_id) self.delete(url) def remove_page_history_keep_version(self, page_id, keep_last_versions): @@ -1227,14 +1158,8 @@ def remove_page_history_keep_version(self, page_id, keep_last_versions): self.remove_page_history(page_id=page_id, version_number=1) page = self.get_page_by_id(page_id=page_id, expand="version") page_number = page.get("version").get("number") - log.info( - "Removed oldest version for {}, now it's {}".format( - page.get("title"), page_number - ) - ) - log.info( - "Kept versions {} for {}".format(keep_last_versions, page.get("title")) - ) + log.info("Removed oldest version for {}, now it's {}".format(page.get("title"), page_number)) + log.info("Kept versions {} for {}".format(keep_last_versions, page.get("title"))) def has_unknown_attachment_error(self, page_id): """ @@ -1242,9 +1167,7 @@ def has_unknown_attachment_error(self, page_id): :param page_id: :return: """ - unknown_attachment_identifier = ( - "plugins/servlet/confluence/placeholder/unknown-attachment" - ) + unknown_attachment_identifier = "plugins/servlet/confluence/placeholder/unknown-attachment" result = self.get_page_by_id(page_id, expand="body.view") if len(result) == 0: return "" @@ -1270,16 +1193,12 @@ def is_page_content_is_already_updated(self, page_id, body, title=None): if self.advanced_mode: confluence_content = ( - (self.get_page_by_id(page_id, expand="body.storage").json() or {}).get( - "body" - ) - or {} - ).get("storage") or {} + (self.get_page_by_id(page_id, expand="body.storage").json() or {}).get("body") or {} + ).get("storage") or {} else: - confluence_content = ( - (self.get_page_by_id(page_id, expand="body.storage") or {}).get("body") - or {} - ).get("storage") or {} + confluence_content = ((self.get_page_by_id(page_id, expand="body.storage") or {}).get("body") or {}).get( + "storage" + ) or {} confluence_body_content = confluence_content.get("value") @@ -1291,23 +1210,21 @@ def is_page_content_is_already_updated(self, page_id, body, title=None): log.debug('New Content: """{body}"""'.format(body=body)) if confluence_body_content.strip() == body.strip(): - log.warning( - "Content of {page_id} is exactly the same".format(page_id=page_id) - ) + log.warning("Content of {page_id} is exactly the same".format(page_id=page_id)) return True else: log.info("Content of {page_id} differs".format(page_id=page_id)) return False def update_existing_page( - self, - page_id, - title, - body, - type="page", - representation="storage", - minor_edit=False, - version_comment=None, + self, + page_id, + title, + body, + type="page", + representation="storage", + minor_edit=False, + version_comment=None, ): """Duplicate update_page. Left for the people who used it before. Use update_page instead""" return self.update_page( @@ -1322,15 +1239,15 @@ def update_existing_page( ) def update_page( - self, - page_id, - title, - body=None, - parent_id=None, - type="page", - representation="storage", - minor_edit=False, - version_comment=None, + self, + page_id, + title, + body=None, + parent_id=None, + type="page", + representation="storage", + minor_edit=False, + version_comment=None, ): """ Update page if already exist @@ -1347,9 +1264,7 @@ def update_page( """ log.info('Updating {type} "{title}"'.format(title=title, type=type)) - if body is not None and self.is_page_content_is_already_updated( - page_id, body, title - ): + if body is not None and self.is_page_content_is_already_updated(page_id, body, title): return self.get_page_by_id(page_id) try: @@ -1387,25 +1302,23 @@ def update_page( reason=e, ) if e.response.status_code == 404: - raise ApiNotFoundError( - "Can not find draft with current content", reason=e - ) + raise ApiNotFoundError("Can not find draft with current content", reason=e) raise return response def _insert_to_existing_page( - self, - page_id, - title, - insert_body, - parent_id=None, - type="page", - representation="storage", - minor_edit=False, - version_comment=None, - top_of_page=False, + self, + page_id, + title, + insert_body, + parent_id=None, + type="page", + representation="storage", + minor_edit=False, + version_comment=None, + top_of_page=False, ): """ Insert body to a page if already exist @@ -1427,16 +1340,10 @@ def _insert_to_existing_page( else: version = self.history(page_id)["lastUpdated"]["number"] + 1 previous_body = ( - (self.get_page_by_id(page_id, expand="body.storage").get("body") or {}) - .get("storage") - .get("value") + (self.get_page_by_id(page_id, expand="body.storage").get("body") or {}).get("storage").get("value") ) previous_body = previous_body.replace("ó", u"ó") - body = ( - insert_body + previous_body - if top_of_page - else previous_body + insert_body - ) + body = insert_body + previous_body if top_of_page else previous_body + insert_body data = { "id": page_id, "type": type, @@ -1461,23 +1368,21 @@ def _insert_to_existing_page( reason=e, ) if e.response.status_code == 404: - raise ApiNotFoundError( - "Can not find draft with current content", reason=e - ) + raise ApiNotFoundError("Can not find draft with current content", reason=e) raise return response def append_page( - self, - page_id, - title, - append_body, - parent_id=None, - type="page", - representation="storage", - minor_edit=False, + self, + page_id, + title, + append_body, + parent_id=None, + type="page", + representation="storage", + minor_edit=False, ): """ Append body to page if already exist @@ -1505,14 +1410,14 @@ def append_page( ) def prepend_page( - self, - page_id, - title, - prepend_body, - parent_id=None, - type="page", - representation="storage", - minor_edit=False, + self, + page_id, + title, + prepend_body, + parent_id=None, + type="page", + representation="storage", + minor_edit=False, ): """ Append body to page if already exist @@ -1540,13 +1445,13 @@ def prepend_page( ) def update_or_create( - self, - parent_id, - title, - body, - representation="storage", - minor_edit=False, - version_comment=None, + self, + parent_id, + title, + body, + representation="storage", + minor_edit=False, + version_comment=None, ): """ Update page or create a page if it is not exists @@ -1562,11 +1467,7 @@ def update_or_create( if self.page_exists(space, title): page_id = self.get_page_id(space, title) - parent_id = ( - parent_id - if parent_id is not None - else self.get_parent_content_id(page_id) - ) + parent_id = parent_id if parent_id is not None else self.get_parent_content_id(page_id) result = self.update_page( parent_id=parent_id, page_id=page_id, @@ -1632,8 +1533,7 @@ def set_page_property(self, page_id, data): ) if e.response.status_code == 403: raise ApiPermissionError( - "The user does not have permission to " - "edit the content with the given id", + "The user does not have permission to " "edit the content with the given id", reason=e, ) if e.response.status_code == 413: @@ -1651,9 +1551,7 @@ def update_page_property(self, page_id, data): :data: property data in json format :return: """ - url = "rest/api/content/{page_id}/property/{key}".format( - page_id=page_id, key=data.get("key") - ) + url = "rest/api/content/{page_id}/property/{key}".format(page_id=page_id, key=data.get("key")) try: response = self.put(path=url, data=data) except HTTPError as e: @@ -1666,8 +1564,7 @@ def update_page_property(self, page_id, data): ) if e.response.status_code == 403: raise ApiPermissionError( - "The user does not have permission to " - "edit the content with the given id", + "The user does not have permission to " "edit the content with the given id", reason=e, ) if e.response.status_code == 404: @@ -1678,8 +1575,7 @@ def update_page_property(self, page_id, data): ) if e.response.status_code == 409: raise ApiConflictError( - "The given version is does not match the expected " - "target version of the updated property", + "The given version is does not match the expected " "target version of the updated property", reason=e, ) if e.response.status_code == 413: @@ -1719,9 +1615,7 @@ def get_page_property(self, page_id, page_property_key): :param page_property_key: key of property :return: """ - url = "rest/api/content/{page_id}/property/{key}".format( - page_id=page_id, key=str(page_property_key) - ) + url = "rest/api/content/{page_id}/property/{key}".format(page_id=page_id, key=str(page_property_key)) try: response = self.get(path=url) except HTTPError as e: @@ -1795,9 +1689,7 @@ def clean_package_cache(self, cache_name="com.gliffy.cache.gon"): """ headers = self.form_token_headers data = {"cacheName": cache_name} - return self.delete( - "rest/cacheManagement/1.0/cacheEntries", data=data, headers=headers - ) + return self.delete("rest/cacheManagement/1.0/cacheEntries", data=data, headers=headers) def get_all_groups(self, start=0, limit=1000): """ @@ -1807,25 +1699,19 @@ def get_all_groups(self, start=0, limit=1000): fixed system limits. Default: 1000 :return: """ - url = "rest/api/group?limit={limit}&start={start}".format( - limit=limit, start=start - ) + url = "rest/api/group?limit={limit}&start={start}".format(limit=limit, start=start) try: response = self.get(url) except HTTPError as e: if e.response.status_code == 403: - raise ApiPermissionError( - "The calling user does not have permission to view groups", reason=e - ) + raise ApiPermissionError("The calling user does not have permission to view groups", reason=e) raise return response.get("results") - def get_group_members( - self, group_name="confluence-users", start=0, limit=1000, expand=None - ): + def get_group_members(self, group_name="confluence-users", start=0, limit=1000, expand=None): """ Get a paginated collection of users in the given group :param group_name @@ -1843,9 +1729,7 @@ def get_group_members( response = self.get(url) except HTTPError as e: if e.response.status_code == 403: - raise ApiPermissionError( - "The calling user does not have permission to view users", reason=e - ) + raise ApiPermissionError("The calling user does not have permission to view users", reason=e) raise @@ -1876,13 +1760,13 @@ def get_space(self, space_key, expand="description.plain,homepage"): return response def get_space_content( - self, - space_key, - depth="all", - start=0, - limit=500, - content_type=None, - expand="body.storage", + self, + space_key, + depth="all", + start=0, + limit=500, + content_type=None, + expand="body.storage", ): """ Get space content. @@ -1900,9 +1784,7 @@ def get_space_content( """ content_type = "{}".format("/" + content_type if content_type else "") - url = "rest/api/space/{space_key}/content{content_type}".format( - space_key=space_key, content_type=content_type - ) + url = "rest/api/space/{space_key}/content{content_type}".format(space_key=space_key, content_type=content_type) params = { "depth": depth, "start": start, @@ -2002,9 +1884,7 @@ def get_user_details_by_username(self, username, expand=None): response = self.get(url, params=params) except HTTPError as e: if e.response.status_code == 403: - raise ApiPermissionError( - "The calling user does not have permission to view users", reason=e - ) + raise ApiPermissionError("The calling user does not have permission to view users", reason=e) if e.response.status_code == 404: raise ApiNotFoundError( "The user with the given username or userkey does not exist", @@ -2032,9 +1912,7 @@ def get_user_details_by_userkey(self, userkey, expand=None): response = self.get(url, params=params) except HTTPError as e: if e.response.status_code == 403: - raise ApiPermissionError( - "The calling user does not have permission to view users", reason=e - ) + raise ApiPermissionError("The calling user does not have permission to view users", reason=e) if e.response.status_code == 404: raise ApiNotFoundError( "The user with the given username or userkey does not exist", @@ -2046,13 +1924,13 @@ def get_user_details_by_userkey(self, userkey, expand=None): return response def cql( - self, - cql, - start=0, - limit=None, - expand=None, - include_archived_spaces=None, - excerpt=None, + self, + cql, + start=0, + limit=None, + expand=None, + include_archived_spaces=None, + excerpt=None, ): """ Get results from cql search result with all related fields @@ -2100,9 +1978,7 @@ def get_page_as_pdf(self, page_id): :return: PDF File """ headers = self.form_token_headers - url = "spaces/flyingpdf/pdfpageexport.action?pageId={pageId}".format( - pageId=page_id - ) + url = "spaces/flyingpdf/pdfpageexport.action?pageId={pageId}".format(pageId=page_id) if self.api_version == "cloud": url = self.get_pdf_download_url_for_confluence_cloud(url) @@ -2136,9 +2012,7 @@ def get_descendant_page_id(self, space, parent_id, title): """ page_id = "" - url = 'rest/api/content/search?cql=parent={}%20AND%20space="{}"'.format( - parent_id, space - ) + url = 'rest/api/content/search?cql=parent={}%20AND%20space="{}"'.format(parent_id, space) try: response = self.get(url, {}) @@ -2282,8 +2156,7 @@ def check_long_task_result(self, task_id, expand=None): if e.response.status_code == 404: # Raise ApiError as the documented reason is ambiguous raise ApiError( - "There is no task with the given key, " - "or the calling user does not have permission to view it", + "There is no task with the given key, " "or the calling user does not have permission to view it", reason=e, ) @@ -2308,14 +2181,10 @@ def get_pdf_download_url_for_confluence_cloud(self, url): log.info("Initiate PDF export from Confluence Cloud") response = self.get(url, headers=headers, not_json_response=True) response_string = response.decode(encoding="utf-8", errors="strict") - task_id = response_string.split('name="ajs-taskId" content="')[1].split( - '">' - )[0] + task_id = response_string.split('name="ajs-taskId" content="')[1].split('">')[0] poll_url = "runningtaskxml.action?taskId={0}".format(task_id) while long_running_task: - long_running_task_response = self.get( - poll_url, headers=headers, not_json_response=True - ) + long_running_task_response = self.get(poll_url, headers=headers, not_json_response=True) long_running_task_response_parts = long_running_task_response.decode( encoding="utf-8", errors="strict" ).split("\n") @@ -2331,9 +2200,7 @@ def get_pdf_download_url_for_confluence_cloud(self, url): log.info("Downloading content...") log.debug("Extract taskId and download PDF.") current_status = long_running_task_response_parts[3] - download_url = current_status.split("href="/wiki/")[ - 1 - ].split(""")[0] + download_url = current_status.split("href="/wiki/")[1].split(""")[0] long_running_task = False elif is_successful == "false": log.error("PDF conversion not successful.") @@ -2346,9 +2213,7 @@ def get_pdf_download_url_for_confluence_cloud(self, url): return download_url - def audit( - self, start_date=None, end_date=None, start=None, limit=None, search_string=None - ): + def audit(self, start_date=None, end_date=None, start=None, limit=None, search_string=None): """ Fetch a paginated list of AuditRecord instances dating back to a certain time :param start_date: @@ -2378,9 +2243,7 @@ def audit( ############################################################################################## """ - def team_calendars_get_sub_calendars( - self, include=None, viewing_space_key=None, calendar_context=None - ): + def team_calendars_get_sub_calendars(self, include=None, viewing_space_key=None, calendar_context=None): """ Get subscribed calendars :param include: @@ -2475,9 +2338,7 @@ def add_user_to_group(self, username, group_name): data = {"name": username} return self.post(url, params=params, data=data) - def add_space_permissions( - self, space_key, subject_type, subject_id, operation_key, operation_target - ): + def add_space_permissions(self, space_key, subject_type, subject_id, operation_key, operation_target): """ Add permissions to a space @@ -2536,8 +2397,6 @@ def set_inline_tasks_checkbox(self, page_id, task_id, status): status is CHECKED or UNCHECKED :return: """ - url = "/rest/inlinetasks/1/task/{page_id}/{task_id}/".format( - page_id=page_id, task_id=task_id - ) + url = "/rest/inlinetasks/1/task/{page_id}/{task_id}/".format(page_id=page_id, task_id=task_id) data = {"status": status, "trigger": "VIEW_PAGE"} - response = self.post(url, json=data) + return self.post(url, json=data) diff --git a/atlassian/crowd.py b/atlassian/crowd.py index f1dd9c8fe..41c543225 100644 --- a/atlassian/crowd.py +++ b/atlassian/crowd.py @@ -11,12 +11,8 @@ class Crowd(AtlassianRestAPI): Important to note that you will have to use an application credentials, not user credentials, in order to access Crowd APIs""" - def __init__( - self, url, username, password, timeout=60, api_root="rest", api_version="latest" - ): - super(Crowd, self).__init__( - url, username, password, timeout, api_root, api_version - ) + def __init__(self, url, username, password, timeout=60, api_root="rest", api_version="latest"): + super(Crowd, self).__init__(url, username, password, timeout, api_root, api_version) def _crowd_api_url(self, api, resource): return "{server}/{api_root}/{api}/{version}/{resource}".format( diff --git a/atlassian/jira.py b/atlassian/jira.py index add60b834..b2f0091f9 100644 --- a/atlassian/jira.py +++ b/atlassian/jira.py @@ -16,9 +16,7 @@ class Jira(AtlassianRestAPI): Reference: https://docs.atlassian.com/software/jira/docs/api/REST/8.5.0/#api/2 """ - def get_permissions( - self, project_id=None, project_key=None, issue_id=None, issue_key=None - ): + def get_permissions(self, project_id=None, project_key=None, issue_id=None, issue_key=None): """ Returns all permissions in the system and whether the currently logged in user has them. You can optionally provide a specific context @@ -199,9 +197,7 @@ def get_attachment_expand_raw(self, attachment_id): Reference: https://docs.atlassian.com/software/jira/docs/api/REST/8.5.0/#api/2/auditing """ - def get_audit_records( - self, offset=None, limit=None, filter=None, from_date=None, to_date=None - ): + def get_audit_records(self, offset=None, limit=None, filter=None, from_date=None, to_date=None): """ Returns auditing records filtered using provided parameters :param offset: the number of record from which search starts @@ -349,9 +345,7 @@ def delete_comment_property(self, comment_id, property_key): """ def component(self, component_id): - return self.get( - "rest/api/2/component/{component_id}".format(component_id=component_id) - ) + return self.get("rest/api/2/component/{component_id}".format(component_id=component_id)) def get_component_related_issues(self, component_id): """ @@ -359,9 +353,7 @@ def get_component_related_issues(self, component_id): :param component_id: :return: """ - url = "rest/api/2/component/{component_id}/relatedIssueCounts".format( - component_id=component_id - ) + url = "rest/api/2/component/{component_id}/relatedIssueCounts".format(component_id=component_id) return self.get(url) def create_component(self, component): @@ -370,12 +362,8 @@ def create_component(self, component): return self.post(url, data=component) def delete_component(self, component_id): - log.warning( - 'Deleting component "{component_id}"'.format(component_id=component_id) - ) - return self.delete( - "rest/api/2/component/{component_id}".format(component_id=component_id) - ) + log.warning('Deleting component "{component_id}"'.format(component_id=component_id)) + return self.delete("rest/api/2/component/{component_id}".format(component_id=component_id)) def update_component_lead(self, component_id, lead): data = {"id": component_id, "leadUserName": lead} @@ -589,9 +577,7 @@ def remove_group(self, name, swap_group=None): return self.delete(url, params=params) - def get_all_users_from_group( - self, group, include_inactive_users=False, start=0, limit=50 - ): + def get_all_users_from_group(self, group, include_inactive_users=False, start=0, limit=50): """ Just wrapping method user group members :param group: @@ -646,9 +632,7 @@ def remove_user_from_group(self, username, group_name): def issue(self, key, fields="*all"): return self.get("rest/api/2/issue/{0}?fields={1}".format(key, fields)) - def get_issue( - self, issue_id_or_key, fields=None, properties=None, update_history=True - ): + def get_issue(self, issue_id_or_key, fields=None, properties=None, update_history=True): """ Returns a full representation of the issue for the given issue key By default, all fields are returned in this get-issue resource @@ -737,9 +721,7 @@ def issue_get_worklog(self, issue_id_or_key): :param issue_id_or_key: :return: """ - url = "rest/api/2/issue/{issueIdOrKey}/worklog".format( - issueIdOrKey=issue_id_or_key - ) + url = "rest/api/2/issue/{issueIdOrKey}/worklog".format(issueIdOrKey=issue_id_or_key) return self.get(url) @@ -756,9 +738,7 @@ def issue_archive(self, issue_id_or_key, notify_users=False): params["notifyUsers"] = "true" else: params["notifyUsers"] = "false" - url = "rest/api/2/issue/{issueIdOrKey}/archive".format( - issueIdOrKey=issue_id_or_key - ) + url = "rest/api/2/issue/{issueIdOrKey}/archive".format(issueIdOrKey=issue_id_or_key) return self.get(url) def issue_field_value(self, key, field): @@ -801,9 +781,7 @@ def issue_exists(self, issue_key): try: resp = self.issue(issue_key, fields="*none") if resp.status_code == 404: - log.info( - 'Issue "{issue_key}" does not exists'.format(issue_key=issue_key) - ) + log.info('Issue "{issue_key}" does not exists'.format(issue_key=issue_key)) return False resp.raise_for_status() log.info('Issue "{issue_key}" exists'.format(issue_key=issue_key)) @@ -842,11 +820,7 @@ def delete_issue(self, issue_id_or_key, delete_subtasks=True): # @todo merge with edit_issue method def issue_update(self, issue_key, fields): - log.warning( - 'Updating issue "{issue_key}" with "{fields}"'.format( - issue_key=issue_key, fields=fields - ) - ) + log.warning('Updating issue "{issue_key}" with "{fields}"'.format(issue_key=issue_key, fields=fields)) url = "rest/api/2/issue/{0}".format(issue_key) return self.put(url, data={"fields": fields}) @@ -878,11 +852,7 @@ def issue_add_watcher(self, issue_key, user): :param user: :return: """ - log.warning( - 'Adding user {user} to "{issue_key}" watchers'.format( - issue_key=issue_key, user=user - ) - ) + log.warning('Adding user {user} to "{issue_key}" watchers'.format(issue_key=issue_key, user=user)) data = user return self.post( "rest/api/2/issue/{issue_key}/watchers".format(issue_key=issue_key), @@ -947,16 +917,12 @@ def issue_create_or_update(self, fields): issue_key = fields.get("issuekey", None) if not issue_key or not self.issue_exists(issue_key): - log.info( - "IssueKey is not provided or does not exists in destination. Will attempt to create an issue" - ) + log.info("IssueKey is not provided or does not exists in destination. Will attempt to create an issue") fields.pop("issuekey", None) return self.issue_create(fields) if self.issue_deleted(issue_key): - log.warning( - 'Issue "{issue_key}" deleted, skipping'.format(issue_key=issue_key) - ) + log.warning('Issue "{issue_key}" deleted, skipping'.format(issue_key=issue_key)) return None log.info('Issue "{issue_key}" exists, will update'.format(issue_key=issue_key)) @@ -1014,9 +980,7 @@ def get_issue_remote_links(self, issue_key, global_id=None, internal_id=None): url += "/" + internal_id return self.get(url, params=params) - def create_or_update_issue_remote_links( - self, issue_key, link_url, title, global_id=None, relationship=None - ): + def create_or_update_issue_remote_links(self, issue_key, link_url, title, global_id=None, relationship=None): """ Add Remote Link to Issue, update url if global_id is passed :param issue_key: str @@ -1034,14 +998,10 @@ def create_or_update_issue_remote_links( return self.post(url, data=data) def get_issue_remote_link_by_id(self, issue_key, link_id): - url = "rest/api/2/issue/{issue_key}/remotelink/{link_id}".format( - issue_key=issue_key, link_id=link_id - ) + url = "rest/api/2/issue/{issue_key}/remotelink/{link_id}".format(issue_key=issue_key, link_id=link_id) return self.get(url) - def update_issue_remote_link_by_id( - self, issue_key, link_id, url, title, global_id=None, relationship=None - ): + def update_issue_remote_link_by_id(self, issue_key, link_id, url, title, global_id=None, relationship=None): """ Update existing Remote Link on Issue :param issue_key: str @@ -1057,9 +1017,7 @@ def update_issue_remote_link_by_id( data["globalId"] = global_id if relationship: data["relationship"] = relationship - url = "rest/api/2/issue/{issue_key}/remotelink/{link_id}".format( - issue_key=issue_key, link_id=link_id - ) + url = "rest/api/2/issue/{issue_key}/remotelink/{link_id}".format(issue_key=issue_key, link_id=link_id) return self.put(url, data=data) def delete_issue_remote_link_by_id(self, issue_key, link_id): @@ -1068,9 +1026,7 @@ def delete_issue_remote_link_by_id(self, issue_key, link_id): :param issue_key: str :param link_id: str """ - url = "rest/api/2/issue/{issue_key}/remotelink/{link_id}".format( - issue_key=issue_key, link_id=link_id - ) + url = "rest/api/2/issue/{issue_key}/remotelink/{link_id}".format(issue_key=issue_key, link_id=link_id) return self.delete(url) def get_issue_transitions(self, issue_key): @@ -1081,9 +1037,7 @@ def get_issue_transitions(self, issue_key): "id": int(transition["id"]), "to": transition["to"]["name"], } - for transition in ( - self.get_issue_transitions_full(issue_key).json() or {} - ).get("transitions") + for transition in (self.get_issue_transitions_full(issue_key).json() or {}).get("transitions") ] else: return [ @@ -1092,9 +1046,7 @@ def get_issue_transitions(self, issue_key): "id": int(transition["id"]), "to": transition["to"]["name"], } - for transition in ( - self.get_issue_transitions_full(issue_key) or {} - ).get("transitions") + for transition in (self.get_issue_transitions_full(issue_key) or {}).get("transitions") ] def issue_transition(self, issue_key, status): @@ -1128,9 +1080,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") or {}).get("status") or {}).get( - "name" - ) or {} + 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) @@ -1264,9 +1214,7 @@ def user_update_email(self, username, email): data = {"name": username, "emailAddress": email} return self.user_update(username, data=data) - def user_create( - self, username, email, display_name, password=None, notification=None - ): + def user_create(self, username, email, display_name, password=None, notification=None): """ Create a user in Jira :param username: @@ -1305,9 +1253,7 @@ def user_property(self, username, key_property): :return: """ params = {"username": username} - return self.get( - "rest/api/2/user/properties/{}".format(key_property), params=params - ) + return self.get("rest/api/2/user/properties/{}".format(key_property), params=params) def user_set_property(self, username, key_property, value_property): """ @@ -1378,15 +1324,11 @@ def user_get_websudo(self): "webSudoPassword": self.password, "webSudoIsPost": "false", } - answer = self.get( - "secure/admin/WebSudoAuthenticate.jspa", self.form_token_headers - ) + answer = self.get("secure/admin/WebSudoAuthenticate.jspa", self.form_token_headers) atl_token = None if answer: atl_token = ( - answer.split( - ' {} {}".format( - method, path, response.status_code, response.reason - ) - ) + log.debug("HTTP: {} {} -> {} {}".format(method, path, response.status_code, response.reason)) if self.advanced_mode: return response diff --git a/atlassian/service_desk.py b/atlassian/service_desk.py index 9410e8c10..b8dbe0e1d 100644 --- a/atlassian/service_desk.py +++ b/atlassian/service_desk.py @@ -24,9 +24,7 @@ def get_service_desks(self): :return: Service Desks """ - service_desks_list = self.get( - "rest/servicedeskapi/servicedesk", headers=self.experimental_headers - ) + service_desks_list = self.get("rest/servicedeskapi/servicedesk", headers=self.experimental_headers) if self.advanced_mode: return service_desks_list else: @@ -57,9 +55,7 @@ def create_customer(self, full_name, email): log.warning("Creating customer...") data = {"fullName": full_name, "email": email} - return self.post( - "rest/servicedeskapi/customer", headers=self.experimental_headers, data=data - ) + return self.post("rest/servicedeskapi/customer", headers=self.experimental_headers, data=data) def get_customer_request(self, issue_id_or_key): """ @@ -76,20 +72,18 @@ def get_customer_request(self, issue_id_or_key): def get_my_customer_requests(self): """ Returning requests where you are the assignee """ - response = self.get( - "rest/servicedeskapi/request", headers=self.experimental_headers - ) + response = self.get("rest/servicedeskapi/request", headers=self.experimental_headers) if self.advanced_mode: return response return (response or {}).get("values") def create_customer_request( - self, - service_desk_id, - request_type_id, - values_dict, - raise_on_behalf_of=None, - request_participants=None, + self, + service_desk_id, + request_type_id, + values_dict, + raise_on_behalf_of=None, + request_participants=None, ): """ Creating customer request @@ -271,9 +265,7 @@ def get_request_comment_by_id(self, issue_id_or_key, comment_id): """ return self.get( - "rest/servicedeskapi/request/{}/comment/{}".format( - issue_id_or_key, comment_id - ), + "rest/servicedeskapi/request/{}/comment/{}".format(issue_id_or_key, comment_id), headers=self.experimental_headers, ) @@ -291,9 +283,7 @@ def get_organisations(self, service_desk_id=None, start=0, limit=50): :return: """ url_without_sd_id = "rest/servicedeskapi/organization" - url_with_sd_id = "rest/servicedeskapi/servicedesk/{}/organization".format( - service_desk_id - ) + url_with_sd_id = "rest/servicedeskapi/servicedesk/{}/organization".format(service_desk_id) params = {} if start is not None: params["start"] = int(start) @@ -301,12 +291,8 @@ def get_organisations(self, service_desk_id=None, start=0, limit=50): params["limit"] = int(limit) if service_desk_id is None: - return self.get( - url_without_sd_id, headers=self.experimental_headers, params=params - ) - return self.get( - url_with_sd_id, headers=self.experimental_headers, params=params - ) + return self.get(url_without_sd_id, headers=self.experimental_headers, params=params) + return self.get(url_with_sd_id, headers=self.experimental_headers, params=params) def get_organization(self, organization_id): """ @@ -464,7 +450,7 @@ def create_attachment(self, service_desk_id, issue_id_or_key, filename, public=T :param comment: OPTIONAL: str (default is None) :return: Request info """ - log.info('Creating attachment...') + log.info("Creating attachment...") return self.create_attachments(service_desk_id, issue_id_or_key, filename, public=public, comment=comment) def attach_temporary_file(self, service_desk_id, filename): @@ -474,12 +460,13 @@ def attach_temporary_file(self, service_desk_id, filename): :param filename: str :return: Temporary Attachment ID """ - url = 'rest/servicedeskapi/servicedesk/{}/attachTemporaryFile'.format(service_desk_id) + url = "rest/servicedeskapi/servicedesk/{}/attachTemporaryFile".format(service_desk_id) - with open(filename, 'rb') as file: - result = self.post(path=url, headers=self.experimental_headers, - files={'file': file}).get('temporaryAttachments') - temp_attachment_id = result[0].get('temporaryAttachmentId') + with open(filename, "rb") as file: + result = self.post(path=url, headers=self.experimental_headers, files={"file": file}).get( + "temporaryAttachments" + ) + temp_attachment_id = result[0].get("temporaryAttachmentId") return temp_attachment_id @@ -492,10 +479,12 @@ def add_attachments(self, issue_id_or_key, temp_attachment_ids, public=True, com :param comment: str (default is None) :return: """ - data = {'temporaryAttachmentIds': temp_attachment_ids, - 'public': public, - 'additionalComment': {'body': comment}} - url = 'rest/servicedeskapi/request/{}/attachment'.format(issue_id_or_key) + data = { + "temporaryAttachmentIds": temp_attachment_ids, + "public": public, + "additionalComment": {"body": comment}, + } + url = "rest/servicedeskapi/request/{}/attachment".format(issue_id_or_key) return self.post(url, headers=self.experimental_headers, data=data) @@ -508,7 +497,7 @@ def add_attachment(self, issue_id_or_key, temp_attachment_id, public=True, comme :param comment: str (default is None) :return: """ - log.info('Adding attachment') + log.info("Adding attachment") return self.add_attachments(issue_id_or_key, [temp_attachment_id], public=public, comment=comment) # SLA actions @@ -579,9 +568,7 @@ def get_approval_by_id(self, issue_id_or_key, approval_id): :param approval_id: str :return: """ - url = "rest/servicedeskapi/request/{0}/approval/{1}".format( - issue_id_or_key, approval_id - ) + url = "rest/servicedeskapi/request/{0}/approval/{1}".format(issue_id_or_key, approval_id) return self.get(url, headers=self.experimental_headers) @@ -594,9 +581,7 @@ def answer_approval(self, issue_id_or_key, approval_id, decision): :param decision: str :return: """ - url = "rest/servicedeskapi/request/{0}/approval/{1}".format( - issue_id_or_key, approval_id - ) + url = "rest/servicedeskapi/request/{0}/approval/{1}".format(issue_id_or_key, approval_id) data = {"decision": decision} return self.post(url, headers=self.experimental_headers, data=data) @@ -671,9 +656,7 @@ def get_issues_in_queue(self, service_desk_id, queue_id, start=0, limit=50): :param limit: int :return: a page of issues """ - url = "rest/servicedeskapi/servicedesk/{0}/queue/{1}/issue".format( - service_desk_id, queue_id - ) + url = "rest/servicedeskapi/servicedesk/{0}/queue/{1}/issue".format(service_desk_id, queue_id) params = {} if start is not None: diff --git a/atlassian/xray.py b/atlassian/xray.py index 005bf0847..24f65f488 100755 --- a/atlassian/xray.py +++ b/atlassian/xray.py @@ -46,9 +46,7 @@ def get_test_runs_with_environment(self, test_key, test_environments): :param test_environments: Test execution environments separated by ','. :return: Returns the exported test runs. """ - env = "?testEnvironments={0}".format( - ",".join([re.escape(env) for env in test_environments]) - ) + env = "?testEnvironments={0}".format(",".join([re.escape(env) for env in test_environments])) url = "rest/raven/1.0/api/test/{0}/testruns{1}".format(test_key, env) return self.get(url) @@ -193,9 +191,7 @@ def delete_test_from_precondition(self, precondition_key, test_key): :param test_key: Test Key which should no longer be associate with the pre-condition (eg. 'TEST-100') :return: """ - url = "rest/raven/1.0/api/precondition/{0}/test/{1}".format( - precondition_key, test_key - ) + url = "rest/raven/1.0/api/precondition/{0}/test/{1}".format(precondition_key, test_key) return self.delete(url) # Test Set API @@ -280,9 +276,7 @@ def delete_test_from_test_plan(self, test_plan_key, test_key): return self.delete(url) # Test Executions API - def get_tests_with_test_execution( - self, test_exec_key, detailed=False, limit=None, page=None - ): + def get_tests_with_test_execution(self, test_exec_key, detailed=False, limit=None, page=None): """ Retrieve the tests associated with the given test execution. :param test_exec_key: Test execution key (eg. 'EXEC-001'). diff --git a/docs/conf.py b/docs/conf.py index cbb61195f..a220ec5ef 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -8,18 +8,18 @@ import os import sys -sys.path.insert(0, os.path.abspath('../..')) -sys.path.insert(0, os.path.abspath('../atlassian/')) +sys.path.insert(0, os.path.abspath("../..")) +sys.path.insert(0, os.path.abspath("../atlassian/")) # -- Project information ----------------------------------------------------- -project = 'Atlassian Python API' -copyright = 'APACHE LICENSE, VERSION 2.0' -author = 'SLRover' +project = "Atlassian Python API" +copyright = "APACHE LICENSE, VERSION 2.0" +author = "SLRover" # The short X.Y version -version = '' +version = "" # The full version, including alpha/beta/rc tags -release = '1.15.3' +release = "1.15.3" # -- General configuration --------------------------------------------------- @@ -31,21 +31,21 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.githubpages', + "sphinx.ext.autodoc", + "sphinx.ext.githubpages", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -57,7 +57,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. pygments_style = None @@ -67,12 +67,12 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alibaster' +html_theme = "alibaster" html_theme_options = { "rightsidebar": "false", } -html_static_path = ['_static'] +html_static_path = ["_static"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -88,7 +88,7 @@ # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'AtlassianPythonAPIdoc' +htmlhelp_basename = "AtlassianPythonAPIdoc" # -- Options for LaTeX output ------------------------------------------------ @@ -98,8 +98,13 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'AtlassianPythonAPI.tex', 'Atlassian Python API Documentation', - author, 'manual'), + ( + master_doc, + "AtlassianPythonAPI.tex", + "Atlassian Python API Documentation", + author, + "manual", + ), ] # -- Options for manual page output ------------------------------------------ @@ -107,8 +112,13 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'atlassianpythonapi', 'Atlassian Python API Documentation', - [author], 1) + ( + master_doc, + "atlassianpythonapi", + "Atlassian Python API Documentation", + [author], + 1, + ) ] # -- Options for Texinfo output ---------------------------------------------- @@ -117,9 +127,15 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'AtlassianPythonAPI', 'Atlassian Python API Documentation', - author, 'AtlassianPythonAPI', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "AtlassianPythonAPI", + "Atlassian Python API Documentation", + author, + "AtlassianPythonAPI", + "One line description of project.", + "Miscellaneous", + ), ] # -- Options for Epub output ------------------------------------------------- @@ -137,6 +153,6 @@ # epub_uid = '' # A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] +epub_exclude_files = ["search.html"] # -- Extension configuration ------------------------------------------------- diff --git a/examples/bamboo/bamboo_add_plan_branch.py b/examples/bamboo/bamboo_add_plan_branch.py index 48def237b..e6d1d16a5 100644 --- a/examples/bamboo/bamboo_add_plan_branch.py +++ b/examples/bamboo/bamboo_add_plan_branch.py @@ -11,9 +11,7 @@ def create_plan_branch(plan, vcs_branch): bamboo_branch = vcs_branch.replace("/", "-") - return bamboo.create_branch( - plan, bamboo_branch, vcs_branch=vcs_branch, enabled=True - ) + return bamboo.create_branch(plan, bamboo_branch, vcs_branch=vcs_branch, enabled=True) def main(): diff --git a/examples/bamboo/bamboo_label_based_cleaner.py b/examples/bamboo/bamboo_label_based_cleaner.py index 560d8cd21..4d3ea25b8 100644 --- a/examples/bamboo/bamboo_label_based_cleaner.py +++ b/examples/bamboo/bamboo_label_based_cleaner.py @@ -29,9 +29,7 @@ def get_plans_from_project(project_key): if __name__ == "__main__": - bamboo = Bamboo( - url=BAMBOO_URL, username=BAMBOO_LOGIN, password=BAMBOO_PASSWORD, timeout=180 - ) + bamboo = Bamboo(url=BAMBOO_URL, username=BAMBOO_LOGIN, password=BAMBOO_PASSWORD, timeout=180) projects = get_all_projects() print("Start analyzing the {} projects".format(len(projects))) for project in projects: @@ -41,10 +39,7 @@ def get_plans_from_project(project_key): for plan in plans: print("Inspecting {} plan".format(plan)) build_results = [ - x - for x in bamboo.results( - plan_key=plan, label=LABEL, max_results=100, include_all_states=True - ) + x for x in bamboo.results(plan_key=plan, label=LABEL, max_results=100, include_all_states=True) ] for build in build_results: build_key = build.get("buildResultKey") or None @@ -53,9 +48,7 @@ def get_plans_from_project(project_key): build_complete_time = build_value.get("buildCompletedTime") or None if not build_complete_time: continue - datetimeObj = datetime.strptime( - build_complete_time.split("+")[0] + "000", "%Y-%m-%dT%H:%M:%S.%f" - ) + datetimeObj = datetime.strptime(build_complete_time.split("+")[0] + "000", "%Y-%m-%dT%H:%M:%S.%f") if datetime.now() > datetimeObj + timedelta(days=OLDER_DAYS): print( "Build is old {} as build complete date {}".format( diff --git a/examples/bamboo/bamboo_remove_old_failed_results.py b/examples/bamboo/bamboo_remove_old_failed_results.py index 55121aec2..3f7688c7f 100644 --- a/examples/bamboo/bamboo_remove_old_failed_results.py +++ b/examples/bamboo/bamboo_remove_old_failed_results.py @@ -28,9 +28,7 @@ def get_plans_from_project(proj): def get_branches_from_plan(plan_key): - return [ - x["id"] for x in bamboo.search_branches(plan_key, max_results=1000, start=0) - ] + return [x["id"] for x in bamboo.search_branches(plan_key, max_results=1000, start=0)] def get_results_from_branch(plan_key): @@ -42,9 +40,7 @@ def remove_build_result(build_key, status): build_complete_time = build_value.get("buildCompletedTime") or None if not build_complete_time: return - datetime_obj = datetime.strptime( - build_complete_time.split("+")[0] + "000", "%Y-%m-%dT%H:%M:%S.%f" - ) + datetime_obj = datetime.strptime(build_complete_time.split("+")[0] + "000", "%Y-%m-%dT%H:%M:%S.%f") if datetime.now() > datetime_obj + timedelta(days=OLDER_DAYS): if build_value.get("buildState") == status: print("Removing build result - {}".format(build_key)) @@ -67,9 +63,7 @@ def project_review(plans): if __name__ == "__main__": - bamboo = Bamboo( - url=BAMBOO_URL, username=BAMBOO_LOGIN, password=BAMBOO_PASS, timeout=180 - ) + bamboo = Bamboo(url=BAMBOO_URL, username=BAMBOO_LOGIN, password=BAMBOO_PASS, timeout=180) projects = get_all_projects() for project in projects: if project in EXCLUDED_PROJECTS: diff --git a/examples/bamboo/bamboo_remove_unknown_status_build_results.py b/examples/bamboo/bamboo_remove_unknown_status_build_results.py index 88b5c7d0e..2d99bdb34 100755 --- a/examples/bamboo/bamboo_remove_unknown_status_build_results.py +++ b/examples/bamboo/bamboo_remove_unknown_status_build_results.py @@ -25,18 +25,11 @@ def get_plans_from_project(proj): def get_branches_from_plan(plan_key): - return [ - x["id"] for x in bamboo.search_branches(plan_key, max_results=1000, start=0) - ] + return [x["id"] for x in bamboo.search_branches(plan_key, max_results=1000, start=0)] def get_results_from_branch(plan_key): - return [ - x - for x in bamboo.results( - plan_key, expand="results.result", max_results=100, include_all_states=True - ) - ] + return [x for x in bamboo.results(plan_key, expand="results.result", max_results=100, include_all_states=True)] def remove_build_result(build_key, status): @@ -62,9 +55,7 @@ def project_review(plans): if __name__ == "__main__": - bamboo = Bamboo( - url=BAMBOO_URL, username=BAMBOO_LOGIN, password=BAMBOO_PASS, timeout=180 - ) + bamboo = Bamboo(url=BAMBOO_URL, username=BAMBOO_LOGIN, password=BAMBOO_PASS, timeout=180) projects = get_all_projects() for project in projects: if project in EXCLUDED_PROJECTS: diff --git a/examples/bamboo/bamboo_trigger_builds_console_app.py b/examples/bamboo/bamboo_trigger_builds_console_app.py index fca5ec9ac..a86bd4cfa 100644 --- a/examples/bamboo/bamboo_trigger_builds_console_app.py +++ b/examples/bamboo/bamboo_trigger_builds_console_app.py @@ -54,9 +54,6 @@ def execute_build(build_key, params): # Getting arguments args = parser.parse_args() # Make a dictionary from the command arguments - build_arguments = { - args.arguments[i]: args.arguments[i + 1] - for i in range(0, len(args.arguments or []), 2) - } + build_arguments = {args.arguments[i]: args.arguments[i + 1] for i in range(0, len(args.arguments or []), 2)} # Pass build key and arguments to the function execute_build(args.build, build_arguments) diff --git a/examples/bitbucket/bitbucket_check_last_auth_users.py b/examples/bitbucket/bitbucket_check_last_auth_users.py index d2ce38029..584b7492b 100644 --- a/examples/bitbucket/bitbucket_check_last_auth_users.py +++ b/examples/bitbucket/bitbucket_check_last_auth_users.py @@ -8,9 +8,7 @@ That example shows how to make a report of bitbucket usage """ -stash = Bitbucket( - url="https://stash.example.com", username="admin", password="*********", timeout=60 -) +stash = Bitbucket(url="https://stash.example.com", username="admin", password="*********", timeout=60) def report(all=False, non_auth=False, limit=20): @@ -23,9 +21,7 @@ def report(all=False, non_auth=False, limit=20): auth_date = user.get("lastAuthenticationTimestamp") or None if auth_date: auth_date = int(auth_date / 1000) - full_date = datetime.utcfromtimestamp(auth_date).strftime( - "%Y-%m-%d %H:%M:%S" - ) + full_date = datetime.utcfromtimestamp(auth_date).strftime("%Y-%m-%d %H:%M:%S") else: full_date = None if full_date: @@ -52,12 +48,8 @@ def report(all=False, non_auth=False, limit=20): description="Simple script to make a report of authenticated or non authenticated users", ) # Adding the build key as the first argument - parser.add_argument( - "--non-auth", help="Find non-auth users", dest="non_auth", action="store_true" - ) - parser.add_argument( - "--all", help="Review all users", dest="all", action="store_true" - ) + parser.add_argument("--non-auth", help="Find non-auth users", dest="non_auth", action="store_true") + parser.add_argument("--all", help="Review all users", dest="all", action="store_true") # Adding key=value parameters after the --arguments key # Getting arguments args = parser.parse_args() diff --git a/examples/bitbucket/bitbucket_clean_jira_branches.py b/examples/bitbucket/bitbucket_clean_jira_branches.py index 36226a45d..a91f93ee3 100644 --- a/examples/bitbucket/bitbucket_clean_jira_branches.py +++ b/examples/bitbucket/bitbucket_clean_jira_branches.py @@ -26,13 +26,9 @@ flag = True time_now = int(time.time()) * 1000 delta_for_time_ms = LAST_COMMIT_CONDITION_IN_DAYS * 24 * 60 * 60 * 1000 -commit_info_key = ( - "com.atlassian.bitbucket.server.bitbucket-branch:latest-commit-metadata" -) +commit_info_key = "com.atlassian.bitbucket.server.bitbucket-branch:latest-commit-metadata" out_going_pull_request = "com.atlassian.bitbucket.server.bitbucket-ref-metadata:outgoing-pull-request-metadata" -branch_related_issues = ( - "com.atlassian.bitbucket.server.bitbucket-jira:branch-list-jira-issues" -) +branch_related_issues = "com.atlassian.bitbucket.server.bitbucket-jira:branch-list-jira-issues" def is_can_removed_branch(branch_candidate): @@ -45,13 +41,8 @@ def is_can_removed_branch(branch_candidate): if branch_candidate.get("isDefault"): print(branch.get("displayId") + " is default") return False - pull_request_info = (branch_candidate.get("metadata") or {}).get( - out_going_pull_request - ) or {} - if ( - pull_request_info.get("pullRequest") is not None - or (pull_request_info.get("open") or 0) > 0 - ): + pull_request_info = (branch_candidate.get("metadata") or {}).get(out_going_pull_request) or {} + if pull_request_info.get("pullRequest") is not None or (pull_request_info.get("open") or 0) > 0: print(branch.get("displayId") + " has open PR") return False # skip branches without pull request info @@ -59,9 +50,7 @@ def is_can_removed_branch(branch_candidate): print(branch.get("displayId") + " without pull request info") # return False - author_time_stamp = ( - branch_candidate.get("metadata").get(commit_info_key).get("authorTimestamp") - ) + author_time_stamp = branch_candidate.get("metadata").get(commit_info_key).get("authorTimestamp") # check latest commit info if time_now - author_time_stamp < delta_for_time_ms: print(branch.get("displayId") + " is too early to remove") @@ -97,15 +86,8 @@ def is_can_removed_branch(branch_candidate): break for branch in branches: display_id = branch["displayId"] - committer_time_stamp = ( - branch.get("metadata") - .get(commit_info_key) - .get("committerTimestamp") - / 1000 - ) - last_date_commit = time.strftime( - "%Y-%m-%d %H:%M:%S", time.localtime(committer_time_stamp) - ) + committer_time_stamp = branch.get("metadata").get(commit_info_key).get("committerTimestamp") / 1000 + last_date_commit = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(committer_time_stamp)) if is_can_removed_branch(branch): if not DRY_RUN: stash.delete_branch( diff --git a/examples/bitbucket/bitbucket_manage_pull_request.py b/examples/bitbucket/bitbucket_manage_pull_request.py index 8322a9337..280f92823 100644 --- a/examples/bitbucket/bitbucket_manage_pull_request.py +++ b/examples/bitbucket/bitbucket_manage_pull_request.py @@ -18,9 +18,7 @@ ver = response.json().get("version") print("PR version: {}".format(ver)) -response = bitbucket.is_pull_request_can_be_merged( - "project_name", "repository_name", pr_id -) +response = bitbucket.is_pull_request_can_be_merged("project_name", "repository_name", pr_id) print("Reopen: {}".format(response)) print("PR version: {}".format(ver)) diff --git a/examples/bitbucket/bitbucket_project.py b/examples/bitbucket/bitbucket_project.py index 6552363f0..0043ad80d 100644 --- a/examples/bitbucket/bitbucket_project.py +++ b/examples/bitbucket/bitbucket_project.py @@ -7,9 +7,7 @@ def html(project): html_data += "\tITEMVALUE\n" html_data += "\tkey{key}\n".format(**project) html_data += "\tname{name}\n".format(**project) - html_data += "\tdescription{description}\n".format( - **project - ) + html_data += "\tdescription{description}\n".format(**project) html_data += "\tid{id}\n".format(**project) return html_data + "\n" diff --git a/examples/bitbucket/bitbucket_projects_administrators.py b/examples/bitbucket/bitbucket_projects_administrators.py index 668910fdb..aa600b88c 100644 --- a/examples/bitbucket/bitbucket_projects_administrators.py +++ b/examples/bitbucket/bitbucket_projects_administrators.py @@ -3,9 +3,7 @@ from atlassian import Bitbucket -logging.basicConfig( - level=logging.DEBUG, format="[%(asctime).19s] [%(levelname)s] %(message)s" -) +logging.basicConfig(level=logging.DEBUG, format="[%(asctime).19s] [%(levelname)s] %(message)s") logging.getLogger("requests").setLevel(logging.WARNING) log = logging.getLogger("bitbucket-projects-administrators") diff --git a/examples/bitbucket/bitbucket_tag_manipulations.py b/examples/bitbucket/bitbucket_tag_manipulations.py index 37c959125..4070c8a5b 100644 --- a/examples/bitbucket/bitbucket_tag_manipulations.py +++ b/examples/bitbucket/bitbucket_tag_manipulations.py @@ -16,12 +16,8 @@ print("Response after set_tag method") print(response) - response = bitbucket.get_project_tags( - project_key="INT", repository_slug="jira-plugins", tag_name="test1" - ) + response = bitbucket.get_project_tags(project_key="INT", repository_slug="jira-plugins", tag_name="test1") print("Retrieve tag") print(response) print("Remove tag") - bitbucket.delete_tag( - project_key="INT", repository_slug="jira-plugins", tag_name="test1" - ) + bitbucket.delete_tag(project_key="INT", repository_slug="jira-plugins", tag_name="test1") diff --git a/examples/bitbucket/stash_user_auth_report.py b/examples/bitbucket/stash_user_auth_report.py index ff0578c22..f27f7a74e 100644 --- a/examples/bitbucket/stash_user_auth_report.py +++ b/examples/bitbucket/stash_user_auth_report.py @@ -25,9 +25,7 @@ def report(limit=200, include_in_active=False): auth_date = user.get("lastAuthenticationTimestamp") or None if auth_date: auth_date = int(auth_date / 1000) - full_date = datetime.utcfromtimestamp(auth_date).strftime( - "%Y-%m-%d %H:%M:%S" - ) + full_date = datetime.utcfromtimestamp(auth_date).strftime("%Y-%m-%d %H:%M:%S") else: full_date = None if include_in_active or user.get("active"): diff --git a/examples/confluence/confluence_check_unknown_attachment_error.py b/examples/confluence/confluence_check_unknown_attachment_error.py index 2bb3f930f..fb8866d76 100644 --- a/examples/confluence/confluence_check_unknown_attachment_error.py +++ b/examples/confluence/confluence_check_unknown_attachment_error.py @@ -3,9 +3,7 @@ """This example how to detect unknown-attachments errors""" -confluence = Confluence( - url="http://localhost:8090", username="admin", password="admin", timeout=185 -) +confluence = Confluence(url="http://localhost:8090", username="admin", password="admin", timeout=185) def get_all_pages_ids(space_key): @@ -15,9 +13,7 @@ def get_all_pages_ids(space_key): flag = True step = 0 while flag: - values = confluence.get_all_pages_from_space( - space=space_key, start=step * limit, limit=limit - ) + values = confluence.get_all_pages_from_space(space=space_key, start=step * limit, limit=limit) step += 1 if len(values) == 0: diff --git a/examples/confluence/confluence_copy_labels.py b/examples/confluence/confluence_copy_labels.py index 200a85241..2b5804d59 100644 --- a/examples/confluence/confluence_copy_labels.py +++ b/examples/confluence/confluence_copy_labels.py @@ -53,9 +53,7 @@ def sync_labels_pages(pages, destination_space): prog="confluence_copy_labes_between_spaces", description="Simple execution for sync labels between 2 spaces", ) - parser.add_argument( - "--source", dest="source", default="SOURCESPACE", help="Just Source Space" - ) + parser.add_argument("--source", dest="source", default="SOURCESPACE", help="Just Source Space") parser.add_argument( "--destination", dest="destination", diff --git a/examples/confluence/confluence_draft_page_cleaner.py b/examples/confluence/confluence_draft_page_cleaner.py index d58d1d16d..eb2a68fb3 100644 --- a/examples/confluence/confluence_draft_page_cleaner.py +++ b/examples/confluence/confluence_draft_page_cleaner.py @@ -16,16 +16,12 @@ def clean_draft_pages_from_space(space_key, count, date_now): :param date_now: :return: int counter """ - pages = confluence.get_all_draft_pages_from_space( - space=space_key, start=0, limit=500 - ) + pages = confluence.get_all_draft_pages_from_space(space=space_key, start=0, limit=500) for page in pages: page_id = page["id"] draft_page = confluence.get_draft_page_by_id(page_id=page_id) last_date_string = draft_page["version"]["when"] - last_date = datetime.datetime.strptime( - last_date_string.replace(".000", "")[:-6], "%Y-%m-%dT%H:%M:%S" - ) + last_date = datetime.datetime.strptime(last_date_string.replace(".000", "")[:-6], "%Y-%m-%dT%H:%M:%S") if (date_now - last_date) > datetime.timedelta(days=DRAFT_DAYS): count += 1 print("Removing page with page id: " + page_id) @@ -51,16 +47,10 @@ def clean_all_draft_pages_from_all_spaces(days=30): i += 1 for space_list in space_lists: print("Start review the space {}".format(space_list["key"])) - count = clean_draft_pages_from_space( - space_key=space_list["key"], count=count, date_now=date_now - ) + count = clean_draft_pages_from_space(space_key=space_list["key"], count=count, date_now=date_now) else: flag = False - print( - "Script has removed {count} draft pages older than {days} days".format( - count=count, days=days - ) - ) + print("Script has removed {count} draft pages older than {days} days".format(count=count, days=days)) if __name__ == "__main__": diff --git a/examples/confluence/confluence_get_group_members.py b/examples/confluence/confluence_get_group_members.py index 0b42ef04c..2ffe9e605 100644 --- a/examples/confluence/confluence_get_group_members.py +++ b/examples/confluence/confluence_get_group_members.py @@ -9,9 +9,7 @@ limit = 50 result = [] while flag: - response = confluence.get_group_members( - group_name=group_name, start=i * limit, limit=limit - ) + response = confluence.get_group_members(group_name=group_name, start=i * limit, limit=limit) if response and len(response): i += 1 result.append(response) diff --git a/examples/confluence/confluence_get_user_details.py b/examples/confluence/confluence_get_user_details.py index e7a0f08a3..a7211d869 100644 --- a/examples/confluence/confluence_get_user_details.py +++ b/examples/confluence/confluence_get_user_details.py @@ -5,7 +5,5 @@ confluence = Confluence(url="http://localhost:8090", username="admin", password="admin") -result = confluence.get_user_details_by_username( - username="gonchik.tsymzhitov", expand="status" -) +result = confluence.get_user_details_by_username(username="gonchik.tsymzhitov", expand="status") print(result) diff --git a/examples/confluence/confluence_nested_error.py b/examples/confluence/confluence_nested_error.py index 9bbc90d2b..373bda7db 100644 --- a/examples/confluence/confluence_nested_error.py +++ b/examples/confluence/confluence_nested_error.py @@ -9,14 +9,8 @@ username="admin", password="admin", ) - result = confluence.get_user_details_by_username( - username="gonchik.tsymzhitov", expand="status" - ) + result = confluence.get_user_details_by_username(username="gonchik.tsymzhitov", expand="status") except ApiError as e: - print( - "FAILURE: {}, caused by {}".format( - e, e.reason if e.reason is not None else "unknown reason" - ) - ) + print("FAILURE: {}, caused by {}".format(e, e.reason if e.reason is not None else "unknown reason")) else: print(result) diff --git a/examples/confluence/confluence_page_create.py b/examples/confluence/confluence_page_create.py index 60ee0c1f7..b3612692d 100644 --- a/examples/confluence/confluence_page_create.py +++ b/examples/confluence/confluence_page_create.py @@ -3,8 +3,6 @@ confluence = Confluence(url="http://localhost:8090", username="admin", password="admin") -status = confluence.create_page( - space="DEMO", title="This is the title", body="This is the body" -) +status = confluence.create_page(space="DEMO", title="This is the title", body="This is the body") print(status) diff --git a/examples/confluence/confluence_page_versions_cleaner.py b/examples/confluence/confluence_page_versions_cleaner.py index fc2075792..a61880850 100644 --- a/examples/confluence/confluence_page_versions_cleaner.py +++ b/examples/confluence/confluence_page_versions_cleaner.py @@ -15,15 +15,11 @@ def page_version_remover(content_id, remained_page_numbers): if len(response) > 0 and latest_version_count > remained_page_numbers: print( "Number of {} latest version {}".format( - confluence.url_joiner( - confluence.url, "/pages/viewpage.action?pageId=" + content_id - ), + confluence.url_joiner(confluence.url, "/pages/viewpage.action?pageId=" + content_id), latest_version_count, ) ) - for version_page_counter in range( - 1, (latest_version_count - remained_page_numbers + 1), 1 - ): + for version_page_counter in range(1, (latest_version_count - remained_page_numbers + 1), 1): confluence.remove_content_history(content_id, 1) else: print("Number of page history smaller than remained") @@ -40,9 +36,7 @@ def get_all_page_ids_from_space(space): content_ids = [] while flag: - values = confluence.get_all_pages_from_space( - space=space, start=limit * step, limit=limit - ) + values = confluence.get_all_pages_from_space(space=space, start=limit * step, limit=limit) step += 1 if len(values) == 0: flag = False @@ -91,6 +85,4 @@ def reduce_page_numbers(page_id, remained_page_history_count): print("Starting review space with key {}".format(space_key)) page_ids = get_all_page_ids_from_space(space_key) for page_id in page_ids: - reduce_page_numbers( - page_id=page_id, remained_page_history_count=REMAINED_PAGE_HISTORY_COUNT - ) + reduce_page_numbers(page_id=page_id, remained_page_history_count=REMAINED_PAGE_HISTORY_COUNT) diff --git a/examples/confluence/confluence_subtree_cleaner.py b/examples/confluence/confluence_subtree_cleaner.py index 828fecd45..81cef34fd 100644 --- a/examples/confluence/confluence_subtree_cleaner.py +++ b/examples/confluence/confluence_subtree_cleaner.py @@ -20,6 +20,4 @@ subtree = confluence.get_subtree_of_content_ids("123123") for page_id in subtree: - confluence.remove_page_history_keep_version( - page_id=page_id, keep_last_versions=remained_count - ) + confluence.remove_page_history_keep_version(page_id=page_id, keep_last_versions=remained_count) diff --git a/examples/confluence/confluence_trash_cleaner.py b/examples/confluence/confluence_trash_cleaner.py index 9aa5bfaf5..5780e7c55 100644 --- a/examples/confluence/confluence_trash_cleaner.py +++ b/examples/confluence/confluence_trash_cleaner.py @@ -15,16 +15,12 @@ def clean_pages_from_space(space_key, limit=500): """ flag = True while flag: - values = confluence.get_all_pages_from_space_trash( - space=space_key, start=0, limit=limit, content_type="page" - ) + values = confluence.get_all_pages_from_space_trash(space=space_key, start=0, limit=limit, content_type="page") if not values or len(values) == 0: flag = False print("For space {} trash is empty".format(space_key)) else: - print( - "Found in space {} pages as trashed {}".format(space_key, len(values)) - ) + print("Found in space {} pages as trashed {}".format(space_key, len(values))) for value in values: print("Removing page with title: " + value["title"]) confluence.remove_page_from_trash(value["id"]) @@ -43,9 +39,7 @@ def clean_blog_posts_from_space(space_key, limit=500): space=space_key, start=0, limit=limit, content_type="blogpost" ) if values and len(values) > 0: - print( - "Found in space {} pages as trashed {}".format(space_key, len(values)) - ) + print("Found in space {} pages as trashed {}".format(space_key, len(values))) for value in values: print("Removing page with title: " + value["title"]) confluence.remove_page_from_trash(value["id"]) diff --git a/examples/crowd/crowd_get_group_nested_members.py b/examples/crowd/crowd_get_group_nested_members.py index 8be6697ac..915e0e7f3 100644 --- a/examples/crowd/crowd_get_group_nested_members.py +++ b/examples/crowd/crowd_get_group_nested_members.py @@ -11,9 +11,7 @@ CROWD_APPLICATION = os.environ.get("CROWD_APPLICATION", "bamboo") CROWD_APPLICATION_PASSWORD = os.environ.get("CROWD_APPLICATION_PASSWORD", "admin") -crowd = Crowd( - url=CROWD_URL, username=CROWD_APPLICATION, password=CROWD_APPLICATION_PASSWORD -) +crowd = Crowd(url=CROWD_URL, username=CROWD_APPLICATION, password=CROWD_APPLICATION_PASSWORD) group_members = crowd.group_nested_members("bamboo-user") print(group_members) diff --git a/examples/crowd/crowd_get_user.py b/examples/crowd/crowd_get_user.py index cf4a2952b..9bacc199e 100644 --- a/examples/crowd/crowd_get_user.py +++ b/examples/crowd/crowd_get_user.py @@ -11,9 +11,7 @@ CROWD_APPLICATION = os.environ.get("CROWD_APPLICATION", "bamboo") CROWD_APPLICATION_PASSWORD = os.environ.get("CROWD_APPLICATION_PASSWORD", "admin") -crowd = Crowd( - url=CROWD_URL, username=CROWD_APPLICATION, password=CROWD_APPLICATION_PASSWORD -) +crowd = Crowd(url=CROWD_URL, username=CROWD_APPLICATION, password=CROWD_APPLICATION_PASSWORD) user_details = crowd.user("xdfjklm") print(user_details) diff --git a/examples/jira/jira_add_comment.py b/examples/jira/jira_add_comment.py index 271a7c4c4..a5dfd25da 100644 --- a/examples/jira/jira_add_comment.py +++ b/examples/jira/jira_add_comment.py @@ -3,8 +3,6 @@ """ How to add comment""" -jira = Jira( - url="https://jira.example.com/", username="gonchik.tsymzhitov", password="admin" -) +jira = Jira(url="https://jira.example.com/", username="gonchik.tsymzhitov", password="admin") jira.issue_add_comment("TST-11098", "test rest api request") diff --git a/examples/jira/jira_add_components_to_all_projects.py b/examples/jira/jira_add_components_to_all_projects.py index 48a4c6599..9ec143e3b 100644 --- a/examples/jira/jira_add_components_to_all_projects.py +++ b/examples/jira/jira_add_components_to_all_projects.py @@ -1,9 +1,7 @@ # coding=utf-8 from atlassian import Jira -jira = Jira( - url="http://localhost:8080/", username="jira-administrator", password="admin" -) +jira = Jira(url="http://localhost:8080/", username="jira-administrator", password="admin") components = ["Data Base", "HTML", "JavaScript"] diff --git a/examples/jira/jira_admins_confluence_page.py b/examples/jira/jira_admins_confluence_page.py index bfece45a2..5703ad0d0 100644 --- a/examples/jira/jira_admins_confluence_page.py +++ b/examples/jira/jira_admins_confluence_page.py @@ -4,9 +4,7 @@ from atlassian import Confluence from atlassian import Jira -logging.basicConfig( - level=logging.DEBUG, format="[%(asctime).19s] [%(levelname)s] %(message)s" -) +logging.basicConfig(level=logging.DEBUG, format="[%(asctime).19s] [%(levelname)s] %(message)s") logging.getLogger("requests").setLevel(logging.WARNING) log = logging.getLogger("jira-projects-administrators") diff --git a/examples/jira/jira_archive_project_procedure.py b/examples/jira/jira_archive_project_procedure.py index 47b4d782c..8442f1896 100644 --- a/examples/jira/jira_archive_project_procedure.py +++ b/examples/jira/jira_archive_project_procedure.py @@ -39,15 +39,9 @@ def get_project_notification_scheme_object(new_scheme="Archived Notification Sch # Setting the logging level. INFO|ERROR|DEBUG are the most common. logging.basicConfig(level=logging.INFO) # Initialize argparse module with some program name and additional information - parser = argparse.ArgumentParser( - prog="Jira Archive Projects", description="Simple execution of th project key" - ) - parser.add_argument( - "--project", dest="project", default="TEST", help="Jira project key" - ) - parser.add_argument( - "--category", dest="category", default="DEPRECATED", help="Project category" - ) + parser = argparse.ArgumentParser(prog="Jira Archive Projects", description="Simple execution of th project key") + parser.add_argument("--project", dest="project", default="TEST", help="Jira project key") + parser.add_argument("--category", dest="category", default="DEPRECATED", help="Project category") parser.add_argument( "--permission", dest="permission", @@ -72,12 +66,8 @@ def get_project_notification_scheme_object(new_scheme="Archived Notification Sch archive_project_key = args.project new_project_category = get_project_category_object(archive_category_name) - new_permission_scheme = get_project_permission_scheme_object( - archive_project_permission_scheme - ) - new_notification_scheme = get_project_notification_scheme_object( - archive_notification_scheme - ) + new_permission_scheme = get_project_permission_scheme_object(archive_project_permission_scheme) + new_notification_scheme = get_project_notification_scheme_object(archive_notification_scheme) projects = jira.get_all_projects() new_project = None for project in projects: @@ -86,21 +76,15 @@ def get_project_notification_scheme_object(new_scheme="Archived Notification Sch if new_project_category is None: print("Did not find the new project category") else: - jira.update_project_category_for_project( - archive_project_key, new_project_category.get("id") - ) + jira.update_project_category_for_project(archive_project_key, new_project_category.get("id")) if new_permission_scheme: - jira.assign_project_permission_scheme( - archive_project_key, new_permission_scheme.get("id") - ) + jira.assign_project_permission_scheme(archive_project_key, new_permission_scheme.get("id")) else: print("Did not find a permission scheme") if new_notification_scheme: - jira.assign_project_notification_scheme( - archive_project_key, new_notification_scheme.get("id") - ) + jira.assign_project_notification_scheme(archive_project_key, new_notification_scheme.get("id")) else: print("Did not find a notification scheme") break diff --git a/examples/jira/jira_convert_group_members_into_user_in_role.py b/examples/jira/jira_convert_group_members_into_user_in_role.py index 687dbee80..e9fdc43e4 100644 --- a/examples/jira/jira_convert_group_members_into_user_in_role.py +++ b/examples/jira/jira_convert_group_members_into_user_in_role.py @@ -12,9 +12,7 @@ def convert_group_into_users_in_role(project_key, role_id, group_name): users = jira.get_all_users_from_group(group=group_name, limit=1000).get("values") for user in users: - jira.add_user_into_project_role( - project_key=project_key, role_id=role_id, user_name=user.get("name") - ) + jira.add_user_into_project_role(project_key=project_key, role_id=role_id, user_name=user.get("name")) print(f"{user.get('name')} added into role_id {role_id} in {project_key}") @@ -23,15 +21,11 @@ def convert_group_into_users_in_role(project_key, role_id, group_name): projects = jira.get_all_projects(included_archived=True) for project in projects: for role in roles: - members_of_role = jira.get_project_actors_for_role_project( - project.get("key"), role.get("id") - ) + members_of_role = jira.get_project_actors_for_role_project(project.get("key"), role.get("id")) if not members_of_role: continue for member in members_of_role: if member.get("type") == "atlassian-group-role-actor": if member.get("name") == group_name_to_find: print(f'{project.get("key")} has {role.get("name")}') - convert_group_into_users_in_role( - project.get("key"), role.get("id"), group_name_to_find - ) + convert_group_into_users_in_role(project.get("key"), role.get("id"), group_name_to_find) diff --git a/examples/jira/jira_copy_components_from_A_to_B.py b/examples/jira/jira_copy_components_from_A_to_B.py index d1f79fef9..e035959ee 100644 --- a/examples/jira/jira_copy_components_from_A_to_B.py +++ b/examples/jira/jira_copy_components_from_A_to_B.py @@ -1,9 +1,7 @@ # coding=utf-8 from atlassian import Jira -jira = Jira( - url="http://localhost:8080/", username="jira-administrator", password="admin" -) +jira = Jira(url="http://localhost:8080/", username="jira-administrator", password="admin") """That example show how to copy components from one project into another""" diff --git a/examples/jira/jira_create_issue.py b/examples/jira/jira_create_issue.py index 89bedf0f4..c1744bca3 100644 --- a/examples/jira/jira_create_issue.py +++ b/examples/jira/jira_create_issue.py @@ -1,9 +1,7 @@ # coding=utf-8 from atlassian import Jira -jira = Jira( - url="https://jira.example.com/", username="gonchik.tsymzhitov", password="admin" -) +jira = Jira(url="https://jira.example.com/", username="gonchik.tsymzhitov", password="admin") jira.issue_create( fields={ diff --git a/examples/jira/jira_edit_comment.py b/examples/jira/jira_edit_comment.py index 4ba0ed861..cf44a098b 100644 --- a/examples/jira/jira_edit_comment.py +++ b/examples/jira/jira_edit_comment.py @@ -3,8 +3,6 @@ """ How to edit comment""" -jira = Jira( - url="https://jira.example.com/", username="gonchik.tsymzhitov", password="admin" -) +jira = Jira(url="https://jira.example.com/", username="gonchik.tsymzhitov", password="admin") jira.issue_edit_comment("TST-11098", 10700, "edited test rest api request") diff --git a/examples/jira/jira_find_screen_similarity.py b/examples/jira/jira_find_screen_similarity.py index 546e94803..2c6f764e5 100644 --- a/examples/jira/jira_find_screen_similarity.py +++ b/examples/jira/jira_find_screen_similarity.py @@ -9,9 +9,7 @@ logging.basicConfig(level=logging.ERROR) -jira = Jira( - url="jira.example.com", username="username", password="********", timeout=10 -) +jira = Jira(url="jira.example.com", username="username", password="********", timeout=10) def extract_count(json): @@ -43,9 +41,7 @@ def extract_count(json): } ) count_fields_per_screen.append(number_fields) - print( - f"Number of available screen fields {number_fields} for screen with name {screen.get('name')}" - ) + print(f"Number of available screen fields {number_fields} for screen with name {screen.get('name')}") screens.sort(key=extract_count, reverse=True) flipped_fields = {} @@ -53,14 +49,10 @@ def extract_count(json): print("The same screen of fields based on the count") for x in screens: if count_fields_per_screen.count(x["available_fields_count"]) > 1: - print( - f"Please, check {jira.url}/secure/admin/ConfigureFieldScreen.jspa?id={x['screen_id']}" - ) + print(f"Please, check {jira.url}/secure/admin/ConfigureFieldScreen.jspa?id={x['screen_id']}") print("=" * 12) print("The same field screens based on the hash") for x in screens: if hashes.count(x["available_fields_hash"]) > 1: - print( - f"Please, check {jira.url}/secure/admin/ConfigureFieldScreen.jspa?id={x['screen_id']}" - ) + print(f"Please, check {jira.url}/secure/admin/ConfigureFieldScreen.jspa?id={x['screen_id']}") diff --git a/examples/jira/jira_jql_fetcher_as_weekly_report.py b/examples/jira/jira_jql_fetcher_as_weekly_report.py index 61371beab..9497044df 100644 --- a/examples/jira/jira_jql_fetcher_as_weekly_report.py +++ b/examples/jira/jira_jql_fetcher_as_weekly_report.py @@ -57,9 +57,7 @@ def __get_changes_of_cases(self, histories): today = datetime.now(timezone.utc) output = "" for history in histories: - change_date = datetime.strptime( - history.get("created"), "%Y-%m-%dT%H:%M:%S.%f%z" - ) + change_date = datetime.strptime(history.get("created"), "%Y-%m-%dT%H:%M:%S.%f%z") difference = today - change_date if difference.days > self.days: continue @@ -69,9 +67,7 @@ def __get_changes_of_cases(self, histories): ] # person who did the change changes = ["Listing all items that changed:"] for item in history.get("items"): - changes.append( - f"{item['field']} - {item['fromString']}- {item['toString']}" - ) + changes.append(f"{item['field']} - {item['fromString']}- {item['toString']}") output.append("\t".join(changes)) return " - ".join(output) diff --git a/examples/jira/jira_notification_schemes_duplicates.py b/examples/jira/jira_notification_schemes_duplicates.py index 985a360b2..578a7a5a9 100644 --- a/examples/jira/jira_notification_schemes_duplicates.py +++ b/examples/jira/jira_notification_schemes_duplicates.py @@ -6,11 +6,7 @@ def compare_dicts(dict1, dict2, print_diffs=False): count = 0 hint = [] - if ( - len(dict1) != len(dict2) - and len(dict1) != len(dict2) + 1 - and len(dict2) != len(dict1) + 1 - ): + if len(dict1) != len(dict2) and len(dict1) != len(dict2) + 1 and len(dict2) != len(dict1) + 1: return False for key in dict1: @@ -49,9 +45,7 @@ def review(): for notificationType in scheme["notifications"]: notification_types.append(notificationType["notificationType"]) notification_scheme_dict[scheme["event"]["name"]] = notification_types - all_notification_schemes_dict[ - notification_schemes["name"] - ] = notification_scheme_dict + all_notification_schemes_dict[notification_schemes["name"]] = notification_scheme_dict show_diffs = False for i in range(len(names)): diff --git a/examples/jira/jira_project_leaders.py b/examples/jira/jira_project_leaders.py index 2f2501463..cad19a3ce 100644 --- a/examples/jira/jira_project_leaders.py +++ b/examples/jira/jira_project_leaders.py @@ -27,8 +27,6 @@ "| {project_key} | {project_name} | {lead_email_link} |".format( project_key=project["project_key"], project_name=project["project_name"], - lead_email_link=MAILTO.format( - lead_name=project["lead_name"], lead_email=project["lead_email"] - ), + lead_email_link=MAILTO.format(lead_name=project["lead_name"], lead_email=project["lead_email"]), ) ) diff --git a/examples/jira/jira_project_security_level_checker.py b/examples/jira/jira_project_security_level_checker.py index 0ca452a6f..60d781099 100644 --- a/examples/jira/jira_project_security_level_checker.py +++ b/examples/jira/jira_project_security_level_checker.py @@ -5,9 +5,7 @@ """ How to get server info with health check""" -jira = Jira( - url="https://jira.example.com/", username="gonchik.tsymzhitov", password="********" -) +jira = Jira(url="https://jira.example.com/", username="gonchik.tsymzhitov", password="********") log = logging.getLogger("com.gonchik.python.scripts.example") logging.basicConfig(level=logging.ERROR) @@ -16,9 +14,7 @@ for project in projects: project_key = project.get("key") try: - value = ( - jira.get_project_issue_security_scheme(project_key).get("name") or "None" - ) + value = jira.get_project_issue_security_scheme(project_key).get("name") or "None" except Exception as e: log.error(e) value = "None" diff --git a/examples/jira/jira_reindex.py b/examples/jira/jira_reindex.py index 177bba24c..05db1b8dd 100644 --- a/examples/jira/jira_reindex.py +++ b/examples/jira/jira_reindex.py @@ -3,9 +3,7 @@ from atlassian import Jira -jira = Jira( - url="http://localhost:8080/", username="jira-administrator", password="admin" -) +jira = Jira(url="http://localhost:8080/", username="jira-administrator", password="admin") jira.reindex() diff --git a/examples/jira/jira_review_groups.py b/examples/jira/jira_review_groups.py index 3b2391c99..4a3ee010d 100644 --- a/examples/jira/jira_review_groups.py +++ b/examples/jira/jira_review_groups.py @@ -13,24 +13,16 @@ def get_all_users(group, include_inactive=True): :return: """ start = 0 - users = jira.get_all_users_from_group( - group, include_inactive_users=include_inactive, start=start - ) + users = jira.get_all_users_from_group(group, include_inactive_users=include_inactive, start=start) processed_data = { "group_name": group, "total": users["total"], - "users": [ - {"name": user["name"], "active": user["active"]} for user in users["values"] - ], + "users": [{"name": user["name"], "active": user["active"]} for user in users["values"]], } while "nextPage" in users: start += 50 - users = jira.get_all_users_from_group( - group, include_inactive_users=include_inactive, start=start - ) - user_list = [ - {"name": user["name"], "active": user["active"]} for user in users["values"] - ] + users = jira.get_all_users_from_group(group, include_inactive_users=include_inactive, start=start) + user_list = [{"name": user["name"], "active": user["active"]} for user in users["values"]] processed_data["users"] = processed_data["users"] + user_list return processed_data @@ -40,9 +32,7 @@ def sort_users_in_group(group): """ Take group, sort users by the name and return group with sorted users """ - group["users"] = [ - sorted_group for sorted_group in sorted(group["users"], key=lambda k: k["name"]) - ] + group["users"] = [sorted_group for sorted_group in sorted(group["users"], key=lambda k: k["name"])] return group @@ -68,9 +58,7 @@ def get_inactive_users(groups): inactive_users = { "group_name": group["group_name"], "users": [ - {"name": user["name"], "active": user["active"]} - for user in group["users"] - if not user["active"] + {"name": user["name"], "active": user["active"]} for user in group["users"] if not user["active"] ], } inactive_users_list.append(inactive_users) @@ -86,11 +74,7 @@ def exclude_inactive_users(groups): """ for group in groups: for user in group["users"]: - print( - "Trying to delete {} from group {}".format( - user["name"], group["group_name"] - ) - ) + print("Trying to delete {} from group {}".format(user["name"], group["group_name"])) jira.remove_user_from_group(user["name"], group["group_name"]) return True diff --git a/pylintrc b/pyproject.toml similarity index 82% rename from pylintrc rename to pyproject.toml index 362ac7883..2054d309b 100644 --- a/pylintrc +++ b/pyproject.toml @@ -1,20 +1,37 @@ -[MASTER] +# pyproject.toml is a new configuration file defined in PEP 518. +# It is design to store build system requirements, but it can also store any +# tool configuration for your Python project, possibly replacing the need for +# setup.cfg or other tool-specific files. +# https://github.com/carlosperate/awesome-pyproject + +[tool.flake8] +max-line-length = 120 +exclude = '.tox,.travis,docs' + +[tool.black] +line-length = 120 +include = '(atlassian|examples|tests)\/.*\.py' + +[tool.pylint] +max-line-length = 120 + +[tool.pylint.MASTER] # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code. -extension-pkg-whitelist= +extension-pkg-whitelist='' # Specify a score threshold to be exceeded before program exits with error. fail-under=10.0 # Add files or directories to the blacklist. They should be base names, not # paths. -ignore=.git +ignore='.git' # Add files or directories matching the regex patterns to the blacklist. The # regex matches against base names, not paths. -ignore-patterns= +ignore-patterns='' # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). @@ -31,25 +48,25 @@ limit-inference-results=100 # List of plugins (as comma separated values of python module names) to load, # usually to register additional checkers. -load-plugins= +load-plugins='' # Pickle collected data for later comparisons. -persistent=yes +persistent='yes' # When enabled, pylint would attempt to guess common misconfiguration and emit # user-friendly hints instead of false-positive error messages. -suggestion-mode=yes +suggestion-mode='yes' # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no +unsafe-load-any-extension='no' -[MESSAGES CONTROL] +['tool.pylint.MESSAGES CONTROL'] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. -confidence= +confidence='' # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this @@ -60,7 +77,7 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use "--disable=all --enable=classes # --disable=W". -disable=print-statement, +disable='''print-statement, parameter-unpacking, unpacking-in-except, old-raise-syntax, @@ -144,22 +161,23 @@ disable=print-statement, missing-function-docstring, W, R0201, +''' # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. -enable=c-extension-no-member +enable='c-extension-no-member' -[REPORTS] +[tool.pylint.REPORTS] # Python expression which should return a score less than or equal to 10. You # have access to the variables 'error', 'warning', 'refactor', and 'convention' # which contain the number of messages in each category, as well as 'statement' # which is the total number of statements analyzed. This score is used by the # global evaluation report (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) +evaluation='10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)' # Template used to display messages. This is a python new-style format string # used to format the message information. See doc for all details. @@ -168,16 +186,16 @@ evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / stateme # Set the output format. Available formats are text, parseable, colorized, json # and msvs (visual studio). You can also give a reporter class, e.g. # mypackage.mymodule.MyReporterClass. -output-format=text +output-format='text' # Tells whether to display a full report or only the messages. -reports=no +reports='no' # Activate the evaluation score. -score=yes +score='yes' -[REFACTORING] +[tool.pylint.REFACTORING] # Maximum number of nested blocks for function / method body max-nested-blocks=5 @@ -186,70 +204,71 @@ max-nested-blocks=5 # inconsistent-return-statements if a never returning function is called then # it will be considered as an explicit return statement and no message will be # printed. -never-returning-functions=sys.exit +never-returning-functions='sys.exit' -[LOGGING] +[tool.pylint.LOGGING] # The type of string formatting that logging methods do. `old` means using % # formatting, `new` is for `{}` formatting. -logging-format-style=old +logging-format-style='old' # Logging modules to check that the string format arguments are in logging # function parameter format. -logging-modules=logging +logging-modules='logging' -[SPELLING] +[tool.pylint.SPELLING] # Limits count of emitted suggestions for spelling mistakes. max-spelling-suggestions=4 # Spelling dictionary name. Available dictionaries: none. To make it work, # install the python-enchant package. -spelling-dict= +spelling-dict='' # List of comma separated words that should not be checked. -spelling-ignore-words= +spelling-ignore-words='' # A path to a file that contains the private dictionary; one word per line. -spelling-private-dict-file= +spelling-private-dict-file='' # Tells whether to store unknown words to the private dictionary (see the # --spelling-private-dict-file option) instead of raising a message. -spelling-store-unknown-words=no +spelling-store-unknown-words='no' -[MISCELLANEOUS] +[tool.pylint.MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. -notes=FIXME, +notes='''FIXME, XXX, TODO +''' # Regular expression of note tags to take in consideration. #notes-rgx= -[TYPECHECK] +[tool.pylint.TYPECHECK] # List of decorators that produce context managers, such as # contextlib.contextmanager. Add to this list to register other decorators that # produce valid context managers. -contextmanager-decorators=contextlib.contextmanager +contextmanager-decorators='contextlib.contextmanager' # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E1101 when accessed. Python regular # expressions are accepted. -generated-members= +generated-members='' # Tells whether missing members accessed in mixin class should be ignored. A # mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes +ignore-mixin-members='yes' # Tells whether to warn about missing members when the owner of the attribute # is inferred to be None. -ignore-none=yes +ignore-none='yes' # This flag controls whether pylint should warn about no-member and similar # checks whenever an opaque object is returned when inferring. The inference @@ -257,22 +276,22 @@ ignore-none=yes # some branches might not be evaluated, which results in partial inference. In # that case, it might be useful to still emit no-member and other checks for # the rest of the inferred objects. -ignore-on-opaque-inference=yes +ignore-on-opaque-inference='yes' # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of # qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local +ignored-classes='optparse.Values,thread._local,_thread._local' # List of module names for which member attributes should not be checked # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis). It # supports qualified module names, as well as Unix pattern matching. -ignored-modules= +ignored-modules='' # Show a hint with possible names when a member name was not found. The aspect # of finding the hint is based on edit distance. -missing-member-hint=yes +missing-member-hint='yes' # The minimum edit distance a name should have in order to be considered a # similar match for a missing member name. @@ -283,46 +302,47 @@ missing-member-hint-distance=1 missing-member-max-choices=1 # List of decorators that change the signature of a decorated function. -signature-mutators= +signature-mutators='' -[VARIABLES] +[tool.pylint.VARIABLES] # List of additional names supposed to be defined in builtins. Remember that # you should avoid defining new builtins when possible. -additional-builtins= +additional-builtins='' # Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes +allow-global-unused-variables='yes' # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. -callbacks=cb_, +callbacks='''cb_, _cb +''' # A regular expression matching the name of dummy variables (i.e. expected to # not be used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ +dummy-variables-rgx='_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_' # Argument names that match this expression will be ignored. Default to name # with leading underscore. -ignored-argument-names=_.*|^ignored_|^unused_ +ignored-argument-names='_.*|^ignored_|^unused_' # Tells whether we should check for unused import in __init__ files. -init-import=no +init-import='no' # List of qualified module names which can have objects that can redefine # builtins. -redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io +redefining-builtins-modules='six.moves,past.builtins,future.builtins,builtins,io' -[FORMAT] +[tool.pylint.FORMAT] # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= +expected-line-ending-format='' # Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ +ignore-long-lines='^\s*(# )??$' # Number of spaces of indent required inside a hanging or continued line. indent-after-paren=4 @@ -339,72 +359,73 @@ max-module-lines=1000 # Allow the body of a class to be on the same line as the declaration if body # contains single statement. -single-line-class-stmt=no +single-line-class-stmt='no' # Allow the body of an if to be on the same line as the test if there is no # else. -single-line-if-stmt=no +single-line-if-stmt='no' -[SIMILARITIES] +[tool.pylint.SIMILARITIES] # Ignore comments when computing similarities. -ignore-comments=yes +ignore-comments='yes' # Ignore docstrings when computing similarities. -ignore-docstrings=yes +ignore-docstrings='yes' # Ignore imports when computing similarities. -ignore-imports=no +ignore-imports='no' # Minimum lines number of a similarity. min-similarity-lines=4 -[BASIC] +[tool.pylint.BASIC] # Naming style matching correct argument names. -argument-naming-style=snake_case +argument-naming-style='snake_case' # Regular expression matching correct argument names. Overrides argument- # naming-style. #argument-rgx= # Naming style matching correct attribute names. -attr-naming-style=snake_case +attr-naming-style='snake_case' # Regular expression matching correct attribute names. Overrides attr-naming- # style. #attr-rgx= # Bad variable names which should always be refused, separated by a comma. -bad-names=foo, +bad-names='''foo, bar, baz, toto, tutu, tata +''' # Bad variable names regexes, separated by a comma. If names match any regex, # they will always be refused -bad-names-rgxs= +bad-names-rgxs='' # Naming style matching correct class attribute names. -class-attribute-naming-style=any +class-attribute-naming-style='any' # Regular expression matching correct class attribute names. Overrides class- # attribute-naming-style. #class-attribute-rgx= # Naming style matching correct class names. -class-naming-style=PascalCase +class-naming-style='PascalCase' # Regular expression matching correct class names. Overrides class-naming- # style. #class-rgx= # Naming style matching correct constant names. -const-naming-style=UPPER_CASE +const-naming-style='UPPER_CASE' # Regular expression matching correct constant names. Overrides const-naming- # style. @@ -415,14 +436,14 @@ const-naming-style=UPPER_CASE docstring-min-length=-1 # Naming style matching correct function names. -function-naming-style=snake_case +function-naming-style='snake_case' # Regular expression matching correct function names. Overrides function- # naming-style. #function-rgx= # Good variable names which should always be accepted, separated by a comma. -good-names=i, +good-names='''i, j, k, ex, @@ -432,30 +453,31 @@ good-names=i, x, y, _ +''' # Good variable names regexes, separated by a comma. If names match any regex, # they will always be accepted -good-names-rgxs= +good-names-rgxs='' # Include a hint for the correct naming format with invalid-name. -include-naming-hint=no +include-naming-hint='no' # Naming style matching correct inline iteration names. -inlinevar-naming-style=any +inlinevar-naming-style='any' # Regular expression matching correct inline iteration names. Overrides # inlinevar-naming-style. #inlinevar-rgx= # Naming style matching correct method names. -method-naming-style=snake_case +method-naming-style='snake_case' # Regular expression matching correct method names. Overrides method-naming- # style. #method-rgx= # Naming style matching correct module names. -module-naming-style=snake_case +module-naming-style='snake_case' # Regular expression matching correct module names. Overrides module-naming- # style. @@ -463,100 +485,102 @@ module-naming-style=snake_case # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. -name-group= +name-group='' # Regular expression which should only match function or class names that do # not require a docstring. -no-docstring-rgx=^_ +no-docstring-rgx='^_' # List of decorators that produce properties, such as abc.abstractproperty. Add # to this list to register other decorators that produce valid properties. # These decorators are taken in consideration only for invalid-name. -property-classes=abc.abstractproperty +property-classes='abc.abstractproperty' # Naming style matching correct variable names. -variable-naming-style=snake_case +variable-naming-style='snake_case' # Regular expression matching correct variable names. Overrides variable- # naming-style. #variable-rgx= -[STRING] +[tool.pylint.STRING] # This flag controls whether inconsistent-quotes generates a warning when the # character used as a quote delimiter is used inconsistently within a module. -check-quote-consistency=no +check-quote-consistency='no' # This flag controls whether the implicit-str-concat should generate a warning # on implicit string concatenation in sequences defined over several lines. -check-str-concat-over-line-jumps=no +check-str-concat-over-line-jumps='no' -[IMPORTS] +[tool.pylint.IMPORTS] # List of modules that can be imported at any level, not just the top level # one. -allow-any-import-level= +allow-any-import-level='' # Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no +allow-wildcard-with-all='no' # Analyse import fallback blocks. This can be used to support both Python 2 and # 3 compatible code, which means that the block might have code that exists # only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no +analyse-fallback-blocks='no' # Deprecated modules which should not be used, separated by a comma. -deprecated-modules=optparse,tkinter.tix +deprecated-modules='optparse,tkinter.tix' # Create a graph of external dependencies in the given file (report RP0402 must # not be disabled). -ext-import-graph= +ext-import-graph='' # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled). -import-graph= +import-graph='' # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled). -int-import-graph= +int-import-graph='' # Force import order to recognize a module as part of the standard # compatibility libraries. -known-standard-library= +known-standard-library='' # Force import order to recognize a module as part of a third party library. -known-third-party=enchant +known-third-party='enchant' # Couples of modules and preferred modules, separated by a comma. -preferred-modules= +preferred-modules='' -[CLASSES] +[tool.pylint.CLASSES] # List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__, +defining-attr-methods='''__init__, __new__, setUp, __post_init__ +''' # List of member names, which should be excluded from the protected access # warning. -exclude-protected=_asdict, +exclude-protected='''_asdict, _fields, _replace, _source, _make +''' # List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls +valid-classmethod-first-arg='cls' # List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=cls +valid-metaclass-classmethod-first-arg='cls' -[DESIGN] +[tool.pylint.DESIGN] # Maximum number of arguments for function / method. max-args=5 @@ -589,9 +613,10 @@ max-statements=50 min-public-methods=2 -[EXCEPTIONS] +[tool.pylint.EXCEPTIONS] # Exceptions that will emit a warning when being caught. Defaults to # "BaseException, Exception". -overgeneral-exceptions=BaseException, +overgeneral-exceptions='''BaseException, Exception +''' diff --git a/requirements-dev.txt b/requirements-dev.txt index 06a9d9ea0..2816f6dc5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,5 @@ -r requirements.txt -flake8 +flake9 pytest +pylint tox diff --git a/setup.py b/setup.py index 309a96313..25f0065b1 100644 --- a/setup.py +++ b/setup.py @@ -2,69 +2,63 @@ from setuptools import find_packages from setuptools import setup -with open(os.path.join('atlassian', 'VERSION')) as file: +with open(os.path.join("atlassian", "VERSION")) as file: version = file.read().strip() -with open('README.rst') as file: +with open("README.rst") as file: long_description = file.read() setup( - name='atlassian-python-api', - description='Python Atlassian REST API Wrapper', + name="atlassian-python-api", + description="Python Atlassian REST API Wrapper", long_description=long_description, - license='Apache License 2.0', + license="Apache License 2.0", version=version, - download_url='https://github.com/atlassian-api/atlassian-python-api', - author='Matt Harasymczuk', - author_email='matt@astrotech.io', - maintainer='Gonchik Tsymzhitov', - maintainer_email='gonchik.tsymzhitov@gmail.com', - url='https://github.com/atlassian-api/atlassian-python-api', - keywords='atlassian jira core software confluence bitbucket bamboo crowd portfolio tempo servicedesk rest api', - + download_url="https://github.com/atlassian-api/atlassian-python-api", + author="Matt Harasymczuk", + author_email="matt@astrotech.io", + maintainer="Gonchik Tsymzhitov", + maintainer_email="gonchik.tsymzhitov@gmail.com", + url="https://github.com/atlassian-api/atlassian-python-api", + keywords="atlassian jira core software confluence bitbucket bamboo crowd portfolio tempo servicedesk rest api", packages=find_packages(), - package_dir={'atlassian': 'atlassian'}, + package_dir={"atlassian": "atlassian"}, include_package_data=True, - zip_safe=False, - install_requires=[ - 'deprecated', - 'requests', - 'six', - 'oauthlib', - 'requests_oauthlib' - ], + install_requires=["deprecated", "requests", "six", "oauthlib", "requests_oauthlib"], extras_require={ - 'kerberos': ['kerberos-sspi ; platform_system=="Windows"', - 'kerberos ; platform_system!="Windows"'] + "kerberos": [ + 'kerberos-sspi ; platform_system=="Windows"', + 'kerberos ; platform_system!="Windows"', + ] }, - platforms='Platform Independent', - + platforms="Platform Independent", classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Web Environment', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'Intended Audience :: Information Technology', - 'License :: OSI Approved :: Apache Software License', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Operating System :: POSIX', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Topic :: Utilities', - 'Topic :: Internet', - 'Topic :: Internet :: WWW/HTTP', - 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: Software Development :: Libraries :: Application Frameworks'] + "Development Status :: 4 - Beta", + "Environment :: Web Environment", + "Environment :: Console", + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "Intended Audience :: Information Technology", + "License :: OSI Approved :: Apache Software License", + "Natural Language :: English", + "Operating System :: OS Independent", + "Operating System :: POSIX", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Topic :: Utilities", + "Topic :: Internet", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Software Development :: Libraries :: Application Frameworks", + ], ) diff --git a/tests/test_base.py b/tests/test_base.py index 2a86f77a0..5eb12e8e4 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -23,9 +23,7 @@ def test_init_jira(self): Jira(url=JIRA_URL, username=ATLASSIAN_USER, password=ATLASSIAN_PASSWORD) def test_init_confluence(self): - Confluence( - url=CONFLUENCE_URL, username=ATLASSIAN_USER, password=ATLASSIAN_PASSWORD - ) + Confluence(url=CONFLUENCE_URL, username=ATLASSIAN_USER, password=ATLASSIAN_PASSWORD) def test_init_bitbucket(self): Bitbucket(url=STASH_URL, username=ATLASSIAN_USER, password=ATLASSIAN_PASSWORD) @@ -41,9 +39,7 @@ def test_init_crowd(self): ) def test_init_service_desk(self): - ServiceDesk( - url=SERVICE_DESK_URL, username=ATLASSIAN_USER, password=ATLASSIAN_PASSWORD - ) + ServiceDesk(url=SERVICE_DESK_URL, username=ATLASSIAN_USER, password=ATLASSIAN_PASSWORD) def test_init_xray(self): Xray(url=XRAY_URL, username=ATLASSIAN_USER, password=ATLASSIAN_PASSWORD) diff --git a/tests/test_confluence_attach.py b/tests/test_confluence_attach.py index 0d3a5b4b5..18c3ef126 100644 --- a/tests/test_confluence_attach.py +++ b/tests/test_confluence_attach.py @@ -48,9 +48,7 @@ def test_confluence_attach_file_1(self): os.write(fd, b"Hello World - Version 1") # upload a new file - result = confluence.attach_file( - filename, "", title=title, space=space, comment="upload from unittest" - ) + result = confluence.attach_file(filename, "", title=title, space=space, comment="upload from unittest") # attach_file() returns: {'results': [{'id': 'att144005326', 'type': 'attachment', ... self.assertTrue("results" in result) @@ -59,9 +57,7 @@ def test_confluence_attach_file_1(self): # upload a new version of an existing file os.lseek(fd, 0, 0) os.write(fd, b"Hello Universe - Version 2") - result = confluence.attach_file( - filename, "", title=title, space=space, comment="upload from unittest" - ) + result = confluence.attach_file(filename, "", title=title, space=space, comment="upload from unittest") # attach_file() returns: {'id': 'att144005326', 'type': 'attachment', ... self.assertTrue("id" in result) diff --git a/tox.ini b/tox.ini index e9a8c3484..5f640af6f 100644 --- a/tox.ini +++ b/tox.ini @@ -5,29 +5,22 @@ linting_targets = atlassian/ examples/ tests/ envlist = py27,py3,flake8,black,mypy,bandit,doc8 skip_missing_interpreters = True -[flake8] -max-line-length = 120 -exclude = .tox,.travis,docs - -[pylint] -max-line-length = 120 - [testenv] deps = pytest commands = pytest -v extras = kerberos -[testenv:flake8] +[testenv:flake9] basepython = python3 skip_install = true -deps = flake8 +deps = flake9 # flake9 is a fork of flake8 which supports pyproject.toml files commands = flake8 [testenv:pylint] basepython = python3 skip_install = true deps = pylint -commands = pylint --rcfile=tox.ini {[base]linting_targets} +commands = pylint {[base]linting_targets} [testenv:black] basepython = python3