From 0fadd6be8ed138f971a71a41923c61c9b5c4bdda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20K=C3=B6pcke?= Date: Sat, 29 Oct 2022 03:03:57 +0200 Subject: [PATCH] Add support for repository autolink references (#2016) --- github/Autolink.py | 62 +++++++++++++++++++ github/Autolink.pyi | 13 ++++ github/Repository.py | 40 ++++++++++++ github/Repository.pyi | 4 ++ tests/Autolink.py | 45 ++++++++++++++ tests/ReplayData/Autolink.setUp.txt | 33 ++++++++++ .../Repository.testCreateAutolink.txt | 11 ++++ .../Repository.testGetAutolinks.txt | 11 ++++ .../Repository.testRemoveAutolink.txt | 11 ++++ tests/Repository.py | 19 ++++++ 10 files changed, 249 insertions(+) create mode 100644 github/Autolink.py create mode 100644 github/Autolink.pyi create mode 100644 tests/Autolink.py create mode 100644 tests/ReplayData/Autolink.setUp.txt create mode 100644 tests/ReplayData/Repository.testCreateAutolink.txt create mode 100644 tests/ReplayData/Repository.testGetAutolinks.txt create mode 100644 tests/ReplayData/Repository.testRemoveAutolink.txt diff --git a/github/Autolink.py b/github/Autolink.py new file mode 100644 index 0000000000..3188128c2d --- /dev/null +++ b/github/Autolink.py @@ -0,0 +1,62 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2021 Marco Köpcke # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +import github.GithubObject + + +class Autolink(github.GithubObject.NonCompletableGithubObject): + def __repr__(self): + return self.get__repr__({"id": self._id.value}) + + @property + def id(self): + """ + :type: integer + """ + return self._id.value + + @property + def key_prefix(self): + """ + :type: string + """ + return self._key_prefix.value + + @property + def url_template(self): + """ + :type: string + """ + return self._url_template.value + + def _initAttributes(self): + self._id = github.GithubObject.NotSet + self._key_prefix = github.GithubObject.NotSet + self._url_template = github.GithubObject.NotSet + + def _useAttributes(self, attributes): + if "id" in attributes: # pragma no branch + self._id = self._makeIntAttribute(attributes["id"]) + if "key_prefix" in attributes: # pragma no branch + self._key_prefix = self._makeStringAttribute(attributes["key_prefix"]) + if "url_template" in attributes: # pragma no branch + self._url_template = self._makeStringAttribute(attributes["url_template"]) diff --git a/github/Autolink.pyi b/github/Autolink.pyi new file mode 100644 index 0000000000..3541da984d --- /dev/null +++ b/github/Autolink.pyi @@ -0,0 +1,13 @@ +from typing import Any, Dict, List + +from github.GithubObject import NonCompletableGithubObject + +class Autolink(NonCompletableGithubObject): + def _initAttributes(self) -> None: ... + def _useAttributes(self, attributes: Dict[str, Any]) -> None: ... + @property + def id(self) -> int: ... + @property + def key_prefix(self) -> str: ... + @property + def url_template(self) -> str: ... diff --git a/github/Repository.py b/github/Repository.py index cc9b97062b..1090c8ade7 100644 --- a/github/Repository.py +++ b/github/Repository.py @@ -93,6 +93,7 @@ from deprecated import deprecated import github.Artifact +import github.Autolink import github.Branch import github.CheckRun import github.CheckSuite @@ -918,6 +919,22 @@ def compare(self, base, head): self._requester, headers, data, completed=True ) + def create_autolink(self, key_prefix, url_template): + """ + :calls: `POST /repos/{owner}/{repo}/autolinks `_ + :param key_prefix: string + :param url_template: string + :rtype: :class:`github.Autolink.Autolink` + """ + assert isinstance(key_prefix, str), key_prefix + assert isinstance(url_template, str), url_template + + post_parameters = {"key_prefix": key_prefix, "url_template": url_template} + headers, data = self._requester.requestJsonAndCheck( + "POST", f"{self.url}/autolinks", input=post_parameters + ) + return github.Autolink.Autolink(self._requester, headers, data, completed=True) + def create_git_blob(self, content, encoding): """ :calls: `POST /repos/{owner}/{repo}/git/blobs `_ @@ -2088,6 +2105,15 @@ def get_projects(self, state=github.GithubObject.NotSet): {"Accept": Consts.mediaTypeProjectsPreview}, ) + def get_autolinks(self): + """ + :calls: `GET /repos/{owner}/{repo}/autolinks `_ + :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.Autolink.Autolink` + """ + return github.PaginatedList.PaginatedList( + github.Autolink.Autolink, self._requester, f"{self.url}/autolinks", None + ) + def create_file( self, path, @@ -3509,6 +3535,20 @@ def remove_self_hosted_runner(self, runner): ) return status == 204 + def remove_autolink(self, autolink): + """ + :calls: `DELETE /repos/{owner}/{repo}/autolinks/{id} `_ + :param autolink: int or :class:`github.Autolink.Autolink` + :rtype: None + """ + is_autolink = isinstance(autolink, github.Autolink.Autolink) + assert is_autolink or isinstance(autolink, int), autolink + + status, _, _ = self._requester.requestJson( + "DELETE", f"{self.url}/autolinks/{autolink.id if is_autolink else autolink}" + ) + return status == 204 + def subscribe_to_hub(self, event, callback, secret=github.GithubObject.NotSet): """ :calls: `POST /hub `_ diff --git a/github/Repository.pyi b/github/Repository.pyi index 16a0a0a65a..705df58bd4 100644 --- a/github/Repository.pyi +++ b/github/Repository.pyi @@ -3,6 +3,7 @@ from typing import Any, Dict, List, Optional, Union, overload from github.Artifact import Artifact from github.AuthenticatedUser import AuthenticatedUser +from github.Autolink import Autolink from github.Branch import Branch from github.CheckRun import CheckRun from github.CheckSuite import CheckSuite @@ -104,6 +105,7 @@ class Repository(CompletableGithubObject): def contents_url(self) -> str: ... @property def contributors_url(self) -> str: ... + def create_autolink(self, key_prefix: str, url_template: str) -> Autolink: ... def create_check_run( self, name: str, @@ -311,6 +313,7 @@ class Repository(CompletableGithubObject): def get_artifact(self) -> Artifact: ... def get_artifacts(self) -> PaginatedList[Artifact]: ... def get_assignees(self) -> PaginatedList[NamedUser]: ... + def get_autolinks(self) -> PaginatedList[Autolink]: ... def get_branch(self, branch: str) -> Branch: ... def rename_branch(self, branch: Union[str, Branch], new_name: str) -> bool: ... def get_branches(self) -> PaginatedList[Branch]: ... @@ -561,6 +564,7 @@ class Repository(CompletableGithubObject): def pushed_at(self) -> datetime: ... @property def releases_url(self) -> str: ... + def remove_autolink(self, autolink: Union[Autolink, int]) -> bool: ... def remove_from_collaborators( self, collaborator: Union[str, NamedUser] ) -> None: ... diff --git a/tests/Autolink.py b/tests/Autolink.py new file mode 100644 index 0000000000..e363e3cb94 --- /dev/null +++ b/tests/Autolink.py @@ -0,0 +1,45 @@ +############################ Copyrights and license ############################ +# # +# Copyright 2021 Marco Köpcke # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ +from tests import Framework + + +class Autolink(Framework.TestCase): + def setUp(self): + super().setUp() + # When recording test, be sure to create a autolink for yourself on + # Github and update it here. + links = [ + x + for x in self.g.get_user("theCapypara").get_repo("PyGithub").get_autolinks() + if x.id == 209614 + ] + self.assertEqual( + 1, len(links), "There must be exactly one autolink with the ID 209614." + ) + self.link = links[0] + + def testAttributes(self): + self.assertEqual(self.link.id, 209614) + self.assertEqual(self.link.key_prefix, "DUMMY-") + self.assertEqual( + self.link.url_template, "https://github.com/PyGithub/PyGithub/issues/" + ) diff --git a/tests/ReplayData/Autolink.setUp.txt b/tests/ReplayData/Autolink.setUp.txt new file mode 100644 index 0000000000..456b4d6f84 --- /dev/null +++ b/tests/ReplayData/Autolink.setUp.txt @@ -0,0 +1,33 @@ +https +GET +api.github.com +None +/users/theCapypara +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 02 Nov 2021 13:15:54 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"83d2773e24c62f5474d8c7daf73e643ed3be693772d094ee8fb97974adc777f4"'), ('Last-Modified', 'Tue, 02 Nov 2021 11:36:31 GMT'), ('X-OAuth-Scopes', 'admin:repo_hook, repo'), ('X-Accepted-OAuth-Scopes', ''), ('github-authentication-token-expiration', '2021-11-09 12:40:40 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4893'), ('X-RateLimit-Reset', '1635859633'), ('X-RateLimit-Used', '107'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'C176:C803:15A3D94:1617DEA:61813A0A')] +{"login":"theCapypara","id":3512122,"node_id":"MDQ6VXNlcjM1MTIxMjI=","avatar_url":"https://avatars.githubusercontent.com/u/3512122?v=4","gravatar_id":"","url":"https://api.github.com/users/theCapypara","html_url":"https://github.com/theCapypara","followers_url":"https://api.github.com/users/theCapypara/followers","following_url":"https://api.github.com/users/theCapypara/following{/other_user}","gists_url":"https://api.github.com/users/theCapypara/gists{/gist_id}","starred_url":"https://api.github.com/users/theCapypara/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/theCapypara/subscriptions","organizations_url":"https://api.github.com/users/theCapypara/orgs","repos_url":"https://api.github.com/users/theCapypara/repos","events_url":"https://api.github.com/users/theCapypara/events{/privacy}","received_events_url":"https://api.github.com/users/theCapypara/received_events","type":"User","site_admin":false,"name":"Marco Köpcke","company":"@tudock","blog":"https://www.linkedin.com/in/marco-koepcke/","location":null,"email":"hello@capypara.de","hireable":null,"bio":"aka. Parakoopa ---\r\nProfessional Magento 2 developer that loves creating tools that help other developers.... And other weird & fun side projects :)","twitter_username":null,"public_repos":88,"public_gists":2,"followers":28,"following":16,"created_at":"2013-02-08T14:53:47Z","updated_at":"2021-11-02T11:36:31Z"} + +https +GET +api.github.com +None +/repos/theCapypara/PyGithub +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 02 Nov 2021 13:15:54 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"d3e74e88c2d48ed5cea0756eba6e373973531859ea786baa58ac755d0c6e301b"'), ('Last-Modified', 'Thu, 14 Oct 2021 13:44:46 GMT'), ('X-OAuth-Scopes', 'admin:repo_hook, repo'), ('X-Accepted-OAuth-Scopes', 'repo'), ('github-authentication-token-expiration', '2021-11-09 12:40:40 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4892'), ('X-RateLimit-Reset', '1635859633'), ('X-RateLimit-Used', '108'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'C178:78E3:182FE59:18A8701:61813A0A')] +{"id":392376264,"node_id":"MDEwOlJlcG9zaXRvcnkzOTIzNzYyNjQ=","name":"PyGithub","full_name":"theCapypara/PyGithub","private":false,"owner":{"login":"theCapypara","id":3512122,"node_id":"MDQ6VXNlcjM1MTIxMjI=","avatar_url":"https://avatars.githubusercontent.com/u/3512122?v=4","gravatar_id":"","url":"https://api.github.com/users/theCapypara","html_url":"https://github.com/theCapypara","followers_url":"https://api.github.com/users/theCapypara/followers","following_url":"https://api.github.com/users/theCapypara/following{/other_user}","gists_url":"https://api.github.com/users/theCapypara/gists{/gist_id}","starred_url":"https://api.github.com/users/theCapypara/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/theCapypara/subscriptions","organizations_url":"https://api.github.com/users/theCapypara/orgs","repos_url":"https://api.github.com/users/theCapypara/repos","events_url":"https://api.github.com/users/theCapypara/events{/privacy}","received_events_url":"https://api.github.com/users/theCapypara/received_events","type":"User","site_admin":false},"html_url":"https://github.com/theCapypara/PyGithub","description":"Typed interactions with the GitHub API v3","fork":true,"url":"https://api.github.com/repos/theCapypara/PyGithub","forks_url":"https://api.github.com/repos/theCapypara/PyGithub/forks","keys_url":"https://api.github.com/repos/theCapypara/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/theCapypara/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/theCapypara/PyGithub/teams","hooks_url":"https://api.github.com/repos/theCapypara/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/theCapypara/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/theCapypara/PyGithub/events","assignees_url":"https://api.github.com/repos/theCapypara/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/theCapypara/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/theCapypara/PyGithub/tags","blobs_url":"https://api.github.com/repos/theCapypara/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/theCapypara/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/theCapypara/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/theCapypara/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/theCapypara/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/theCapypara/PyGithub/languages","stargazers_url":"https://api.github.com/repos/theCapypara/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/theCapypara/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/theCapypara/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/theCapypara/PyGithub/subscription","commits_url":"https://api.github.com/repos/theCapypara/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/theCapypara/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/theCapypara/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/theCapypara/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/theCapypara/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/theCapypara/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/theCapypara/PyGithub/merges","archive_url":"https://api.github.com/repos/theCapypara/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/theCapypara/PyGithub/downloads","issues_url":"https://api.github.com/repos/theCapypara/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/theCapypara/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/theCapypara/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/theCapypara/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/theCapypara/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/theCapypara/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/theCapypara/PyGithub/deployments","created_at":"2021-08-03T16:10:46Z","updated_at":"2021-10-14T13:44:46Z","pushed_at":"2021-10-14T13:44:37Z","git_url":"git://github.com/theCapypara/PyGithub.git","ssh_url":"git@github.com:theCapypara/PyGithub.git","clone_url":"https://github.com/theCapypara/PyGithub.git","svn_url":"https://github.com/theCapypara/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":13474,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"allow_forking":true,"is_template":false,"topics":[],"visibility":"public","forks":0,"open_issues":0,"watchers":0,"default_branch":"master","permissions":{"admin":true,"maintain":true,"push":true,"triage":true,"pull":true},"temp_clone_token":"","allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"allow_auto_merge":false,"delete_branch_on_merge":false,"parent":{"id":3544490,"node_id":"MDEwOlJlcG9zaXRvcnkzNTQ0NDkw","name":"PyGithub","full_name":"PyGithub/PyGithub","private":false,"owner":{"login":"PyGithub","id":11288996,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExMjg4OTk2","avatar_url":"https://avatars.githubusercontent.com/u/11288996?v=4","gravatar_id":"","url":"https://api.github.com/users/PyGithub","html_url":"https://github.com/PyGithub","followers_url":"https://api.github.com/users/PyGithub/followers","following_url":"https://api.github.com/users/PyGithub/following{/other_user}","gists_url":"https://api.github.com/users/PyGithub/gists{/gist_id}","starred_url":"https://api.github.com/users/PyGithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PyGithub/subscriptions","organizations_url":"https://api.github.com/users/PyGithub/orgs","repos_url":"https://api.github.com/users/PyGithub/repos","events_url":"https://api.github.com/users/PyGithub/events{/privacy}","received_events_url":"https://api.github.com/users/PyGithub/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/PyGithub/PyGithub","description":"Typed interactions with the GitHub API v3","fork":false,"url":"https://api.github.com/repos/PyGithub/PyGithub","forks_url":"https://api.github.com/repos/PyGithub/PyGithub/forks","keys_url":"https://api.github.com/repos/PyGithub/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PyGithub/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PyGithub/PyGithub/teams","hooks_url":"https://api.github.com/repos/PyGithub/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/PyGithub/PyGithub/events","assignees_url":"https://api.github.com/repos/PyGithub/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/PyGithub/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/PyGithub/PyGithub/tags","blobs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PyGithub/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/PyGithub/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PyGithub/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/PyGithub/PyGithub/languages","stargazers_url":"https://api.github.com/repos/PyGithub/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/PyGithub/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/PyGithub/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/PyGithub/PyGithub/subscription","commits_url":"https://api.github.com/repos/PyGithub/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/PyGithub/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/PyGithub/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/PyGithub/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/PyGithub/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PyGithub/PyGithub/merges","archive_url":"https://api.github.com/repos/PyGithub/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PyGithub/PyGithub/downloads","issues_url":"https://api.github.com/repos/PyGithub/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/PyGithub/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/PyGithub/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/PyGithub/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PyGithub/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/PyGithub/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/PyGithub/PyGithub/deployments","created_at":"2012-02-25T12:53:47Z","updated_at":"2021-11-02T12:35:21Z","pushed_at":"2021-11-02T08:12:52Z","git_url":"git://github.com/PyGithub/PyGithub.git","ssh_url":"git@github.com:PyGithub/PyGithub.git","clone_url":"https://github.com/PyGithub/PyGithub.git","svn_url":"https://github.com/PyGithub/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":13577,"stargazers_count":4744,"watchers_count":4744,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1397,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":143,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"allow_forking":true,"is_template":false,"topics":["github","github-api","pygithub","python"],"visibility":"public","forks":1397,"open_issues":143,"watchers":4744,"default_branch":"master"},"source":{"id":3544490,"node_id":"MDEwOlJlcG9zaXRvcnkzNTQ0NDkw","name":"PyGithub","full_name":"PyGithub/PyGithub","private":false,"owner":{"login":"PyGithub","id":11288996,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExMjg4OTk2","avatar_url":"https://avatars.githubusercontent.com/u/11288996?v=4","gravatar_id":"","url":"https://api.github.com/users/PyGithub","html_url":"https://github.com/PyGithub","followers_url":"https://api.github.com/users/PyGithub/followers","following_url":"https://api.github.com/users/PyGithub/following{/other_user}","gists_url":"https://api.github.com/users/PyGithub/gists{/gist_id}","starred_url":"https://api.github.com/users/PyGithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PyGithub/subscriptions","organizations_url":"https://api.github.com/users/PyGithub/orgs","repos_url":"https://api.github.com/users/PyGithub/repos","events_url":"https://api.github.com/users/PyGithub/events{/privacy}","received_events_url":"https://api.github.com/users/PyGithub/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/PyGithub/PyGithub","description":"Typed interactions with the GitHub API v3","fork":false,"url":"https://api.github.com/repos/PyGithub/PyGithub","forks_url":"https://api.github.com/repos/PyGithub/PyGithub/forks","keys_url":"https://api.github.com/repos/PyGithub/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PyGithub/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PyGithub/PyGithub/teams","hooks_url":"https://api.github.com/repos/PyGithub/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/PyGithub/PyGithub/events","assignees_url":"https://api.github.com/repos/PyGithub/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/PyGithub/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/PyGithub/PyGithub/tags","blobs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PyGithub/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/PyGithub/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PyGithub/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/PyGithub/PyGithub/languages","stargazers_url":"https://api.github.com/repos/PyGithub/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/PyGithub/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/PyGithub/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/PyGithub/PyGithub/subscription","commits_url":"https://api.github.com/repos/PyGithub/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/PyGithub/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/PyGithub/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/PyGithub/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/PyGithub/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PyGithub/PyGithub/merges","archive_url":"https://api.github.com/repos/PyGithub/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PyGithub/PyGithub/downloads","issues_url":"https://api.github.com/repos/PyGithub/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/PyGithub/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/PyGithub/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/PyGithub/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PyGithub/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/PyGithub/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/PyGithub/PyGithub/deployments","created_at":"2012-02-25T12:53:47Z","updated_at":"2021-11-02T12:35:21Z","pushed_at":"2021-11-02T08:12:52Z","git_url":"git://github.com/PyGithub/PyGithub.git","ssh_url":"git@github.com:PyGithub/PyGithub.git","clone_url":"https://github.com/PyGithub/PyGithub.git","svn_url":"https://github.com/PyGithub/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":13577,"stargazers_count":4744,"watchers_count":4744,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1397,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":143,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"allow_forking":true,"is_template":false,"topics":["github","github-api","pygithub","python"],"visibility":"public","forks":1397,"open_issues":143,"watchers":4744,"default_branch":"master"},"network_count":1397,"subscribers_count":0} + +https +GET +api.github.com +None +/repos/theCapypara/PyGithub/autolinks +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 02 Nov 2021 13:15:54 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"535a973f8ad8495063caa679cdbf106f079769e4c6060713042dc3a9fc844b87"'), ('X-OAuth-Scopes', 'admin:repo_hook, repo'), ('X-Accepted-OAuth-Scopes', 'repo'), ('github-authentication-token-expiration', '2021-11-09 12:40:40 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4891'), ('X-RateLimit-Reset', '1635859633'), ('X-RateLimit-Used', '109'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'C17A:34FD:E2AD69:E8E4C0:61813A0A')] +[{"id":209614,"key_prefix":"DUMMY-","url_template":"https://github.com/PyGithub/PyGithub/issues/"}] + diff --git a/tests/ReplayData/Repository.testCreateAutolink.txt b/tests/ReplayData/Repository.testCreateAutolink.txt new file mode 100644 index 0000000000..2439bbbe07 --- /dev/null +++ b/tests/ReplayData/Repository.testCreateAutolink.txt @@ -0,0 +1,11 @@ +https +POST +api.github.com +None +/repos/jacquev6/PyGithub/autolinks +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python', 'Content-Type': 'application/json'} +{"key_prefix": "DUMMY-", "url_template": "https://github.com/PyGithub/PyGithub/issues/"} +201 +[('Server', 'GitHub.com'), ('Date', 'Tue, 02 Nov 2021 12:57:55 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Content-Length', '102'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', '"f90a1a598b996d3d1967b96c218459edde984e62d452623ff4aba2530a256b85"'), ('X-OAuth-Scopes', 'admin:repo_hook, repo'), ('X-Accepted-OAuth-Scopes', 'repo'), ('github-authentication-token-expiration', '2021-11-09 12:40:40 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4947'), ('X-RateLimit-Reset', '1635859633'), ('X-RateLimit-Used', '53'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('X-GitHub-Request-Id', 'C6E6:34FE:190079B:197523C:618135D3')] +{"id":209614,"key_prefix":"DUMMY-","url_template":"https://github.com/PyGithub/PyGithub/issues/"} + diff --git a/tests/ReplayData/Repository.testGetAutolinks.txt b/tests/ReplayData/Repository.testGetAutolinks.txt new file mode 100644 index 0000000000..92e5a8ea58 --- /dev/null +++ b/tests/ReplayData/Repository.testGetAutolinks.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/repos/jacquev6/PyGithub/autolinks +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Tue, 02 Nov 2021 13:01:39 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP, Accept-Encoding, Accept, X-Requested-With'), ('ETag', 'W/"4d453f5f31fb634e68e615083db0c61dc2d1925cd6f16586a81b24e2369872ba"'), ('X-OAuth-Scopes', 'admin:repo_hook, repo'), ('X-Accepted-OAuth-Scopes', 'repo'), ('github-authentication-token-expiration', '2021-11-09 12:40:40 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4944'), ('X-RateLimit-Reset', '1635859633'), ('X-RateLimit-Used', '56'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'C11A:B2A9:62722:A8B2E:618136B3')] +[{"id":209614,"key_prefix":"DUMMY-","url_template":"https://github.com/PyGithub/PyGithub/issues/"},{"id":209611,"key_prefix":"TEST-","url_template":"https://github.com/PyGithub/PyGithub/issues/"}] + diff --git a/tests/ReplayData/Repository.testRemoveAutolink.txt b/tests/ReplayData/Repository.testRemoveAutolink.txt new file mode 100644 index 0000000000..917da8ff6c --- /dev/null +++ b/tests/ReplayData/Repository.testRemoveAutolink.txt @@ -0,0 +1,11 @@ +https +DELETE +api.github.com +None +/repos/jacquev6/PyGithub/autolinks/209611 +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +204 +[('Server', 'GitHub.com'), ('Date', 'Tue, 02 Nov 2021 13:05:13 GMT'), ('X-OAuth-Scopes', 'admin:repo_hook, repo'), ('X-Accepted-OAuth-Scopes', 'repo'), ('github-authentication-token-expiration', '2021-11-09 12:40:40 UTC'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4941'), ('X-RateLimit-Reset', '1635859633'), ('X-RateLimit-Used', '59'), ('X-RateLimit-Resource', 'core'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '0'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Vary', 'Accept-Encoding, Accept, X-Requested-With'), ('X-GitHub-Request-Id', 'C120:10BD6:34C209:39806B:61813789')] + + diff --git a/tests/Repository.py b/tests/Repository.py index 74f1b05e38..95bf5e4fbd 100644 --- a/tests/Repository.py +++ b/tests/Repository.py @@ -258,6 +258,12 @@ def testCreateGitRef(self): "https://api.github.com/repos/jacquev6/PyGithub/git/refs/heads/BranchCreatedByPyGithub", ) + def testCreateAutolink(self): + key = self.repo.create_autolink( + "DUMMY-", "https://github.com/PyGithub/PyGithub/issues/" + ) + self.assertEqual(key.id, 209614) + def testCreateGitBlob(self): blob = self.repo.create_git_blob("Blob created by PyGithub", "latin1") self.assertEqual(blob.sha, "5dd930f591cd5188e9ea7200e308ad355182a1d8") @@ -478,6 +484,9 @@ def testGetPendingInvitations(self): def testRemoveInvitation(self): self.repo.remove_invitation(17285388) + def testRemoveAutolink(self): + self.repo.remove_autolink(209611) + def testCollaboratorPermissionNoPushAccess(self): with self.assertRaises(github.GithubException) as raisedexp: self.repo.get_collaborator_permission("lyloa") @@ -1170,6 +1179,16 @@ def testGetPullsWithArguments(self): self.repo.get_pulls("closed"), lambda p: p.id, [1448168, 1436310, 1436215] ) + def testGetAutolinks(self): + self.assertListKeyEqual( + self.repo.get_autolinks(), + lambda i: i.id, + [ + 209614, + 209611, + ], + ) + def testLegacySearchIssues(self): issues = self.repo.legacy_search_issues("open", "search") self.assertListKeyEqual(issues, lambda i: i.title, ["Support new Search API"])