Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5bc158d

Browse files
authored
Merge pull request#1333 from python-gitlab/feat/user-follow-api
feat(users): add follow/unfollow API
2 parentsb0d75d9 +e456869 commit5bc158d

File tree

4 files changed

+152
-0
lines changed

4 files changed

+152
-0
lines changed

‎docs/gl_objects/users.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ Activate/Deactivate a user::
6767
user.activate()
6868
user.deactivate()
6969

70+
Follow/Unfollow a user::
71+
72+
user.follow()
73+
user.unfollow()
74+
7075
Set the avatar image for a user::
7176

7277
# the avatar image can be passed as data (content of the file) or as a file
@@ -84,6 +89,15 @@ Delete an external identity by provider name::
8489

8590
user.identityproviders.delete('oauth2_generic')
8691

92+
Get the followers of a user
93+
94+
user.followers_users.list()
95+
96+
Get the followings of a user
97+
98+
user.following_users.list()
99+
100+
87101
User custom attributes
88102
======================
89103

‎gitlab/exceptions.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,14 @@ class GitlabLicenseError(GitlabOperationError):
261261
pass
262262

263263

264+
classGitlabFollowError(GitlabOperationError):
265+
pass
266+
267+
268+
classGitlabUnfollowError(GitlabOperationError):
269+
pass
270+
271+
264272
defon_http_error(error):
265273
"""Manage GitlabHttpError exceptions.
266274

‎gitlab/tests/objects/test_users.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,72 @@ def resp_delete_user_identity(no_content):
108108
yieldrsps
109109

110110

111+
@pytest.fixture
112+
defresp_follow_unfollow():
113+
user= {
114+
"id":1,
115+
"username":"john_smith",
116+
"name":"John Smith",
117+
"state":"active",
118+
"avatar_url":"http://localhost:3000/uploads/user/avatar/1/cd8.jpeg",
119+
"web_url":"http://localhost:3000/john_smith",
120+
}
121+
withresponses.RequestsMock()asrsps:
122+
rsps.add(
123+
method=responses.POST,
124+
url="http://localhost/api/v4/users/1/follow",
125+
json=user,
126+
content_type="application/json",
127+
status=201,
128+
)
129+
rsps.add(
130+
method=responses.POST,
131+
url="http://localhost/api/v4/users/1/unfollow",
132+
json=user,
133+
content_type="application/json",
134+
status=201,
135+
)
136+
yieldrsps
137+
138+
139+
@pytest.fixture
140+
defresp_followers_following():
141+
content= [
142+
{
143+
"id":2,
144+
"name":"Lennie Donnelly",
145+
"username":"evette.kilback",
146+
"state":"active",
147+
"avatar_url":"https://www.gravatar.com/avatar/7955171a55ac4997ed81e5976287890a?s=80&d=identicon",
148+
"web_url":"http://127.0.0.1:3000/evette.kilback",
149+
},
150+
{
151+
"id":4,
152+
"name":"Serena Bradtke",
153+
"username":"cammy",
154+
"state":"active",
155+
"avatar_url":"https://www.gravatar.com/avatar/a2daad869a7b60d3090b7b9bef4baf57?s=80&d=identicon",
156+
"web_url":"http://127.0.0.1:3000/cammy",
157+
},
158+
]
159+
withresponses.RequestsMock()asrsps:
160+
rsps.add(
161+
method=responses.GET,
162+
url="http://localhost/api/v4/users/1/followers",
163+
json=content,
164+
content_type="application/json",
165+
status=200,
166+
)
167+
rsps.add(
168+
method=responses.GET,
169+
url="http://localhost/api/v4/users/1/following",
170+
json=content,
171+
content_type="application/json",
172+
status=200,
173+
)
174+
yieldrsps
175+
176+
111177
deftest_get_user(gl,resp_get_user):
112178
user=gl.users.get(1)
113179
assertisinstance(user,User)
@@ -135,3 +201,17 @@ def test_user_activate_deactivate(user, resp_activate):
135201

136202
deftest_delete_user_identity(user,resp_delete_user_identity):
137203
user.identityproviders.delete("test_provider")
204+
205+
206+
deftest_user_follow_unfollow(user,resp_follow_unfollow):
207+
user.follow()
208+
user.unfollow()
209+
210+
211+
deftest_list_followers(user,resp_followers_following):
212+
followers=user.followers_users.list()
213+
followings=user.following_users.list()
214+
assertisinstance(followers[0],User)
215+
assertfollowers[0].id==2
216+
assertisinstance(followings[0],User)
217+
assertfollowings[1].id==4

‎gitlab/v4/objects/users.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
115115
_managers= (
116116
("customattributes","UserCustomAttributeManager"),
117117
("emails","UserEmailManager"),
118+
("followers_users","UserFollowersManager"),
119+
("following_users","UserFollowingManager"),
118120
("events","UserEventManager"),
119121
("gpgkeys","UserGPGKeyManager"),
120122
("identityproviders","UserIdentityProviderManager"),
@@ -146,6 +148,42 @@ def block(self, **kwargs):
146148
self._attrs["state"]="blocked"
147149
returnserver_data
148150

151+
@cli.register_custom_action("User")
152+
@exc.on_http_error(exc.GitlabFollowError)
153+
deffollow(self,**kwargs):
154+
"""Follow the user.
155+
156+
Args:
157+
**kwargs: Extra options to send to the server (e.g. sudo)
158+
159+
Raises:
160+
GitlabAuthenticationError: If authentication is not correct
161+
GitlabFollowError: If the user could not be followed
162+
163+
Returns:
164+
dict: The new object data (*not* a RESTObject)
165+
"""
166+
path="/users/%s/follow"%self.id
167+
returnself.manager.gitlab.http_post(path,**kwargs)
168+
169+
@cli.register_custom_action("User")
170+
@exc.on_http_error(exc.GitlabUnfollowError)
171+
defunfollow(self,**kwargs):
172+
"""Unfollow the user.
173+
174+
Args:
175+
**kwargs: Extra options to send to the server (e.g. sudo)
176+
177+
Raises:
178+
GitlabAuthenticationError: If authentication is not correct
179+
GitlabUnfollowError: If the user could not be followed
180+
181+
Returns:
182+
dict: The new object data (*not* a RESTObject)
183+
"""
184+
path="/users/%s/unfollow"%self.id
185+
returnself.manager.gitlab.http_post(path,**kwargs)
186+
149187
@cli.register_custom_action("User")
150188
@exc.on_http_error(exc.GitlabUnblockError)
151189
defunblock(self,**kwargs):
@@ -453,3 +491,15 @@ def list(self, **kwargs):
453491
else:
454492
path="/users/%s/projects"%kwargs["user_id"]
455493
returnListMixin.list(self,path=path,**kwargs)
494+
495+
496+
classUserFollowersManager(ListMixin,RESTManager):
497+
_path="/users/%(user_id)s/followers"
498+
_obj_cls=User
499+
_from_parent_attrs= {"user_id":"id"}
500+
501+
502+
classUserFollowingManager(ListMixin,RESTManager):
503+
_path="/users/%(user_id)s/following"
504+
_obj_cls=User
505+
_from_parent_attrs= {"user_id":"id"}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp