We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Epic notes list returns 404 error
Tried using epic.notes.list() but it's returning 404 error, this matches the behavior described in https://docs.gitlab.com/ee/api/notes.html#list-all-epic-notes when **epic IID** is used.

So guessing these need to change to epic ID instead?
https://github.com/python-gitlab/python-gitlab/blob/3f91d2455657c570851f625c0d80c685d9393cbb/gitlab/v4/objects/notes.py#L52
https://github.com/python-gitlab/python-gitlab/blob/3f91d2455657c570851f625c0d80c685d9393cbb/gitlab/v4/objects/notes.py#L54

--- 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/notes.py`
Content:
```
1 from typing import Any, cast, Union
2 
3 from gitlab.base import RESTManager, RESTObject
4 from gitlab.mixins import (
5     CreateMixin,
6     CRUDMixin,
7     DeleteMixin,
8     GetMixin,
9     ObjectDeleteMixin,
10     RetrieveMixin,
11     SaveMixin,
12     UpdateMixin,
13 )
14 from gitlab.types import RequiredOptional
15 
16 from .award_emojis import (  # noqa: F401
17     GroupEpicNoteAwardEmojiManager,
18     ProjectIssueNoteAwardEmojiManager,
19     ProjectMergeRequestNoteAwardEmojiManager,
20     ProjectSnippetNoteAwardEmojiManager,
21 )
22 
23 __all__ = [
24     "GroupEpicNote",
25     "GroupEpicNoteManager",
26     "GroupEpicDiscussionNote",
27     "GroupEpicDiscussionNoteManager",
28     "ProjectNote",
29     "ProjectNoteManager",
30     "ProjectCommitDiscussionNote",
31     "ProjectCommitDiscussionNoteManager",
32     "ProjectIssueNote",
33     "ProjectIssueNoteManager",
34     "ProjectIssueDiscussionNote",
35     "ProjectIssueDiscussionNoteManager",
36     "ProjectMergeRequestNote",
37     "ProjectMergeRequestNoteManager",
38     "ProjectMergeRequestDiscussionNote",
39     "ProjectMergeRequestDiscussionNoteManager",
40     "ProjectSnippetNote",
41     "ProjectSnippetNoteManager",
42     "ProjectSnippetDiscussionNote",
43     "ProjectSnippetDiscussionNoteManager",
44 ]
45 
46 
47 class GroupEpicNote(SaveMixin, ObjectDeleteMixin, RESTObject):
48     awardemojis: GroupEpicNoteAwardEmojiManager
49 
50 
51 class GroupEpicNoteManager(CRUDMixin, RESTManager):
52     _path = "/groups/{group_id}/epics/{epic_iid}/notes"
53     _obj_cls = GroupEpicNote
54     _from_parent_attrs = {"group_id": "group_id", "epic_iid": "iid"}
55     _create_attrs = RequiredOptional(required=("body",), optional=("created_at",))
56     _update_attrs = RequiredOptional(required=("body",))
57 
58     def get(
59         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
60     ) -> GroupEpicNote:
61         return cast(GroupEpicNote, super().get(id=id, lazy=lazy, **kwargs))
62 
63 
64 class GroupEpicDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):
65     pass
66 
67 
68 class GroupEpicDiscussionNoteManager(
69     GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager
70 ):
71     _path = "/groups/{group_id}/epics/{epic_iid}/discussions/{discussion_id}/notes"
72     _obj_cls = GroupEpicDiscussionNote
73     _from_parent_attrs = {
74         "group_id": "group_id",
75         "epic_iid": "epic_iid",
76         "discussion_id": "id",
77     }
78     _create_attrs = RequiredOptional(required=("body",), optional=("created_at",))
79     _update_attrs = RequiredOptional(required=("body",))
80 
81     def get(
82         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
83     ) -> GroupEpicDiscussionNote:
84         return cast(GroupEpicDiscussionNote, super().get(id=id, lazy=lazy, **kwargs))
85 
86 
87 class ProjectNote(RESTObject):
88     pass
89 
90 
91 class ProjectNoteManager(RetrieveMixin, RESTManager):
92     _path = "/projects/{project_id}/notes"
93     _obj_cls = ProjectNote
94     _from_parent_attrs = {"project_id": "id"}
95     _create_attrs = RequiredOptional(required=("body",))
96 
97     def get(
98         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
99     ) -> ProjectNote:
100         return cast(ProjectNote, super().get(id=id, lazy=lazy, **kwargs))
101 
102 
103 class ProjectCommitDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):
104     pass
105 
106 
107 class ProjectCommitDiscussionNoteManager(
108     GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager
109 ):
110     _path = (
111         "/projects/{project_id}/repository/commits/{commit_id}/"
112         "discussions/{discussion_id}/notes"
113     )
114     _obj_cls = ProjectCommitDiscussionNote
115     _from_parent_attrs = {
116         "project_id": "project_id",
117         "commit_id": "commit_id",
118         "discussion_id": "id",
119     }
120     _create_attrs = RequiredOptional(
121         required=("body",), optional=("created_at", "position")
122     )
123     _update_attrs = RequiredOptional(required=("body",))
124 
125     def get(
126         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
127     ) -> ProjectCommitDiscussionNote:
128         return cast(
129             ProjectCommitDiscussionNote, super().get(id=id, lazy=lazy, **kwargs)
130         )
131 
132 
133 class ProjectIssueNote(SaveMixin, ObjectDeleteMixin, RESTObject):
134     awardemojis: ProjectIssueNoteAwardEmojiManager
135 
136 
137 class ProjectIssueNoteManager(CRUDMixin, RESTManager):
138     _path = "/projects/{project_id}/issues/{issue_iid}/notes"
139     _obj_cls = ProjectIssueNote
140     _from_parent_attrs = {"project_id": "project_id", "issue_iid": "iid"}
141     _create_attrs = RequiredOptional(required=("body",), optional=("created_at",))
142     _update_attrs = RequiredOptional(required=("body",))
143 
144     def get(
145         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
146     ) -> ProjectIssueNote:
147         return cast(ProjectIssueNote, super().get(id=id, lazy=lazy, **kwargs))
148 
149 
150 class ProjectIssueDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):
151     pass
152 
153 
154 class ProjectIssueDiscussionNoteManager(
155     GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager
156 ):
157     _path = (
158         "/projects/{project_id}/issues/{issue_iid}/discussions/{discussion_id}/notes"
159     )
160     _obj_cls = ProjectIssueDiscussionNote
161     _from_parent_attrs = {
162         "project_id": "project_id",
163         "issue_iid": "issue_iid",
164         "discussion_id": "id",
165     }
166     _create_attrs = RequiredOptional(required=("body",), optional=("created_at",))
167     _update_attrs = RequiredOptional(required=("body",))
168 
169     def get(
170         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
171     ) -> ProjectIssueDiscussionNote:
172         return cast(ProjectIssueDiscussionNote, super().get(id=id, lazy=lazy, **kwargs))
173 
174 
175 class ProjectMergeRequestNote(SaveMixin, ObjectDeleteMixin, RESTObject):
176     awardemojis: ProjectMergeRequestNoteAwardEmojiManager
177 
178 
179 class ProjectMergeRequestNoteManager(CRUDMixin, RESTManager):
180     _path = "/projects/{project_id}/merge_requests/{mr_iid}/notes"
181     _obj_cls = ProjectMergeRequestNote
182     _from_parent_attrs = {"project_id": "project_id", "mr_iid": "iid"}
183     _create_attrs = RequiredOptional(required=("body",))
184     _update_attrs = RequiredOptional(required=("body",))
185 
186     def get(
187         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
188     ) -> ProjectMergeRequestNote:
189         return cast(ProjectMergeRequestNote, super().get(id=id, lazy=lazy, **kwargs))
190 
191 
192 class ProjectMergeRequestDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):
193     pass
194 
195 
196 class ProjectMergeRequestDiscussionNoteManager(
197     GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager
198 ):
199     _path = (
200         "/projects/{project_id}/merge_requests/{mr_iid}/"
201         "discussions/{discussion_id}/notes"
202     )
203     _obj_cls = ProjectMergeRequestDiscussionNote
204     _from_parent_attrs = {
205         "project_id": "project_id",
206         "mr_iid": "mr_iid",
207         "discussion_id": "id",
208     }
209     _create_attrs = RequiredOptional(required=("body",), optional=("created_at",))
210     _update_attrs = RequiredOptional(required=("body",))
211 
212     def get(
213         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
214     ) -> ProjectMergeRequestDiscussionNote:
215         return cast(
216             ProjectMergeRequestDiscussionNote, super().get(id=id, lazy=lazy, **kwargs)
217         )
218 
219 
220 class ProjectSnippetNote(SaveMixin, ObjectDeleteMixin, RESTObject):
221     awardemojis: ProjectSnippetNoteAwardEmojiManager
222 
223 
224 class ProjectSnippetNoteManager(CRUDMixin, RESTManager):
225     _path = "/projects/{project_id}/snippets/{snippet_id}/notes"
226     _obj_cls = ProjectSnippetNote
227     _from_parent_attrs = {"project_id": "project_id", "snippet_id": "id"}
228     _create_attrs = RequiredOptional(required=("body",))
229     _update_attrs = RequiredOptional(required=("body",))
230 
231     def get(
232         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
233     ) -> ProjectSnippetNote:
234         return cast(ProjectSnippetNote, super().get(id=id, lazy=lazy, **kwargs))
235 
236 
237 class ProjectSnippetDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):
238     pass
239 
240 
241 class ProjectSnippetDiscussionNoteManager(
242     GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager
243 ):
244     _path = (
245         "/projects/{project_id}/snippets/{snippet_id}/"
246         "discussions/{discussion_id}/notes"
247     )
248     _obj_cls = ProjectSnippetDiscussionNote
249     _from_parent_attrs = {
250         "project_id": "project_id",
251         "snippet_id": "snippet_id",
252         "discussion_id": "id",
253     }
254     _create_attrs = RequiredOptional(required=("body",), optional=("created_at",))
255     _update_attrs = RequiredOptional(required=("body",))
256 
257     def get(
258         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
259     ) -> ProjectSnippetDiscussionNote:
260         return cast(
261             ProjectSnippetDiscussionNote, super().get(id=id, lazy=lazy, **kwargs)
262         )
263
```
--- 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/notes.py b/gitlab/v4/objects/notes.py
--- a/gitlab/v4/objects/notes.py
+++ b/gitlab/v4/objects/notes.py
@@ -49,9 +49,9 @@
 
 
 class GroupEpicNoteManager(CRUDMixin, RESTManager):
-    _path = "/groups/{group_id}/epics/{epic_iid}/notes"
+    _path = "/groups/{group_id}/epics/{epic_id}/notes"
     _obj_cls = GroupEpicNote
-    _from_parent_attrs = {"group_id": "group_id", "epic_iid": "iid"}
+    _from_parent_attrs = {"group_id": "group_id", "epic_id": "id"}
     _create_attrs = RequiredOptional(required=("body",), optional=("created_at",))
     _update_attrs = RequiredOptional(required=("body",))
 
@@ -68,11 +68,11 @@
 class GroupEpicDiscussionNoteManager(
     GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager
 ):
-    _path = "/groups/{group_id}/epics/{epic_iid}/discussions/{discussion_id}/notes"
+    _path = "/groups/{group_id}/epics/{epic_id}/discussions/{discussion_id}/notes"
     _obj_cls = GroupEpicDiscussionNote
     _from_parent_attrs = {
         "group_id": "group_id",
-        "epic_iid": "epic_iid",
+        "epic_id": "epic_id",
         "discussion_id": "id",
     }
     _create_attrs = RequiredOptional(required=("body",), optional=("created_at",))

{"golden_diff": "diff --git a/gitlab/v4/objects/notes.py b/gitlab/v4/objects/notes.py\n--- a/gitlab/v4/objects/notes.py\n+++ b/gitlab/v4/objects/notes.py\n@@ -49,9 +49,9 @@\n \n \n class GroupEpicNoteManager(CRUDMixin, RESTManager):\n-    _path = \"/groups/{group_id}/epics/{epic_iid}/notes\"\n+    _path = \"/groups/{group_id}/epics/{epic_id}/notes\"\n     _obj_cls = GroupEpicNote\n-    _from_parent_attrs = {\"group_id\": \"group_id\", \"epic_iid\": \"iid\"}\n+    _from_parent_attrs = {\"group_id\": \"group_id\", \"epic_id\": \"id\"}\n     _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n     _update_attrs = RequiredOptional(required=(\"body\",))\n \n@@ -68,11 +68,11 @@\n class GroupEpicDiscussionNoteManager(\n     GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n ):\n-    _path = \"/groups/{group_id}/epics/{epic_iid}/discussions/{discussion_id}/notes\"\n+    _path = \"/groups/{group_id}/epics/{epic_id}/discussions/{discussion_id}/notes\"\n     _obj_cls = GroupEpicDiscussionNote\n     _from_parent_attrs = {\n         \"group_id\": \"group_id\",\n-        \"epic_iid\": \"epic_iid\",\n+        \"epic_id\": \"epic_id\",\n         \"discussion_id\": \"id\",\n     }\n     _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n", "issue": "Epic notes list returns 404 error\nTried using epic.notes.list() but it's returning 404 error, this matches the behavior described in https://docs.gitlab.com/ee/api/notes.html#list-all-epic-notes when **epic IID** is used.\r\n\r\nSo guessing these need to change to epic ID instead?\r\nhttps://github.com/python-gitlab/python-gitlab/blob/3f91d2455657c570851f625c0d80c685d9393cbb/gitlab/v4/objects/notes.py#L52\r\nhttps://github.com/python-gitlab/python-gitlab/blob/3f91d2455657c570851f625c0d80c685d9393cbb/gitlab/v4/objects/notes.py#L54\n", "before_files": [{"content": "from typing import Any, cast, Union\n\nfrom gitlab.base import RESTManager, RESTObject\nfrom gitlab.mixins import (\n    CreateMixin,\n    CRUDMixin,\n    DeleteMixin,\n    GetMixin,\n    ObjectDeleteMixin,\n    RetrieveMixin,\n    SaveMixin,\n    UpdateMixin,\n)\nfrom gitlab.types import RequiredOptional\n\nfrom .award_emojis import (  # noqa: F401\n    GroupEpicNoteAwardEmojiManager,\n    ProjectIssueNoteAwardEmojiManager,\n    ProjectMergeRequestNoteAwardEmojiManager,\n    ProjectSnippetNoteAwardEmojiManager,\n)\n\n__all__ = [\n    \"GroupEpicNote\",\n    \"GroupEpicNoteManager\",\n    \"GroupEpicDiscussionNote\",\n    \"GroupEpicDiscussionNoteManager\",\n    \"ProjectNote\",\n    \"ProjectNoteManager\",\n    \"ProjectCommitDiscussionNote\",\n    \"ProjectCommitDiscussionNoteManager\",\n    \"ProjectIssueNote\",\n    \"ProjectIssueNoteManager\",\n    \"ProjectIssueDiscussionNote\",\n    \"ProjectIssueDiscussionNoteManager\",\n    \"ProjectMergeRequestNote\",\n    \"ProjectMergeRequestNoteManager\",\n    \"ProjectMergeRequestDiscussionNote\",\n    \"ProjectMergeRequestDiscussionNoteManager\",\n    \"ProjectSnippetNote\",\n    \"ProjectSnippetNoteManager\",\n    \"ProjectSnippetDiscussionNote\",\n    \"ProjectSnippetDiscussionNoteManager\",\n]\n\n\nclass GroupEpicNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    awardemojis: GroupEpicNoteAwardEmojiManager\n\n\nclass GroupEpicNoteManager(CRUDMixin, RESTManager):\n    _path = \"/groups/{group_id}/epics/{epic_iid}/notes\"\n    _obj_cls = GroupEpicNote\n    _from_parent_attrs = {\"group_id\": \"group_id\", \"epic_iid\": \"iid\"}\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> GroupEpicNote:\n        return cast(GroupEpicNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass GroupEpicDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass GroupEpicDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = \"/groups/{group_id}/epics/{epic_iid}/discussions/{discussion_id}/notes\"\n    _obj_cls = GroupEpicDiscussionNote\n    _from_parent_attrs = {\n        \"group_id\": \"group_id\",\n        \"epic_iid\": \"epic_iid\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> GroupEpicDiscussionNote:\n        return cast(GroupEpicDiscussionNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectNote(RESTObject):\n    pass\n\n\nclass ProjectNoteManager(RetrieveMixin, RESTManager):\n    _path = \"/projects/{project_id}/notes\"\n    _obj_cls = ProjectNote\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _create_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectNote:\n        return cast(ProjectNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectCommitDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass ProjectCommitDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = (\n        \"/projects/{project_id}/repository/commits/{commit_id}/\"\n        \"discussions/{discussion_id}/notes\"\n    )\n    _obj_cls = ProjectCommitDiscussionNote\n    _from_parent_attrs = {\n        \"project_id\": \"project_id\",\n        \"commit_id\": \"commit_id\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(\n        required=(\"body\",), optional=(\"created_at\", \"position\")\n    )\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectCommitDiscussionNote:\n        return cast(\n            ProjectCommitDiscussionNote, super().get(id=id, lazy=lazy, **kwargs)\n        )\n\n\nclass ProjectIssueNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    awardemojis: ProjectIssueNoteAwardEmojiManager\n\n\nclass ProjectIssueNoteManager(CRUDMixin, RESTManager):\n    _path = \"/projects/{project_id}/issues/{issue_iid}/notes\"\n    _obj_cls = ProjectIssueNote\n    _from_parent_attrs = {\"project_id\": \"project_id\", \"issue_iid\": \"iid\"}\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectIssueNote:\n        return cast(ProjectIssueNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectIssueDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass ProjectIssueDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = (\n        \"/projects/{project_id}/issues/{issue_iid}/discussions/{discussion_id}/notes\"\n    )\n    _obj_cls = ProjectIssueDiscussionNote\n    _from_parent_attrs = {\n        \"project_id\": \"project_id\",\n        \"issue_iid\": \"issue_iid\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectIssueDiscussionNote:\n        return cast(ProjectIssueDiscussionNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectMergeRequestNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    awardemojis: ProjectMergeRequestNoteAwardEmojiManager\n\n\nclass ProjectMergeRequestNoteManager(CRUDMixin, RESTManager):\n    _path = \"/projects/{project_id}/merge_requests/{mr_iid}/notes\"\n    _obj_cls = ProjectMergeRequestNote\n    _from_parent_attrs = {\"project_id\": \"project_id\", \"mr_iid\": \"iid\"}\n    _create_attrs = RequiredOptional(required=(\"body\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectMergeRequestNote:\n        return cast(ProjectMergeRequestNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectMergeRequestDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass ProjectMergeRequestDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = (\n        \"/projects/{project_id}/merge_requests/{mr_iid}/\"\n        \"discussions/{discussion_id}/notes\"\n    )\n    _obj_cls = ProjectMergeRequestDiscussionNote\n    _from_parent_attrs = {\n        \"project_id\": \"project_id\",\n        \"mr_iid\": \"mr_iid\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectMergeRequestDiscussionNote:\n        return cast(\n            ProjectMergeRequestDiscussionNote, super().get(id=id, lazy=lazy, **kwargs)\n        )\n\n\nclass ProjectSnippetNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    awardemojis: ProjectSnippetNoteAwardEmojiManager\n\n\nclass ProjectSnippetNoteManager(CRUDMixin, RESTManager):\n    _path = \"/projects/{project_id}/snippets/{snippet_id}/notes\"\n    _obj_cls = ProjectSnippetNote\n    _from_parent_attrs = {\"project_id\": \"project_id\", \"snippet_id\": \"id\"}\n    _create_attrs = RequiredOptional(required=(\"body\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectSnippetNote:\n        return cast(ProjectSnippetNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectSnippetDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass ProjectSnippetDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = (\n        \"/projects/{project_id}/snippets/{snippet_id}/\"\n        \"discussions/{discussion_id}/notes\"\n    )\n    _obj_cls = ProjectSnippetDiscussionNote\n    _from_parent_attrs = {\n        \"project_id\": \"project_id\",\n        \"snippet_id\": \"snippet_id\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectSnippetDiscussionNote:\n        return cast(\n            ProjectSnippetDiscussionNote, super().get(id=id, lazy=lazy, **kwargs)\n        )\n", "path": "gitlab/v4/objects/notes.py"}], "after_files": [{"content": "from typing import Any, cast, Union\n\nfrom gitlab.base import RESTManager, RESTObject\nfrom gitlab.mixins import (\n    CreateMixin,\n    CRUDMixin,\n    DeleteMixin,\n    GetMixin,\n    ObjectDeleteMixin,\n    RetrieveMixin,\n    SaveMixin,\n    UpdateMixin,\n)\nfrom gitlab.types import RequiredOptional\n\nfrom .award_emojis import (  # noqa: F401\n    GroupEpicNoteAwardEmojiManager,\n    ProjectIssueNoteAwardEmojiManager,\n    ProjectMergeRequestNoteAwardEmojiManager,\n    ProjectSnippetNoteAwardEmojiManager,\n)\n\n__all__ = [\n    \"GroupEpicNote\",\n    \"GroupEpicNoteManager\",\n    \"GroupEpicDiscussionNote\",\n    \"GroupEpicDiscussionNoteManager\",\n    \"ProjectNote\",\n    \"ProjectNoteManager\",\n    \"ProjectCommitDiscussionNote\",\n    \"ProjectCommitDiscussionNoteManager\",\n    \"ProjectIssueNote\",\n    \"ProjectIssueNoteManager\",\n    \"ProjectIssueDiscussionNote\",\n    \"ProjectIssueDiscussionNoteManager\",\n    \"ProjectMergeRequestNote\",\n    \"ProjectMergeRequestNoteManager\",\n    \"ProjectMergeRequestDiscussionNote\",\n    \"ProjectMergeRequestDiscussionNoteManager\",\n    \"ProjectSnippetNote\",\n    \"ProjectSnippetNoteManager\",\n    \"ProjectSnippetDiscussionNote\",\n    \"ProjectSnippetDiscussionNoteManager\",\n]\n\n\nclass GroupEpicNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    awardemojis: GroupEpicNoteAwardEmojiManager\n\n\nclass GroupEpicNoteManager(CRUDMixin, RESTManager):\n    _path = \"/groups/{group_id}/epics/{epic_id}/notes\"\n    _obj_cls = GroupEpicNote\n    _from_parent_attrs = {\"group_id\": \"group_id\", \"epic_id\": \"id\"}\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> GroupEpicNote:\n        return cast(GroupEpicNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass GroupEpicDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass GroupEpicDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = \"/groups/{group_id}/epics/{epic_id}/discussions/{discussion_id}/notes\"\n    _obj_cls = GroupEpicDiscussionNote\n    _from_parent_attrs = {\n        \"group_id\": \"group_id\",\n        \"epic_id\": \"epic_id\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> GroupEpicDiscussionNote:\n        return cast(GroupEpicDiscussionNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectNote(RESTObject):\n    pass\n\n\nclass ProjectNoteManager(RetrieveMixin, RESTManager):\n    _path = \"/projects/{project_id}/notes\"\n    _obj_cls = ProjectNote\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _create_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectNote:\n        return cast(ProjectNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectCommitDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass ProjectCommitDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = (\n        \"/projects/{project_id}/repository/commits/{commit_id}/\"\n        \"discussions/{discussion_id}/notes\"\n    )\n    _obj_cls = ProjectCommitDiscussionNote\n    _from_parent_attrs = {\n        \"project_id\": \"project_id\",\n        \"commit_id\": \"commit_id\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(\n        required=(\"body\",), optional=(\"created_at\", \"position\")\n    )\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectCommitDiscussionNote:\n        return cast(\n            ProjectCommitDiscussionNote, super().get(id=id, lazy=lazy, **kwargs)\n        )\n\n\nclass ProjectIssueNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    awardemojis: ProjectIssueNoteAwardEmojiManager\n\n\nclass ProjectIssueNoteManager(CRUDMixin, RESTManager):\n    _path = \"/projects/{project_id}/issues/{issue_iid}/notes\"\n    _obj_cls = ProjectIssueNote\n    _from_parent_attrs = {\"project_id\": \"project_id\", \"issue_iid\": \"iid\"}\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectIssueNote:\n        return cast(ProjectIssueNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectIssueDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass ProjectIssueDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = (\n        \"/projects/{project_id}/issues/{issue_iid}/discussions/{discussion_id}/notes\"\n    )\n    _obj_cls = ProjectIssueDiscussionNote\n    _from_parent_attrs = {\n        \"project_id\": \"project_id\",\n        \"issue_iid\": \"issue_iid\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectIssueDiscussionNote:\n        return cast(ProjectIssueDiscussionNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectMergeRequestNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    awardemojis: ProjectMergeRequestNoteAwardEmojiManager\n\n\nclass ProjectMergeRequestNoteManager(CRUDMixin, RESTManager):\n    _path = \"/projects/{project_id}/merge_requests/{mr_iid}/notes\"\n    _obj_cls = ProjectMergeRequestNote\n    _from_parent_attrs = {\"project_id\": \"project_id\", \"mr_iid\": \"iid\"}\n    _create_attrs = RequiredOptional(required=(\"body\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectMergeRequestNote:\n        return cast(ProjectMergeRequestNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectMergeRequestDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass ProjectMergeRequestDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = (\n        \"/projects/{project_id}/merge_requests/{mr_iid}/\"\n        \"discussions/{discussion_id}/notes\"\n    )\n    _obj_cls = ProjectMergeRequestDiscussionNote\n    _from_parent_attrs = {\n        \"project_id\": \"project_id\",\n        \"mr_iid\": \"mr_iid\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectMergeRequestDiscussionNote:\n        return cast(\n            ProjectMergeRequestDiscussionNote, super().get(id=id, lazy=lazy, **kwargs)\n        )\n\n\nclass ProjectSnippetNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    awardemojis: ProjectSnippetNoteAwardEmojiManager\n\n\nclass ProjectSnippetNoteManager(CRUDMixin, RESTManager):\n    _path = \"/projects/{project_id}/snippets/{snippet_id}/notes\"\n    _obj_cls = ProjectSnippetNote\n    _from_parent_attrs = {\"project_id\": \"project_id\", \"snippet_id\": \"id\"}\n    _create_attrs = RequiredOptional(required=(\"body\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectSnippetNote:\n        return cast(ProjectSnippetNote, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectSnippetDiscussionNote(SaveMixin, ObjectDeleteMixin, RESTObject):\n    pass\n\n\nclass ProjectSnippetDiscussionNoteManager(\n    GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager\n):\n    _path = (\n        \"/projects/{project_id}/snippets/{snippet_id}/\"\n        \"discussions/{discussion_id}/notes\"\n    )\n    _obj_cls = ProjectSnippetDiscussionNote\n    _from_parent_attrs = {\n        \"project_id\": \"project_id\",\n        \"snippet_id\": \"snippet_id\",\n        \"discussion_id\": \"id\",\n    }\n    _create_attrs = RequiredOptional(required=(\"body\",), optional=(\"created_at\",))\n    _update_attrs = RequiredOptional(required=(\"body\",))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectSnippetDiscussionNote:\n        return cast(\n            ProjectSnippetDiscussionNote, super().get(id=id, lazy=lazy, **kwargs)\n        )\n", "path": "gitlab/v4/objects/notes.py"}]}