Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

chore: add get() methods for GetWithoutIdMixin based classes#1710

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
nejch merged 1 commit intomainfromjlvillal/get_without_id
Dec 11, 2021
Merged
Show file tree
Hide file tree
Changes fromall 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
2 changes: 1 addition & 1 deletiongitlab/v4/objects/appearance.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -61,4 +61,4 @@ def update(
def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ApplicationAppearance]:
return cast(ApplicationAppearance, super().get(id=id, **kwargs))
return cast(Optional[ApplicationAppearance], super().get(id=id, **kwargs))
8 changes: 4 additions & 4 deletionsgitlab/v4/objects/export_import.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ class GroupExportManager(GetWithoutIdMixin, CreateMixin, RESTManager):
def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[GroupExport]:
return cast(GroupExport, super().get(id=id, **kwargs))
return cast(Optional[GroupExport], super().get(id=id, **kwargs))


class GroupImport(RESTObject):
Expand All@@ -42,7 +42,7 @@ class GroupImportManager(GetWithoutIdMixin, RESTManager):
def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[GroupImport]:
return cast(GroupImport, super().get(id=id, **kwargs))
return cast(Optional[GroupImport], super().get(id=id, **kwargs))


class ProjectExport(DownloadMixin, RefreshMixin, RESTObject):
Expand All@@ -58,7 +58,7 @@ class ProjectExportManager(GetWithoutIdMixin, CreateMixin, RESTManager):
def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectExport]:
return cast(ProjectExport, super().get(id=id, **kwargs))
return cast(Optional[ProjectExport], super().get(id=id, **kwargs))


class ProjectImport(RefreshMixin, RESTObject):
Expand All@@ -73,4 +73,4 @@ class ProjectImportManager(GetWithoutIdMixin, RESTManager):
def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectImport]:
return cast(ProjectImport, super().get(id=id, **kwargs))
return cast(Optional[ProjectImport], super().get(id=id, **kwargs))
19 changes: 18 additions & 1 deletiongitlab/v4/objects/merge_request_approvals.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, List, Optional, TYPE_CHECKING
from typing import Any,cast,Dict, List, Optional, TYPE_CHECKING, Union

from gitlab import exceptions as exc
from gitlab.base import RequiredOptional, RESTManager, RESTObject
Expand DownExpand Up@@ -45,6 +45,11 @@ class ProjectApprovalManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
)
_update_uses_post = True

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectApproval]:
return cast(Optional[ProjectApproval], super().get(id=id, **kwargs))

@exc.on_http_error(exc.GitlabUpdateError)
def set_approvers(
self,
Expand DownExpand Up@@ -105,6 +110,11 @@ class ProjectMergeRequestApprovalManager(GetWithoutIdMixin, UpdateMixin, RESTMan
_update_attrs = RequiredOptional(required=("approvals_required",))
_update_uses_post = True

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectMergeRequestApproval]:
return cast(Optional[ProjectMergeRequestApproval], super().get(id=id, **kwargs))

@exc.on_http_error(exc.GitlabUpdateError)
def set_approvers(
self,
Expand DownExpand Up@@ -241,3 +251,10 @@ class ProjectMergeRequestApprovalStateManager(GetWithoutIdMixin, RESTManager):
_path = "/projects/{project_id}/merge_requests/{mr_iid}/approval_state"
_obj_cls = ProjectMergeRequestApprovalState
_from_parent_attrs = {"project_id": "project_id", "mr_iid": "iid"}

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectMergeRequestApprovalState]:
return cast(
Optional[ProjectMergeRequestApprovalState], super().get(id=id, **kwargs)
)
17 changes: 17 additions & 0 deletionsgitlab/v4/objects/notification_settings.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
from typing import Any, cast, Optional, Union

from gitlab.base import RequiredOptional, RESTManager, RESTObject
from gitlab.mixins import GetWithoutIdMixin, SaveMixin, UpdateMixin

Expand DownExpand Up@@ -36,6 +38,11 @@ class NotificationSettingsManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
),
)

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[NotificationSettings]:
return cast(Optional[NotificationSettings], super().get(id=id, **kwargs))


class GroupNotificationSettings(NotificationSettings):
pass
Expand All@@ -46,6 +53,11 @@ class GroupNotificationSettingsManager(NotificationSettingsManager):
_obj_cls = GroupNotificationSettings
_from_parent_attrs = {"group_id": "id"}

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[GroupNotificationSettings]:
return cast(Optional[GroupNotificationSettings], super().get(id=id, **kwargs))


