From 7828ba2fd13c833c118a673bac09b215587ba33b Mon Sep 17 00:00:00 2001 From: "John L. Villalovos" Date: Sat, 6 Nov 2021 21:33:07 -0700 Subject: [PATCH] chore: enforce type-hints on most files in gitlab/v4/objects/ * Add type-hints to some of the files in gitlab/v4/objects/ * Fix issues detected when adding type-hints * Changed mypy exclusion to explicitly list the 13 files that have not yet had type-hints added. --- gitlab/client.py | 14 ++++++---- gitlab/v4/cli.py | 2 ++ gitlab/v4/objects/appearance.py | 16 +++++++++-- gitlab/v4/objects/badges.py | 7 +++++ gitlab/v4/objects/boards.py | 20 +++++++++++++ gitlab/v4/objects/clusters.py | 14 +++++++--- gitlab/v4/objects/container_registry.py | 6 +++- gitlab/v4/objects/deploy_keys.py | 16 +++++++++-- gitlab/v4/objects/environments.py | 11 ++++++-- gitlab/v4/objects/export_import.py | 22 +++++++++++++++ gitlab/v4/objects/features.py | 24 ++++++++++------ gitlab/v4/objects/ldap.py | 4 ++- gitlab/v4/objects/milestones.py | 4 ++- gitlab/v4/objects/packages.py | 12 +++++++- gitlab/v4/objects/push_rules.py | 7 +++++ gitlab/v4/objects/releases.py | 12 ++++++++ gitlab/v4/objects/runners.py | 9 ++++-- gitlab/v4/objects/settings.py | 16 +++++++++-- gitlab/v4/objects/todos.py | 12 ++++++-- gitlab/v4/objects/variables.py | 15 ++++++++++ gitlab/v4/objects/wikis.py | 10 +++++++ pyproject.toml | 37 +++++++++---------------- 22 files changed, 232 insertions(+), 58 deletions(-) diff --git a/gitlab/client.py b/gitlab/client.py index 903b37ebc..295712cc0 100644 --- a/gitlab/client.py +++ b/gitlab/client.py @@ -495,10 +495,10 @@ def _check_redirects(self, result: requests.Response) -> None: def _prepare_send_data( self, files: Optional[Dict[str, Any]] = None, - post_data: Optional[Dict[str, Any]] = None, + post_data: Optional[Union[Dict[str, Any], bytes]] = None, raw: bool = False, ) -> Tuple[ - Optional[Dict[str, Any]], + Optional[Union[Dict[str, Any], bytes]], Optional[Union[Dict[str, Any], MultipartEncoder]], str, ]: @@ -508,6 +508,8 @@ def _prepare_send_data( else: # booleans does not exists for data (neither for MultipartEncoder): # cast to string int to avoid: 'bool' object has no attribute 'encode' + if TYPE_CHECKING: + assert isinstance(post_data, dict) for k, v in post_data.items(): if isinstance(v, bool): post_data[k] = str(int(v)) @@ -527,7 +529,7 @@ def http_request( verb: str, path: str, query_data: Optional[Dict[str, Any]] = None, - post_data: Optional[Dict[str, Any]] = None, + post_data: Optional[Union[Dict[str, Any], bytes]] = None, raw: bool = False, streamed: bool = False, files: Optional[Dict[str, Any]] = None, @@ -544,7 +546,7 @@ def http_request( path (str): Path or full URL to query ('/projects' or 'http://whatever/v4/api/projecs') query_data (dict): Data to send as query parameters - post_data (dict): Data to send in the body (will be converted to + post_data (dict|bytes): Data to send in the body (will be converted to json by default) raw (bool): If True, do not convert post_data to json streamed (bool): Whether the data should be streamed @@ -800,7 +802,7 @@ def http_put( self, path: str, query_data: Optional[Dict[str, Any]] = None, - post_data: Optional[Dict[str, Any]] = None, + post_data: Optional[Union[Dict[str, Any], bytes]] = None, raw: bool = False, files: Optional[Dict[str, Any]] = None, **kwargs: Any, @@ -811,7 +813,7 @@ def http_put( path (str): Path or full URL to query ('/projects' or 'http://whatever/v4/api/projecs') query_data (dict): Data to send as query parameters - post_data (dict): Data to send in the body (will be converted to + post_data (dict|bytes): Data to send in the body (will be converted to json by default) raw (bool): If True, do not convert post_data to json files (dict): The files to send to the server diff --git a/gitlab/v4/cli.py b/gitlab/v4/cli.py index f46e9af41..6cffce7d3 100644 --- a/gitlab/v4/cli.py +++ b/gitlab/v4/cli.py @@ -103,6 +103,8 @@ def do_project_export_download(self) -> None: if TYPE_CHECKING: assert export_status is not None data = export_status.download() + if TYPE_CHECKING: + assert data is not None sys.stdout.buffer.write(data) except Exception as e: diff --git a/gitlab/v4/objects/appearance.py b/gitlab/v4/objects/appearance.py index a34398e40..6a0c20a69 100644 --- a/gitlab/v4/objects/appearance.py +++ b/gitlab/v4/objects/appearance.py @@ -1,3 +1,5 @@ +from typing import Any, cast, Dict, Optional, Union + from gitlab import exceptions as exc from gitlab.base import RequiredOptional, RESTManager, RESTObject from gitlab.mixins import GetWithoutIdMixin, SaveMixin, UpdateMixin @@ -32,7 +34,12 @@ class ApplicationAppearanceManager(GetWithoutIdMixin, UpdateMixin, RESTManager): ) @exc.on_http_error(exc.GitlabUpdateError) - def update(self, id=None, new_data=None, **kwargs): + def update( + self, + id: Optional[Union[str, int]] = None, + new_data: Dict[str, Any] = None, + **kwargs: Any + ) -> Dict[str, Any]: """Update an object on the server. Args: @@ -49,4 +56,9 @@ def update(self, id=None, new_data=None, **kwargs): """ new_data = new_data or {} data = new_data.copy() - super(ApplicationAppearanceManager, self).update(id, data, **kwargs) + return super(ApplicationAppearanceManager, self).update(id, data, **kwargs) + + def get( + self, id: Optional[Union[int, str]] = None, **kwargs: Any + ) -> Optional[ApplicationAppearance]: + return cast(ApplicationAppearance, super().get(id=id, **kwargs)) diff --git a/gitlab/v4/objects/badges.py b/gitlab/v4/objects/badges.py index 198f6ea8e..33439a2cc 100644 --- a/gitlab/v4/objects/badges.py +++ b/gitlab/v4/objects/badges.py @@ -1,3 +1,5 @@ +from typing import Any, cast, Union + from gitlab.base import RequiredOptional, RESTManager, RESTObject from gitlab.mixins import BadgeRenderMixin, CRUDMixin, ObjectDeleteMixin, SaveMixin @@ -31,3 +33,8 @@ class ProjectBadgeManager(BadgeRenderMixin, CRUDMixin, RESTManager): _from_parent_attrs = {"project_id": "id"} _create_attrs = RequiredOptional(required=("link_url", "image_url")) _update_attrs = RequiredOptional(optional=("link_url", "image_url")) + + def get( + self, id: Union[str, int], lazy: bool = False, **kwargs: Any + ) -> ProjectBadge: + return cast(ProjectBadge, super().get(id=id, lazy=lazy, **kwargs)) diff --git a/gitlab/v4/objects/boards.py b/gitlab/v4/objects/boards.py index 8b2959d9a..f9dc8c288 100644 --- a/gitlab/v4/objects/boards.py +++ b/gitlab/v4/objects/boards.py @@ -1,3 +1,5 @@ +from typing import Any, cast, Union + from gitlab.base import RequiredOptional, RESTManager, RESTObject from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin @@ -24,6 +26,11 @@ class GroupBoardListManager(CRUDMixin, RESTManager): _create_attrs = RequiredOptional(required=("label_id",)) _update_attrs = RequiredOptional(required=("position",)) + def get( + self, id: Union[str, int], lazy: bool = False, **kwargs: Any + ) -> GroupBoardList: + return cast(GroupBoardList, super().get(id=id, lazy=lazy, **kwargs)) + class GroupBoard(SaveMixin, ObjectDeleteMixin, RESTObject): lists: GroupBoardListManager @@ -35,6 +42,9 @@ class GroupBoardManager(CRUDMixin, RESTManager): _from_parent_attrs = {"group_id": "id"} _create_attrs = RequiredOptional(required=("name",)) + def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> GroupBoard: + return cast(GroupBoard, super().get(id=id, lazy=lazy, **kwargs)) + class ProjectBoardList(SaveMixin, ObjectDeleteMixin, RESTObject): pass @@ -47,6 +57,11 @@ class ProjectBoardListManager(CRUDMixin, RESTManager): _create_attrs = RequiredOptional(required=("label_id",)) _update_attrs = RequiredOptional(required=("position",)) + def get( + self, id: Union[str, int], lazy: bool = False, **kwargs: Any + ) -> ProjectBoardList: + return cast(ProjectBoardList, super().get(id=id, lazy=lazy, **kwargs)) + class ProjectBoard(SaveMixin, ObjectDeleteMixin, RESTObject): lists: ProjectBoardListManager @@ -57,3 +72,8 @@ class ProjectBoardManager(CRUDMixin, RESTManager): _obj_cls = ProjectBoard _from_parent_attrs = {"project_id": "id"} _create_attrs = RequiredOptional(required=("name",)) + + def get( + self, id: Union[str, int], lazy: bool = False, **kwargs: Any + ) -> ProjectBoard: + return cast(ProjectBoard, super().get(id=id, lazy=lazy, **kwargs)) diff --git a/gitlab/v4/objects/clusters.py b/gitlab/v4/objects/clusters.py index 3dcf6539e..a6ff67027 100644 --- a/gitlab/v4/objects/clusters.py +++ b/gitlab/v4/objects/clusters.py @@ -1,3 +1,5 @@ +from typing import Any, cast, Dict, Optional + from gitlab import exceptions as exc from gitlab.base import RequiredOptional, RESTManager, RESTObject from gitlab.mixins import CreateMixin, CRUDMixin, ObjectDeleteMixin, SaveMixin @@ -33,7 +35,9 @@ class GroupClusterManager(CRUDMixin, RESTManager): ) @exc.on_http_error(exc.GitlabStopError) - def create(self, data, **kwargs): + def create( + self, data: Optional[Dict[str, Any]] = None, **kwargs: Any + ) -> GroupCluster: """Create a new object. Args: @@ -51,7 +55,7 @@ def create(self, data, **kwargs): the data sent by the server """ path = f"{self.path}/user" - return CreateMixin.create(self, data, path=path, **kwargs) + return cast(GroupCluster, CreateMixin.create(self, data, path=path, **kwargs)) class ProjectCluster(SaveMixin, ObjectDeleteMixin, RESTObject): @@ -77,7 +81,9 @@ class ProjectClusterManager(CRUDMixin, RESTManager): ) @exc.on_http_error(exc.GitlabStopError) - def create(self, data, **kwargs): + def create( + self, data: Optional[Dict[str, Any]] = None, **kwargs: Any + ) -> ProjectCluster: """Create a new object. Args: @@ -95,4 +101,4 @@ def create(self, data, **kwargs): the data sent by the server """ path = f"{self.path}/user" - return CreateMixin.create(self, data, path=path, **kwargs) + return cast(ProjectCluster, CreateMixin.create(self, data, path=path, **kwargs)) diff --git a/gitlab/v4/objects/container_registry.py b/gitlab/v4/objects/container_registry.py index ce03d357d..f9fd02074 100644 --- a/gitlab/v4/objects/container_registry.py +++ b/gitlab/v4/objects/container_registry.py @@ -1,3 +1,5 @@ +from typing import Any, TYPE_CHECKING + from gitlab import cli from gitlab import exceptions as exc from gitlab.base import RESTManager, RESTObject @@ -36,7 +38,7 @@ class ProjectRegistryTagManager(DeleteMixin, RetrieveMixin, RESTManager): optional=("keep_n", "name_regex_keep", "older_than"), ) @exc.on_http_error(exc.GitlabDeleteError) - def delete_in_bulk(self, name_regex_delete, **kwargs): + def delete_in_bulk(self, name_regex_delete: str, **kwargs: Any) -> None: """Delete Tag in bulk Args: @@ -55,4 +57,6 @@ def delete_in_bulk(self, name_regex_delete, **kwargs): valid_attrs = ["keep_n", "name_regex_keep", "older_than"] data = {"name_regex_delete": name_regex_delete} data.update({k: v for k, v in kwargs.items() if k in valid_attrs}) + if TYPE_CHECKING: + assert self.path is not None self.gitlab.http_delete(self.path, query_data=data, **kwargs) diff --git a/gitlab/v4/objects/deploy_keys.py b/gitlab/v4/objects/deploy_keys.py index 9c0a90954..82a5855e1 100644 --- a/gitlab/v4/objects/deploy_keys.py +++ b/gitlab/v4/objects/deploy_keys.py @@ -1,3 +1,7 @@ +from typing import Any, cast, Dict, Union + +import requests + from gitlab import cli from gitlab import exceptions as exc from gitlab.base import RequiredOptional, RESTManager, RESTObject @@ -33,7 +37,9 @@ class ProjectKeyManager(CRUDMixin, RESTManager): @cli.register_custom_action("ProjectKeyManager", ("key_id",)) @exc.on_http_error(exc.GitlabProjectDeployKeyError) - def enable(self, key_id, **kwargs): + def enable( + self, key_id: int, **kwargs: Any + ) -> Union[Dict[str, Any], requests.Response]: """Enable a deploy key for a project. Args: @@ -43,6 +49,12 @@ def enable(self, key_id, **kwargs): Raises: GitlabAuthenticationError: If authentication is not correct GitlabProjectDeployKeyError: If the key could not be enabled + + Returns: + A dict of the result. """ path = f"{self.path}/{key_id}/enable" - self.gitlab.http_post(path, **kwargs) + return self.gitlab.http_post(path, **kwargs) + + def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> ProjectKey: + return cast(ProjectKey, super().get(id=id, lazy=lazy, **kwargs)) diff --git a/gitlab/v4/objects/environments.py b/gitlab/v4/objects/environments.py index 3ecb95717..67787b0cb 100644 --- a/gitlab/v4/objects/environments.py +++ b/gitlab/v4/objects/environments.py @@ -1,3 +1,7 @@ +from typing import Any, Dict, Union + +import requests + from gitlab import cli from gitlab import exceptions as exc from gitlab.base import RequiredOptional, RESTManager, RESTObject @@ -19,7 +23,7 @@ class ProjectEnvironment(SaveMixin, ObjectDeleteMixin, RESTObject): @cli.register_custom_action("ProjectEnvironment") @exc.on_http_error(exc.GitlabStopError) - def stop(self, **kwargs): + def stop(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]: """Stop the environment. Args: @@ -28,9 +32,12 @@ def stop(self, **kwargs): Raises: GitlabAuthenticationError: If authentication is not correct GitlabStopError: If the operation failed + + Returns: + A dict of the result. """ path = f"{self.manager.path}/{self.get_id()}/stop" - self.manager.gitlab.http_post(path, **kwargs) + return self.manager.gitlab.http_post(path, **kwargs) class ProjectEnvironmentManager( diff --git a/gitlab/v4/objects/export_import.py b/gitlab/v4/objects/export_import.py index ec4532ac3..85e9789a2 100644 --- a/gitlab/v4/objects/export_import.py +++ b/gitlab/v4/objects/export_import.py @@ -1,3 +1,5 @@ +from typing import Any, cast, Optional, Union + from gitlab.base import RequiredOptional, RESTManager, RESTObject from gitlab.mixins import CreateMixin, DownloadMixin, GetWithoutIdMixin, RefreshMixin @@ -22,6 +24,11 @@ class GroupExportManager(GetWithoutIdMixin, CreateMixin, RESTManager): _obj_cls = GroupExport _from_parent_attrs = {"group_id": "id"} + def get( + self, id: Optional[Union[int, str]] = None, **kwargs: Any + ) -> Optional[GroupExport]: + return cast(GroupExport, super().get(id=id, **kwargs)) + class GroupImport(RESTObject): _id_attr = None @@ -32,6 +39,11 @@ class GroupImportManager(GetWithoutIdMixin, RESTManager): _obj_cls = GroupImport _from_parent_attrs = {"group_id": "id"} + def get( + self, id: Optional[Union[int, str]] = None, **kwargs: Any + ) -> Optional[GroupImport]: + return cast(GroupImport, super().get(id=id, **kwargs)) + class ProjectExport(DownloadMixin, RefreshMixin, RESTObject): _id_attr = None @@ -43,6 +55,11 @@ class ProjectExportManager(GetWithoutIdMixin, CreateMixin, RESTManager): _from_parent_attrs = {"project_id": "id"} _create_attrs = RequiredOptional(optional=("description",)) + def get( + self, id: Optional[Union[int, str]] = None, **kwargs: Any + ) -> Optional[ProjectExport]: + return cast(ProjectExport, super().get(id=id, **kwargs)) + class ProjectImport(RefreshMixin, RESTObject): _id_attr = None @@ -52,3 +69,8 @@ class ProjectImportManager(GetWithoutIdMixin, RESTManager): _path = "/projects/%(project_id)s/import" _obj_cls = ProjectImport _from_parent_attrs = {"project_id": "id"} + + def get( + self, id: Optional[Union[int, str]] = None, **kwargs: Any + ) -> Optional[ProjectImport]: + return cast(ProjectImport, super().get(id=id, **kwargs)) diff --git a/gitlab/v4/objects/features.py b/gitlab/v4/objects/features.py index 65144a7b6..4aaa1850d 100644 --- a/gitlab/v4/objects/features.py +++ b/gitlab/v4/objects/features.py @@ -1,3 +1,9 @@ +""" +GitLab API: +https://docs.gitlab.com/ee/api/features.html +""" +from typing import Any, Optional, TYPE_CHECKING, Union + from gitlab import exceptions as exc from gitlab import utils from gitlab.base import RESTManager, RESTObject @@ -20,14 +26,14 @@ class FeatureManager(ListMixin, DeleteMixin, RESTManager): @exc.on_http_error(exc.GitlabSetError) def set( self, - name, - value, - feature_group=None, - user=None, - group=None, - project=None, - **kwargs, - ): + name: str, + value: Union[bool, int], + feature_group: Optional[str] = None, + user: Optional[str] = None, + group: Optional[str] = None, + project: Optional[str] = None, + **kwargs: Any, + ) -> Feature: """Create or update the object. Args: @@ -56,4 +62,6 @@ def set( } data = utils.remove_none_from_dict(data) server_data = self.gitlab.http_post(path, post_data=data, **kwargs) + if TYPE_CHECKING: + assert isinstance(server_data, dict) return self._obj_cls(self, server_data) diff --git a/gitlab/v4/objects/ldap.py b/gitlab/v4/objects/ldap.py index cecb1e9a9..0ba9354c4 100644 --- a/gitlab/v4/objects/ldap.py +++ b/gitlab/v4/objects/ldap.py @@ -1,3 +1,5 @@ +from typing import Any, List, Union + from gitlab import exceptions as exc from gitlab.base import RESTManager, RESTObject, RESTObjectList @@ -17,7 +19,7 @@ class LDAPGroupManager(RESTManager): _list_filters = ("search", "provider") @exc.on_http_error(exc.GitlabListError) - def list(self, **kwargs): + def list(self, **kwargs: Any) -> Union[List[LDAPGroup], RESTObjectList]: """Retrieve a list of objects. Args: diff --git a/gitlab/v4/objects/milestones.py b/gitlab/v4/objects/milestones.py index fc39df77e..53ad66df6 100644 --- a/gitlab/v4/objects/milestones.py +++ b/gitlab/v4/objects/milestones.py @@ -1,3 +1,5 @@ +from typing import Any + from gitlab import cli from gitlab import exceptions as exc from gitlab import types @@ -123,7 +125,7 @@ def issues(self, **kwargs): @cli.register_custom_action("ProjectMilestone") @exc.on_http_error(exc.GitlabListError) - def merge_requests(self, **kwargs): + def merge_requests(self, **kwargs: Any) -> RESTObjectList: """List the merge requests related to this milestone. Args: diff --git a/gitlab/v4/objects/packages.py b/gitlab/v4/objects/packages.py index d049d2897..57f2f6061 100644 --- a/gitlab/v4/objects/packages.py +++ b/gitlab/v4/objects/packages.py @@ -1,3 +1,9 @@ +""" +GitLab API: +https://docs.gitlab.com/ee/api/packages.html +https://docs.gitlab.com/ee/user/packages/generic_packages/ +""" + from pathlib import Path from typing import Any, Callable, Optional, TYPE_CHECKING, Union @@ -41,7 +47,7 @@ def upload( package_version: str, file_name: str, path: Union[str, Path], - **kwargs, + **kwargs: Any, ) -> GenericPackage: """Upload a file as a generic package. @@ -60,6 +66,8 @@ def upload( Returns: GenericPackage: An object storing the metadata of the uploaded package. + + https://docs.gitlab.com/ee/user/packages/generic_packages/ """ try: @@ -70,6 +78,8 @@ def upload( url = f"{self._computed_path}/{package_name}/{package_version}/{file_name}" server_data = self.gitlab.http_put(url, post_data=file_data, raw=True, **kwargs) + if TYPE_CHECKING: + assert isinstance(server_data, dict) return self._obj_cls( self, diff --git a/gitlab/v4/objects/push_rules.py b/gitlab/v4/objects/push_rules.py index ee20f960d..d8cfafa05 100644 --- a/gitlab/v4/objects/push_rules.py +++ b/gitlab/v4/objects/push_rules.py @@ -1,3 +1,5 @@ +from typing import Any, cast, Optional, Union + from gitlab.base import RequiredOptional, RESTManager, RESTObject from gitlab.mixins import ( CreateMixin, @@ -48,3 +50,8 @@ class ProjectPushRulesManager( "max_file_size", ), ) + + def get( + self, id: Optional[Union[int, str]] = None, **kwargs: Any + ) -> Optional[ProjectPushRules]: + return cast(ProjectPushRules, super().get(id=id, **kwargs)) diff --git a/gitlab/v4/objects/releases.py b/gitlab/v4/objects/releases.py index 2af3248db..64ea7c5b7 100644 --- a/gitlab/v4/objects/releases.py +++ b/gitlab/v4/objects/releases.py @@ -1,3 +1,5 @@ +from typing import Any, cast, Union + from gitlab.base import RequiredOptional, RESTManager, RESTObject from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin @@ -26,6 +28,11 @@ class ProjectReleaseManager(CRUDMixin, RESTManager): optional=("name", "description", "milestones", "released_at") ) + def get( + self, id: Union[str, int], lazy: bool = False, **kwargs: Any + ) -> ProjectRelease: + return cast(ProjectRelease, super().get(id=id, lazy=lazy, **kwargs)) + class ProjectReleaseLink(ObjectDeleteMixin, SaveMixin, RESTObject): pass @@ -39,3 +46,8 @@ class ProjectReleaseLinkManager(CRUDMixin, RESTManager): required=("name", "url"), optional=("filepath", "link_type") ) _update_attrs = RequiredOptional(optional=("name", "url", "filepath", "link_type")) + + def get( + self, id: Union[str, int], lazy: bool = False, **kwargs: Any + ) -> ProjectReleaseLink: + return cast(ProjectReleaseLink, super().get(id=id, lazy=lazy, **kwargs)) diff --git a/gitlab/v4/objects/runners.py b/gitlab/v4/objects/runners.py index ec8153f4d..fac910028 100644 --- a/gitlab/v4/objects/runners.py +++ b/gitlab/v4/objects/runners.py @@ -1,3 +1,5 @@ +from typing import Any, cast, List, Optional, Union + from gitlab import cli from gitlab import exceptions as exc from gitlab import types @@ -70,7 +72,7 @@ class RunnerManager(CRUDMixin, RESTManager): @cli.register_custom_action("RunnerManager", tuple(), ("scope",)) @exc.on_http_error(exc.GitlabListError) - def all(self, scope=None, **kwargs): + def all(self, scope: Optional[str] = None, **kwargs: Any) -> List[Runner]: """List all the runners. Args: @@ -99,7 +101,7 @@ def all(self, scope=None, **kwargs): @cli.register_custom_action("RunnerManager", ("token",)) @exc.on_http_error(exc.GitlabVerifyError) - def verify(self, token, **kwargs): + def verify(self, token: str, **kwargs: Any) -> None: """Validates authentication credentials for a registered Runner. Args: @@ -114,6 +116,9 @@ def verify(self, token, **kwargs): post_data = {"token": token} self.gitlab.http_post(path, post_data=post_data, **kwargs) + def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Runner: + return cast(Runner, super().get(id=id, lazy=lazy, **kwargs)) + class GroupRunner(RESTObject): pass diff --git a/gitlab/v4/objects/settings.py b/gitlab/v4/objects/settings.py index 1c8be2520..2e8ac7918 100644 --- a/gitlab/v4/objects/settings.py +++ b/gitlab/v4/objects/settings.py @@ -1,3 +1,5 @@ +from typing import Any, cast, Dict, Optional, Union + from gitlab import exceptions as exc from gitlab import types from gitlab.base import RequiredOptional, RESTManager, RESTObject @@ -87,7 +89,12 @@ class ApplicationSettingsManager(GetWithoutIdMixin, UpdateMixin, RESTManager): } @exc.on_http_error(exc.GitlabUpdateError) - def update(self, id=None, new_data=None, **kwargs): + def update( + self, + id: Optional[Union[str, int]] = None, + new_data: Dict[str, Any] = None, + **kwargs: Any + ) -> Dict[str, Any]: """Update an object on the server. Args: @@ -106,4 +113,9 @@ def update(self, id=None, new_data=None, **kwargs): data = new_data.copy() if "domain_whitelist" in data and data["domain_whitelist"] is None: data.pop("domain_whitelist") - super(ApplicationSettingsManager, self).update(id, data, **kwargs) + return super(ApplicationSettingsManager, self).update(id, data, **kwargs) + + def get( + self, id: Optional[Union[int, str]] = None, **kwargs: Any + ) -> Optional[ApplicationSettings]: + return cast(ApplicationSettings, super().get(id=id, **kwargs)) diff --git a/gitlab/v4/objects/todos.py b/gitlab/v4/objects/todos.py index eecd2221f..9f8c52d32 100644 --- a/gitlab/v4/objects/todos.py +++ b/gitlab/v4/objects/todos.py @@ -1,3 +1,5 @@ +from typing import Any, Dict, TYPE_CHECKING + from gitlab import cli from gitlab import exceptions as exc from gitlab.base import RESTManager, RESTObject @@ -12,7 +14,7 @@ class Todo(ObjectDeleteMixin, RESTObject): @cli.register_custom_action("Todo") @exc.on_http_error(exc.GitlabTodoError) - def mark_as_done(self, **kwargs): + def mark_as_done(self, **kwargs: Any) -> Dict[str, Any]: """Mark the todo as done. Args: @@ -21,10 +23,16 @@ def mark_as_done(self, **kwargs): Raises: GitlabAuthenticationError: If authentication is not correct GitlabTodoError: If the server failed to perform the request + + Returns: + A dict with the result """ path = f"{self.manager.path}/{self.id}/mark_as_done" server_data = self.manager.gitlab.http_post(path, **kwargs) + if TYPE_CHECKING: + assert isinstance(server_data, dict) self._update_attrs(server_data) + return server_data class TodoManager(ListMixin, DeleteMixin, RESTManager): @@ -34,7 +42,7 @@ class TodoManager(ListMixin, DeleteMixin, RESTManager): @cli.register_custom_action("TodoManager") @exc.on_http_error(exc.GitlabTodoError) - def mark_all_as_done(self, **kwargs): + def mark_all_as_done(self, **kwargs: Any) -> None: """Mark all the todos as done. Args: diff --git a/gitlab/v4/objects/variables.py b/gitlab/v4/objects/variables.py index 2e5e483a8..d5f32e382 100644 --- a/gitlab/v4/objects/variables.py +++ b/gitlab/v4/objects/variables.py @@ -4,6 +4,8 @@ https://docs.gitlab.com/ee/api/project_level_variables.html https://docs.gitlab.com/ee/api/group_level_variables.html """ +from typing import Any, cast, Union + from gitlab.base import RequiredOptional, RESTManager, RESTObject from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin @@ -31,6 +33,9 @@ class VariableManager(CRUDMixin, RESTManager): required=("key", "value"), optional=("protected", "variable_type", "masked") ) + def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Variable: + return cast(Variable, super().get(id=id, lazy=lazy, **kwargs)) + class GroupVariable(SaveMixin, ObjectDeleteMixin, RESTObject): _id_attr = "key" @@ -47,6 +52,11 @@ class GroupVariableManager(CRUDMixin, RESTManager): required=("key", "value"), optional=("protected", "variable_type", "masked") ) + def get( + self, id: Union[str, int], lazy: bool = False, **kwargs: Any + ) -> GroupVariable: + return cast(GroupVariable, super().get(id=id, lazy=lazy, **kwargs)) + class ProjectVariable(SaveMixin, ObjectDeleteMixin, RESTObject): _id_attr = "key" @@ -64,3 +74,8 @@ class ProjectVariableManager(CRUDMixin, RESTManager): required=("key", "value"), optional=("protected", "variable_type", "masked", "environment_scope"), ) + + def get( + self, id: Union[str, int], lazy: bool = False, **kwargs: Any + ) -> ProjectVariable: + return cast(ProjectVariable, super().get(id=id, lazy=lazy, **kwargs)) diff --git a/gitlab/v4/objects/wikis.py b/gitlab/v4/objects/wikis.py index a86b442da..e372d8693 100644 --- a/gitlab/v4/objects/wikis.py +++ b/gitlab/v4/objects/wikis.py @@ -1,3 +1,5 @@ +from typing import Any, cast, Union + from gitlab.base import RequiredOptional, RESTManager, RESTObject from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin @@ -24,6 +26,11 @@ class ProjectWikiManager(CRUDMixin, RESTManager): _update_attrs = RequiredOptional(optional=("title", "content", "format")) _list_filters = ("with_content",) + def get( + self, id: Union[str, int], lazy: bool = False, **kwargs: Any + ) -> ProjectWiki: + return cast(ProjectWiki, super().get(id=id, lazy=lazy, **kwargs)) + class GroupWiki(SaveMixin, ObjectDeleteMixin, RESTObject): _id_attr = "slug" @@ -39,3 +46,6 @@ class GroupWikiManager(CRUDMixin, RESTManager): ) _update_attrs = RequiredOptional(optional=("title", "content", "format")) _list_filters = ("with_content",) + + def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> GroupWiki: + return cast(GroupWiki, super().get(id=id, lazy=lazy, **kwargs)) diff --git a/pyproject.toml b/pyproject.toml index 5553c3476..7043c5832 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,19 @@ files = "." module = [ "docs.*", "docs.ext.*", - "gitlab.v4.objects.*", + "gitlab.v4.objects.epics", + "gitlab.v4.objects.files", + "gitlab.v4.objects.geo_nodes", + "gitlab.v4.objects.issues", + "gitlab.v4.objects.jobs", + "gitlab.v4.objects.labels", + "gitlab.v4.objects.merge_request_approvals", + "gitlab.v4.objects.milestones", + "gitlab.v4.objects.pipelines", + "gitlab.v4.objects.repositories", + "gitlab.v4.objects.services", + "gitlab.v4.objects.sidekiq", + "gitlab.v4.objects.snippets", "setup", "tests.functional.*", "tests.functional.api.*", @@ -21,29 +33,6 @@ module = [ ] ignore_errors = true -[[tool.mypy.overrides]] # Overrides to negate above patterns -module = [ - "gitlab.v4.objects.access_requests", - "gitlab.v4.objects.applications", - "gitlab.v4.objects.broadcast_messages", - "gitlab.v4.objects.deployments", - "gitlab.v4.objects.commits", - "gitlab.v4.objects.groups", - "gitlab.v4.objects.keys", - "gitlab.v4.objects.merge_requests", - "gitlab.v4.objects.merge_trains", - "gitlab.v4.objects.namespaces", - "gitlab.v4.objects.pages", - "gitlab.v4.objects.personal_access_tokens", - "gitlab.v4.objects.project_access_tokens", - "gitlab.v4.objects.projects", - "gitlab.v4.objects.tags", - "gitlab.v4.objects.templates", - "gitlab.v4.objects.triggers", - "gitlab.v4.objects.users", -] -ignore_errors = false - [tool.semantic_release] branch = "main" version_variable = "gitlab/__version__.py:__version__"