We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Feature Request: Support Milestone Promotion
## Description of the problem, including code/CLI snippet
This request is for supporting the ability to 'promote' a project milestone to a group one. This exists in the Gitlab API.

Specifically, https://docs.gitlab.com/ee/api/milestones.html#promote-project-milestone-to-a-group-milestone

## Expected Behavior

`project.milestones.promote(milestone_id)`

## Actual Behavior

Promotion not supported

## Specifications

  - python-gitlab version: latest
  - API version you are using (v3/v4): v4
  - Gitlab server version (or gitlab.com): Any


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gitlab/v4/objects/milestones.py`
Content:
```
1 from gitlab import cli
2 from gitlab import exceptions as exc
3 from gitlab import types
4 from gitlab.base import RequiredOptional, RESTManager, RESTObject, RESTObjectList
5 from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin
6 
7 from .issues import GroupIssue, GroupIssueManager, ProjectIssue, ProjectIssueManager
8 from .merge_requests import (
9     GroupMergeRequest,
10     ProjectMergeRequest,
11     ProjectMergeRequestManager,
12 )
13 
14 __all__ = [
15     "GroupMilestone",
16     "GroupMilestoneManager",
17     "ProjectMilestone",
18     "ProjectMilestoneManager",
19 ]
20 
21 
22 class 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 
79 class 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 
93 class 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 
152 class 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
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gitlab/v4/objects/milestones.py b/gitlab/v4/objects/milestones.py
--- a/gitlab/v4/objects/milestones.py
+++ b/gitlab/v4/objects/milestones.py
@@ -2,7 +2,7 @@
 from gitlab import exceptions as exc
 from gitlab import types
 from gitlab.base import RequiredOptional, RESTManager, RESTObject, RESTObjectList
