Skip to content

Commit 66461ba

Browse files
nejchJohnVillalovos
authored andcommitted
feat(groups): add support for shared projects API
1 parent 8d4f13b commit 66461ba

File tree

4 files changed

+72
-4
lines changed

4 files changed

+72
-4
lines changed

docs/gl_objects/groups.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,15 @@ List a group's projects::
3131

3232
projects = group.projects.list()
3333

34+
List a group's shared projects::
35+
36+
projects = group.shared_projects.list()
37+
3438
.. note::
3539

36-
``GroupProject`` objects returned by this API call are very limited, and do
37-
not provide all the features of ``Project`` objects. If you need to
38-
manipulate projects, create a new ``Project`` object::
40+
``GroupProject`` and ``SharedProject`` objects returned by these two API calls
41+
are very limited, and do not provide all the features of ``Project`` objects.
42+
If you need to manipulate projects, create a new ``Project`` object::
3943

4044
first_group_project = group.projects.list()[0]
4145
manageable_project = gl.projects.get(first_group_project.id, lazy=True)

gitlab/v4/objects/groups.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from .milestones import GroupMilestoneManager # noqa: F401
3535
from .notification_settings import GroupNotificationSettingsManager # noqa: F401
3636
from .packages import GroupPackageManager # noqa: F401
37-
from .projects import GroupProjectManager # noqa: F401
37+
from .projects import GroupProjectManager, SharedProjectManager # noqa: F401
3838
from .push_rules import GroupPushRulesManager
3939
from .runners import GroupRunnerManager # noqa: F401
4040
from .statistics import GroupIssuesStatisticsManager # noqa: F401
@@ -79,6 +79,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject):
7979
notificationsettings: GroupNotificationSettingsManager
8080
packages: GroupPackageManager
8181
projects: GroupProjectManager
82+
shared_projects: SharedProjectManager
8283
pushrules: GroupPushRulesManager
8384
registry_repositories: GroupRegistryRepositoryManager
8485
runners: GroupRunnerManager

gitlab/v4/objects/projects.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@
103103
"ProjectRemoteMirrorManager",
104104
"ProjectStorage",
105105
"ProjectStorageManager",
106+
"SharedProject",
107+
"SharedProjectManager",
106108
]
107109

108110

@@ -1081,3 +1083,26 @@ class ProjectStorageManager(GetWithoutIdMixin, RESTManager):
10811083

10821084
def get(self, **kwargs: Any) -> ProjectStorage:
10831085
return cast(ProjectStorage, super().get(**kwargs))
1086+
1087+
1088+
class SharedProject(RESTObject):
1089+
pass
1090+
1091+
1092+
class SharedProjectManager(ListMixin, RESTManager):
1093+
_path = "/groups/{group_id}/projects/shared"
1094+
_obj_cls = SharedProject
1095+
_from_parent_attrs = {"group_id": "id"}
1096+
_list_filters = (
1097+
"archived",
1098+
"visibility",
1099+
"order_by",
1100+
"sort",
1101+
"search",
1102+
"simple",
1103+
"starred",
1104+
"with_issues_enabled",
1105+
"with_merge_requests_enabled",
1106+
"min_access_level",
1107+
"with_custom_attributes",
1108+
)

tests/unit/objects/test_groups.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,21 @@
99

1010
import gitlab
1111
from gitlab.v4.objects import GroupDescendantGroup, GroupSubgroup
12+
from gitlab.v4.objects.projects import GroupProject, SharedProject
1213

1314
content = {"name": "name", "id": 1, "path": "path"}
15+
projects_content = [
16+
{
17+
"id": 9,
18+
"description": "foo",
19+
"default_branch": "master",
20+
"name": "Html5 Boilerplate",
21+
"name_with_namespace": "Experimental / Html5 Boilerplate",
22+
"path": "html5-boilerplate",
23+
"path_with_namespace": "h5bp/html5-boilerplate",
24+
"namespace": {"id": 5, "name": "Experimental", "path": "h5bp", "kind": "group"},
25+
}
26+
]
1427
subgroup_descgroup_content = [
1528
{
1629
"id": 2,
@@ -80,6 +93,19 @@ def resp_groups():
8093
yield rsps
8194

8295

96+
@pytest.fixture
97+
def resp_list_group_projects():
98+
with responses.RequestsMock() as rsps:
99+
rsps.add(
100+
method=responses.GET,
101+
url=re.compile(r"http://localhost/api/v4/groups/1/projects(/shared)?"),
102+
json=projects_content,
103+
content_type="application/json",
104+
status=200,
105+
)
106+
yield rsps
107+
108+
83109
@pytest.fixture
84110
def resp_list_subgroups_descendant_groups():
85111
with responses.RequestsMock() as rsps:
@@ -211,6 +237,18 @@ def test_create_group_export(group, resp_export):
211237
assert export.message == "202 Accepted"
212238

213239

240+
def test_list_group_projects(group, resp_list_group_projects):
241+
projects = group.projects.list()
242+
assert isinstance(projects[0], GroupProject)
243+
assert projects[0].path == projects_content[0]["path"]
244+
245+
246+
def test_list_group_shared_projects(group, resp_list_group_projects):
247+
projects = group.shared_projects.list()
248+
assert isinstance(projects[0], SharedProject)
249+
assert projects[0].path == projects_content[0]["path"]
250+
251+
214252
def test_list_group_subgroups(group, resp_list_subgroups_descendant_groups):
215253
subgroups = group.subgroups.list()
216254
assert isinstance(subgroups[0], GroupSubgroup)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy