Skip to content

Commit 608c937

Browse files
committed
feat(async): split edge postprocesses in v4 objects
Implement decorator that deals with possible awaitable object and run function that is passed as callback and return awaitable or data Decorate all edge cases with postprocessing in v4 objects with awaitable_postprocess
1 parent 52625a5 commit 608c937

File tree

2 files changed

+113
-47
lines changed

2 files changed

+113
-47
lines changed

gitlab/mixins.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@
2525
from gitlab import utils
2626

2727

28+
async def async_postprocess(self, awaitable, callback, *args, **kwargs):
29+
obj = await awaitable
30+
return callback(self, obj, *args, **kwargs)
31+
32+
33+
def awaitable_postprocess(f):
34+
@functools.wraps(f)
35+
def wrapped_f(self, obj, *args, **kwargs):
36+
if asyncio.iscoroutine(obj):
37+
return async_postprocess(self, obj, f, *args, **kwarsg)
38+
else:
39+
return f(self, obj, *args, **kwargs)
40+
41+
return wrapped_f
42+
43+
2844
def update_attrs(f):
2945
"""Update attrs with returned server_data
3046

gitlab/v4/objects.py

Lines changed: 97 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from gitlab.base import * # noqa
2424
from gitlab.exceptions import * # noqa
2525
from gitlab.mixins import * # noqa
26-
from gitlab.mixins import update_attrs
26+
from gitlab.mixins import awaitable_postprocess, update_attrs
2727

2828
VISIBILITY_PRIVATE = "private"
2929
VISIBILITY_INTERNAL = "internal"
@@ -1075,6 +1075,10 @@ class GroupMemberManager(CRUDMixin, RESTManager):
10751075
_create_attrs = (("access_level", "user_id"), ("expires_at",))
10761076
_update_attrs = (("access_level",), ("expires_at",))
10771077

1078+
@awaitable_postprocess
1079+
def _all_postprocess(self, sever_data):
1080+
return [self._obj_cls(self, item) for item in server_data]
1081+
10781082
@cli.register_custom_action("GroupMemberManager")
10791083
@exc.on_http_error(exc.GitlabListError)
10801084
def all(self, **kwargs):
@@ -1098,7 +1102,7 @@ def all(self, **kwargs):
10981102

10991103
path = "%s/all" % self.path
11001104
obj = self.gitlab.http_list(path, **kwargs)
1101-
return [self._obj_cls(self, item) for item in obj] # TODO???
1105+
return self._all_postprocess(obj)
11021106

11031107

11041108
class GroupMergeRequest(RESTObject):
@@ -1134,6 +1138,12 @@ class GroupMergeRequestManager(ListMixin, RESTManager):
11341138
class GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
11351139
_short_print_attr = "title"
11361140

1141+
@awaitable_postprocess
1142+
def _issues_postprocess(self, server_data):
1143+
manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent)
1144+
# FIXME(gpocentek): the computed manager path is not correct
1145+
return RESTObjectList(manager, GroupIssue, server_data)
1146+
11371147
@cli.register_custom_action("GroupMilestone")
11381148
@exc.on_http_error(exc.GitlabListError)
11391149
def issues(self, **kwargs):
@@ -1157,9 +1167,13 @@ def issues(self, **kwargs):
11571167

11581168
path = "%s/%s/issues" % (self.manager.path, self.get_id())
11591169
data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
1170+
return self._issues_postprocess(data_list)
1171+
1172+
@awaitable_postprocess
1173+
def _merge_requests_postprocess(self, server_data):
11601174
manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent)
11611175
# FIXME(gpocentek): the computed manager path is not correct
1162-
return RESTObjectList(manager, GroupIssue, data_list) # TODO: ???
1176+
return RESTObjectList(manager, GroupMergeRequest, server_data)
11631177

11641178
@cli.register_custom_action("GroupMilestone")
11651179
@exc.on_http_error(exc.GitlabListError)
@@ -1183,9 +1197,7 @@ def merge_requests(self, **kwargs):
11831197
"""
11841198
path = "%s/%s/merge_requests" % (self.manager.path, self.get_id())
11851199
data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
1186-
manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent)
1187-
# FIXME(gpocentek): the computed manager path is not correct
1188-
return RESTObjectList(manager, GroupMergeRequest, data_list) # TODO: ???
1200+
return self._merge_requests_postprocess(data_list)
11891201

11901202

11911203
class GroupMilestoneManager(CRUDMixin, RESTManager):
@@ -1466,6 +1478,13 @@ class LDAPGroupManager(RESTManager):
14661478
_obj_cls = LDAPGroup
14671479
_list_filters = ("search", "provider")
14681480

1481+
@awaitable_postprocess
1482+
def _list_postprocess(self, server_data):
1483+
if isinstance(obj, list):
1484+
return [self._obj_cls(self, item) for item in server_data]
1485+
else:
1486+
return base.RESTObjectList(self, self._obj_cls, server_data)
1487+
14691488
@exc.on_http_error(exc.GitlabListError)
14701489
def list(self, **kwargs):
14711490
"""Retrieve a list of objects.
@@ -1494,11 +1513,8 @@ def list(self, **kwargs):
14941513
else:
14951514
path = self._path
14961515

1497-
obj = self.gitlab.http_list(path, **data) # TODO: ???
1498-
if isinstance(obj, list):
1499-
return [self._obj_cls(self, item) for item in obj]
1500-
else:
1501-
return base.RESTObjectList(self, self._obj_cls, obj)
1516+
obj = self.gitlab.http_list(path, **data)
1517+
return self._list_postprocess(server_data)
15021518

15031519

15041520
class License(RESTObject):
@@ -2406,6 +2422,12 @@ class ProjectIssueLinkManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):
24062422
_from_parent_attrs = {"project_id": "project_id", "issue_iid": "iid"}
24072423
_create_attrs = (("target_project_id", "target_issue_iid"), tuple())
24082424

2425+
@awaitable_postprocess
2426+
def _create_postprocess(self, server_data):
2427+
source_issue = ProjectIssue(self._parent.manager, server_data["source_issue"])
2428+
target_issue = ProjectIssue(self._parent.manager, server_data["target_issue"])
2429+
return source_issue, target_issue
2430+
24092431
@exc.on_http_error(exc.GitlabCreateError)
24102432
def create(self, data, **kwargs):
24112433
"""Create a new object.
@@ -2424,9 +2446,7 @@ def create(self, data, **kwargs):
24242446
"""
24252447
self._check_missing_create_attrs(data)
24262448
server_data = self.gitlab.http_post(self.path, post_data=data, **kwargs)
2427-
source_issue = ProjectIssue(self._parent.manager, server_data["source_issue"])
2428-
target_issue = ProjectIssue(self._parent.manager, server_data["target_issue"])
2429-
return source_issue, target_issue # TODO: ???
2449+
return self._create_postprocess(server_data)
24302450

24312451

24322452
class ProjectIssueResourceLabelEvent(RESTObject):
@@ -2654,6 +2674,18 @@ class ProjectTag(ObjectDeleteMixin, RESTObject):
26542674
_id_attr = "name"
26552675
_short_print_attr = "name"
26562676

2677+
@exc.on_http_error(exc.GitlabCreateError)
2678+
def _create_release_description(self, path, data, **kwargs):
2679+
return self.manager.gitlab.http_post(path, post_data=data, **kwargs)
2680+
2681+
@exc.on_http_error(exc.GitlabUpdateError)
2682+
def _update_release_description(self, path, data, **kwargs):
2683+
return self.manager.gitlab.http_put(path, post_data=data, **kwargs)
2684+
2685+
@awaitable_postprocess
2686+
def _set_release_description_postprocess(self, server_data):
2687+
self.release = server_data
2688+
26572689
@cli.register_custom_action("ProjectTag", ("description",))
26582690
def set_release_description(self, description, **kwargs):
26592691
"""Set the release notes on the tag.
@@ -2674,20 +2706,10 @@ def set_release_description(self, description, **kwargs):
26742706
path = "%s/%s/release" % (self.manager.path, id)
26752707
data = {"description": description}
26762708
if self.release is None:
2677-
try:
2678-
server_data = self.manager.gitlab.http_post(
2679-
path, post_data=data, **kwargs
2680-
)
2681-
except exc.GitlabHttpError as e:
2682-
raise exc.GitlabCreateError(e.response_code, e.error_message)
2709+
server_data = self._create_release_description(path, data, **kwargs)
26832710
else:
2684-
try:
2685-
server_data = self.manager.gitlab.http_put(
2686-
path, post_data=data, **kwargs
2687-
)
2688-
except exc.GitlabHttpError as e:
2689-
raise exc.GitlabUpdateError(e.response_code, e.error_message)
2690-
self.release = server_data # TODO: ???
2711+
server_data = self._update_release_description(path, data, **kwargs)
2712+
return self._set_release_description_postprocess(server_data)
26912713

