1from gitlab import cli
2from gitlab import exceptions as exc
3from gitlab import types
4from gitlab.base import RequiredOptional, RESTManager, RESTObject, RESTObjectList
5from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin
6
7from .issues import GroupIssue, GroupIssueManager, ProjectIssue, ProjectIssueManager
8from .merge_requests import (
9    GroupMergeRequest,
10    ProjectMergeRequest,
11    ProjectMergeRequestManager,
12)
13
14__all__ = [
15    "GroupMilestone",
16    "GroupMilestoneManager",
17    "ProjectMilestone",
18    "ProjectMilestoneManager",
19]
20
21
22class GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
23    _short_print_attr = "title"
24
25    @cli.register_custom_action("GroupMilestone")
26    @exc.on_http_error(exc.GitlabListError)
27    def issues(self, **kwargs):
28        """List issues related to this milestone.
29
30        Args:
31            all (bool): If True, return all the items, without pagination
32            per_page (int): Number of items to retrieve per request
33            page (int): ID of the page to return (starts with page 1)
34            as_list (bool): If set to False and no pagination option is
35                defined, return a generator instead of a list
36            **kwargs: Extra options to send to the server (e.g. sudo)
37
38        Raises:
39            GitlabAuthenticationError: If authentication is not correct
40            GitlabListError: If the list could not be retrieved
41
42        Returns:
43            RESTObjectList: The list of issues
44        """
45
46        path = "%s/%s/issues" % (self.manager.path, self.get_id())
47        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
48        manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent)
49        # FIXME(gpocentek): the computed manager path is not correct
50        return RESTObjectList(manager, GroupIssue, data_list)
51
52    @cli.register_custom_action("GroupMilestone")
53    @exc.on_http_error(exc.GitlabListError)
54    def merge_requests(self, **kwargs):
55        """List the merge requests related to this milestone.
56
57        Args:
58            all (bool): If True, return all the items, without pagination
59            per_page (int): Number of items to retrieve per request
60            page (int): ID of the page to return (starts with page 1)
61            as_list (bool): If set to False and no pagination option is
62                defined, return a generator instead of a list
63            **kwargs: Extra options to send to the server (e.g. sudo)
64
65        Raises:
66            GitlabAuthenticationError: If authentication is not correct
67            GitlabListError: If the list could not be retrieved
68
69        Returns:
70            RESTObjectList: The list of merge requests
71        """
72        path = "%s/%s/merge_requests" % (self.manager.path, self.get_id())
73        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
74        manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent)
75        # FIXME(gpocentek): the computed manager path is not correct
76        return RESTObjectList(manager, GroupMergeRequest, data_list)
77
78
79class GroupMilestoneManager(CRUDMixin, RESTManager):
80    _path = "/groups/%(group_id)s/milestones"
81    _obj_cls = GroupMilestone
82    _from_parent_attrs = {"group_id": "id"}
83    _create_attrs = RequiredOptional(
84        required=("title",), optional=("description", "due_date", "start_date")
85    )
86    _update_attrs = RequiredOptional(
87        optional=("title", "description", "due_date", "start_date", "state_event"),
88    )
89    _list_filters = ("iids", "state", "search")
90    _types = {"iids": types.ListAttribute}
91
92
93class ProjectMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
94    _short_print_attr = "title"
95
96    @cli.register_custom_action("ProjectMilestone")
97    @exc.on_http_error(exc.GitlabListError)
98    def issues(self, **kwargs):
99        """List issues related to this milestone.
100
101        Args:
102            all (bool): If True, return all the items, without pagination
103            per_page (int): Number of items to retrieve per request
104            page (int): ID of the page to return (starts with page 1)
105            as_list (bool): If set to False and no pagination option is
106                defined, return a generator instead of a list
107            **kwargs: Extra options to send to the server (e.g. sudo)
108
109        Raises:
110            GitlabAuthenticationError: If authentication is not correct
111            GitlabListError: If the list could not be retrieved
112
113        Returns:
114            RESTObjectList: The list of issues
115        """
116
117        path = "%s/%s/issues" % (self.manager.path, self.get_id())
118        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
119        manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)
120        # FIXME(gpocentek): the computed manager path is not correct
121        return RESTObjectList(manager, ProjectIssue, data_list)
122
123    @cli.register_custom_action("ProjectMilestone")
124    @exc.on_http_error(exc.GitlabListError)
125    def merge_requests(self, **kwargs):
126        """List the merge requests related to this milestone.
127
128        Args:
129            all (bool): If True, return all the items, without pagination
130            per_page (int): Number of items to retrieve per request
131            page (int): ID of the page to return (starts with page 1)
132            as_list (bool): If set to False and no pagination option is
133                defined, return a generator instead of a list
134            **kwargs: Extra options to send to the server (e.g. sudo)
135
136        Raises:
137            GitlabAuthenticationError: If authentication is not correct
138            GitlabListError: If the list could not be retrieved
139
140        Returns:
141            RESTObjectList: The list of merge requests
142        """
143        path = "%s/%s/merge_requests" % (self.manager.path, self.get_id())
144        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)
145        manager = ProjectMergeRequestManager(
146            self.manager.gitlab, parent=self.manager._parent
147        )
148        # FIXME(gpocentek): the computed manager path is not correct
149        return RESTObjectList(manager, ProjectMergeRequest, data_list)
150
151
152class ProjectMilestoneManager(CRUDMixin, RESTManager):
153    _path = "/projects/%(project_id)s/milestones"
154    _obj_cls = ProjectMilestone
155    _from_parent_attrs = {"project_id": "id"}
156    _create_attrs = RequiredOptional(
157        required=("title",),
158        optional=("description", "due_date", "start_date", "state_event"),
159    )
160    _update_attrs = RequiredOptional(
161        optional=("title", "description", "due_date", "start_date", "state_event"),
162    )
163    _list_filters = ("iids", "state", "search")
164    _types = {"iids": types.ListAttribute}
165