diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5a471c08..caa0bb2d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,6 +15,7 @@ jobs: python-version: "3.x" - run: | python -m pip install --upgrade pip + pip install -r requirements.txt pip install -r requirements-types.txt - uses: liskin/gh-problem-matcher-wrap@v2 with: diff --git a/.isort.cfg b/.isort.cfg index aa9496b0..58fc9801 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -4,5 +4,5 @@ include_trailing_comma=True force_grid_wrap=0 use_parentheses=True line_length=88 -known_third_party=dateutil,deprecated,httpretty,jwt,nacl,pytest,requests,setuptools,urllib3 +known_third_party=dateutil,deprecated,httpretty,jwt,nacl,pytest,requests,setuptools,typing_extensions,urllib3 known_first_party=github diff --git a/github/Branch.py b/github/Branch.py index bfba5b7f..a3836199 100644 --- a/github/Branch.py +++ b/github/Branch.py @@ -30,17 +30,37 @@ # along with PyGithub. If not, see . # # # ################################################################################ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any import github.BranchProtection import github.Commit -import github.GithubObject import github.RequiredPullRequestReviews import github.RequiredStatusChecks +from github import Consts +from github.GithubObject import ( + Attribute, + NonCompletableGithubObject, + NotSet, + Opt, + is_defined, + is_optional, + is_optional_list, + is_undefined, +) -from . import Consts +if TYPE_CHECKING: + from github.BranchProtection import BranchProtection + from github.Commit import Commit + from github.NamedUser import NamedUser + from github.PaginatedList import PaginatedList + from github.RequiredPullRequestReviews import RequiredPullRequestReviews + from github.RequiredStatusChecks import RequiredStatusChecks + from github.Team import Team -class Branch(github.GithubObject.NonCompletableGithubObject): +class Branch(NonCompletableGithubObject): """ This class represents Branches. The reference can be found here https://docs.github.com/en/rest/reference/repos#branches """ @@ -49,40 +69,28 @@ class Branch(github.GithubObject.NonCompletableGithubObject): return self.get__repr__({"name": self._name.value}) @property - def commit(self): - """ - :type: :class:`github.Commit.Commit` - """ + def commit(self) -> Commit: return self._commit.value @property - def name(self): - """ - :type: string - """ + def name(self) -> str: return self._name.value @property - def protected(self): - """ - :type: bool - """ + def protected(self) -> bool: return self._protected.value @property - def protection_url(self): - """ - :type: string - """ + def protection_url(self) -> str: return self._protection_url.value - def _initAttributes(self): - self._commit = github.GithubObject.NotSet - self._name = github.GithubObject.NotSet - self._protection_url = github.GithubObject.NotSet - self._protected = github.GithubObject.NotSet + def _initAttributes(self) -> None: + self._commit: Attribute[Commit] = github.GithubObject.NotSet + self._name: Attribute[str] = github.GithubObject.NotSet + self._protection_url: Attribute[str] = github.GithubObject.NotSet + self._protected: Attribute[bool] = github.GithubObject.NotSet - def _useAttributes(self, attributes): + def _useAttributes(self, attributes) -> None: if "commit" in attributes: # pragma no branch self._commit = self._makeClassAttribute( github.Commit.Commit, attributes["commit"] @@ -96,7 +104,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): if "protected" in attributes: # pragma no branch self._protected = self._makeBoolAttribute(attributes["protected"]) - def get_protection(self): + def get_protection(self) -> BranchProtection: """ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection `_ """ @@ -111,124 +119,68 @@ class Branch(github.GithubObject.NonCompletableGithubObject): def edit_protection( self, - strict=github.GithubObject.NotSet, - contexts=github.GithubObject.NotSet, - enforce_admins=github.GithubObject.NotSet, - dismissal_users=github.GithubObject.NotSet, - dismissal_teams=github.GithubObject.NotSet, - dismissal_apps=github.GithubObject.NotSet, - dismiss_stale_reviews=github.GithubObject.NotSet, - require_code_owner_reviews=github.GithubObject.NotSet, - required_approving_review_count=github.GithubObject.NotSet, - user_push_restrictions=github.GithubObject.NotSet, - team_push_restrictions=github.GithubObject.NotSet, - app_push_restrictions=github.GithubObject.NotSet, - required_linear_history=github.GithubObject.NotSet, - allow_force_pushes=github.GithubObject.NotSet, - required_conversation_resolution=github.GithubObject.NotSet, - lock_branch=github.GithubObject.NotSet, - allow_fork_syncing=github.GithubObject.NotSet, - users_bypass_pull_request_allowances=github.GithubObject.NotSet, - teams_bypass_pull_request_allowances=github.GithubObject.NotSet, - apps_bypass_pull_request_allowances=github.GithubObject.NotSet, - block_creations=github.GithubObject.NotSet, + strict: Opt[bool] = NotSet, + contexts: Opt[list[str]] = NotSet, + enforce_admins: Opt[bool] = NotSet, + dismissal_users: Opt[list[str]] = NotSet, + dismissal_teams: Opt[list[str]] = NotSet, + dismissal_apps: Opt[list[str]] = NotSet, + dismiss_stale_reviews: Opt[bool] = NotSet, + require_code_owner_reviews: Opt[bool] = NotSet, + required_approving_review_count: Opt[int] = NotSet, + user_push_restrictions: Opt[list[str]] = NotSet, + team_push_restrictions: Opt[list[str]] = NotSet, + app_push_restrictions: Opt[list[str]] = NotSet, + required_linear_history: Opt[bool] = NotSet, + allow_force_pushes: Opt[bool] = NotSet, + required_conversation_resolution: Opt[bool] = NotSet, + lock_branch: Opt[bool] = NotSet, + allow_fork_syncing: Opt[bool] = NotSet, + users_bypass_pull_request_allowances: Opt[list[str]] = NotSet, + teams_bypass_pull_request_allowances: Opt[list[str]] = NotSet, + apps_bypass_pull_request_allowances: Opt[list[str]] = NotSet, + block_creations: Opt[bool] = NotSet, ): """ :calls: `PUT /repos/{owner}/{repo}/branches/{branch}/protection `_ - :strict: bool - :contexts: list of strings - :enforce_admins: bool - :dismissal_users: list of strings - :dismissal_teams: list of strings - :dismissal_apps: list of strings - :dismiss_stale_reviews: bool - :require_code_owner_reviews: bool - :required_approving_review_count: int - :user_push_restrictions: list of strings - :team_push_restrictions: list of strings - :app_push_restrictions: list of strings - :required_linear_history: bool - :allow_force_pushes: bool - :required_conversation_resolution: bool - :lock_branch: bool - :allow_fork_syncing: bool - :users_bypass_pull_request_allowances: list of strings - :teams_bypass_pull_request_allowances: list of strings - :apps_bypass_pull_request_allowances: list of strings - :block_creations: bool NOTE: The GitHub API groups strict and contexts together, both must be submitted. Take care to pass both as arguments even if only one is changing. Use edit_required_status_checks() to avoid this. """ - assert strict is github.GithubObject.NotSet or isinstance(strict, bool), strict - assert contexts is github.GithubObject.NotSet or all( - isinstance(element, str) for element in contexts - ), contexts - assert enforce_admins is github.GithubObject.NotSet or isinstance( - enforce_admins, bool - ), enforce_admins - assert dismissal_users is github.GithubObject.NotSet or all( - isinstance(element, str) for element in dismissal_users - ), dismissal_users - assert dismissal_teams is github.GithubObject.NotSet or all( - isinstance(element, str) for element in dismissal_teams - ), dismissal_teams - assert dismissal_apps is github.GithubObject.NotSet or all( - isinstance(element, str) for element in dismissal_apps - ), dismissal_apps - assert dismiss_stale_reviews is github.GithubObject.NotSet or isinstance( - dismiss_stale_reviews, bool - ), dismiss_stale_reviews - assert require_code_owner_reviews is github.GithubObject.NotSet or isinstance( - require_code_owner_reviews, bool - ), require_code_owner_reviews - assert ( - required_approving_review_count is github.GithubObject.NotSet - or isinstance(required_approving_review_count, int) - ), (required_approving_review_count) - assert required_linear_history is github.GithubObject.NotSet or isinstance( + assert is_optional(strict, bool), strict + assert is_optional_list(contexts, str), contexts + assert is_optional(enforce_admins, bool), enforce_admins + assert is_optional_list(dismissal_users, str), dismissal_users + assert is_optional_list(dismissal_teams, str), dismissal_teams + assert is_optional_list(dismissal_apps, str), dismissal_apps + assert is_optional(dismiss_stale_reviews, bool), dismiss_stale_reviews + assert is_optional(require_code_owner_reviews, bool), require_code_owner_reviews + assert is_optional( + required_approving_review_count, int + ), required_approving_review_count + assert is_optional(required_linear_history, bool), required_linear_history + assert is_optional(allow_force_pushes, bool), allow_force_pushes + assert is_optional( required_linear_history, bool - ), required_linear_history - assert allow_force_pushes is github.GithubObject.NotSet or isinstance( - allow_force_pushes, bool - ), allow_force_pushes - assert ( - required_conversation_resolution is github.GithubObject.NotSet - or isinstance(required_linear_history, bool) ), required_conversation_resolution - assert lock_branch is github.GithubObject.NotSet or isinstance( - lock_branch, bool - ), lock_branch - assert allow_fork_syncing is github.GithubObject.NotSet or isinstance( - allow_fork_syncing, bool - ), allow_fork_syncing - assert ( - users_bypass_pull_request_allowances is github.GithubObject.NotSet - or all( - isinstance(element, str) - for element in users_bypass_pull_request_allowances - ) - ), (users_bypass_pull_request_allowances) - assert ( - teams_bypass_pull_request_allowances is github.GithubObject.NotSet - or all( - isinstance(element, str) - for element in teams_bypass_pull_request_allowances - ) - ), (teams_bypass_pull_request_allowances) - assert apps_bypass_pull_request_allowances is github.GithubObject.NotSet or all( - isinstance(element, str) for element in apps_bypass_pull_request_allowances + assert is_optional(lock_branch, bool), lock_branch + assert is_optional(allow_fork_syncing, bool), allow_fork_syncing + assert is_optional_list( + users_bypass_pull_request_allowances, str + ), users_bypass_pull_request_allowances + assert is_optional_list( + teams_bypass_pull_request_allowances, str + ), teams_bypass_pull_request_allowances + assert is_optional_list( + apps_bypass_pull_request_allowances, str ), apps_bypass_pull_request_allowances - post_parameters = {} - if ( - strict is not github.GithubObject.NotSet - or contexts is not github.GithubObject.NotSet - ): - if strict is github.GithubObject.NotSet: + post_parameters: dict[str, Any] = {} + if is_defined(strict) or is_defined(contexts): + if is_undefined(strict): strict = False - if contexts is github.GithubObject.NotSet: + if is_undefined(contexts): contexts = [] post_parameters["required_status_checks"] = { "strict": strict, @@ -237,42 +189,42 @@ class Branch(github.GithubObject.NonCompletableGithubObject): else: post_parameters["required_status_checks"] = None - if enforce_admins is not github.GithubObject.NotSet: + if is_defined(enforce_admins): post_parameters["enforce_admins"] = enforce_admins else: post_parameters["enforce_admins"] = None if ( - dismissal_users is not github.GithubObject.NotSet - or dismissal_teams is not github.GithubObject.NotSet - or dismissal_apps is not github.GithubObject.NotSet - or dismiss_stale_reviews is not github.GithubObject.NotSet - or require_code_owner_reviews is not github.GithubObject.NotSet - or required_approving_review_count is not github.GithubObject.NotSet - or users_bypass_pull_request_allowances is not github.GithubObject.NotSet - or teams_bypass_pull_request_allowances is not github.GithubObject.NotSet - or apps_bypass_pull_request_allowances is not github.GithubObject.NotSet + is_defined(dismissal_users) + or is_defined(dismissal_teams) + or is_defined(dismissal_apps) + or is_defined(dismiss_stale_reviews) + or is_defined(require_code_owner_reviews) + or is_defined(required_approving_review_count) + or is_defined(users_bypass_pull_request_allowances) + or is_defined(teams_bypass_pull_request_allowances) + or is_defined(apps_bypass_pull_request_allowances) ): post_parameters["required_pull_request_reviews"] = {} - if dismiss_stale_reviews is not github.GithubObject.NotSet: + if is_defined(dismiss_stale_reviews): post_parameters["required_pull_request_reviews"][ "dismiss_stale_reviews" ] = dismiss_stale_reviews - if require_code_owner_reviews is not github.GithubObject.NotSet: + if is_defined(require_code_owner_reviews): post_parameters["required_pull_request_reviews"][ "require_code_owner_reviews" ] = require_code_owner_reviews - if required_approving_review_count is not github.GithubObject.NotSet: + if is_defined(required_approving_review_count): post_parameters["required_pull_request_reviews"][ "required_approving_review_count" ] = required_approving_review_count dismissal_restrictions = {} - if dismissal_users is not github.GithubObject.NotSet: + if is_defined(dismissal_users): dismissal_restrictions["users"] = dismissal_users - if dismissal_teams is not github.GithubObject.NotSet: + if is_defined(dismissal_teams): dismissal_restrictions["teams"] = dismissal_teams - if dismissal_apps is not github.GithubObject.NotSet: + if is_defined(dismissal_apps): dismissal_restrictions["apps"] = dismissal_apps if dismissal_restrictions: @@ -281,15 +233,15 @@ class Branch(github.GithubObject.NonCompletableGithubObject): ] = dismissal_restrictions bypass_pull_request_allowances = {} - if users_bypass_pull_request_allowances is not github.GithubObject.NotSet: + if is_defined(users_bypass_pull_request_allowances): bypass_pull_request_allowances[ "users" ] = users_bypass_pull_request_allowances - if teams_bypass_pull_request_allowances is not github.GithubObject.NotSet: + if is_defined(teams_bypass_pull_request_allowances): bypass_pull_request_allowances[ "teams" ] = teams_bypass_pull_request_allowances - if apps_bypass_pull_request_allowances is not github.GithubObject.NotSet: + if is_defined(apps_bypass_pull_request_allowances): bypass_pull_request_allowances[ "apps" ] = apps_bypass_pull_request_allowances @@ -301,15 +253,15 @@ class Branch(github.GithubObject.NonCompletableGithubObject): else: post_parameters["required_pull_request_reviews"] = None if ( - user_push_restrictions is not github.GithubObject.NotSet - or team_push_restrictions is not github.GithubObject.NotSet - or app_push_restrictions is not github.GithubObject.NotSet + is_defined(user_push_restrictions) + or is_defined(team_push_restrictions) + or is_defined(app_push_restrictions) ): - if user_push_restrictions is github.GithubObject.NotSet: + if is_undefined(user_push_restrictions): user_push_restrictions = [] - if team_push_restrictions is github.GithubObject.NotSet: + if is_undefined(team_push_restrictions): team_push_restrictions = [] - if app_push_restrictions is github.GithubObject.NotSet: + if is_undefined(app_push_restrictions): app_push_restrictions = [] post_parameters["restrictions"] = { "users": user_push_restrictions, @@ -318,29 +270,29 @@ class Branch(github.GithubObject.NonCompletableGithubObject): } else: post_parameters["restrictions"] = None - if required_linear_history is not github.GithubObject.NotSet: + if is_defined(required_linear_history): post_parameters["required_linear_history"] = required_linear_history else: post_parameters["required_linear_history"] = None - if allow_force_pushes is not github.GithubObject.NotSet: + if is_defined(allow_force_pushes): post_parameters["allow_force_pushes"] = allow_force_pushes else: post_parameters["allow_force_pushes"] = None - if required_conversation_resolution is not github.GithubObject.NotSet: + if is_defined(required_conversation_resolution): post_parameters[ "required_conversation_resolution" ] = required_conversation_resolution else: post_parameters["required_conversation_resolution"] = None - if lock_branch is not github.GithubObject.NotSet: + if is_defined(lock_branch): post_parameters["lock_branch"] = lock_branch else: post_parameters["lock_branch"] = None - if allow_fork_syncing is not github.GithubObject.NotSet: + if is_defined(allow_fork_syncing): post_parameters["allow_fork_syncing"] = allow_fork_syncing else: post_parameters["allow_fork_syncing"] = None - if block_creations is not github.GithubObject.NotSet: + if is_defined(block_creations): post_parameters["block_creations"] = block_creations else: post_parameters["block_creations"] = None @@ -352,7 +304,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): input=post_parameters, ) - def remove_protection(self): + def remove_protection(self) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection `_ """ @@ -361,7 +313,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): self.protection_url, ) - def get_required_status_checks(self): + def get_required_status_checks(self) -> RequiredStatusChecks: """ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks `_ :rtype: :class:`github.RequiredStatusChecks.RequiredStatusChecks` @@ -374,23 +326,19 @@ class Branch(github.GithubObject.NonCompletableGithubObject): ) def edit_required_status_checks( - self, strict=github.GithubObject.NotSet, contexts=github.GithubObject.NotSet + self, + strict: Opt[bool] = NotSet, + contexts: Opt[list[str]] = NotSet, ): """ :calls: `PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks `_ - :strict: bool - :contexts: list of strings """ - assert strict is github.GithubObject.NotSet or isinstance(strict, bool), strict - assert contexts is github.GithubObject.NotSet or all( - isinstance(element, str) for element in contexts - ), contexts + assert is_optional(strict, bool), strict + assert is_optional_list(contexts, str), contexts - post_parameters = {} - if strict is not github.GithubObject.NotSet: - post_parameters["strict"] = strict - if contexts is not github.GithubObject.NotSet: - post_parameters["contexts"] = contexts + post_parameters: dict[str, Any] = NotSet.remove_unset_items( + {"strict": strict, "contexts": contexts} + ) headers, data = self._requester.requestJsonAndCheck( "PATCH", f"{self.protection_url}/required_status_checks", @@ -406,10 +354,9 @@ class Branch(github.GithubObject.NonCompletableGithubObject): f"{self.protection_url}/required_status_checks", ) - def get_required_pull_request_reviews(self): + def get_required_pull_request_reviews(self) -> RequiredPullRequestReviews: """ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews `_ - :rtype: :class:`github.RequiredPullRequestReviews.RequiredPullRequestReviews` """ headers, data = self._requester.requestJsonAndCheck( "GET", @@ -422,62 +369,39 @@ class Branch(github.GithubObject.NonCompletableGithubObject): def edit_required_pull_request_reviews( self, - dismissal_users=github.GithubObject.NotSet, - dismissal_teams=github.GithubObject.NotSet, - dismissal_apps=github.GithubObject.NotSet, - dismiss_stale_reviews=github.GithubObject.NotSet, - require_code_owner_reviews=github.GithubObject.NotSet, - required_approving_review_count=github.GithubObject.NotSet, + dismissal_users: Opt[list[str]] = NotSet, + dismissal_teams: Opt[list[str]] = NotSet, + dismissal_apps: Opt[list[str]] = NotSet, + dismiss_stale_reviews: Opt[bool] = NotSet, + require_code_owner_reviews: Opt[bool] = NotSet, + required_approving_review_count: Opt[int] = NotSet, ): """ :calls: `PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews `_ - :dismissal_users: list of strings - :dismissal_teams: list of strings - :dismissal_apps: list of strings - :dismiss_stale_reviews: bool - :require_code_owner_reviews: bool - :required_approving_review_count: int """ - assert dismissal_users is github.GithubObject.NotSet or all( - isinstance(element, str) for element in dismissal_users - ), dismissal_users - assert dismissal_teams is github.GithubObject.NotSet or all( - isinstance(element, str) for element in dismissal_teams - ), dismissal_teams - assert dismiss_stale_reviews is github.GithubObject.NotSet or isinstance( - dismiss_stale_reviews, bool - ), dismiss_stale_reviews - assert require_code_owner_reviews is github.GithubObject.NotSet or isinstance( - require_code_owner_reviews, bool - ), require_code_owner_reviews - assert ( - required_approving_review_count is github.GithubObject.NotSet - or isinstance(required_approving_review_count, int) - ), (required_approving_review_count) + assert is_optional_list(dismissal_users, str), dismissal_users + assert is_optional_list(dismissal_teams, str), dismissal_teams + assert is_optional(dismiss_stale_reviews, bool), dismiss_stale_reviews + assert is_optional(require_code_owner_reviews, bool), require_code_owner_reviews + assert is_optional( + required_approving_review_count, int + ), required_approving_review_count - post_parameters = {} - if ( - dismissal_users is not github.GithubObject.NotSet - or dismissal_teams is not github.GithubObject.NotSet - or dismissal_apps is not github.GithubObject.NotSet - ): - post_parameters["dismissal_restrictions"] = {} + post_parameters: dict[str, Any] = NotSet.remove_unset_items( + { + "dismiss_stale_reviews": dismiss_stale_reviews, + "require_code_owner_reviews": require_code_owner_reviews, + "required_approving_review_count": required_approving_review_count, + } + ) - if dismissal_users is not github.GithubObject.NotSet: - post_parameters["dismissal_restrictions"]["users"] = dismissal_users - if dismissal_teams is not github.GithubObject.NotSet: - post_parameters["dismissal_restrictions"]["teams"] = dismissal_teams - if dismissal_apps is not github.GithubObject.NotSet: - post_parameters["dismissal_restrictions"]["apps"] = dismissal_apps + dismissal_restrictions: dict[str, Any] = NotSet.remove_unset_items( + {"users": dismissal_users, "teams": dismissal_teams, "apps": dismissal_apps} + ) + + if dismissal_restrictions: + post_parameters["dismissal_restrictions"] = dismissal_restrictions - if dismiss_stale_reviews is not github.GithubObject.NotSet: - post_parameters["dismiss_stale_reviews"] = dismiss_stale_reviews - if require_code_owner_reviews is not github.GithubObject.NotSet: - post_parameters["require_code_owner_reviews"] = require_code_owner_reviews - if required_approving_review_count is not github.GithubObject.NotSet: - post_parameters[ - "required_approving_review_count" - ] = required_approving_review_count headers, data = self._requester.requestJsonAndCheck( "PATCH", f"{self.protection_url}/required_pull_request_reviews", @@ -494,17 +418,16 @@ class Branch(github.GithubObject.NonCompletableGithubObject): f"{self.protection_url}/required_pull_request_reviews", ) - def get_admin_enforcement(self): + def get_admin_enforcement(self) -> bool: """ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins `_ - :rtype: bool """ headers, data = self._requester.requestJsonAndCheck( "GET", f"{self.protection_url}/enforce_admins" ) return data["enabled"] - def set_admin_enforcement(self): + def set_admin_enforcement(self) -> None: """ :calls: `POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins `_ """ @@ -512,7 +435,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): "POST", f"{self.protection_url}/enforce_admins" ) - def remove_admin_enforcement(self): + def remove_admin_enforcement(self) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins `_ """ @@ -520,10 +443,9 @@ class Branch(github.GithubObject.NonCompletableGithubObject): "DELETE", f"{self.protection_url}/enforce_admins" ) - def get_user_push_restrictions(self): + def get_user_push_restrictions(self) -> PaginatedList[NamedUser]: """ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users `_ - :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.NamedUser.NamedUser` """ return github.PaginatedList.PaginatedList( github.NamedUser.NamedUser, @@ -532,10 +454,9 @@ class Branch(github.GithubObject.NonCompletableGithubObject): None, ) - def get_team_push_restrictions(self): + def get_team_push_restrictions(self) -> PaginatedList[Team]: """ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams `_ - :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.Team.Team` """ return github.PaginatedList.PaginatedList( github.Team.Team, @@ -544,7 +465,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): None, ) - def add_user_push_restrictions(self, *users): + def add_user_push_restrictions(self, *users: str) -> None: """ :calls: `POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users `_ :users: list of strings (user names) @@ -555,7 +476,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): "POST", f"{self.protection_url}/restrictions/users", input=users ) - def replace_user_push_restrictions(self, *users): + def replace_user_push_restrictions(self, *users: str) -> None: """ :calls: `PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users `_ :users: list of strings (user names) @@ -566,7 +487,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): "PUT", f"{self.protection_url}/restrictions/users", input=users ) - def remove_user_push_restrictions(self, *users): + def remove_user_push_restrictions(self, *users: str) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users `_ :users: list of strings (user names) @@ -577,7 +498,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): "DELETE", f"{self.protection_url}/restrictions/users", input=users ) - def add_team_push_restrictions(self, *teams): + def add_team_push_restrictions(self, *teams: str) -> None: """ :calls: `POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams `_ :teams: list of strings (team slugs) @@ -588,7 +509,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): "POST", f"{self.protection_url}/restrictions/teams", input=teams ) - def replace_team_push_restrictions(self, *teams): + def replace_team_push_restrictions(self, *teams: str) -> None: """ :calls: `PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams `_ :teams: list of strings (team slugs) @@ -599,7 +520,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): "PUT", f"{self.protection_url}/restrictions/teams", input=teams ) - def remove_team_push_restrictions(self, *teams): + def remove_team_push_restrictions(self, *teams: str) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams `_ :teams: list of strings (team slugs) @@ -610,7 +531,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): "DELETE", f"{self.protection_url}/restrictions/teams", input=teams ) - def remove_push_restrictions(self): + def remove_push_restrictions(self) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions `_ """ @@ -618,7 +539,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): "DELETE", f"{self.protection_url}/restrictions" ) - def get_required_signatures(self): + def get_required_signatures(self) -> bool: """ :calls: `GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures `_ """ @@ -629,7 +550,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): ) return data["enabled"] - def add_required_signatures(self): + def add_required_signatures(self) -> None: """ :calls: `POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures `_ """ @@ -639,7 +560,7 @@ class Branch(github.GithubObject.NonCompletableGithubObject): headers={"Accept": Consts.signaturesProtectedBranchesPreview}, ) - def remove_required_signatures(self): + def remove_required_signatures(self) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures `_ """ diff --git a/github/Branch.pyi b/github/Branch.pyi deleted file mode 100644 index 2c086776..00000000 --- a/github/Branch.pyi +++ /dev/null @@ -1,77 +0,0 @@ -from typing import Any, Dict, List, Union - -from github.BranchProtection import BranchProtection -from github.Commit import Commit -from github.GithubObject import NonCompletableGithubObject, _NotSetType -from github.NamedUser import NamedUser -from github.PaginatedList import PaginatedList -from github.RequiredPullRequestReviews import RequiredPullRequestReviews -from github.RequiredStatusChecks import RequiredStatusChecks -from github.Team import Team - -class Branch(NonCompletableGithubObject): - def __repr__(self) -> str: ... - def _initAttributes(self) -> None: ... - def _useAttributes(self, attributes: Dict[str, Any]) -> None: ... - def add_required_signatures(self) -> None: ... - @property - def commit(self) -> Commit: ... - def edit_protection( - self, - strict: Union[bool, _NotSetType] = ..., - contexts: Union[List[str], _NotSetType] = ..., - enforce_admins: Union[bool, _NotSetType] = ..., - dismissal_users: Union[_NotSetType, List[str]] = ..., - dismissal_teams: Union[_NotSetType, List[str]] = ..., - dismissal_apps: Union[_NotSetType, List[str]] = ..., - dismiss_stale_reviews: Union[bool, _NotSetType] = ..., - require_code_owner_reviews: Union[bool, _NotSetType] = ..., - required_approving_review_count: Union[int, _NotSetType] = ..., - user_push_restrictions: Union[_NotSetType, List[str]] = ..., - team_push_restrictions: Union[_NotSetType, List[str]] = ..., - app_push_restrictions: Union[_NotSetType, List[str]] = ..., - required_linear_history: Union[bool, _NotSetType] = ..., - allow_force_pushes: Union[bool, _NotSetType] = ..., - required_conversation_resolution: Union[bool, _NotSetType] = ..., - lock_branch: Union[bool, _NotSetType] = ..., - allow_fork_syncing: Union[bool, _NotSetType] = ..., - users_bypass_pull_request_allowances: Union[_NotSetType, List[str]] = ..., - teams_bypass_pull_request_allowances: Union[_NotSetType, List[str]] = ..., - apps_bypass_pull_request_allowances: Union[_NotSetType, List[str]] = ..., - ) -> None: ... - def edit_required_pull_request_reviews( - self, - dismissal_users: Union[_NotSetType, List[str]] = ..., - dismissal_teams: Union[_NotSetType, List[str]] = ..., - dismissal_apps: Union[_NotSetType, List[str]] = ..., - dismiss_stale_reviews: Union[bool, _NotSetType] = ..., - require_code_owner_reviews: Union[_NotSetType, bool] = ..., - required_approving_review_count: Union[int, _NotSetType] = ..., - ) -> None: ... - def edit_required_status_checks( - self, - strict: Union[_NotSetType, bool] = ..., - contexts: Union[List[str], _NotSetType] = ..., - ) -> None: ... - def edit_team_push_restrictions(self, *teams: str) -> None: ... - def edit_user_push_restrictions(self, *users: str) -> None: ... - def get_admin_enforcement(self) -> bool: ... - def get_protection(self) -> BranchProtection: ... - def get_required_pull_request_reviews(self) -> RequiredPullRequestReviews: ... - def get_required_signatures(self) -> bool: ... - def get_required_status_checks(self) -> RequiredStatusChecks: ... - def get_team_push_restrictions(self) -> PaginatedList[Team]: ... - def get_user_push_restrictions(self) -> PaginatedList[NamedUser]: ... - @property - def name(self) -> str: ... - @property - def protected(self) -> bool: ... - @property - def protection_url(self) -> str: ... - def remove_admin_enforcement(self) -> None: ... - def remove_protection(self) -> None: ... - def remove_push_restrictions(self) -> None: ... - def remove_required_pull_request_reviews(self) -> None: ... - def remove_required_signatures(self) -> None: ... - def remove_required_status_checks(self) -> None: ... - def set_admin_enforcement(self) -> None: ... diff --git a/github/GithubObject.py b/github/GithubObject.py index dadad2f9..6e59d48f 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -54,6 +54,7 @@ from typing import ( ) from dateutil import parser +from typing_extensions import TypeGuard from . import Consts from .GithubException import BadAttributeException, IncompletableObject @@ -92,6 +93,26 @@ NotSet = _NotSetType() Opt = Union[T, _NotSetType] +def is_defined(v: Union[T, _NotSetType]) -> TypeGuard[T]: + return not isinstance(v, _NotSetType) + + +def is_undefined(v: Any) -> TypeGuard[_NotSetType]: + return isinstance(v, _NotSetType) + + +def is_optional(v, type: Type[T]) -> TypeGuard[Opt[T]]: + return isinstance(v, _NotSetType) or isinstance(v, type) + + +def is_optional_list(v, type: Type[T]) -> TypeGuard[Opt[List[T]]]: + return ( + isinstance(v, _NotSetType) + or isinstance(v, list) + and all(isinstance(element, type) for element in v) + ) + + class _ValuedAttribute(Attribute, Generic[T]): def __init__(self, value: T): self._value = value diff --git a/setup.py b/setup.py index 137401f6..e6c4b75c 100755 --- a/setup.py +++ b/setup.py @@ -116,6 +116,7 @@ if __name__ == "__main__": "pynacl>=1.4.0", "requests>=2.14.0", "python-dateutil", + "typing-extensions>=4.0.0", ], # can be removed, still here to avoid breaking user code extras_require={"integrations": []},