Skip to content

Commit aee1f49

Browse files
JohnVillalovosnejch
authored andcommitted
chore: have _create_attrs & _update_attrs be a namedtuple
Convert _create_attrs and _update_attrs to use a NamedTuple (RequiredOptional) to help with code readability. Update all code to use the NamedTuple.
1 parent 8603248 commit aee1f49

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+362
-286
lines changed

gitlab/base.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@
1717

1818
import importlib
1919
from types import ModuleType
20-
from typing import Any, Dict, Optional, Tuple, Type
20+
from typing import Any, Dict, NamedTuple, Optional, Tuple, Type
2121

2222
from .client import Gitlab, GitlabList
2323
from gitlab import types as g_types
2424

2525
__all__ = [
26+
"RequiredOptional",
2627
"RESTObject",
2728
"RESTObjectList",
2829
"RESTManager",
@@ -249,6 +250,11 @@ def total(self) -> int:
249250
return self._list.total
250251

251252

253+
class RequiredOptional(NamedTuple):
254+
required: Tuple[str, ...] = tuple()
255+
optional: Tuple[str, ...] = tuple()
256+
257+
252258
class RESTManager(object):
253259
"""Base class for CRUD operations on objects.
254260
@@ -258,8 +264,8 @@ class RESTManager(object):
258264
``_obj_cls``: The class of objects that will be created
259265
"""
260266

261-
_create_attrs: Tuple[Tuple[str, ...], Tuple[str, ...]] = (tuple(), tuple())
262-
_update_attrs: Tuple[Tuple[str, ...], Tuple[str, ...]] = (tuple(), tuple())
267+
_create_attrs: RequiredOptional = RequiredOptional()
268+
_update_attrs: RequiredOptional = RequiredOptional()
263269
_path: Optional[str] = None
264270
_obj_cls: Optional[Type[RESTObject]] = None
265271
_from_parent_attrs: Dict[str, Any] = {}

gitlab/mixins.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ class CreateMixin(_RestManagerBase):
267267

268268
def _check_missing_create_attrs(self, data: Dict[str, Any]) -> None:
269269
missing = []
270-
for attr in self._create_attrs[0]:
270+
for attr in self._create_attrs.required:
271271
if attr not in data:
272272
missing.append(attr)
273273
continue
@@ -339,7 +339,7 @@ def _check_missing_update_attrs(self, data: Dict[str, Any]) -> None:
339339
# Remove the id field from the required list as it was previously moved
340340
# to the http path.
341341
required = tuple(
342-
[k for k in self._update_attrs[0] if k != self._obj_cls._id_attr]
342+
[k for k in self._update_attrs.required if k != self._obj_cls._id_attr]
343343
)
344344
missing = []
345345
for attr in required:
@@ -518,7 +518,7 @@ class SaveMixin(_RestObjectBase):
518518

519519
def _get_updated_data(self) -> Dict[str, Any]:
520520
updated_data = {}
521-
for attr in self.manager._update_attrs[0]:
521+
for attr in self.manager._update_attrs.required:
522522
# Get everything required, no matter if it's been updated
523523
updated_data[attr] = getattr(self, attr)
524524
# Add the updated attributes

gitlab/tests/mixins/test_mixin_methods.py

+22-10
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ def resp_cont(url, request):
131131

132132
def test_create_mixin_missing_attrs(gl):
133133
class M(CreateMixin, FakeManager):
134-
_create_attrs = (("foo",), ("bar", "baz"))
134+
_create_attrs = base.RequiredOptional(
135+
required=("foo",), optional=("bar", "baz")
136+
)
135137

136138
mgr = M(gl)
137139
data = {"foo": "bar", "baz": "blah"}
@@ -145,8 +147,10 @@ class M(CreateMixin, FakeManager):
145147

146148
def test_create_mixin(gl):
147149
class M(CreateMixin, FakeManager):
148-
_create_attrs = (("foo",), ("bar", "baz"))
149-
_update_attrs = (("foo",), ("bam",))
150+
_create_attrs = base.RequiredOptional(
151+
required=("foo",), optional=("bar", "baz")
152+
)
153+
_update_attrs = base.RequiredOptional(required=("foo",), optional=("bam",))
150154

151155
@urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests", method="post")
152156
def resp_cont(url, request):
@@ -164,8 +168,10 @@ def resp_cont(url, request):
164168

165169
def test_create_mixin_custom_path(gl):
166170
class M(CreateMixin, FakeManager):
167-
_create_attrs = (("foo",), ("bar", "baz"))
168-
_update_attrs = (("foo",), ("bam",))
171+
_create_attrs = base.RequiredOptional(
172+
required=("foo",), optional=("bar", "baz")
173+
)
174+
_update_attrs = base.RequiredOptional(required=("foo",), optional=("bam",))
169175

170176
@urlmatch(scheme="http", netloc="localhost", path="/api/v4/others", method="post")
171177
def resp_cont(url, request):
@@ -183,7 +189,9 @@ def resp_cont(url, request):
183189

184190
def test_update_mixin_missing_attrs(gl):
185191
class M(UpdateMixin, FakeManager):
186-
_update_attrs = (("foo",), ("bar", "baz"))
192+
_update_attrs = base.RequiredOptional(
193+
required=("foo",), optional=("bar", "baz")
194+
)
187195

188196
mgr = M(gl)
189197
data = {"foo": "bar", "baz": "blah"}
@@ -197,8 +205,10 @@ class M(UpdateMixin, FakeManager):
197205

198206
def test_update_mixin(gl):
199207
class M(UpdateMixin, FakeManager):
200-
_create_attrs = (("foo",), ("bar", "baz"))
201-
_update_attrs = (("foo",), ("bam",))
208+
_create_attrs = base.RequiredOptional(
209+
required=("foo",), optional=("bar", "baz")
210+
)
211+
_update_attrs = base.RequiredOptional(required=("foo",), optional=("bam",))
202212

203213
@urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests/42", method="put")
204214
def resp_cont(url, request):
@@ -216,8 +226,10 @@ def resp_cont(url, request):
216226

217227
def test_update_mixin_no_id(gl):
218228
class M(UpdateMixin, FakeManager):
219-
_create_attrs = (("foo",), ("bar", "baz"))
220-
_update_attrs = (("foo",), ("bam",))
229+
_create_attrs = base.RequiredOptional(
230+
required=("foo",), optional=("bar", "baz")
231+
)
232+
_update_attrs = base.RequiredOptional(required=("foo",), optional=("bam",))
221233

222234
@urlmatch(scheme="http", netloc="localhost", path="/api/v4/tests", method="put")
223235
def resp_cont(url, request):

gitlab/v4/cli.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ def _populate_sub_parser_by_class(cls, sub_parser):
177177
]
178178