-from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin
+from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, PromoteMixin, SaveMixin
 
 from .issues import GroupIssue, GroupIssueManager, ProjectIssue, ProjectIssueManager
 from .merge_requests import (
@@ -90,8 +90,9 @@
     _types = {"iids": types.ListAttribute}
 
 
-class ProjectMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
+class ProjectMilestone(PromoteMixin, SaveMixin, ObjectDeleteMixin, RESTObject):
     _short_print_attr = "title"
+    _update_uses_post = True
 
     @cli.register_custom_action("ProjectMilestone")
     @exc.on_http_error(exc.GitlabListError)

{"golden_diff": "diff --git a/gitlab/v4/objects/milestones.py b/gitlab/v4/objects/milestones.py\n--- a/gitlab/v4/objects/milestones.py\n+++ b/gitlab/v4/objects/milestones.py\n@@ -2,7 +2,7 @@\n from gitlab import exceptions as exc\n from gitlab import types\n from gitlab.base import RequiredOptional, RESTManager, RESTObject, RESTObjectList\n-from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin\n+from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, PromoteMixin, SaveMixin\n \n from .issues import GroupIssue, GroupIssueManager, ProjectIssue, ProjectIssueManager\n from .merge_requests import (\n@@ -90,8 +90,9 @@\n     _types = {\"iids\": types.ListAttribute}\n \n \n-class ProjectMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):\n+class ProjectMilestone(PromoteMixin, SaveMixin, ObjectDeleteMixin, RESTObject):\n     _short_print_attr = \"title\"\n+    _update_uses_post = True\n \n     @cli.register_custom_action(\"ProjectMilestone\")\n     @exc.on_http_error(exc.GitlabListError)\n", "issue": "Feature Request: Support Milestone Promotion\n## Description of the problem, including code/CLI snippet\r\nThis request is for supporting the ability to 'promote' a project milestone to a group one. This exists in the Gitlab API.\r\n\r\nSpecifically, https://docs.gitlab.com/ee/api/milestones.html#promote-project-milestone-to-a-group-milestone\r\n\r\n## Expected Behavior\r\n\r\n`project.milestones.promote(milestone_id)`\r\n\r\n## Actual Behavior\r\n\r\nPromotion not supported\r\n\r\n## Specifications\r\n\r\n  - python-gitlab version: latest\r\n  - API version you are using (v3/v4): v4\r\n  - Gitlab server version (or gitlab.com): Any\r\n\n", "before_files": [{"content": "from gitlab import cli\nfrom gitlab import exceptions as exc\nfrom gitlab import types\nfrom gitlab.base import RequiredOptional, RESTManager, RESTObject, RESTObjectList\nfrom gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin\n\nfrom .issues import GroupIssue, GroupIssueManager, ProjectIssue, ProjectIssueManager\nfrom .merge_requests import (\n    GroupMergeRequest,\n    ProjectMergeRequest,\n    ProjectMergeRequestManager,\n)\n\n__all__ = [\n    \"GroupMilestone\",\n    \"GroupMilestoneManager\",\n    \"ProjectMilestone\",\n    \"ProjectMilestoneManager\",\n]\n\n\nclass GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):\n    _short_print_attr = \"title\"\n\n    @cli.register_custom_action(\"GroupMilestone\")\n    @exc.on_http_error(exc.GitlabListError)\n    def issues(self, **kwargs):\n        \"\"\"List issues related to this milestone.\n\n        Args:\n            all (bool): If True, return all the items, without pagination\n            per_page (int): Number of items to retrieve per request\n            page (int): ID of the page to return (starts with page 1)\n            as_list (bool): If set to False and no pagination option is\n                defined, return a generator instead of a list\n            **kwargs: Extra options to send to the server (e.g. sudo)\n\n        Raises:\n            GitlabAuthenticationError: If authentication is not correct\n            GitlabListError: If the list could not be retrieved\n\n        Returns:\n            RESTObjectList: The list of issues\n        \"\"\"\n\n        path = \"%s/%s/issues\" % (self.manager.path, self.get_id())\n        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)\n        manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent)\n        # FIXME(gpocentek): the computed manager path is not correct\n        return RESTObjectList(manager, GroupIssue, data_list)\n\n    @cli.register_custom_action(\"GroupMilestone\")\n    @exc.on_http_error(exc.GitlabListError)\n    def merge_requests(self, **kwargs):\n        \"\"\"List the merge requests related to this milestone.\n\n        Args:\n            all (bool): If True, return all the items, without pagination\n            per_page (int): Number of items to retrieve per request\n            page (int): ID of the page to return (starts with page 1)\n            as_list (bool): If set to False and no pagination option is\n                defined, return a generator instead of a list\n            **kwargs: Extra options to send to the server (e.g. sudo)\n\n        Raises:\n            GitlabAuthenticationError: If authentication is not correct\n            GitlabListError: If the list could not be retrieved\n\n        Returns:\n            RESTObjectList: The list of merge requests\n        \"\"\"\n        path = \"%s/%s/merge_requests\" % (self.manager.path, self.get_id())\n        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)\n        manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent)\n        # FIXME(gpocentek): the computed manager path is not correct\n        return RESTObjectList(manager, GroupMergeRequest, data_list)\n\n\nclass GroupMilestoneManager(CRUDMixin, RESTManager):\n    _path = \"/groups/%(group_id)s/milestones\"\n    _obj_cls = GroupMilestone\n    _from_parent_attrs = {\"group_id\": \"id\"}\n    _create_attrs = RequiredOptional(\n        required=(\"title\",), optional=(\"description\", \"due_date\", \"start_date\")\n    )\n    _update_attrs = RequiredOptional(\n        optional=(\"title\", \"description\", \"due_date\", \"start_date\", \"state_event\"),\n    )\n    _list_filters = (\"iids\", \"state\", \"search\")\n    _types = {\"iids\": types.ListAttribute}\n\n\nclass ProjectMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):\n    _short_print_attr = \"title\"\n\n    @cli.register_custom_action(\"ProjectMilestone\")\n    @exc.on_http_error(exc.GitlabListError)\n    def issues(self, **kwargs):\n        \"\"\"List issues related to this milestone.\n\n        Args:\n            all (bool): If True, return all the items, without pagination\n            per_page (int): Number of items to retrieve per request\n            page (int): ID of the page to return (starts with page 1)\n            as_list (bool): If set to False and no pagination option is\n                defined, return a generator instead of a list\n            **kwargs: Extra options to send to the server (e.g. sudo)\n\n        Raises:\n            GitlabAuthenticationError: If authentication is not correct\n            GitlabListError: If the list could not be retrieved\n\n        Returns:\n            RESTObjectList: The list of issues\n        \"\"\"\n\n        path = \"%s/%s/issues\" % (self.manager.path, self.get_id())\n        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)\n        manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)\n        # FIXME(gpocentek): the computed manager path is not correct\n        return RESTObjectList(manager, ProjectIssue, data_list)\n\n    @cli.register_custom_action(\"ProjectMilestone\")\n    @exc.on_http_error(exc.GitlabListError)\n    def merge_requests(self, **kwargs):\n        \"\"\"List the merge requests related to this milestone.\n\n        Args:\n            all (bool): If True, return all the items, without pagination\n            per_page (int): Number of items to retrieve per request\n            page (int): ID of the page to return (starts with page 1)\n            as_list (bool): If set to False and no pagination option is\n                defined, return a generator instead of a list\n            **kwargs: Extra options to send to the server (e.g. sudo)\n\n        Raises:\n            GitlabAuthenticationError: If authentication is not correct\n            GitlabListError: If the list could not be retrieved\n\n        Returns:\n            RESTObjectList: The list of merge requests\n        \"\"\"\n        path = \"%s/%s/merge_requests\" % (self.manager.path, self.get_id())\n        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)\n        manager = ProjectMergeRequestManager(\n            self.manager.gitlab, parent=self.manager._parent\n        )\n        # FIXME(gpocentek): the computed manager path is not correct\n        return RESTObjectList(manager, ProjectMergeRequest, data_list)\n\n\nclass ProjectMilestoneManager(CRUDMixin, RESTManager):\n    _path = \"/projects/%(project_id)s/milestones\"\n    _obj_cls = ProjectMilestone\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _create_attrs = RequiredOptional(\n        required=(\"title\",),\n        optional=(\"description\", \"due_date\", \"start_date\", \"state_event\"),\n    )\n    _update_attrs = RequiredOptional(\n        optional=(\"title\", \"description\", \"due_date\", \"start_date\", \"state_event\"),\n    )\n    _list_filters = (\"iids\", \"state\", \"search\")\n    _types = {\"iids\": types.ListAttribute}\n", "path": "gitlab/v4/objects/milestones.py"}], "after_files": [{"content": "from gitlab import cli\nfrom gitlab import exceptions as exc\nfrom gitlab import types\nfrom gitlab.base import RequiredOptional, RESTManager, RESTObject, RESTObjectList\nfrom gitlab.mixins import CRUDMixin, ObjectDeleteMixin, PromoteMixin, SaveMixin\n\nfrom .issues import GroupIssue, GroupIssueManager, ProjectIssue, ProjectIssueManager\nfrom .merge_requests import (\n    GroupMergeRequest,\n    ProjectMergeRequest,\n    ProjectMergeRequestManager,\n)\n\n__all__ = [\n    \"GroupMilestone\",\n    \"GroupMilestoneManager\",\n    \"ProjectMilestone\",\n    \"ProjectMilestoneManager\",\n]\n\n\nclass GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):\n    _short_print_attr = \"title\"\n\n    @cli.register_custom_action(\"GroupMilestone\")\n    @exc.on_http_error(exc.GitlabListError)\n    def issues(self, **kwargs):\n        \"\"\"List issues related to this milestone.\n\n        Args:\n            all (bool): If True, return all the items, without pagination\n            per_page (int): Number of items to retrieve per request\n            page (int): ID of the page to return (starts with page 1)\n            as_list (bool): If set to False and no pagination option is\n                defined, return a generator instead of a list\n            **kwargs: Extra options to send to the server (e.g. sudo)\n\n        Raises:\n            GitlabAuthenticationError: If authentication is not correct\n            GitlabListError: If the list could not be retrieved\n\n        Returns:\n            RESTObjectList: The list of issues\n        \"\"\"\n\n        path = \"%s/%s/issues\" % (self.manager.path, self.get_id())\n        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)\n        manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent)\n        # FIXME(gpocentek): the computed manager path is not correct\n        return RESTObjectList(manager, GroupIssue, data_list)\n\n    @cli.register_custom_action(\"GroupMilestone\")\n    @exc.on_http_error(exc.GitlabListError)\n    def merge_requests(self, **kwargs):\n        \"\"\"List the merge requests related to this milestone.\n\n        Args:\n            all (bool): If True, return all the items, without pagination\n            per_page (int): Number of items to retrieve per request\n            page (int): ID of the page to return (starts with page 1)\n            as_list (bool): If set to False and no pagination option is\n                defined, return a generator instead of a list\n            **kwargs: Extra options to send to the server (e.g. sudo)\n\n        Raises:\n            GitlabAuthenticationError: If authentication is not correct\n            GitlabListError: If the list could not be retrieved\n\n        Returns:\n            RESTObjectList: The list of merge requests\n        \"\"\"\n        path = \"%s/%s/merge_requests\" % (self.manager.path, self.get_id())\n        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)\n        manager = GroupIssueManager(self.manager.gitlab, parent=self.manager._parent)\n        # FIXME(gpocentek): the computed manager path is not correct\n        return RESTObjectList(manager, GroupMergeRequest, data_list)\n\n\nclass GroupMilestoneManager(CRUDMixin, RESTManager):\n    _path = \"/groups/%(group_id)s/milestones\"\n    _obj_cls = GroupMilestone\n    _from_parent_attrs = {\"group_id\": \"id\"}\n    _create_attrs = RequiredOptional(\n        required=(\"title\",), optional=(\"description\", \"due_date\", \"start_date\")\n    )\n    _update_attrs = RequiredOptional(\n        optional=(\"title\", \"description\", \"due_date\", \"start_date\", \"state_event\"),\n    )\n    _list_filters = (\"iids\", \"state\", \"search\")\n    _types = {\"iids\": types.ListAttribute}\n\n\nclass ProjectMilestone(PromoteMixin, SaveMixin, ObjectDeleteMixin, RESTObject):\n    _short_print_attr = \"title\"\n    _update_uses_post = True\n\n    @cli.register_custom_action(\"ProjectMilestone\")\n    @exc.on_http_error(exc.GitlabListError)\n    def issues(self, **kwargs):\n        \"\"\"List issues related to this milestone.\n\n        Args:\n            all (bool): If True, return all the items, without pagination\n            per_page (int): Number of items to retrieve per request\n            page (int): ID of the page to return (starts with page 1)\n            as_list (bool): If set to False and no pagination option is\n                defined, return a generator instead of a list\n            **kwargs: Extra options to send to the server (e.g. sudo)\n\n        Raises:\n            GitlabAuthenticationError: If authentication is not correct\n            GitlabListError: If the list could not be retrieved\n\n        Returns:\n            RESTObjectList: The list of issues\n        \"\"\"\n\n        path = \"%s/%s/issues\" % (self.manager.path, self.get_id())\n        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)\n        manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)\n        # FIXME(gpocentek): the computed manager path is not correct\n        return RESTObjectList(manager, ProjectIssue, data_list)\n\n    @cli.register_custom_action(\"ProjectMilestone\")\n    @exc.on_http_error(exc.GitlabListError)\n    def merge_requests(self, **kwargs):\n        \"\"\"List the merge requests related to this milestone.\n\n        Args:\n            all (bool): If True, return all the items, without pagination\n            per_page (int): Number of items to retrieve per request\n            page (int): ID of the page to return (starts with page 1)\n            as_list (bool): If set to False and no pagination option is\n                defined, return a generator instead of a list\n            **kwargs: Extra options to send to the server (e.g. sudo)\n\n        Raises:\n            GitlabAuthenticationError: If authentication is not correct\n            GitlabListError: If the list could not be retrieved\n\n        Returns:\n            RESTObjectList: The list of merge requests\n        \"\"\"\n        path = \"%s/%s/merge_requests\" % (self.manager.path, self.get_id())\n        data_list = self.manager.gitlab.http_list(path, as_list=False, **kwargs)\n        manager = ProjectMergeRequestManager(\n            self.manager.gitlab, parent=self.manager._parent\n        )\n        # FIXME(gpocentek): the computed manager path is not correct\n        return RESTObjectList(manager, ProjectMergeRequest, data_list)\n\n\nclass ProjectMilestoneManager(CRUDMixin, RESTManager):\n    _path = \"/projects/%(project_id)s/milestones\"\n    _obj_cls = ProjectMilestone\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _create_attrs = RequiredOptional(\n        required=(\"title\",),\n        optional=(\"description\", \"due_date\", \"start_date\", \"state_event\"),\n    )\n    _update_attrs = RequiredOptional(\n        optional=(\"title\", \"description\", \"due_date\", \"start_date\", \"state_event\"),\n    )\n    _list_filters = (\"iids\", \"state\", \"search\")\n    _types = {\"iids\": types.ListAttribute}\n", "path": "gitlab/v4/objects/milestones.py"}]}