Sync GithubIntegration __init__ arguments with github.Github (#2556)

Github and GithubIntegration now both support the same (full) set of Requester arguments.
Creating a Github instance for a Github App Installation coming from GithubIntegration uses the same
Requester arguments (except for auth).
This commit is contained in:
Enrico Minack
2023-06-21 09:04:19 +02:00
committed by GitHub
parent f4e9dcb341
commit ea45237d3b
16 changed files with 333 additions and 27 deletions
+1
View File
@@ -134,6 +134,7 @@ repoVisibilityPreview = "application/vnd.github.nebula-preview+json"
DEFAULT_BASE_URL = "https://api.github.com"
DEFAULT_STATUS_URL = "https://status.github.com"
DEFAULT_USER_AGENT = "PyGithub/Python"
# As of 2018-05-17, Github imposes a 10s limit for completion of API requests.
# Thus, the timeout should be slightly > 10s to account for network/front-end
# latency.
+39 -6
View File
@@ -1,7 +1,9 @@
import warnings
import deprecated
import urllib3
import github
from github import Consts
from github.Auth import AppAuth
from github.GithubApp import GithubApp
@@ -17,6 +19,7 @@ class GithubIntegration:
Main class to obtain tokens for a GitHub integration.
"""
# keep non-deprecated arguments in-sync with Requester
# v2: remove integration_id, private_key, jwt_expiry, jwt_issued_at and jwt_algorithm
# v2: move auth to the front of arguments
# v2: add * before first argument so all arguments must be named,
@@ -26,6 +29,12 @@ class GithubIntegration:
integration_id=None,
private_key=None,
base_url=Consts.DEFAULT_BASE_URL,
timeout=Consts.DEFAULT_TIMEOUT,
user_agent=Consts.DEFAULT_USER_AGENT,
per_page=Consts.DEFAULT_PER_PAGE,
verify=True,
retry=None,
pool_size=None,
jwt_expiry=Consts.DEFAULT_JWT_EXPIRY,
jwt_issued_at=Consts.DEFAULT_JWT_ISSUED_AT,
jwt_algorithm=Consts.DEFAULT_JWT_ALGORITHM,
@@ -35,8 +44,15 @@ class GithubIntegration:
:param integration_id: int deprecated, use auth=github.Auth.AppAuth(...) instead
:param private_key: string deprecated, use auth=github.Auth.AppAuth(...) instead
:param base_url: string
:param timeout: integer
:param user_agent: string
:param per_page: int
:param verify: boolean or string
:param retry: int or urllib3.util.retry.Retry object
:param pool_size: int
:param jwt_expiry: int deprecated, use auth=github.Auth.AppAuth(...) instead
:param jwt_issued_at: int deprecated, use auth=github.Auth.AppAuth(...) instead
:param jwt_algorithm: string deprecated, use auth=github.Auth.AppAuth(...) instead
:param auth: authentication method
"""
if integration_id is not None:
@@ -46,6 +62,16 @@ class GithubIntegration:
private_key, str
), "supplied private key should be a string"
assert isinstance(base_url, str), base_url
assert isinstance(timeout, int), timeout
assert user_agent is None or isinstance(user_agent, str), user_agent
assert isinstance(per_page, int), per_page
assert isinstance(verify, (bool, str)), verify
assert (
retry is None
or isinstance(retry, int)
or isinstance(retry, urllib3.util.Retry)
), retry
assert pool_size is None or isinstance(pool_size, int), pool_size
assert isinstance(jwt_expiry, int), jwt_expiry
assert Consts.MIN_JWT_EXPIRY <= jwt_expiry <= Consts.MAX_JWT_EXPIRY, jwt_expiry
assert isinstance(jwt_issued_at, int)
@@ -81,14 +107,21 @@ class GithubIntegration:
self.__requester = Requester(
auth=auth,
base_url=self.base_url,
timeout=Consts.DEFAULT_TIMEOUT,
user_agent="PyGithub/Python",
per_page=Consts.DEFAULT_PER_PAGE,
verify=True,
retry=None,
pool_size=None,
timeout=timeout,
user_agent=user_agent,
per_page=per_page,
verify=verify,
retry=retry,
pool_size=pool_size,
)
def get_github_for_installation(self, installation_id):
# The installation has to authenticate as an installation, not an app
auth = self.auth.get_installation_auth(
installation_id, requester=self.__requester
)
return github.Github(**self.__requester.withAuth(auth).kwargs)
def _get_headers(self):
"""
Get headers for the requests.
+10
View File
@@ -1,5 +1,8 @@
from typing import Union, Optional, Dict
from urllib3 import Retry
import github
from github.Auth import AppAuth
from github.Installation import Installation
from github.InstallationAuthorization import InstallationAuthorization
@@ -15,11 +18,18 @@ class GithubIntegration:
integration_id: Optional[Union[int, str]] = ...,
private_key: Optional[str] = ...,
base_url: str = ...,
timeout: int = ...,
user_agent: str = ...,
per_page: int = ...,
verify: Union[bool, str] = ...,
retry: Optional[Union[int, Retry]] = ...,
pool_size: Optional[int] = ...,
jwt_expiry: int = ...,
jwt_issued_at: int = ...,
jwt_algorithm: str = ...,
auth: Optional[AppAuth] = ...,
) -> None: ...
def get_github_for_installation(self, installation_id: int) -> github.Github: ...
def _get_installed_app(self, url: str) -> Installation: ...
def _get_headers(self) -> Dict[str, str]: ...
def create_jwt(self, expiration: Optional[int] = ...) -> str: ...
+3
View File
@@ -60,6 +60,9 @@ class Installation(github.GithubObject.NonCompletableGithubObject):
def __repr__(self):
return self.get__repr__({"id": self._id.value})
def get_github_for_installation(self):
return github.Github(**self._requester.kwargs)
@property
def id(self):
"""
+2
View File
@@ -1,5 +1,6 @@
from typing import Any, Dict
import github
from github.GithubObject import NonCompletableGithubObject
from github.PaginatedList import PaginatedList
from github.Repository import Repository
@@ -7,6 +8,7 @@ from github.Repository import Repository
class Installation(NonCompletableGithubObject):
def _initAttributes(self) -> None: ...
def _useAttributes(self, attributes: Dict[str, Any]) -> None: ...
def get_github_for_installation(self) -> github.Github: ...
@property
def id(self) -> int: ...
def get_repos(self) -> PaginatedList[Repository]: ...
+4 -1
View File
@@ -83,6 +83,7 @@ class Github:
This is the main class you instantiate to access the Github API v3. Optional parameters allow different authentication methods.
"""
# keep non-deprecated arguments in-sync with Requester
# v2: remove login_or_token, password, jwt and app_auth
# v2: move auth to the front of arguments
# v2: add * before first argument so all arguments must be named,
@@ -95,7 +96,7 @@ class Github:
app_auth=None,
base_url=Consts.DEFAULT_BASE_URL,
timeout=Consts.DEFAULT_TIMEOUT,
user_agent="PyGithub/Python",
user_agent=Consts.DEFAULT_USER_AGENT,
per_page=Consts.DEFAULT_PER_PAGE,
verify=True,
retry=None,
@@ -123,6 +124,8 @@ class Github:
assert isinstance(base_url, str), base_url
assert isinstance(timeout, int), timeout
assert user_agent is None or isinstance(user_agent, str), user_agent
assert isinstance(per_page, int), per_page
assert isinstance(verify, (bool, str)), verify
assert (
retry is None
or isinstance(retry, int)
+3 -1
View File
@@ -38,7 +38,7 @@ class Github:
timeout: int = ...,
user_agent: str = ...,
per_page: int = ...,
verify: bool = ...,
verify: Union[bool, str] = ...,
retry: Optional[Union[int, Retry]] = ...,
pool_size: Optional[int] = ...,
auth: Optional[Auth] = ...,
@@ -95,6 +95,8 @@ class Github:
self, since: Union[int, _NotSetType] = ...
) -> PaginatedList[NamedUser]: ...
def load(self, f: BytesIO) -> Repository: ...
# argument slug is deprecated, not included here
def get_app(self): ...
def get_oauth_application(
self, client_id: str, client_secret: str
) -> ApplicationOAuth: ...
+24 -12
View File
@@ -344,6 +344,7 @@ class Requester:
__hostname: str
__authorizationHeader: Optional[str]
# keep arguments in-sync with github.MainClass and GithubIntegration
def __init__(
self,
auth: Optional["Auth"],
@@ -351,7 +352,7 @@ class Requester:
timeout: int,
user_agent: str,
per_page: int,
verify: bool,
verify: Union[bool, str],
retry: Optional[Union[int, Retry]],
pool_size: Optional[int],
):
@@ -394,6 +395,24 @@ class Requester:
if isinstance(self.__auth, WithRequester):
self.__auth.withRequester(self)
@property
def kwargs(self):
"""
Returns arguments required to recreate this Requester with Requester.__init__, as well as
with MainClass.__init__ and GithubIntegration.__init__.
:return:
"""
return dict(
auth=self.__auth,
base_url=self.__base_url,
timeout=self.__timeout,
user_agent=self.__userAgent,
per_page=self.per_page,
verify=self.__verify,
retry=self.__retry,
pool_size=self.__pool_size,
)
@property
def base_url(self) -> str:
return self.__base_url
@@ -406,18 +425,11 @@ class Requester:
"""
Create a new requester instance with identical configuration but the given authentication method.
:param auth: authentication method
:return: new Reqester implementation
:return: new Requester implementation
"""
return Requester(
auth=auth,
base_url=self.__base_url,
timeout=self.__timeout,
user_agent=self.__userAgent,
per_page=self.per_page,
verify=self.__verify,
retry=self.__retry,
pool_size=self.__pool_size,
)
kwargs = self.kwargs
kwargs.update(auth=auth)
return Requester(**kwargs)
def requestJsonAndCheck(
self,