diff --git a/docs/api-objects.rst b/docs/api-objects.rst index eaacf7de8..254621d5e 100644 --- a/docs/api-objects.rst +++ b/docs/api-objects.rst @@ -7,6 +7,7 @@ API examples gl_objects/access_requests gl_objects/emojis + gl_objects/badges gl_objects/branches gl_objects/protected_branches gl_objects/messages diff --git a/docs/gl_objects/badges.rst b/docs/gl_objects/badges.rst new file mode 100644 index 000000000..1bda282dd --- /dev/null +++ b/docs/gl_objects/badges.rst @@ -0,0 +1,52 @@ +###### +Badges +###### + +Badges can be associated with groups and projects. + +Reference +--------- + +* v4 API: + + + :class:`gitlab.v4.objects.GroupBadge` + + :class:`gitlab.v4.objects.GroupBadgeManager` + + :attr:`gitlab.v4.objects.Group.badges` + + :class:`gitlab.v4.objects.ProjectBadge` + + :class:`gitlab.v4.objects.ProjectBadgeManager` + + :attr:`gitlab.v4.objects.Project.badges` + +* GitLab API: + + + https://docs.gitlab.com/ce/api/group_badges.html + + https://docs.gitlab.com/ce/api/project_badges.html + +Examples +-------- + +List badges:: + + badges = group_or_project.badges.list() + +Get ad badge:: + + badge = group_or_project.badges.get(badge_id) + +Create a badge:: + + badge = group_or_project.badges.create({'link_url': link, 'image_url': image_link}) + +Update a badge:: + + badge.image_link = new_link + badge.save() + +Delete a badge:: + + badge.delete() + +Render a badge (preview the generate URLs):: + + output = group_or_project.badges.render(link, image_link) + print(output['rendered_link_url']) + print(output['rendered_image_url']) diff --git a/gitlab/exceptions.py b/gitlab/exceptions.py index 6912e3388..514d742ca 100644 --- a/gitlab/exceptions.py +++ b/gitlab/exceptions.py @@ -213,6 +213,10 @@ class GitlabVerifyError(GitlabOperationError): pass +class GitlabRenderError(GitlabOperationError): + pass + + def on_http_error(error): """Manage GitlabHttpError exceptions. diff --git a/gitlab/mixins.py b/gitlab/mixins.py index 7119aefa7..05e31c0fb 100644 --- a/gitlab/mixins.py +++ b/gitlab/mixins.py @@ -571,3 +571,27 @@ def participants(self, **kwargs): path = '%s/%s/participants' % (self.manager.path, self.get_id()) return self.manager.gitlab.http_get(path, **kwargs) + + +class BadgeRenderMixin(object): + @cli.register_custom_action(('GroupBadgeManager', 'ProjectBadgeManager'), + ('link_url', 'image_url')) + @exc.on_http_error(exc.GitlabRenderError) + def render(self, link_url, image_url, **kwargs): + """Preview link_url and image_url after interpolation. + + Args: + link_url (str): URL of the badge link + image_url (str): URL of the badge image + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabRenderError: If the rendering failed + + Returns: + dict: The rendering properties + """ + path = '%s/render' % self.path + data = {'link_url': link_url, 'image_url': image_url} + return self.gitlab.http_get(path, data, **kwargs) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 3223b63c2..81c7078a6 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -555,6 +555,18 @@ class GroupAccessRequestManager(ListMixin, CreateMixin, DeleteMixin, _from_parent_attrs = {'group_id': 'id'} +class GroupBadge(SaveMixin, ObjectDeleteMixin, RESTObject): + pass + + +class GroupBadgeManager(BadgeRenderMixin, CRUDMixin, RESTManager): + _path = '/groups/%(group_id)s/badges' + _obj_cls = GroupBadge + _from_parent_attrs = {'group_id': 'id'} + _create_attrs = (('link_url', 'image_url'), tuple()) + _update_attrs = (tuple(), ('link_url', 'image_url')) + + class GroupBoardList(SaveMixin, ObjectDeleteMixin, RESTObject): pass @@ -746,6 +758,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject): _short_print_attr = 'name' _managers = ( ('accessrequests', 'GroupAccessRequestManager'), + ('badges', 'GroupBadgeManager'), ('boards', 'GroupBoardManager'), ('customattributes', 'GroupCustomAttributeManager'), ('issues', 'GroupIssueManager'), @@ -1398,12 +1411,12 @@ class ProjectBadge(SaveMixin, ObjectDeleteMixin, RESTObject): pass -class ProjectBadgeManager(CRUDMixin, RESTManager): +class ProjectBadgeManager(BadgeRenderMixin, CRUDMixin, RESTManager): _path = '/projects/%(project_id)s/badges' _obj_cls = ProjectBadge _from_parent_attrs = {'project_id': 'id'} _create_attrs = (('link_url', 'image_url'), tuple()) - _update_attrs = (('link_url', 'image_url'), tuple()) + _update_attrs = (tuple(), ('link_url', 'image_url')) class ProjectEvent(Event): diff --git a/tools/python_test_v4.py b/tools/python_test_v4.py index 70f093d35..02496a483 100644 --- a/tools/python_test_v4.py +++ b/tools/python_test_v4.py @@ -274,6 +274,18 @@ settings = group2.notificationsettings.get() assert(settings.level == 'disabled') +# group badges +badge_image = 'http://example.com' +badge_link = 'http://example/img.svg' +badge = group2.badges.create({'link_url': badge_link, 'image_url': badge_image}) +assert(len(group2.badges.list()) == 1) +badge.image_url = 'http://another.example.com' +badge.save() +badge = group2.badges.get(badge.id) +assert(badge.image_url == 'http://another.example.com') +badge.delete() +assert(len(group2.badges.list()) == 0) + # group milestones gm1 = group1.milestones.create({'title': 'groupmilestone1'}) assert(len(group1.milestones.list()) == 1) @@ -656,8 +668,14 @@ # project badges badge_image = 'http://example.com' badge_link = 'http://example/img.svg' -bp = admin_project.badges.create({'link_url': badge_link, 'image_url': badge_image}) +badge = admin_project.badges.create({'link_url': badge_link, 'image_url': badge_image}) assert(len(admin_project.badges.list()) == 1) +badge.image_url = 'http://another.example.com' +badge.save() +badge = admin_project.badges.get(badge.id) +assert(badge.image_url == 'http://another.example.com') +badge.delete() +assert(len(admin_project.badges.list()) == 0) # project wiki wiki_content = 'Wiki page content'