We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Allow update of protected branches
In gitlab 15.6 gitlab finally added api support to update protected branch settings, so ProjectProtectedBranch should be updated accordingly

https://gitlab.com/gitlab-org/gitlab/-/issues/20229/




--- 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/branches.py`
Content:
```
1 from typing import Any, cast, Union
2 
3 from gitlab.base import RESTManager, RESTObject
4 from gitlab.mixins import NoUpdateMixin, ObjectDeleteMixin
5 from gitlab.types import RequiredOptional
6 
7 __all__ = [
8     "ProjectBranch",
9     "ProjectBranchManager",
10     "ProjectProtectedBranch",
11     "ProjectProtectedBranchManager",
12 ]
13 
14 
15 class ProjectBranch(ObjectDeleteMixin, RESTObject):
16     _id_attr = "name"
17 
18 
19 class ProjectBranchManager(NoUpdateMixin, RESTManager):
20     _path = "/projects/{project_id}/repository/branches"
21     _obj_cls = ProjectBranch
22     _from_parent_attrs = {"project_id": "id"}
23     _create_attrs = RequiredOptional(required=("branch", "ref"))
24 
25     def get(
26         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
27     ) -> ProjectBranch:
28         return cast(ProjectBranch, super().get(id=id, lazy=lazy, **kwargs))
29 
30 
31 class ProjectProtectedBranch(ObjectDeleteMixin, RESTObject):
32     _id_attr = "name"
33 
34 
35 class ProjectProtectedBranchManager(NoUpdateMixin, RESTManager):
36     _path = "/projects/{project_id}/protected_branches"
37     _obj_cls = ProjectProtectedBranch
38     _from_parent_attrs = {"project_id": "id"}
39     _create_attrs = RequiredOptional(
40         required=("name",),
41         optional=(
42             "push_access_level",
43             "merge_access_level",
44             "unprotect_access_level",
45             "allow_force_push",
46             "allowed_to_push",
47             "allowed_to_merge",
48             "allowed_to_unprotect",
49             "code_owner_approval_required",
50         ),
51     )
52 
53     def get(
54         self, id: Union[str, int], lazy: bool = False, **kwargs: Any
55     ) -> ProjectProtectedBranch:
56         return cast(ProjectProtectedBranch, super().get(id=id, lazy=lazy, **kwargs))
57
```
--- 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/branches.py b/gitlab/v4/objects/branches.py
--- a/gitlab/v4/objects/branches.py
+++ b/gitlab/v4/objects/branches.py
@@ -1,7 +1,13 @@
 from typing import Any, cast, Union
 
 from gitlab.base import RESTManager, RESTObject
-from gitlab.mixins import NoUpdateMixin, ObjectDeleteMixin
+from gitlab.mixins import (
+    CRUDMixin,
+    NoUpdateMixin,
+    ObjectDeleteMixin,
+    SaveMixin,
+    UpdateMethod,
+)
 from gitlab.types import RequiredOptional
 
 __all__ = [
@@ -28,11 +34,11 @@
         return cast(ProjectBranch, super().get(id=id, lazy=lazy, **kwargs))
 
 
-class ProjectProtectedBranch(ObjectDeleteMixin, RESTObject):
+class ProjectProtectedBranch(SaveMixin, ObjectDeleteMixin, RESTObject):
     _id_attr = "name"
 
 
-class ProjectProtectedBranchManager(NoUpdateMixin, RESTManager):
+class ProjectProtectedBranchManager(CRUDMixin, RESTManager):
     _path = "/projects/{project_id}/protected_branches"
     _obj_cls = ProjectProtectedBranch
     _from_parent_attrs = {"project_id": "id"}
@@ -49,6 +55,7 @@
             "code_owner_approval_required",
         ),
     )
+    _update_method = UpdateMethod.PATCH
 
     def get(
         self, id: Union[str, int], lazy: bool = False, **kwargs: Any

{"golden_diff": "diff --git a/gitlab/v4/objects/branches.py b/gitlab/v4/objects/branches.py\n--- a/gitlab/v4/objects/branches.py\n+++ b/gitlab/v4/objects/branches.py\n@@ -1,7 +1,13 @@\n from typing import Any, cast, Union\n \n from gitlab.base import RESTManager, RESTObject\n-from gitlab.mixins import NoUpdateMixin, ObjectDeleteMixin\n+from gitlab.mixins import (\n+    CRUDMixin,\n+    NoUpdateMixin,\n+    ObjectDeleteMixin,\n+    SaveMixin,\n+    UpdateMethod,\n+)\n from gitlab.types import RequiredOptional\n \n __all__ = [\n@@ -28,11 +34,11 @@\n         return cast(ProjectBranch, super().get(id=id, lazy=lazy, **kwargs))\n \n \n-class ProjectProtectedBranch(ObjectDeleteMixin, RESTObject):\n+class ProjectProtectedBranch(SaveMixin, ObjectDeleteMixin, RESTObject):\n     _id_attr = \"name\"\n \n \n-class ProjectProtectedBranchManager(NoUpdateMixin, RESTManager):\n+class ProjectProtectedBranchManager(CRUDMixin, RESTManager):\n     _path = \"/projects/{project_id}/protected_branches\"\n     _obj_cls = ProjectProtectedBranch\n     _from_parent_attrs = {\"project_id\": \"id\"}\n@@ -49,6 +55,7 @@\n             \"code_owner_approval_required\",\n         ),\n     )\n+    _update_method = UpdateMethod.PATCH\n \n     def get(\n         self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n", "issue": "Allow update of protected branches\nIn gitlab 15.6 gitlab finally added api support to update protected branch settings, so ProjectProtectedBranch should be updated accordingly\r\n\r\nhttps://gitlab.com/gitlab-org/gitlab/-/issues/20229/\r\n\r\n\r\n\n", "before_files": [{"content": "from typing import Any, cast, Union\n\nfrom gitlab.base import RESTManager, RESTObject\nfrom gitlab.mixins import NoUpdateMixin, ObjectDeleteMixin\nfrom gitlab.types import RequiredOptional\n\n__all__ = [\n    \"ProjectBranch\",\n    \"ProjectBranchManager\",\n    \"ProjectProtectedBranch\",\n    \"ProjectProtectedBranchManager\",\n]\n\n\nclass ProjectBranch(ObjectDeleteMixin, RESTObject):\n    _id_attr = \"name\"\n\n\nclass ProjectBranchManager(NoUpdateMixin, RESTManager):\n    _path = \"/projects/{project_id}/repository/branches\"\n    _obj_cls = ProjectBranch\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _create_attrs = RequiredOptional(required=(\"branch\", \"ref\"))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectBranch:\n        return cast(ProjectBranch, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectProtectedBranch(ObjectDeleteMixin, RESTObject):\n    _id_attr = \"name\"\n\n\nclass ProjectProtectedBranchManager(NoUpdateMixin, RESTManager):\n    _path = \"/projects/{project_id}/protected_branches\"\n    _obj_cls = ProjectProtectedBranch\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _create_attrs = RequiredOptional(\n        required=(\"name\",),\n        optional=(\n            \"push_access_level\",\n            \"merge_access_level\",\n            \"unprotect_access_level\",\n            \"allow_force_push\",\n            \"allowed_to_push\",\n            \"allowed_to_merge\",\n            \"allowed_to_unprotect\",\n            \"code_owner_approval_required\",\n        ),\n    )\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectProtectedBranch:\n        return cast(ProjectProtectedBranch, super().get(id=id, lazy=lazy, **kwargs))\n", "path": "gitlab/v4/objects/branches.py"}], "after_files": [{"content": "from typing import Any, cast, Union\n\nfrom gitlab.base import RESTManager, RESTObject\nfrom gitlab.mixins import (\n    CRUDMixin,\n    NoUpdateMixin,\n    ObjectDeleteMixin,\n    SaveMixin,\n    UpdateMethod,\n)\nfrom gitlab.types import RequiredOptional\n\n__all__ = [\n    \"ProjectBranch\",\n    \"ProjectBranchManager\",\n    \"ProjectProtectedBranch\",\n    \"ProjectProtectedBranchManager\",\n]\n\n\nclass ProjectBranch(ObjectDeleteMixin, RESTObject):\n    _id_attr = \"name\"\n\n\nclass ProjectBranchManager(NoUpdateMixin, RESTManager):\n    _path = \"/projects/{project_id}/repository/branches\"\n    _obj_cls = ProjectBranch\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _create_attrs = RequiredOptional(required=(\"branch\", \"ref\"))\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectBranch:\n        return cast(ProjectBranch, super().get(id=id, lazy=lazy, **kwargs))\n\n\nclass ProjectProtectedBranch(SaveMixin, ObjectDeleteMixin, RESTObject):\n    _id_attr = \"name\"\n\n\nclass ProjectProtectedBranchManager(CRUDMixin, RESTManager):\n    _path = \"/projects/{project_id}/protected_branches\"\n    _obj_cls = ProjectProtectedBranch\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _create_attrs = RequiredOptional(\n        required=(\"name\",),\n        optional=(\n            \"push_access_level\",\n            \"merge_access_level\",\n            \"unprotect_access_level\",\n            \"allow_force_push\",\n            \"allowed_to_push\",\n            \"allowed_to_merge\",\n            \"allowed_to_unprotect\",\n            \"code_owner_approval_required\",\n        ),\n    )\n    _update_method = UpdateMethod.PATCH\n\n    def get(\n        self, id: Union[str, int], lazy: bool = False, **kwargs: Any\n    ) -> ProjectProtectedBranch:\n        return cast(ProjectProtectedBranch, super().get(id=id, lazy=lazy, **kwargs))\n", "path": "gitlab/v4/objects/branches.py"}]}