Skip to content

Update type-hints #2159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions gitlab/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import pprint
import textwrap
from types import ModuleType
from typing import Any, Dict, Iterable, Optional, Type, Union
from typing import Any, Dict, Iterable, Optional, Type, TYPE_CHECKING, Union

import gitlab
from gitlab import types as g_types
Expand Down Expand Up @@ -245,14 +245,22 @@ def get_id(self) -> Optional[Union[int, str]]:
"""Returns the id of the resource."""
if self._id_attr is None or not hasattr(self, self._id_attr):
return None
return getattr(self, self._id_attr)
id_val = getattr(self, self._id_attr)
if id_val is None:
return None
if TYPE_CHECKING:
assert isinstance(id_val, (int, str))
return id_val

@property
def _repr_value(self) -> Optional[str]:
"""Safely returns the human-readable resource name if present."""
if self._repr_attr is None or not hasattr(self, self._repr_attr):
return None
return getattr(self, self._repr_attr)
repr_val = getattr(self, self._repr_attr)
if TYPE_CHECKING:
assert isinstance(repr_val, str)
return repr_val

@property
def encoded_id(self) -> Optional[Union[int, str]]:
Expand Down
20 changes: 17 additions & 3 deletions gitlab/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,18 @@
import re
import sys
from types import ModuleType
from typing import Any, Callable, cast, Dict, Optional, Tuple, Type, TypeVar, Union
from typing import (
Any,
Callable,
cast,
Dict,
Optional,
Tuple,
Type,
TYPE_CHECKING,
TypeVar,
Union,
)

from requests.structures import CaseInsensitiveDict

Expand Down Expand Up @@ -96,8 +107,11 @@ def gitlab_resource_to_cls(
) -> Type[RESTObject]:
classes = CaseInsensitiveDict(namespace.__dict__)
lowercase_class = gitlab_resource.replace("-", "")

return classes[lowercase_class]
class_type = classes[lowercase_class]
if TYPE_CHECKING:
assert isinstance(class_type, type)
assert issubclass(class_type, RESTObject)
return class_type


def cls_to_gitlab_resource(cls: RESTObject) -> str:
Expand Down
28 changes: 20 additions & 8 deletions gitlab/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
f"api-usage.html#pagination"
)

HttpResponseType = Union[Dict[str, Any], List[Any], requests.Response]


class Gitlab:
"""Represents a GitLab server connection.
Expand Down Expand Up @@ -411,7 +413,7 @@ def lint(self, content: str, **kwargs: Any) -> Tuple[bool, List[str]]:
post_data = {"content": content}
data = self.http_post("/ci/lint", post_data=post_data, **kwargs)
if TYPE_CHECKING:
assert not isinstance(data, requests.Response)
assert isinstance(data, dict)
return (data["status"] == "valid", data["errors"])

@gitlab.exceptions.on_http_error(gitlab.exceptions.GitlabMarkdownError)
Expand All @@ -438,7 +440,8 @@ def markdown(
post_data["project"] = project
data = self.http_post("/markdown", post_data=post_data, **kwargs)
if TYPE_CHECKING:
assert not isinstance(data, requests.Response)
assert isinstance(data, dict)
assert isinstance(data["html"], str)
return data["html"]

@gitlab.exceptions.on_http_error(gitlab.exceptions.GitlabLicenseError)
Expand Down Expand Up @@ -478,7 +481,7 @@ def set_license(self, license: str, **kwargs: Any) -> Dict[str, Any]:
data = {"license": license}
result = self.http_post("/license", post_data=data, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result

def _set_auth_info(self) -> None:
Expand Down Expand Up @@ -777,7 +780,7 @@ def http_get(
streamed: bool = False,
raw: bool = False,
**kwargs: Any,
) -> Union[Dict[str, Any], requests.Response]:
) -> HttpResponseType:
"""Make a GET request to the Gitlab server.