class ProjectNotificationSettings(NotificationSettings):
pass
Expand All@@ -55,3 +67,8 @@ class ProjectNotificationSettingsManager(NotificationSettingsManager):
_path = "/projects/{project_id}/notification_settings"
_obj_cls = ProjectNotificationSettings
_from_parent_attrs = {"project_id": "id"}

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectNotificationSettings]:
return cast(Optional[ProjectNotificationSettings], super().get(id=id, **kwargs))
5 changes: 5 additions & 0 deletionsgitlab/v4/objects/pipelines.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -246,3 +246,8 @@ class ProjectPipelineTestReportManager(GetWithoutIdMixin, RESTManager):
_path = "/projects/{project_id}/pipelines/{pipeline_id}/test_report"
_obj_cls = ProjectPipelineTestReport
_from_parent_attrs = {"project_id": "project_id", "pipeline_id": "id"}

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectPipelineTestReport]:
return cast(Optional[ProjectPipelineTestReport], super().get(id=id, **kwargs))
2 changes: 1 addition & 1 deletiongitlab/v4/objects/push_rules.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,4 +54,4 @@ class ProjectPushRulesManager(
def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectPushRules]:
return cast(ProjectPushRules, super().get(id=id, **kwargs))
return cast(Optional[ProjectPushRules], super().get(id=id, **kwargs))
2 changes: 1 addition & 1 deletiongitlab/v4/objects/settings.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -118,4 +118,4 @@ def update(
def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ApplicationSettings]:
return cast(ApplicationSettings, super().get(id=id, **kwargs))
return cast(Optional[ApplicationSettings], super().get(id=id, **kwargs))
22 changes: 22 additions & 0 deletionsgitlab/v4/objects/statistics.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
from typing import Any, cast, Optional, Union

from gitlab.base import RESTManager, RESTObject
from gitlab.mixins import GetWithoutIdMixin, RefreshMixin

Expand All@@ -22,6 +24,11 @@ class ProjectAdditionalStatisticsManager(GetWithoutIdMixin, RESTManager):
_obj_cls = ProjectAdditionalStatistics
_from_parent_attrs = {"project_id": "id"}

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectAdditionalStatistics]:
return cast(Optional[ProjectAdditionalStatistics], super().get(id=id, **kwargs))


class IssuesStatistics(RefreshMixin, RESTObject):
_id_attr = None
Expand All@@ -31,6 +38,11 @@ class IssuesStatisticsManager(GetWithoutIdMixin, RESTManager):
_path = "/issues_statistics"
_obj_cls = IssuesStatistics

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[IssuesStatistics]:
return cast(Optional[IssuesStatistics], super().get(id=id, **kwargs))


class GroupIssuesStatistics(RefreshMixin, RESTObject):
_id_attr = None
Expand All@@ -41,6 +53,11 @@ class GroupIssuesStatisticsManager(GetWithoutIdMixin, RESTManager):
_obj_cls = GroupIssuesStatistics
_from_parent_attrs = {"group_id": "id"}

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[GroupIssuesStatistics]:
return cast(Optional[GroupIssuesStatistics], super().get(id=id, **kwargs))


class ProjectIssuesStatistics(RefreshMixin, RESTObject):
_id_attr = None
Expand All@@ -50,3 +67,8 @@ class ProjectIssuesStatisticsManager(GetWithoutIdMixin, RESTManager):
_path = "/projects/{project_id}/issues_statistics"
_obj_cls = ProjectIssuesStatistics
_from_parent_attrs = {"project_id": "id"}

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[ProjectIssuesStatistics]:
return cast(Optional[ProjectIssuesStatistics], super().get(id=id, **kwargs))
17 changes: 16 additions & 1 deletiongitlab/v4/objects/users.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@
https://docs.gitlab.com/ee/api/users.html
https://docs.gitlab.com/ee/api/projects.html#list-projects-starred-by-a-user
"""
from typing import Any, cast, Dict, List, Union
from typing import Any, cast, Dict, List,Optional,Union

import requests

Expand DownExpand Up@@ -120,6 +120,11 @@ class CurrentUserStatusManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
_obj_cls = CurrentUserStatus
_update_attrs = RequiredOptional(optional=("emoji", "message"))

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[CurrentUserStatus]:
return cast(Optional[CurrentUserStatus], super().get(id=id, **kwargs))


class CurrentUser(RESTObject):
_id_attr = None
Expand All@@ -135,6 +140,11 @@ class CurrentUserManager(GetWithoutIdMixin, RESTManager):
_path = "/user"
_obj_cls = CurrentUser

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[CurrentUser]:
return cast(Optional[CurrentUser], super().get(id=id, **kwargs))


class User(SaveMixin, ObjectDeleteMixin, RESTObject):
_short_print_attr = "username"
Expand DownExpand Up@@ -390,6 +400,11 @@ class UserStatusManager(GetWithoutIdMixin, RESTManager):
_obj_cls = UserStatus
_from_parent_attrs = {"user_id": "id"}

def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[UserStatus]:
return cast(Optional[UserStatus], super().get(id=id, **kwargs))


class UserActivitiesManager(ListMixin, RESTManager):
_path = "/user/activities"
Expand Down
103 changes: 84 additions & 19 deletionstests/meta/test_ensure_type_hints.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,15 +4,34 @@
Original notes by John L. Villalovos

"""
import dataclasses
import functools
import inspect
from typing importTuple, Type
from typing importOptional, Type

import _pytest

import gitlab.mixins
import gitlab.v4.objects


@functools.total_ordering
@dataclasses.dataclass(frozen=True)
class ClassInfo:
name: str
type: Type

def __lt__(self, other: object) -> bool:
if not isinstance(other, ClassInfo):
return NotImplemented
return (self.type.__module__, self.name) < (other.type.__module__, other.name)

def __eq__(self, other: object) -> bool:
if not isinstance(other, ClassInfo):
return NotImplemented
return (self.type.__module__, self.name) == (other.type.__module__, other.name)


def pytest_generate_tests(metafunc: _pytest.python.Metafunc) -> None:
"""Find all of the classes in gitlab.v4.objects and pass them to our test
function"""
Expand All@@ -35,38 +54,84 @@ def pytest_generate_tests(metafunc: _pytest.python.Metafunc) -> None:
if not class_name.endswith("Manager"):
continue

class_info_set.add((class_name, class_value))
class_info_set.add(ClassInfo(name=class_name, type=class_value))

metafunc.parametrize("class_info", sorted(class_info_set))

metafunc.parametrize("class_info", class_info_set)

GET_ID_METHOD_TEMPLATE = """
def get(
self, id: Union[str, int], lazy: bool = False, **kwargs: Any
) -> {obj_cls.__name__}:
return cast({obj_cls.__name__}, super().get(id=id, lazy=lazy, **kwargs))

You may also need to add the following imports:
from typing import Any, cast, Union"
"""

GET_WITHOUT_ID_METHOD_TEMPLATE = """
def get(
self, id: Optional[Union[int, str]] = None, **kwargs: Any
) -> Optional[{obj_cls.__name__}]:
return cast(Optional[{obj_cls.__name__}], super().get(id=id, **kwargs))

You may also need to add the following imports:
from typing import Any, cast, Optional, Union"
"""


class TestTypeHints:
def test_check_get_function_type_hints(self, class_info:Tuple[str, Type]) -> None:
def test_check_get_function_type_hints(self, class_info:ClassInfo) -> None:
"""Ensure classes derived from GetMixin have defined a 'get()' method with
correct type-hints.
"""
class_name, class_value = class_info
if not class_name.endswith("Manager"):
return
self.get_check_helper(
base_type=gitlab.mixins.GetMixin,
class_info=class_info,
method_template=GET_ID_METHOD_TEMPLATE,
optional_return=False,
)

mro = class_value.mro()
def test_check_get_without_id_function_type_hints(
self, class_info: ClassInfo
) -> None:
"""Ensure classes derived from GetMixin have defined a 'get()' method with
correct type-hints.
"""
self.get_check_helper(
base_type=gitlab.mixins.GetWithoutIdMixin,
class_info=class_info,
method_template=GET_WITHOUT_ID_METHOD_TEMPLATE,
optional_return=True,
)

def get_check_helper(
self,
*,
base_type: Type,
class_info: ClassInfo,
method_template: str,
optional_return: bool,
) -> None:
if not class_info.name.endswith("Manager"):
return
mro = class_info.type.mro()
# The class needs to be derived from GetMixin or we ignore it
ifgitlab.mixins.GetMixin not in mro:
ifbase_type not in mro:
return

obj_cls =class_value._obj_cls
signature = inspect.signature(class_value.get)
filename = inspect.getfile(class_value)
obj_cls =class_info.type._obj_cls
signature = inspect.signature(class_info.type.get)
filename = inspect.getfile(class_info.type)

fail_message = (
f"class definition for {class_name!r} in file {filename!r} "
f"class definition for {class_info.name!r} in file {filename!r} "
f"must have defined a 'get' method with a return annotation of "
f"{obj_cls} but found {signature.return_annotation}\n"
f"Recommend adding the followinng method:\n"
f"def get(\n"
f" self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n"
f" ) -> {obj_cls.__name__}:\n"
f" return cast({obj_cls.__name__}, super().get(id=id, lazy=lazy, "
f"**kwargs))\n"
)
assert obj_cls == signature.return_annotation, fail_message
fail_message += method_template.format(obj_cls=obj_cls)
check_type = obj_cls
if optional_return:
check_type = Optional[obj_cls]
assert check_type == signature.return_annotation, fail_message

[8]ページ先頭

©2009-2025 Movatter.jp