| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ac5defa commit e7559bf
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -53,6 +53,7 @@ API examples | |||
| 53 | 53 | gl_objects/system_hooks | |
| 54 | 54 | gl_objects/templates | |
| 55 | 55 | gl_objects/todos | |
| 56 | + gl_objects/topics | ||
| 56 | 57 | gl_objects/users | |
| 57 | 58 | gl_objects/variables | |
| 58 | 59 | gl_objects/sidekiq | |
| Original file line number | Diff line number | Diff 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) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -180,6 +180,8 @@ def __init__( | |||
| 180 | 180 | """See :class:`~gitlab.v4.objects.VariableManager`""" | |
| 181 | 181 | self.personal_access_tokens = objects.PersonalAccessTokenManager(self) | |
| 182 | 182 | """See :class:`~gitlab.v4.objects.PersonalAccessTokenManager`""" | |
| 183 | + self.topics = objects.TopicManager(self) | ||
| 184 | + """See :class:`~gitlab.v4.objects.TopicManager`""" | ||
| 183 | 185 | ||
| 184 | 186 | def __enter__(self) -> "Gitlab": | |
| 185 | 187 | return self | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -70,6 +70,7 @@ | |||
| 70 | 70 | from .tags import * | |
| 71 | 71 | from .templates import * | |
| 72 | 72 | from .todos import * | |
| 73 | + from .topics import * | ||
| 73 | 74 | from .triggers import * | |
| 74 | 75 | from .users import * | |
| 75 | 76 | from .variables import * | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,27 @@ | |||
| 1 | + from typing import Any, cast, Union | ||
| 2 | + | ||
| 3 | + from gitlab import types | ||
| 4 | + from gitlab.base import RequiredOptional, RESTManager, RESTObject | ||
| 5 | + from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin | ||
| 6 | + | ||
| 7 | + __all__ = [ | ||
| 8 | + "Topic", | ||
| 9 | + "TopicManager", | ||
| 10 | + ] | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + class Topic(SaveMixin, ObjectDeleteMixin, RESTObject): | ||
| 14 | + pass | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + class TopicManager(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 | + def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Topic: | ||
| 27 | + return cast(Topic, super().get(id=id, lazy=lazy, **kwargs)) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,21 @@ | |||
| 1 | + """ | ||
| 2 | + GitLab API: | ||
| 3 | + https://docs.gitlab.com/ce/api/topics.html | ||
| 4 | + """ | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + def test_topics(gl): | ||
| 8 | + assert not gl.topics.list() | ||
| 9 | + | ||
| 10 | + topic = gl.topics.create({"name": "my-topic", "description": "My Topic"}) | ||
| 11 | + assert topic.name == "my-topic" | ||
| 12 | + assert gl.topics.list() | ||
| 13 | + | ||
| 14 | + topic.description = "My Updated Topic" | ||
| 15 | + topic.save() | ||
| 16 | + | ||
| 17 | + updated_topic = gl.topics.get(topic.id) | ||
| 18 | + assert updated_topic.description == topic.description | ||
| 19 | + | ||
| 20 | + topic.delete() | ||
| 21 | + assert not gl.topics.list() | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,6 +24,8 @@ def reset_gitlab(gl): | |||
| 24 | 24 | for deploy_token in group.deploytokens.list(): | |
| 25 | 25 | deploy_token.delete() | |
| 26 | 26 | group.delete() | |
| 27 | + for topic in gl.topics.list(): | ||
| 28 | + topic.delete() | ||
| 27 | 29 | for variable in gl.variables.list(): | |
| 28 | 30 | variable.delete() | |
| 29 | 31 | for user in gl.users.list(): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,2 +1,2 @@ | |||
| 1 | 1 | GITLAB_IMAGE=gitlab/gitlab-ce | |
| 2 | - GITLAB_TAG=14.3.2-ce.0 | ||
| 2 | + GITLAB_TAG=14.5.2-ce.0 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,119 @@ | |||
| 1 | + """ | ||
| 2 | + GitLab API: | ||
| 3 | + https://docs.gitlab.com/ce/api/topics.html | ||
| 4 | + """ | ||
| 5 | + import pytest | ||
| 6 | + import responses | ||
| 7 | + | ||
| 8 | + from gitlab.v4.objects import Topic | ||
| 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 | + def resp_list_topics(): | ||
| 25 | + with responses.RequestsMock() as rsps: | ||
| 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 | + yield rsps | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + @pytest.fixture | ||
| 37 | + def resp_get_topic(): | ||
| 38 | + with responses.RequestsMock() as rsps: | ||
| 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 | + yield rsps | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + @pytest.fixture | ||
| 50 | + def resp_create_topic(): | ||
| 51 | + with responses.RequestsMock() as rsps: | ||
| 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 | + yield rsps | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + @pytest.fixture | ||
| 63 | + def resp_update_topic(): | ||
| 64 | + updated_content = dict(topic_content) | ||
| 65 | + updated_content["name"] = new_name | ||
| 66 | + | ||
| 67 | + with responses.RequestsMock() as rsps: | ||
| 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 | + yield rsps | ||
| 76 | + | ||
| 77 | + | ||
| 78 | + @pytest.fixture | ||
| 79 | + def resp_delete_topic(no_content): | ||
| 80 | + with responses.RequestsMock() as rsps: | ||
| 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 | + yield rsps | ||
| 89 | + | ||
| 90 | + | ||
| 91 | + def test_list_topics(gl, resp_list_topics): | ||
| 92 | + topics = gl.topics.list() | ||
| 93 | + assert isinstance(topics, list) | ||
| 94 | + assert isinstance(topics[0], Topic) | ||
| 95 | + assert topics[0].name == name | ||
| 96 | + | ||
| 97 | + | ||
| 98 | + def test_get_topic(gl, resp_get_topic): | ||
| 99 | + topic = gl.topics.get(1) | ||
| 100 | + assert isinstance(topic, Topic) | ||
| 101 | + assert topic.name == name | ||
| 102 | + | ||
| 103 | + | ||
| 104 | + def test_create_topic(gl, resp_create_topic): | ||
| 105 | + topic = gl.topics.create({"name": name}) | ||
| 106 | + assert isinstance(topic, Topic) | ||
| 107 | + assert topic.name == name | ||
| 108 | + | ||
| 109 | + | ||
| 110 | + def test_update_topic(gl, resp_update_topic): | ||
| 111 | + topic = gl.topics.get(1, lazy=True) | ||
| 112 | + topic.name = new_name | ||
| 113 | + topic.save() | ||
| 114 | + assert topic.name == new_name | ||
| 115 | + | ||
| 116 | + | ||
| 117 | + def test_delete_topic(gl, resp_delete_topic): | ||
| 118 | + topic = gl.topics.get(1, lazy=True) | ||
| 119 | + topic.delete() | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments