Skip to content

Commit 184b94b

Browse files
Merge pull request #1456 from python-gitlab/feat/billable-members
feat(objects): add support for billable members
2 parents 7824811 + fb0b083 commit 184b94b

File tree

4 files changed

+111
-2
lines changed

4 files changed

+111
-2
lines changed

docs/gl_objects/groups.rst

+19-1
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,15 @@ Reference
226226
+ :class:`gitlab.v4.objects.GroupMember`
227227
+ :class:`gitlab.v4.objects.GroupMemberManager`
228228
+ :class:`gitlab.v4.objects.GroupMemberAllManager`
229+
+ :class:`gitlab.v4.objects.GroupBillableMember`
230+
+ :class:`gitlab.v4.objects.GroupBillableMemberManager`
229231
+ :attr:`gitlab.v4.objects.Group.members`
230232
+ :attr:`gitlab.v4.objects.Group.members_all`
233+
+ :attr:`gitlab.v4.objects.Group.billable_members`
231234

232-
* GitLab API: https://docs.gitlab.com/ce/api/groups.html
235+
* GitLab API: https://docs.gitlab.com/ce/api/members.html
233236

237+
Billable group members are only available in GitLab EE.
234238

235239
Examples
236240
--------
@@ -270,6 +274,20 @@ Remove a member from the group::
270274
# or
271275
member.delete()
272276

277+
List billable members of a group (top-level groups only)::
278+
279+
billable_members = group.billable_members.list()
280+
281+
Remove a billable member from the group::
282+
283+
group.billable_members.delete(member_id)
284+
# or
285+
billable_member.delete()
286+
287+
List memberships of a billable member::
288+
289+
billable_member.memberships.list()
290+
273291
LDAP group links
274292
================
275293

gitlab/tests/objects/test_members.py

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""
2+
GitLab API: https://docs.gitlab.com/ee/api/members.html
3+
"""
4+
import pytest
5+
import responses
6+
7+
from gitlab.v4.objects import GroupBillableMember
8+
9+
billable_members_content = [
10+
{
11+
"id": 1,
12+
"username": "raymond_smith",
13+
"name": "Raymond Smith",
14+
"state": "active",
15+
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
16+
"web_url": "http://192.168.1.8:3000/root",
17+
"last_activity_on": "2021-01-27",
18+
"membership_type": "group_member",
19+
"removable": True,
20+
}
21+
]
22+
23+
24+
@pytest.fixture
25+
def resp_list_billable_group_members():
26+
with responses.RequestsMock() as rsps:
27+
rsps.add(
28+
method=responses.GET,
29+
url="http://localhost/api/v4/groups/1/billable_members",
30+
json=billable_members_content,
31+
content_type="application/json",
32+
status=200,
33+
)
34+
yield rsps
35+
36+
37+
@pytest.fixture
38+
def resp_delete_billable_group_member(no_content):
39+
with responses.RequestsMock() as rsps:
40+
rsps.add(
41+
method=responses.DELETE,
42+
url="http://localhost/api/v4/groups/1/billable_members/1",
43+
json=no_content,
44+
content_type="application/json",
45+
status=204,
46+
)
47+
yield rsps
48+
49+
50+
def test_list_group_billable_members(group, resp_list_billable_group_members):
51+
billable_members = group.billable_members.list()
52+
assert isinstance(billable_members, list)
53+
assert isinstance(billable_members[0], GroupBillableMember)
54+
assert billable_members[0].removable is True
55+
56+
57+
def test_delete_group_billable_member(group, resp_delete_billable_group_member):
58+
group.billable_members.delete(1)

gitlab/v4/objects/groups.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
from .export_import import GroupExportManager, GroupImportManager # noqa: F401
1616
from .issues import GroupIssueManager # noqa: F401
1717
from .labels import GroupLabelManager # noqa: F401
18-
from .members import GroupMemberAllManager, GroupMemberManager # noqa: F401
18+
from .members import ( # noqa: F401
19+
GroupBillableMemberManager,
20+
GroupMemberAllManager,
21+
GroupMemberManager,
22+
)
1923
from .merge_requests import GroupMergeRequestManager # noqa: F401
2024
from .milestones import GroupMilestoneManager # noqa: F401
2125
from .notification_settings import GroupNotificationSettingsManager # noqa: F401
@@ -38,6 +42,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
3842
("accessrequests", "GroupAccessRequestManager"),
3943
("audit_events", "GroupAuditEventManager"),
4044
("badges", "GroupBadgeManager"),
45+
("billable_members", "GroupBillableMemberManager"),
4146
("boards", "GroupBoardManager"),
4247
("customattributes", "GroupCustomAttributeManager"),
4348
("exports", "GroupExportManager"),

gitlab/v4/objects/members.py

+28
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22
from gitlab.base import RequiredOptional, RESTManager, RESTObject
33
from gitlab.mixins import (
44
CRUDMixin,
5+
DeleteMixin,
6+
ListMixin,
57
MemberAllMixin,
68
ObjectDeleteMixin,
79
RetrieveMixin,
810
SaveMixin,
911
)
1012

1113
__all__ = [
14+
"GroupBillableMember",
15+
"GroupBillableMemberManager",
16+
"GroupBillableMemberMembership",
17+
"GroupBillableMemberMembershipManager",
1218
"GroupMember",
1319
"GroupMemberManager",
1420
"GroupMemberAllManager",
@@ -35,6 +41,28 @@ class GroupMemberManager(MemberAllMixin, CRUDMixin, RESTManager):
3541
_types = {"user_ids": types.ListAttribute}
3642

3743

44+
class GroupBillableMember(ObjectDeleteMixin, RESTObject):
45+
_short_print_attr = "username"
46+
_managers = (("memberships", "GroupBillableMemberMembershipManager"),)
47+
48+
49+
class GroupBillableMemberManager(ListMixin, DeleteMixin, RESTManager):
50+
_path = "/groups/%(group_id)s/billable_members"
51+
_obj_cls = GroupBillableMember
52+
_from_parent_attrs = {"group_id": "id"}
53+
_list_filters = ("search", "sort")
54+
55+
56+
class GroupBillableMemberMembership(RESTObject):
57+
_id_attr = "user_id"
58+
59+
60+
class GroupBillableMemberMembershipManager(ListMixin, RESTManager):
61+
_path = "/groups/%(group_id)s/billable_members/%(user_id)s/memberships"
62+
_obj_cls = GroupBillableMemberMembership
63+
_from_parent_attrs = {"group_id": "group_id", "user_id": "id"}
64+
65+
3866
class GroupMemberAllManager(RetrieveMixin, RESTManager):
3967
_path = "/groups/%(group_id)s/members/all"
4068
_obj_cls = GroupMember

0 commit comments

Comments
 (0)