Skip to content

Commit e444b39

Browse files
Oleksii Shkurupiinejch
authored andcommitted
feat: add feature to get inherited member for project/group
1 parent 0d3b8ae commit e444b39

File tree

7 files changed

+97
-62
lines changed

7 files changed

+97
-62
lines changed

docs/gl_objects/groups.rst

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,27 +225,35 @@ Reference
225225

226226
+ :class:`gitlab.v4.objects.GroupMember`
227227
+ :class:`gitlab.v4.objects.GroupMemberManager`
228+
+ :class:`gitlab.v4.objects.GroupMemberAllManager`
228229
+ :attr:`gitlab.v4.objects.Group.members`
230+
+ :attr:`gitlab.v4.objects.Group.members_all`
229231

230232
* GitLab API: https://docs.gitlab.com/ce/api/groups.html
231233

232234

233235
Examples
234236
--------
235237

236-
List group members::
238+
List only direct group members::
237239

238240
members = group.members.list()
239241

240242
List the group members recursively (including inherited members through
241243
ancestor groups)::
242244

243-
members = group.members.all(all=True)
245+
members = group.members_all.list(all=True)
246+
# or
247+
members = group.members.all(all=True) # Deprecated
244248

245-
Get a group member::
249+
Get only direct group member::
246250

247251
members = group.members.get(member_id)
248252

253+
Get a member of a group, including members inherited through ancestor groups::
254+
255+
members = group.members_all.get(member_id)
256+
249257
Add a member to the group::
250258

251259
member = group.members.create({'user_id': user_id,

docs/gl_objects/projects.rst

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,30 +502,39 @@ Reference
502502

503503
+ :class:`gitlab.v4.objects.ProjectMember`
504504
+ :class:`gitlab.v4.objects.ProjectMemberManager`
505+
+ :class:`gitlab.v4.objects.ProjectMemberAllManager`
505506
+ :attr:`gitlab.v4.objects.Project.members`
507+
+ :attr:`gitlab.v4.objects.Project.members_all`
506508

507509
* GitLab API: https://docs.gitlab.com/ce/api/members.html
508510

509511
Examples
510512
--------
511513

512-
List the project members::
514+
List only direct project members::
513515

514516
members = project.members.list()
515517

516518
List the project members recursively (including inherited members through
517519
ancestor groups)::
518520

519-
members = project.members.all(all=True)
521+
members = project.members_all.list(all=True)
522+
# or
523+
members = project.members.all(all=True) # Deprecated
520524

521525
Search project members matching a query string::
522526

523527
members = project.members.list(query='bar')
524528

525-
Get a single project member::
529+
Get only direct project member::
526530

527531
member = project.members.get(user_id)
528532

533+
Get a member of a project, including members inherited through ancestor groups::
534+
535+
members = project.members_all.get(member_id)
536+
537+
529538
Add a project member::
530539

531540
member = project.members.create({'user_id': user.id, 'access_level':

gitlab/mixins.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
from gitlab import exceptions as exc
3737
from gitlab import types as g_types
3838
from gitlab import utils
39-
39+
import warnings
4040

4141
__all__ = [
4242
"GetMixin",
@@ -928,3 +928,50 @@ def render(self, link_url: str, image_url: str, **kwargs: Any) -> Dict[str, Any]
928928
if TYPE_CHECKING:
929929
assert not isinstance(result, requests.Response)
930930
return result
931+
932+
933+
class MemberAllMixin(_RestManagerBase):
934+
"""This mixin is deprecated."""
935+
936+
_computed_path: Optional[str]
937+
_from_parent_attrs: Dict[str, Any]
938+
_obj_cls: Optional[Type[base.RESTObject]]
939+
_parent: Optional[base.RESTObject]
940+
_parent_attrs: Dict[str, Any]
941+
_path: Optional[str]
942+
gitlab: gitlab.Gitlab
943+
944+
@cli.register_custom_action(("GroupMemberManager", "ProjectMemberManager"))
945+
@exc.on_http_error(exc.GitlabListError)
946+
def all(self, **kwargs: Any) -> List[base.RESTObject]:
947+
"""List all the members, included inherited ones.
948+
949+
This Method is deprecated.
950+
951+
Args:
952+
all (bool): If True, return all the items, without pagination
953+
per_page (int): Number of items to retrieve per request
954+
page (int): ID of the page to return (starts with page 1)
955+
as_list (bool): If set to False and no pagination option is
956+
defined, return a generator instead of a list
957+
**kwargs: Extra options to send to the server (e.g. sudo)
958+
959+
Raises:
960+
GitlabAuthenticationError: If authentication is not correct
961+
GitlabListError: If the list could not be retrieved
962+
963+
Returns:
964+
RESTObjectList: The list of members
965+
"""
966+
967+
warnings.warn(
968+
"The all() method for this object is deprecated "
969+
"and will be removed in a future version.",
970+
DeprecationWarning,
971+
)
972+
path = "%s/all" % self.path
973+
974+
if TYPE_CHECKING:
975+
assert self._obj_cls is not None
976+
obj = self.gitlab.http_list(path, **kwargs)
977+
return [self._obj_cls(self, item) for item in obj]

gitlab/v4/objects/groups.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from .epics import GroupEpicManager # noqa: F401
1212
from .issues import GroupIssueManager # noqa: F401
1313
from .labels import GroupLabelManager # noqa: F401
14-
from .members import GroupMemberManager # noqa: F401
14+
from .members import GroupMemberManager, GroupMemberAllManager # noqa: F401
1515
from .merge_requests import GroupMergeRequestManager # noqa: F401
1616
from .milestones import GroupMilestoneManager # noqa: F401
1717
from .notification_settings import GroupNotificationSettingsManager # noqa: F401
@@ -45,6 +45,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
4545
("issues", "GroupIssueManager"),
4646
("labels", "GroupLabelManager"),
4747
("members", "GroupMemberManager"),
48+
("members_all", "GroupMemberAllManager"),
4849
("mergerequests", "GroupMergeRequestManager"),
4950
("milestones", "GroupMilestoneManager"),
5051
("notificationsettings", "GroupNotificationSettingsManager"),

gitlab/v4/objects/members.py

Lines changed: 20 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
1-
from gitlab import cli, types
2-
from gitlab import exceptions as exc
1+
from gitlab import types
32
from gitlab.base import RequiredOptional, RESTManager, RESTObject
4-
from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin
5-
3+
from gitlab.mixins import (
4+
CRUDMixin,
5+
ObjectDeleteMixin,
6+
SaveMixin,
7+
RetrieveMixin,
8+
MemberAllMixin,
9+
)
610

711
__all__ = [
812
"GroupMember",
913
"GroupMemberManager",
14+
"GroupMemberAllManager",
1015
"ProjectMember",
1116
"ProjectMemberManager",
17+
"ProjectMemberAllManager",
1218
]
1319

1420

1521
class GroupMember(SaveMixin, ObjectDeleteMixin, RESTObject):
1622
_short_print_attr = "username"
1723

1824

19-
class GroupMemberManager(CRUDMixin, RESTManager):
25+
class GroupMemberManager(MemberAllMixin, CRUDMixin, RESTManager):
2026
_path = "/groups/%(group_id)s/members"
2127
_obj_cls = GroupMember
2228
_from_parent_attrs = {"group_id": "id"}
@@ -28,37 +34,18 @@ class GroupMemberManager(CRUDMixin, RESTManager):
2834
)
2935
_types = {"user_ids": types.ListAttribute}
3036

31-
@cli.register_custom_action("GroupMemberManager")
32-
@exc.on_http_error(exc.GitlabListError)
33-
def all(self, **kwargs):
34-
"""List all the members, included inherited ones.
35-
36-
Args:
37-
all (bool): If True, return all the items, without pagination
38-
per_page (int): Number of items to retrieve per request
39-
page (int): ID of the page to return (starts with page 1)
40-
as_list (bool): If set to False and no pagination option is
41-
defined, return a generator instead of a list
42-
**kwargs: Extra options to send to the server (e.g. sudo)
43-
44-
Raises:
45-
GitlabAuthenticationError: If authentication is not correct
46-
GitlabListError: If the list could not be retrieved
4737

48-
Returns:
49-
RESTObjectList: The list of members
50-
"""
51-
52-
path = "%s/all" % self.path
53-
obj = self.gitlab.http_list(path, **kwargs)
54-
return [self._obj_cls(self, item) for item in obj]
38+
class GroupMemberAllManager(RetrieveMixin, RESTManager):
39+
_path = "/groups/%(group_id)s/members/all"
40+
_obj_cls = GroupMember
41+
_from_parent_attrs = {"group_id": "id"}
5542

5643

5744
class ProjectMember(SaveMixin, ObjectDeleteMixin, RESTObject):
5845
_short_print_attr = "username"
5946

6047

61-
class ProjectMemberManager(CRUDMixin, RESTManager):
48+
class ProjectMemberManager(MemberAllMixin, CRUDMixin, RESTManager):
6249
_path = "/projects/%(project_id)s/members"
6350
_obj_cls = ProjectMember
6451
_from_parent_attrs = {"project_id": "id"}
@@ -70,27 +57,8 @@ class ProjectMemberManager(CRUDMixin, RESTManager):
7057
)
7158
_types = {"user_ids": types.ListAttribute}
7259

73-
@cli.register_custom_action("ProjectMemberManager")
74-
@exc.on_http_error(exc.GitlabListError)
75-
def all(self, **kwargs):
76-
"""List all the members, included inherited ones.
7760

78-
Args:
79-
all (bool): If True, return all the items, without pagination
80-
per_page (int): Number of items to retrieve per request
81-
page (int): ID of the page to return (starts with page 1)
82-
as_list (bool): If set to False and no pagination option is
83-
defined, return a generator instead of a list
84-
**kwargs: Extra options to send to the server (e.g. sudo)
85-
86-
Raises:
87-
GitlabAuthenticationError: If authentication is not correct
88-
GitlabListError: If the list could not be retrieved
89-
90-
Returns:
91-
RESTObjectList: The list of members
92-
"""
93-
94-
path = "%s/all" % self.path
95-
obj = self.gitlab.http_list(path, **kwargs)
96-
return [self._obj_cls(self, item) for item in obj]
61+
class ProjectMemberAllManager(RetrieveMixin, RESTManager):
62+
_path = "/projects/%(project_id)s/members/all"
63+
_obj_cls = ProjectMember
64+
_from_parent_attrs = {"project_id": "id"}

gitlab/v4/objects/projects.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from .issues import ProjectIssueManager # noqa: F401
3333
from .jobs import ProjectJobManager # noqa: F401
3434
from .labels import ProjectLabelManager # noqa: F401
35-
from .members import ProjectMemberManager # noqa: F401
35+
from .members import ProjectMemberManager, ProjectMemberAllManager # noqa: F401
3636
from .merge_request_approvals import ( # noqa: F401
3737
ProjectApprovalManager,
3838
ProjectApprovalRuleManager,
@@ -130,6 +130,7 @@ class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTO
130130
("issues", "ProjectIssueManager"),
131131
("labels", "ProjectLabelManager"),
132132
("members", "ProjectMemberManager"),
133+
("members_all", "ProjectMemberAllManager"),
133134
("mergerequests", "ProjectMergeRequestManager"),
134135
("milestones", "ProjectMilestoneManager"),
135136
("notes", "ProjectNoteManager"),

tools/functional/api/test_groups.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ def test_groups(gl):
8888

8989
group1.members.delete(user.id)
9090
assert len(group1.members.list()) == 2
91-
assert len(group1.members.all())
91+
assert len(group1.members.all()) # Deprecated
92+
assert len(group1.members_all.list())
9293
member = group1.members.get(user2.id)
9394
member.access_level = gitlab.const.OWNER_ACCESS
9495
member.save()

0 commit comments

Comments
 (0)