8000 feat(api): add support for topics merge API · python-gitlab/python-gitlab@9a6d197 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9a6d197

Browse files
nejchJohnVillalovos
authored andcommitted
feat(api): add support for topics merge API
1 parent 153d373 commit 9a6d197

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed

docs/gl_objects/topics.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,7 @@ Delete a topic::
4646

4747
# or
4848
gl.topics.delete(topic_id)
49+
50+
Merge a source topic into a target topic::
51+
52+
gl.topics.merge(topic_id, target_topic_id)

gitlab/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@ class GitlabTodoError(GitlabOperationError):
221221
pass
222222

223223

224+
class GitlabTopicMergeError(GitlabOperationError):
225+
pass
226+
227+
224228
class GitlabTimeTrackingError(GitlabOperationError):
225229
pass
226230

gitlab/v4/objects/topics.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
from typing import Any, cast, Union
1+
from typing import Any, cast, Dict, TYPE_CHECKING, Union
22

3+
from gitlab import cli
4+
from gitlab import exceptions as exc
35
from gitlab import types
46
from gitlab.base import RESTManager, RESTObject
57
from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin
@@ -29,3 +31,39 @@ class TopicManager(CRUDMixin, RESTManager):
2931

3032
def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Topic:
3133
return cast(Topic, super().get(id=id, lazy=lazy, **kwargs))
34+
35+
@cli.register_custom_action(
36+
"TopicManager",
37+
mandatory=("source_topic_id", "target_topic_id"),
38+
)
39+
@exc.on_http_error(exc.GitlabMRClosedError)
40+
def merge(
41+
self,
42+
source_topic_id: Union[int, str],
43+
target_topic_id: Union[int, str],
44+
**kwargs: Any,
45+
) -> Dict[str, Any]:
46+
"""Merge two topics, assigning all projects to the target topic.
47+
48+
Args:
49+
source_topic_id: ID of source project topic
50+
target_topic_id: ID of target project topic
51+
**kwargs: Extra options to send to the server (e.g. sudo)
52+
53+
Raises:
54+
GitlabAuthenticationError: If authentication is not correct
55+
GitlabTopicMergeError: If the merge failed
56+
57+
Returns:
58+
The merged topic data (*not* a RESTObject)
59+
"""
60+
path = f"{self.path}/merge"
61+
data = {
62+
"source_topic_id": source_topic_id,
63+
"target_topic_id": target_topic_id,
64+
}
65+
66+
server_data = self.gitlab.http_post(path, post_data=data, **kwargs)
67+
if TYPE_CHECKING:
68+
assert isinstance(server_data, dict)
69+
return server_data

tests/unit/objects/test_topics.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,19 @@ def resp_delete_topic(no_content):
9090
yield rsps
9191

9292

93+
@pytest.fixture
94+
def resp_merge_topics():
95+
with responses.RequestsMock() as rsps:
96+
rsps.add(
97+
method=responses.POST,
98+
url=f"{topics_url}/merge",
99+
json=topic_content,
100+
content_type="application/json",
101+
status=200,
102+
)
103+
yield rsps
104+
105+
93106
def test_list_topics(gl, resp_list_topics):
94107
topics = gl.topics.list()
95108
assert isinstance(topics, list)
@@ -120,3 +133,8 @@ def test_update_topic(gl, resp_update_topic):
120133
def test_delete_topic(gl, resp_delete_topic):
121134
topic = gl.topics.get(1, lazy=True)
122135
topic.delete()
136+
137+
138+
def test_merge_topic(gl, resp_merge_topics):
139+
topic = gl.topics.merge(123, 1)
140+
assert topic["id"] == 1

0 commit comments

Comments
 (0)
0