26922714

26932715
class ProjectTagManager(NoUpdateMixin, RESTManager):
@@ -2890,6 +2912,11 @@ def cancel_merge_when_pipeline_succeeds(self, **kwargs):
28902912
)
28912913
return self.manager.gitlab.http_put(path, **kwargs)
28922914

2915+
@awaitable_postprocess
2916+
def _close_issues_postprocess(self, data_list):
2917+
manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)
2918+
return RESTObjectList(manager, ProjectIssue, data_list)
2919+
28932920
@cli.register_custom_action("ProjectMergeRequest")
28942921
@exc.on_http_error(exc.GitlabListError)
28952922
def closes_issues(self, **kwargs):
@@ -2912,8 +2939,12 @@ def closes_issues(self, **kwargs):
29122939
"""
29132940
path = "%s/%s/closes_issues" % (self.manager.path, self.get_id())
29142941
data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
2915-
manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)
2916-
return RESTObjectList(manager, ProjectIssue, data_list) # TODO: ???
2942+
return self._close_issues_postprocess(data_list)
2943+
2944+
@awaitable_postprocess
2945+
def _commits_postprocess(self, data_list):
2946+
manager = ProjectCommitManager(self.manager.gitlab, parent=self.manager._parent)
2947+
return RESTObjectList(manager, ProjectCommit, data_list)
29172948

29182949
@cli.register_custom_action("ProjectMergeRequest")
29192950
@exc.on_http_error(exc.GitlabListError)
@@ -2938,8 +2969,7 @@ def commits(self, **kwargs):
29382969

29392970
path = "%s/%s/commits" % (self.manager.path, self.get_id())
29402971
data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
2941-
manager = ProjectCommitManager(self.manager.gitlab, parent=self.manager._parent)
2942-
return RESTObjectList(manager, ProjectCommit, data_list) # TODO: ???
2972+
return self._commits_postprocess(server_data)
29432973

29442974
@cli.register_custom_action("ProjectMergeRequest")
29452975
@exc.on_http_error(exc.GitlabListError)
@@ -3135,6 +3165,12 @@ class ProjectMergeRequestManager(CRUDMixin, RESTManager):
31353165
class ProjectMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
31363166
_short_print_attr = "title"
31373167

3168+
@awaitable_postprocess
3169+
def _issues_postprocess(self, data_list):
3170+
manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)
3171+
# FIXME(gpocentek): the computed manager path is not correct
3172+
return RESTObjectList(manager, ProjectIssue, data_list)
3173+
31383174
@cli.register_custom_action("ProjectMilestone")
31393175
@exc.on_http_error(exc.GitlabListError)
31403176
def issues(self, **kwargs):
@@ -3158,9 +3194,15 @@ def issues(self, **kwargs):
31583194

31593195
path = "%s/%s/issues" % (self.manager.path, self.get_id())
31603196
data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
3161-
manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)
3197+
return self._issues_postprocess(data_list)
3198+
3199+
@awaitable_postprocess
3200+
def _merge_requests_postprocess(self, data_list):
3201+
manager = ProjectMergeRequestManager(
3202+
self.manager.gitlab, parent=self.manager._parent
3203+
)
31623204
# FIXME(gpocentek): the computed manager path is not correct
3163-
return RESTObjectList(manager, ProjectIssue, data_list) # TODO: ???
3205+
return RESTObjectList(manager, ProjectMergeRequest, data_list)
31643206

31653207
@cli.register_custom_action("ProjectMilestone")
31663208
@exc.on_http_error(exc.GitlabListError)
@@ -3184,11 +3226,7 @@ def merge_requests(self, **kwargs):
31843226
"""
31853227
path = "%s/%s/merge_requests" % (self.manager.path, self.get_id())
31863228
data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
3187-
manager = ProjectMergeRequestManager(
3188-
self.manager.gitlab, parent=self.manager._parent
3189-
)
3190-
# FIXME(gpocentek): the computed manager path is not correct
3191-
return RESTObjectList(manager, ProjectMergeRequest, data_list) # TODO: ???
3229+
return self._merge_requests_postprocess(server_data)
31923230

