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

Commite7559bf

Browse files
nejchJohnVillalovos
authored andcommitted
feat(api): add support for Topics API
1 parentac5defa commite7559bf

File tree

9 files changed

+222
-1
lines changed

9 files changed

+222
-1
lines changed

‎docs/api-objects.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ API examples
5353
gl_objects/system_hooks
5454
gl_objects/templates
5555
gl_objects/todos
56+
gl_objects/topics
5657
gl_objects/users
5758
gl_objects/variables
5859
gl_objects/sidekiq

‎docs/gl_objects/topics.rst

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
########
2+
Topics
3+
########
4+
5+
Topics can be used to categorize projects and find similar new projects.
6+
7+
Reference
8+
---------
9+
10+
* v4 API:
11+
12+
+:class:`gitlab.v4.objects.Topic`
13+
+:class:`gitlab.v4.objects.TopicManager`
14+
+:attr:`gitlab.Gitlab.topics`
15+
16+
* GitLab API: https://docs.gitlab.com/ce/api/topics.html
17+
18+
This endpoint requires admin access for creating, updating and deleting objects.
19+
20+
Examples
21+
--------
22+
23+
List project topics on the GitLab instance::
24+
25+
topics = gl.topics.list()
26+
27+
Get a specific topic by its ID::
28+
29+
topic = gl.topics.get(topic_id)
30+
31+
Create a new topic::
32+
33+
topic = gl.topics.create({"name": "my-topic"})
34+
35+
Update a topic::
36+
37+
topic.description = "My new topic"
38+
topic.save()
39+
40+
# or
41+
gl.topics.update(topic_id, {"description": "My new topic"})
42+
43+
Delete a topic::
44+
45+
topic.delete()
46+
47+
# or
48+
gl.topics.delete(topic_id)

‎gitlab/client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ def __init__(
180180
"""See :class:`~gitlab.v4.objects.VariableManager`"""
181181
self.personal_access_tokens=objects.PersonalAccessTokenManager(self)
182182
"""See :class:`~gitlab.v4.objects.PersonalAccessTokenManager`"""
183+
self.topics=objects.TopicManager(self)
184+
"""See :class:`~gitlab.v4.objects.TopicManager`"""
183185

184186
def__enter__(self)->"Gitlab":
185187
returnself

‎gitlab/v4/objects/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
from .tagsimport*
7171
from .templatesimport*
7272
from .todosimport*
73+
from .topicsimport*
7374
from .triggersimport*
7475
from .usersimport*
7576
from .variablesimport*

‎gitlab/v4/objects/topics.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
fromtypingimportAny,cast,Union
2+
3+
fromgitlabimporttypes
4+
fromgitlab.baseimportRequiredOptional,RESTManager,RESTObject
5+
fromgitlab.mixinsimportCRUDMixin,ObjectDeleteMixin,SaveMixin
6+
7+
__all__= [
8+
"Topic",
9+
"TopicManager",
10+
]
11+
12+
13+
classTopic(SaveMixin,ObjectDeleteMixin,RESTObject):
14+
pass
15+
16+
17+
classTopicManager(CRUDMixin,RESTManager):
18+
_path="/topics"
19+
_obj_cls=Topic
20+
_create_attrs=RequiredOptional(
21+
required=("name",),optional=("avatar","description")
22+
)
23+
_update_attrs=RequiredOptional(optional=("avatar","description","name"))
24+
_types= {"avatar":types.ImageAttribute}
25+
26+
defget(self,id:Union[str,int],lazy:bool=False,**kwargs:Any)->Topic:
27+
returncast(Topic,super().get(id=id,lazy=lazy,**kwargs))

‎tests/functional/api/test_topics.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""
2+
GitLab API:
3+
https://docs.gitlab.com/ce/api/topics.html
4+
"""
5+
6+
7+
deftest_topics(gl):
8+
assertnotgl.topics.list()
9+
10+
topic=gl.topics.create({"name":"my-topic","description":"My Topic"})
11+
asserttopic.name=="my-topic"
12+
assertgl.topics.list()
13+
14+
topic.description="My Updated Topic"
15+
topic.save()
16+
17+
updated_topic=gl.topics.get(topic.id)
18+
assertupdated_topic.description==topic.description
19+
20+
topic.delete()
21+
assertnotgl.topics.list()

‎tests/functional/conftest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ def reset_gitlab(gl):
2424
fordeploy_tokeningroup.deploytokens.list():
2525
deploy_token.delete()
2626
group.delete()
27+
fortopicingl.topics.list():
28+
topic.delete()
2729
forvariableingl.variables.list():
2830
variable.delete()
2931
foruseringl.users.list():

‎tests/functional/fixtures/.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
GITLAB_IMAGE=gitlab/gitlab-ce
2-
GITLAB_TAG=14.3.2-ce.0
2+
GITLAB_TAG=14.5.2-ce.0

‎tests/unit/objects/test_topics.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
"""
2+
GitLab API:
3+
https://docs.gitlab.com/ce/api/topics.html
4+
"""
5+
importpytest
6+
importresponses
7+
8+
fromgitlab.v4.objectsimportTopic
9+
10+
name="GitLab"
11+
new_name="gitlab-test"
12+
topic_content= {
13+
"id":1,
14+
"name":name,
15+
"description":"GitLab is an open source end-to-end software development platform.",
16+
"total_projects_count":1000,
17+
"avatar_url":"http://www.gravatar.com/avatar/a0d477b3ea21970ce6ffcbb817b0b435?s=80&d=identicon",
18+
}
19+
topics_url="http://localhost/api/v4/topics"
20+
topic_url=f"{topics_url}/1"
21+
22+
23+
@pytest.fixture
24+
defresp_list_topics():
25+
withresponses.RequestsMock()asrsps:
26+
rsps.add(
27+
method=responses.GET,
28+
url=topics_url,
29+
json=[topic_content],
30+
content_type="application/json",
31+
status=200,
32+
)
33+
yieldrsps
34+
35+
36+
@pytest.fixture
37+
defresp_get_topic():
38+
withresponses.RequestsMock()asrsps:
39+
rsps.add(
40+
method=responses.GET,
41+
url=topic_url,
42+
json=topic_content,
43+
content_type="application/json",
44+
status=200,
45+
)
46+
yieldrsps
47+
48+
49+
@pytest.fixture
50+
defresp_create_topic():
51+
withresponses.RequestsMock()asrsps:
52+
rsps.add(
53+
method=responses.POST,
54+
url=topics_url,
55+
json=topic_content,
56+
content_type="application/json",
57+
status=200,
58+
)
59+
yieldrsps
60+
61+
62+
@pytest.fixture
63+
defresp_update_topic():
64+
updated_content=dict(topic_content)
65+
updated_content["name"]=new_name
66+
67+
withresponses.RequestsMock()asrsps:
68+
rsps.add(
69+
method=responses.PUT,
70+
url=topic_url,
71+
json=updated_content,
72+
content_type="application/json",
73+
status=200,
74+
)
75+
yieldrsps
76+
77+
78+
@pytest.fixture
79+
defresp_delete_topic(no_content):
80+
withresponses.RequestsMock()asrsps:
81+
rsps.add(
82+
method=responses.DELETE,
83+
url=topic_url,
84+
json=no_content,
85+
content_type="application/json",
86+
status=204,
87+
)
88+
yieldrsps
89+
90+
91+
deftest_list_topics(gl,resp_list_topics):
92+
topics=gl.topics.list()
93+
assertisinstance(topics,list)
94+
assertisinstance(topics[0],Topic)
95+
asserttopics[0].name==name
96+
97+
98+
deftest_get_topic(gl,resp_get_topic):
99+
topic=gl.topics.get(1)
100+
assertisinstance(topic,Topic)
101+
asserttopic.name==name
102+
103+
104+
deftest_create_topic(gl,resp_create_topic):
105+
topic=gl.topics.create({"name":name})
106+
assertisinstance(topic,Topic)
107+
asserttopic.name==name
108+
109+
110+
deftest_update_topic(gl,resp_update_topic):
111+
topic=gl.topics.get(1,lazy=True)
112+
topic.name=new_name
113+
topic.save()
114+
asserttopic.name==new_name
115+
116+
117+
deftest_delete_topic(gl,resp_delete_topic):
118+
topic=gl.topics.get(1,lazy=True)
119+
topic.delete()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp