From f486bc761bf45a543f55b14d3d3ea6fa2b229635 Mon Sep 17 00:00:00 2001 From: darkhaniop <72267237+darkhaniop@users.noreply.github.com> Date: Wed, 23 Apr 2025 12:11:56 +0900 Subject: [PATCH] feat(api): add listing user contributed projects --- docs/gl_objects/users.rst | 4 ++++ gitlab/v4/objects/users.py | 14 ++++++++++++++ tests/unit/objects/test_users.py | 27 ++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/gl_objects/users.rst b/docs/gl_objects/users.rst index 185167f92..5ebfa296b 100644 --- a/docs/gl_objects/users.rst +++ b/docs/gl_objects/users.rst @@ -107,6 +107,10 @@ Get the followings of a user:: user.following_users.list(get_all=True) +List a user's contributed projects:: + + user.contributed_projects.list(get_all=True) + List a user's starred projects:: user.starred_projects.list(get_all=True) diff --git a/gitlab/v4/objects/users.py b/gitlab/v4/objects/users.py index 2c7c28a2c..dec0b375d 100644 --- a/gitlab/v4/objects/users.py +++ b/gitlab/v4/objects/users.py @@ -68,6 +68,8 @@ "UserMembershipManager", "UserProject", "UserProjectManager", + "UserContributedProject", + "UserContributedProjectManager", ] @@ -182,6 +184,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject): memberships: UserMembershipManager personal_access_tokens: UserPersonalAccessTokenManager projects: UserProjectManager + contributed_projects: UserContributedProjectManager starred_projects: StarredProjectManager status: UserStatusManager @@ -665,6 +668,17 @@ def list( return super().list(path=path, iterator=iterator, **kwargs) +class UserContributedProject(RESTObject): + _id_attr = "id" + _repr_attr = "path_with_namespace" + + +class UserContributedProjectManager(ListMixin[UserContributedProject]): + _path = "/users/{user_id}/contributed_projects" + _obj_cls = UserContributedProject + _from_parent_attrs = {"user_id": "id"} + + class StarredProject(RESTObject): pass diff --git a/tests/unit/objects/test_users.py b/tests/unit/objects/test_users.py index c120581fe..ff8c4479d 100644 --- a/tests/unit/objects/test_users.py +++ b/tests/unit/objects/test_users.py @@ -7,7 +7,13 @@ import pytest import responses -from gitlab.v4.objects import StarredProject, User, UserMembership, UserStatus +from gitlab.v4.objects import ( + StarredProject, + User, + UserContributedProject, + UserMembership, + UserStatus, +) from .test_projects import project_content @@ -242,6 +248,19 @@ def resp_starred_projects(): yield rsps +@pytest.fixture +def resp_contributed_projects(): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/users/1/contributed_projects", + json=[project_content], + content_type="application/json", + status=200, + ) + yield rsps + + @pytest.fixture def resp_runner_create(): with responses.RequestsMock() as rsps: @@ -314,6 +333,12 @@ def test_list_followers(user, resp_followers_following): assert followings[1].id == 4 +def test_list_contributed_projects(user, resp_contributed_projects): + projects = user.contributed_projects.list() + assert isinstance(projects[0], UserContributedProject) + assert projects[0].id == project_content["id"] + + def test_list_starred_projects(user, resp_starred_projects): projects = user.starred_projects.list() assert isinstance(projects[0], StarredProject)