Args:
Expand Down Expand Up @@ -808,7 +811,10 @@ def http_get(
and not raw
):
try:
return result.json()
json_result = result.json()
if TYPE_CHECKING:
assert isinstance(json_result, dict)
return json_result
except Exception as e:
raise gitlab.exceptions.GitlabParsingError(
error_message="Failed to parse the server message"
Expand Down Expand Up @@ -954,7 +960,7 @@ def http_post(
raw: bool = False,
files: Optional[Dict[str, Any]] = None,
**kwargs: Any,
) -> Union[Dict[str, Any], requests.Response]:
) -> HttpResponseType:
"""Make a POST request to the Gitlab server.

Args:
Expand Down Expand Up @@ -989,7 +995,10 @@ def http_post(
)
try:
if result.headers.get("Content-Type", None) == "application/json":
return result.json()
json_result = result.json()
if TYPE_CHECKING:
assert isinstance(json_result, dict)
return json_result
except Exception as e:
raise gitlab.exceptions.GitlabParsingError(
error_message="Failed to parse the server message"
Expand Down Expand Up @@ -1037,7 +1046,10 @@ def http_put(
**kwargs,
)
try:
return result.json()
json_result = result.json()
if TYPE_CHECKING:
assert isinstance(json_result, dict)
return json_result
except Exception as e:
raise gitlab.exceptions.GitlabParsingError(
error_message="Failed to parse the server message"
Expand Down
44 changes: 24 additions & 20 deletions gitlab/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import requests

import gitlab
import gitlab.client as gl_client
from gitlab import base, cli
from gitlab import exceptions as exc
from gitlab import utils
Expand Down Expand Up @@ -138,7 +139,7 @@ def get(
return self._obj_cls(self, {self._obj_cls._id_attr: id}, lazy=lazy)
server_data = self.gitlab.http_get(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(server_data, requests.Response)
assert isinstance(server_data, dict)
return self._obj_cls(self, server_data, lazy=lazy)


Expand Down Expand Up @@ -170,7 +171,7 @@ def get(self, **kwargs: Any) -> base.RESTObject:
assert self.path is not None
server_data = self.gitlab.http_get(self.path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(server_data, requests.Response)
assert isinstance(server_data, dict)
assert self._obj_cls is not None
return self._obj_cls(self, server_data)

Expand Down Expand Up @@ -204,7 +205,7 @@ def refresh(self, **kwargs: Any) -> None:
path = self.manager.path
server_data = self.manager.gitlab.http_get(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(server_data, requests.Response)
assert isinstance(server_data, dict)
self._update_attrs(server_data)


Expand Down Expand Up @@ -309,7 +310,7 @@ def create(
path = kwargs.pop("path", self.path)
server_data = self.gitlab.http_post(path, post_data=data, files=files, **kwargs)
if TYPE_CHECKING:
assert not isinstance(server_data, requests.Response)
assert isinstance(server_data, dict)
assert self._obj_cls is not None
return self._obj_cls(self, server_data)

Expand All @@ -326,7 +327,7 @@ class UpdateMixin(_RestManagerBase):

def _get_update_method(
self,
) -> Callable[..., Union[Dict[str, Any], requests.Response]]:
) -> Callable[..., gl_client.HttpResponseType]:
"""Return the HTTP method to use.

Returns:
Expand Down Expand Up @@ -375,7 +376,7 @@ def update(
http_method = self._get_update_method()
result = http_method(path, post_data=new_data, files=files, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result


Expand Down Expand Up @@ -562,7 +563,7 @@ def user_agent_detail(self, **kwargs: Any) -> Dict[str, Any]:
path = f"{self.manager.path}/{self.encoded_id}/user_agent_detail"
result = self.manager.gitlab.http_get(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result


Expand Down Expand Up @@ -675,7 +676,7 @@ def subscribe(self, **kwargs: Any) -> None:
path = f"{self.manager.path}/{self.encoded_id}/subscribe"
server_data = self.manager.gitlab.http_post(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(server_data, requests.Response)
assert isinstance(server_data, dict)
self._update_attrs(server_data)

@cli.register_custom_action(
Expand All @@ -695,7 +696,7 @@ def unsubscribe(self, **kwargs: Any) -> None:
path = f"{self.manager.path}/{self.encoded_id}/unsubscribe"
server_data = self.manager.gitlab.http_post(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(server_data, requests.Response)
assert isinstance(server_data, dict)
self._update_attrs(server_data)


Expand Down Expand Up @@ -746,12 +747,15 @@ def time_stats(self, **kwargs: Any) -> Dict[str, Any]:
# Use the existing time_stats attribute if it exist, otherwise make an
# API call
if "time_stats" in self.attributes:
return self.attributes["time_stats"]
time_stats = self.attributes["time_stats"]
if TYPE_CHECKING:
assert isinstance(time_stats, dict)
return time_stats

path = f"{self.manager.path}/{self.encoded_id}/time_stats"
result = self.manager.gitlab.http_get(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result

@cli.register_custom_action(("ProjectIssue", "ProjectMergeRequest"), ("duration",))
Expand All @@ -771,7 +775,7 @@ def time_estimate(self, duration: str, **kwargs: Any) -> Dict[str, Any]:
data = {"duration": duration}
result = self.manager.gitlab.http_post(path, post_data=data, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result

@cli.register_custom_action(("ProjectIssue", "ProjectMergeRequest"))
Expand All @@ -789,7 +793,7 @@ def reset_time_estimate(self, **kwargs: Any) -> Dict[str, Any]:
path = f"{self.manager.path}/{self.encoded_id}/reset_time_estimate"
result = self.manager.gitlab.http_post(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result

@cli.register_custom_action(("ProjectIssue", "ProjectMergeRequest"), ("duration",))
Expand All @@ -809,7 +813,7 @@ def add_spent_time(self, duration: str, **kwargs: Any) -> Dict[str, Any]:
data = {"duration": duration}
result = self.manager.gitlab.http_post(path, post_data=data, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result

@cli.register_custom_action(("ProjectIssue", "ProjectMergeRequest"))
Expand All @@ -827,7 +831,7 @@ def reset_spent_time(self, **kwargs: Any) -> Dict[str, Any]:
path = f"{self.manager.path}/{self.encoded_id}/reset_spent_time"
result = self.manager.gitlab.http_post(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result


Expand All @@ -841,7 +845,7 @@ class ParticipantsMixin(_RestObjectBase):

@cli.register_custom_action(("ProjectMergeRequest", "ProjectIssue"))
@exc.on_http_error(exc.GitlabListError)
def participants(self, **kwargs: Any) -> Dict[str, Any]:
def participants(self, **kwargs: Any) -> List[Any]:
"""List the participants.

Args:
Expand All @@ -861,7 +865,7 @@ def participants(self, **kwargs: Any) -> Dict[str, Any]:
path = f"{self.manager.path}/{self.encoded_id}/participants"
result = self.manager.gitlab.http_get(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, list)
return result


Expand Down Expand Up @@ -889,7 +893,7 @@ def render(self, link_url: str, image_url: str, **kwargs: Any) -> Dict[str, Any]
data = {"link_url": link_url, "image_url": image_url}
result = self.gitlab.http_get(path, data, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result


Expand All @@ -904,7 +908,7 @@ class PromoteMixin(_RestObjectBase):

def _get_update_method(
self,
) -> Callable[..., Union[Dict[str, Any], requests.Response]]:
) -> Callable[..., gl_client.HttpResponseType]:
"""Return the HTTP method to use.

Returns:
Expand Down Expand Up @@ -936,5 +940,5 @@ def promote(self, **kwargs: Any) -> Dict[str, Any]:
http_method = self._get_update_method()
result = http_method(path, **kwargs)
if TYPE_CHECKING:
assert not isinstance(result, requests.Response)
assert isinstance(result, dict)
return result
8 changes: 2 additions & 6 deletions gitlab/v4/objects/commits.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from typing import Any, cast, Dict, List, Optional, TYPE_CHECKING, Union

import requests

import gitlab
from gitlab import cli
from gitlab import exceptions as exc
Expand Down Expand Up @@ -107,9 +105,7 @@ def merge_requests(

@cli.register_custom_action("ProjectCommit", ("branch",))
@exc.on_http_error(exc.GitlabRevertError)
def revert(
self, branch: str, **kwargs: Any
) -> Union[Dict[str, Any], requests.Response]:
def revert(self, branch: str, **kwargs: Any) -> gitlab.client.HttpResponseType:
"""Revert a commit on a given branch.

Args:
Expand All @@ -129,7 +125,7 @@ def revert(

@cli.register_custom_action("ProjectCommit")
@exc.on_http_error(exc.GitlabGetError)
def signature(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
def signature(self, **kwargs: Any) -> gitlab.client.HttpResponseType:
"""Get the signature of the commit.

Args:
Expand Down
9 changes: 3 additions & 6 deletions gitlab/v4/objects/deploy_keys.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import Any, cast, Dict, Union

import requests
from typing import Any, cast, Union

import gitlab
from gitlab import cli
from gitlab import exceptions as exc
from gitlab.base import RESTManager, RESTObject
Expand Down Expand Up @@ -38,9 +37,7 @@ class ProjectKeyManager(CRUDMixin, RESTManager):

@cli.register_custom_action("ProjectKeyManager", ("key_id",))
@exc.on_http_error(exc.GitlabProjectDeployKeyError)
def enable(
self, key_id: int, **kwargs: Any
) -> Union[Dict[str, Any], requests.Response]:
def enable(self, key_id: int, **kwargs: Any) -> gitlab.client.HttpResponseType:
"""Enable a deploy key for a project.

Args:
Expand Down
Loading