179179
if action_name == "create":
180-
for x in mgr_cls._create_attrs[0]:
180+
for x in mgr_cls._create_attrs.required:
181181
sub_parser_action.add_argument(
182182
"--%s" % x.replace("_", "-"), required=True
183183
)
184-
for x in mgr_cls._create_attrs[1]:
184+
for x in mgr_cls._create_attrs.optional:
185185
sub_parser_action.add_argument(
186186
"--%s" % x.replace("_", "-"), required=False
187187
)
@@ -191,13 +191,13 @@ def _populate_sub_parser_by_class(cls, sub_parser):
191191
id_attr = cls._id_attr.replace("_", "-")
192192
sub_parser_action.add_argument("--%s" % id_attr, required=True)
193193

194-
for x in mgr_cls._update_attrs[0]:
194+
for x in mgr_cls._update_attrs.required:
195195
if x != cls._id_attr:
196196
sub_parser_action.add_argument(
197197
"--%s" % x.replace("_", "-"), required=True
198198
)
199199

200-
for x in mgr_cls._update_attrs[1]:
200+
for x in mgr_cls._update_attrs.optional:
201201
if x != cls._id_attr:
202202
sub_parser_action.add_argument(
203203
"--%s" % x.replace("_", "-"), required=False

gitlab/v4/objects/appearance.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from gitlab import exceptions as exc
2-
from gitlab.base import RESTManager, RESTObject
2+
from gitlab.base import RequiredOptional, RESTManager, RESTObject
33
from gitlab.mixins import GetWithoutIdMixin, SaveMixin, UpdateMixin
44

55

@@ -16,9 +16,8 @@ class ApplicationAppearance(SaveMixin, RESTObject):
1616
class ApplicationAppearanceManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
1717
_path = "/application/appearance"
1818
_obj_cls = ApplicationAppearance
19-
_update_attrs = (
20-
tuple(),
21-
(
19+
_update_attrs = RequiredOptional(
20+
optional=(
2221
"title",
2322
"description",
2423
"logo",

gitlab/v4/objects/applications.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from gitlab.base import RESTManager, RESTObject
1+
from gitlab.base import RequiredOptional, RESTManager, RESTObject
22
from gitlab.mixins import CreateMixin, DeleteMixin, ListMixin, ObjectDeleteMixin
33

44
__all__ = [
@@ -15,4 +15,6 @@ class Application(ObjectDeleteMixin, RESTObject):
1515
class ApplicationManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):
1616
_path = "/applications"
1717
_obj_cls = Application
18-
_create_attrs = (("name", "redirect_uri", "scopes"), ("confidential",))
18+
_create_attrs = RequiredOptional(
19+
required=("name", "redirect_uri", "scopes"), optional=("confidential",)
20+
)

gitlab/v4/objects/award_emojis.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from gitlab.base import RESTManager, RESTObject
1+
from gitlab.base import RequiredOptional, RESTManager, RESTObject
22
from gitlab.mixins import NoUpdateMixin, ObjectDeleteMixin
33

44

@@ -26,7 +26,7 @@ class ProjectIssueAwardEmojiManager(NoUpdateMixin, RESTManager):
2626
_path = "/projects/%(project_id)s/issues/%(issue_iid)s/award_emoji"
2727
_obj_cls = ProjectIssueAwardEmoji
2828
_from_parent_attrs = {"project_id": "project_id", "issue_iid": "iid"}
29-
_create_attrs = (("name",), tuple())
29+
_create_attrs = RequiredOptional(required=("name",))
3030

3131

3232
class ProjectIssueNoteAwardEmoji(ObjectDeleteMixin, RESTObject):
@@ -43,7 +43,7 @@ class ProjectIssueNoteAwardEmojiManager(NoUpdateMixin, RESTManager):
4343
"issue_iid": "issue_iid",
4444
"note_id": "id",
4545
}
46-
_create_attrs = (("name",), tuple())
46+
_create_attrs = RequiredOptional(required=("name",))
4747

4848

4949
class ProjectMergeRequestAwardEmoji(ObjectDeleteMixin, RESTObject):
@@ -54,7 +54,7 @@ class ProjectMergeRequestAwardEmojiManager(NoUpdateMixin, RESTManager):
5454
_path = "/projects/%(project_id)s/merge_requests/%(mr_iid)s/award_emoji"
5555
_obj_cls = ProjectMergeRequestAwardEmoji
5656
_from_parent_attrs = {"project_id": "project_id", "mr_iid": "iid"}
57-
_create_attrs = (("name",), tuple())
57+
_create_attrs = RequiredOptional(required=("name",))
5858

5959

6060
class ProjectMergeRequestNoteAwardEmoji(ObjectDeleteMixin, RESTObject):
@@ -72,7 +72,7 @@ class ProjectMergeRequestNoteAwardEmojiManager(NoUpdateMixin, RESTManager):
7272
"mr_iid": "mr_iid",
7373
"note_id": "id",
7474
}
75-
_create_attrs = (("name",), tuple())
75+
_create_attrs = RequiredOptional(required=("name",))
7676

7777

7878
class ProjectSnippetAwardEmoji(ObjectDeleteMixin, RESTObject):
@@ -83,7 +83,7 @@ class ProjectSnippetAwardEmojiManager(NoUpdateMixin, RESTManager):
8383
_path = "/projects/%(project_id)s/snippets/%(snippet_id)s/award_emoji"
8484
_obj_cls = ProjectSnippetAwardEmoji
8585
_from_parent_attrs = {"project_id": "project_id", "snippet_id": "id"}
86-
_create_attrs = (("name",), tuple())
86+
_create_attrs = RequiredOptional(required=("name",))
8787

8888

8989
class ProjectSnippetNoteAwardEmoji(ObjectDeleteMixin, RESTObject):
@@ -101,4 +101,4 @@ class ProjectSnippetNoteAwardEmojiManager(NoUpdateMixin, RESTManager):
101101
"snippet_id": "snippet_id",
102102
"note_id": "id",
103103
}
104-
_create_attrs = (("name",), tuple())
104+
_create_attrs = RequiredOptional(required=("name",))

gitlab/v4/objects/badges.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from gitlab.base import RESTManager, RESTObject
1+
from gitlab.base import RequiredOptional, RESTManager, RESTObject
22
from gitlab.mixins import BadgeRenderMixin, CRUDMixin, ObjectDeleteMixin, SaveMixin
33

44

@@ -18,8 +18,8 @@ class GroupBadgeManager(BadgeRenderMixin, CRUDMixin, RESTManager):
1818
_path = "/groups/%(group_id)s/badges"
1919
_obj_cls = GroupBadge
2020
_from_parent_attrs = {"group_id": "id"}
21-
_create_attrs = (("link_url", "image_url"), tuple())
22-
_update_attrs = (tuple(), ("link_url", "image_url"))
21+
_create_attrs = RequiredOptional(required=("link_url", "image_url"))
22+
_update_attrs = RequiredOptional(optional=("link_url", "image_url"))
2323

2424

2525
class ProjectBadge(SaveMixin, ObjectDeleteMixin, RESTObject):
@@ -30,5 +30,5 @@ class ProjectBadgeManager(BadgeRenderMixin, CRUDMixin, RESTManager):
3030
_path = "/projects/%(project_id)s/badges"
3131
_obj_cls = ProjectBadge
3232
_from_parent_attrs = {"project_id": "id"}
33-
_create_attrs = (("link_url", "image_url"), tuple())
34-
_update_attrs = (tuple(), ("link_url", "image_url"))
33+
_create_attrs = RequiredOptional(required=("link_url", "image_url"))
34+
_update_attrs = RequiredOptional(optional=("link_url", "image_url"))

gitlab/v4/objects/boards.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from gitlab.base import RESTManager, RESTObject
1+
from gitlab.base import RequiredOptional, RESTManager, RESTObject
22
from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin
33

44

@@ -22,8 +22,8 @@ class GroupBoardListManager(CRUDMixin, RESTManager):
2222
_path = "/groups/%(group_id)s/boards/%(board_id)s/lists"
2323
_obj_cls = GroupBoardList
2424
_from_parent_attrs = {"group_id": "group_id", "board_id": "id"}
25-
_create_attrs = (("label_id",), tuple())
26-
_update_attrs = (("position",), tuple())
25+
_create_attrs = RequiredOptional(required=("label_id",))
26+
_update_attrs = RequiredOptional(required=("position",))
2727

2828

2929
class GroupBoard(SaveMixin, ObjectDeleteMixin, RESTObject):
@@ -34,7 +34,7 @@ class GroupBoardManager(CRUDMixin, RESTManager):
3434
_path = "/groups/%(group_id)s/boards"
3535
_obj_cls = GroupBoard
3636
_from_parent_attrs = {"group_id": "id"}
37-
_create_attrs = (("name",), tuple())
37+
_create_attrs = RequiredOptional(required=("name",))
3838

3939

4040
class ProjectBoardList(SaveMixin, ObjectDeleteMixin, RESTObject):
@@ -45,8 +45,8 @@ class ProjectBoardListManager(CRUDMixin, RESTManager):
4545
_path = "/projects/%(project_id)s/boards/%(board_id)s/lists"
4646
_obj_cls = ProjectBoardList
4747
_from_parent_attrs = {"project_id": "project_id", "board_id": "id"}
48-
_create_attrs = (("label_id",), tuple())
49-
_update_attrs = (("position",), tuple())
48+
_create_attrs = RequiredOptional(required=("label_id",))
49+
_update_attrs = RequiredOptional(required=("position",))
5050

5151

5252
class ProjectBoard(SaveMixin, ObjectDeleteMixin, RESTObject):
@@ -57,4 +57,4 @@ class ProjectBoardManager(CRUDMixin, RESTManager):
5757
_path = "/projects/%(project_id)s/boards"
5858
_obj_cls = ProjectBoard
5959
_from_parent_attrs = {"project_id": "id"}
60-
_create_attrs = (("name",), tuple())
60+
_create_attrs = RequiredOptional(required=("name",))

gitlab/v4/objects/branches.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from gitlab import cli
22
from gitlab import exceptions as exc
3-
from gitlab.base import RESTManager, RESTObject
3+
from gitlab.base import RequiredOptional, RESTManager, RESTObject
44
from gitlab.mixins import NoUpdateMixin, ObjectDeleteMixin
55

66

@@ -64,7 +64,7 @@ class ProjectBranchManager(NoUpdateMixin, RESTManager):
6464
_path = "/projects/%(project_id)s/repository/branches"
6565
_obj_cls = ProjectBranch
6666
_from_parent_attrs = {"project_id": "id"}
67-
_create_attrs = (("branch", "ref"), tuple())
67+
_create_attrs = RequiredOptional(required=("branch", "ref"))
6868

6969

7070
class ProjectProtectedBranch(ObjectDeleteMixin, RESTObject):
@@ -75,9 +75,9 @@ class ProjectProtectedBranchManager(NoUpdateMixin, RESTManager):
7575
_path = "/projects/%(project_id)s/protected_branches"
7676
_obj_cls = ProjectProtectedBranch
7777
_from_parent_attrs = {"project_id": "id"}
78-
_create_attrs = (
79-
("name",),
80-
(
78+
_create_attrs = RequiredOptional(
79+
required=("name",),
80+
optional=(
8181
"push_access_level",
8282
"merge_access_level",
8383
"unprotect_access_level",

gitlab/v4/objects/broadcast_messages.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from gitlab.base import RESTManager, RESTObject
1+
from gitlab.base import RequiredOptional, RESTManager, RESTObject
22
from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin
33

44

@@ -16,5 +16,9 @@ class BroadcastMessageManager(CRUDMixin, RESTManager):
1616
_path = "/broadcast_messages"
1717
_obj_cls = BroadcastMessage
1818

19-
_create_attrs = (("message",), ("starts_at", "ends_at", "color", "font"))
20-
_update_attrs = (tuple(), ("message", "starts_at", "ends_at", "color", "font"))
19+
_create_attrs = RequiredOptional(
20+
required=("message",), optional=("starts_at", "ends_at", "color", "font")
21+
)
22+
_update_attrs = RequiredOptional(
23+
optional=("message", "starts_at", "ends_at", "color", "font")
24+
)

0 commit comments

Comments
 (0)