Skip to content

Commit 6b47c26

Browse files
nejchJohnVillalovos
authored andcommitted
feat: display human-readable attribute in repr() if present
1 parent 2373a4f commit 6b47c26

18 files changed

+85
-51
lines changed

gitlab/base.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,20 @@ class RESTObject:
4949
another. This allows smart updates, if the object allows it.
5050
5151
You can redefine ``_id_attr`` in child classes to specify which attribute
52-
must be used as uniq ID. ``None`` means that the object can be updated
52+
must be used as the unique ID. ``None`` means that the object can be updated
5353
without ID in the url.
54+
55+
Likewise, you can define a ``_repr_attr`` in subclasses to specify which
56+
attribute should be added as a human-readable identifier when called in the
57+
object's ``__repr__()`` method.
5458
"""
5559

5660
_id_attr: Optional[str] = "id"
5761
_attrs: Dict[str, Any]
5862
_created_from_list: bool # Indicates if object was created from a list() action
5963
_module: ModuleType
6064
_parent_attrs: Dict[str, Any]
61-
_short_print_attr: Optional[str] = None
65+
_repr_attr: Optional[str] = None
6266
_updated_attrs: Dict[str, Any]
6367
manager: "RESTManager"
6468

@@ -158,10 +162,19 @@ def pprint(self) -> None:
158162
print(self.pformat())
159163

160164
def __repr__(self) -> str:
165+
name = self.__class__.__name__
166+
167+
if (self._id_attr and self._repr_attr) and (self._id_attr != self._repr_attr):
168+
return (
169+
f"<{name} {self._id_attr}:{self.get_id()} "
170+
f"{self._repr_attr}:{getattr(self, self._repr_attr)}>"
171+
)
161172
if self._id_attr:
162-
return f"<{self.__class__.__name__} {self._id_attr}:{self.get_id()}>"
163-
else:
164-
return f"<{self.__class__.__name__}>"
173+
return f"<{name} {self._id_attr}:{self.get_id()}>"
174+
if self._repr_attr:
175+
return f"<{name} {self._repr_attr}:{getattr(self, self._repr_attr)}>"
176+
177+
return f"<{name}>"
165178

166179
def __eq__(self, other: object) -> bool:
167180
if not isinstance(other, RESTObject):

gitlab/v4/cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,12 +449,12 @@ def display_dict(d: Dict[str, Any], padding: int) -> None:
449449
if obj._id_attr:
450450
id = getattr(obj, obj._id_attr)
451451
print(f"{obj._id_attr.replace('_', '-')}: {id}")
452-
if obj._short_print_attr:
453-
value = getattr(obj, obj._short_print_attr) or "None"
452+
if obj._repr_attr:
453+
value = getattr(obj, obj._repr_attr, "None")
454454
value = value.replace("\r", "").replace("\n", " ")
455455
# If the attribute is a note (ProjectCommitComment) then we do
456456
# some modifications to fit everything on one line
457-
line = f"{obj._short_print_attr}: {value}"
457+
line = f"{obj._repr_attr}: {value}"
458458
# ellipsize long lines (comments)
459459
if len(line) > 79:
460460
line = f"{line[:76]}..."

gitlab/v4/objects/applications.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
class Application(ObjectDeleteMixin, RESTObject):
1111
_url = "/applications"
12-
_short_print_attr = "name"
12+
_repr_attr = "name"
1313

1414

1515
class ApplicationManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):

gitlab/v4/objects/commits.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222

2323
class ProjectCommit(RESTObject):
24-
_short_print_attr = "title"
24+
_repr_attr = "title"
2525

2626
comments: "ProjectCommitCommentManager"
2727
discussions: ProjectCommitDiscussionManager
@@ -172,7 +172,7 @@ def get(
172172

173173
class ProjectCommitComment(RESTObject):
174174
_id_attr = None
175-
_short_print_attr = "note"
175+
_repr_attr = "note"
176176

177177

178178
class ProjectCommitCommentManager(ListMixin, CreateMixin, RESTManager):

gitlab/v4/objects/events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
class Event(RESTObject):
3131
_id_attr = None
32-
_short_print_attr = "target_title"
32+
_repr_attr = "target_title"
3333

3434

3535
class EventManager(ListMixin, RESTManager):

gitlab/v4/objects/files.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
class ProjectFile(SaveMixin, ObjectDeleteMixin, RESTObject):
2626
_id_attr = "file_path"
27-
_short_print_attr = "file_path"
27+
_repr_attr = "file_path"
2828
file_path: str
2929
manager: "ProjectFileManager"
3030

gitlab/v4/objects/groups.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949

5050
class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
51-
_short_print_attr = "name"
51+
_repr_attr = "name"
5252

5353
access_tokens: GroupAccessTokenManager
5454
accessrequests: GroupAccessRequestManager

gitlab/v4/objects/hooks.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
class Hook(ObjectDeleteMixin, RESTObject):
1717
_url = "/hooks"
18-
_short_print_attr = "url"
18+
_repr_attr = "url"
1919

2020

2121
class HookManager(NoUpdateMixin, RESTManager):
@@ -28,7 +28,7 @@ def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Hook:
2828

2929

3030
class ProjectHook(SaveMixin, ObjectDeleteMixin, RESTObject):
31-
_short_print_attr = "url"
31+
_repr_attr = "url"
3232

3333

3434
class ProjectHookManager(CRUDMixin, RESTManager):
@@ -75,7 +75,7 @@ def get(
7575

7676

7777
class GroupHook(SaveMixin, ObjectDeleteMixin, RESTObject):
78-
_short_print_attr = "url"
78+
_repr_attr = "url"
7979

8080

8181
class GroupHookManager(CRUDMixin, RESTManager):

gitlab/v4/objects/issues.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
class Issue(RESTObject):
4444
_url = "/issues"
45-
_short_print_attr = "title"
45+
_repr_attr = "title"
4646

4747

4848
class IssueManager(RetrieveMixin, RESTManager):
@@ -108,7 +108,7 @@ class ProjectIssue(
108108
ObjectDeleteMixin,
109109
RESTObject,
110110
):
111-
_short_print_attr = "title"
111+
_repr_attr = "title"
112112
_id_attr = "iid"
113113

114114
awardemojis: ProjectIssueAwardEmojiManager

gitlab/v4/objects/members.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929

3030
class GroupMember(SaveMixin, ObjectDeleteMixin, RESTObject):
31-
_short_print_attr = "username"
31+
_repr_attr = "username"
3232

3333

3434
class GroupMemberManager(CRUDMixin, RESTManager):
@@ -50,7 +50,7 @@ def get(
5050

5151

5252
class GroupBillableMember(ObjectDeleteMixin, RESTObject):
53-
_short_print_attr = "username"
53+
_repr_attr = "username"
5454

5555
memberships: "GroupBillableMemberMembershipManager"
5656

@@ -73,7 +73,7 @@ class GroupBillableMemberMembershipManager(ListMixin, RESTManager):
7373

7474

7575
class GroupMemberAll(RESTObject):
76-
_short_print_attr = "username"
76+
_repr_attr = "username"
7777

7878

7979
class GroupMemberAllManager(RetrieveMixin, RESTManager):
@@ -88,7 +88,7 @@ def get(
8888

8989

9090
class ProjectMember(SaveMixin, ObjectDeleteMixin, RESTObject):
91-
_short_print_attr = "username"
91+
_repr_attr = "username"
9292

9393

9494
class ProjectMemberManager(CRUDMixin, RESTManager):
@@ -110,7 +110,7 @@ def get(
110110

111111

112112
class ProjectMemberAll(RESTObject):
113-
_short_print_attr = "username"
113+
_repr_attr = "username"
114114

115115

116116
class ProjectMemberAllManager(RetrieveMixin, RESTManager):

gitlab/v4/objects/merge_request_approvals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def set_approvers(
165165

166166
class ProjectMergeRequestApprovalRule(SaveMixin, ObjectDeleteMixin, RESTObject):
167167
_id_attr = "approval_rule_id"
168-
_short_print_attr = "approval_rule"
168+
_repr_attr = "approval_rule"
169169
id: int
170170

171171
@exc.on_http_error(exc.GitlabUpdateError)

gitlab/v4/objects/milestones.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323

2424
class GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
25-
_short_print_attr = "title"
25+
_repr_attr = "title"
2626

2727
@cli.register_custom_action("GroupMilestone")
2828
@exc.on_http_error(exc.GitlabListError)
@@ -102,7 +102,7 @@ def get(
102102

103103

104104
class ProjectMilestone(PromoteMixin, SaveMixin, ObjectDeleteMixin, RESTObject):
105-
_short_print_attr = "title"
105+
_repr_attr = "title"
106106
_update_uses_post = True
107107

108108
@cli.register_custom_action("ProjectMilestone")

gitlab/v4/objects/projects.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class ProjectGroupManager(ListMixin, RESTManager):
129129

130130

131131
class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTObject):
132-
_short_print_attr = "path"
132+
_repr_attr = "path"
133133

134134
access_tokens: ProjectAccessTokenManager
135135
accessrequests: ProjectAccessRequestManager
@@ -186,16 +186,6 @@ class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTO
186186
variables: ProjectVariableManager
187187
wikis: ProjectWikiManager
188188

189-
def __repr__(self) -> str:
190-
project_repr = super().__repr__()
191-
192-
if hasattr(self, "name_with_namespace"):
193-
return (
194-
f'{project_repr[:-1]} name_with_namespace:"{self.name_with_namespace}">'
195-
)
196-
else:
197-
return project_repr
198-
199189
@cli.register_custom_action("Project", ("forked_from_id",))
200190
@exc.on_http_error(exc.GitlabCreateError)
201191
def create_fork_relation(self, forked_from_id: int, **kwargs: Any) -> None:

gitlab/v4/objects/snippets.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222

2323
class Snippet(UserAgentDetailMixin, SaveMixin, ObjectDeleteMixin, RESTObject):
24-
_short_print_attr = "title"
24+
_repr_attr = "title"
2525

2626
@cli.register_custom_action("Snippet")
2727
@exc.on_http_error(exc.GitlabGetError)
@@ -91,7 +91,7 @@ def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Snippet
9191

9292
class ProjectSnippet(UserAgentDetailMixin, SaveMixin, ObjectDeleteMixin, RESTObject):
9393
_url = "/projects/{project_id}/snippets"
94-
_short_print_attr = "title"
94+
_repr_attr = "title"
9595

9696
awardemojis: ProjectSnippetAwardEmojiManager
9797
discussions: ProjectSnippetDiscussionManager

gitlab/v4/objects/tags.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
class ProjectTag(ObjectDeleteMixin, RESTObject):
1515
_id_attr = "name"
16-
_short_print_attr = "name"
16+
_repr_attr = "name"
1717

1818

1919
class ProjectTagManager(NoUpdateMixin, RESTManager):
@@ -30,7 +30,7 @@ def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Project
3030

3131
class ProjectProtectedTag(ObjectDeleteMixin, RESTObject):
3232
_id_attr = "name"
33-
_short_print_attr = "name"
33+
_repr_attr = "name"
3434

3535

3636
class ProjectProtectedTagManager(NoUpdateMixin, RESTManager):

gitlab/v4/objects/users.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666

6767

6868
class CurrentUserEmail(ObjectDeleteMixin, RESTObject):
69-
_short_print_attr = "email"
69+
_repr_attr = "email"
7070

7171

7272
class CurrentUserEmailManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager):
@@ -96,7 +96,7 @@ def get(
9696

9797

9898
class CurrentUserKey(ObjectDeleteMixin, RESTObject):
99-
_short_print_attr = "title"
99+
_repr_attr = "title"
100100

101101

102102
class CurrentUserKeyManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager):
@@ -112,7 +112,7 @@ def get(
112112

113113
class CurrentUserStatus(SaveMixin, RESTObject):
114114
_id_attr = None
115-
_short_print_attr = "message"
115+
_repr_attr = "message"
116116

117117

118118
class CurrentUserStatusManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
@@ -128,7 +128,7 @@ def get(
128128

129129
class CurrentUser(RESTObject):
130130
_id_attr = None
131-
_short_print_attr = "username"
131+
_repr_attr = "username"
132132

133133
emails: CurrentUserEmailManager
134134
gpgkeys: CurrentUserGPGKeyManager
@@ -147,7 +147,7 @@ def get(
147147

148148

149149
class User(SaveMixin, ObjectDeleteMixin, RESTObject):
150-
_short_print_attr = "username"
150+
_repr_attr = "username"
151151

152152
customattributes: UserCustomAttributeManager
153153
emails: "UserEmailManager"
@@ -373,7 +373,7 @@ class ProjectUserManager(ListMixin, RESTManager):
373373

374374

375375
class UserEmail(ObjectDeleteMixin, RESTObject):
376-
_short_print_attr = "email"
376+
_repr_attr = "email"
377377

378378

379379
class UserEmailManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager):
@@ -392,7 +392,7 @@ class UserActivities(RESTObject):
392392

393393
class UserStatus(RESTObject):
394394
_id_attr = None
395-
_short_print_attr = "message"
395+
_repr_attr = "message"
396396

397397

398398
class UserStatusManager(GetWithoutIdMixin, RESTManager):

gitlab/v4/objects/wikis.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
class ProjectWiki(SaveMixin, ObjectDeleteMixin, RESTObject):
1515
_id_attr = "slug"
16-
_short_print_attr = "slug"
16+
_repr_attr = "slug"
1717

1818

1919
class ProjectWikiManager(CRUDMixin, RESTManager):
@@ -34,7 +34,7 @@ def get(
3434

3535
class GroupWiki(SaveMixin, ObjectDeleteMixin, RESTObject):
3636
_id_attr = "slug"
37-
_short_print_attr = "slug"
37+
_repr_attr = "slug"
3838

3939

4040
class GroupWikiManager(CRUDMixin, RESTManager):

0 commit comments

Comments
 (0)