31933231

31943232
class ProjectMilestoneManager(CRUDMixin, RESTManager):
@@ -3883,6 +3921,11 @@ class ProjectServiceManager(GetMixin, UpdateMixin, DeleteMixin, RESTManager):
38833921
"teamcity": (("teamcity_url", "build_type", "username", "password"), tuple()),
38843922
}
38853923

3924+
@awaitable_postprocess
3925+
def _get_postprocess(self, obj, id):
3926+
obj.id = id
3927+
return obj
3928+
38863929
def get(self, id, **kwargs):
38873930
"""Retrieve a single object.
38883931
@@ -3901,8 +3944,11 @@ def get(self, id, **kwargs):
39013944
GitlabGetError: If the server cannot perform the request
39023945
"""
39033946
obj = super(ProjectServiceManager, self).get(id, **kwargs)
3904-
obj.id = id
3905-
return obj # TODO: ???
3947+
return self._get_postprocess(obj, id)
3948+
3949+
@awaitable_postprocess
3950+
def _update_postprocess(self, server_data, id):
3951+
self.id = id
39063952

39073953
def update(self, id=None, new_data=None, **kwargs):
39083954
"""Update an object on the server.
@@ -3920,8 +3966,8 @@ def update(self, id=None, new_data=None, **kwargs):
39203966
GitlabUpdateError: If the server cannot perform the request
39213967
"""
39223968
new_data = new_data or {}
3923-
super(ProjectServiceManager, self).update(id, new_data, **kwargs)
3924-
self.id = id # TODO: ???
3969+
server_data = super(ProjectServiceManager, self).update(id, new_data, **kwargs)
3970+
return self._update_postprocess(server_data, id)
39253971

39263972
@cli.register_custom_action("ProjectServiceManager")
39273973
def available(self, **kwargs):
@@ -4557,6 +4603,14 @@ def housekeeping(self, **kwargs):
45574603
path = "/projects/%s/housekeeping" % self.get_id()
45584604
return self.manager.gitlab.http_post(path, **kwargs)
45594605

4606+
@awaitable_postprocess
4607+
def _upload_postprocess(self, sever_data):
4608+
return {
4609+
"alt": server_data["alt"],
4610+
"url": server_data["url"],
4611+
"markdown": server_data["markdown"],
4612+
}
4613+
45604614
# see #56 - add file attachment features
45614615
@cli.register_custom_action("Project", ("filename", "filepath"))
45624616
@exc.on_http_error(exc.GitlabUploadError)
@@ -4600,11 +4654,7 @@ def upload(self, filename, filedata=None, filepath=None, **kwargs):
46004654
file_info = {"file": (filename, filedata)}
46014655
data = self.manager.gitlab.http_post(url, files=file_info)
46024656

4603-
return {
4604-
"alt": data["alt"],
4605-
"url": data["url"],
4606-
"markdown": data["markdown"],
4607-
} # TODO: ???
4657+
return self._upload_post_process(data)
46084658

46094659
@cli.register_custom_action("Project", optional=("wiki",))
46104660
@exc.on_http_error(exc.GitlabGetError)

0 commit comments

Comments
 (0)