codemie-sdk-python 0.1.520__tar.gz → 0.1.522__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/PKG-INFO +1 -1
  2. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/pyproject.toml +1 -1
  3. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/__init__.py +6 -4
  4. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/assistant.py +35 -8
  5. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/assistant.py +57 -42
  6. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/datasource.py +43 -12
  7. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/utils/http.py +34 -0
  8. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/README.md +0 -0
  9. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/auth/__init__.py +0 -0
  10. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/auth/credentials.py +0 -0
  11. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/client/__init__.py +0 -0
  12. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/client/client.py +0 -0
  13. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/exceptions.py +0 -0
  14. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/__init__.py +0 -0
  15. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/activity_event.py +0 -0
  16. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/admin.py +0 -0
  17. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/analytics.py +0 -0
  18. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/categories.py +0 -0
  19. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/common.py +0 -0
  20. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/conversation.py +0 -0
  21. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/datasource.py +0 -0
  22. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/errors.py +0 -0
  23. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/file_operation.py +0 -0
  24. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/guardrails.py +0 -0
  25. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/integration.py +0 -0
  26. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/llm.py +0 -0
  27. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/mermaid.py +0 -0
  28. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/project.py +0 -0
  29. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/skill.py +0 -0
  30. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/task.py +0 -0
  31. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/user.py +0 -0
  32. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/vendor_assistant.py +0 -0
  33. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/vendor_guardrail.py +0 -0
  34. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/vendor_knowledgebase.py +0 -0
  35. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/vendor_runtime.py +0 -0
  36. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/vendor_workflow.py +0 -0
  37. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/workflow.py +0 -0
  38. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/workflow_execution_payload.py +0 -0
  39. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/workflow_state.py +0 -0
  40. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/workflow_thoughts.py +0 -0
  41. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/models/workflow_transition.py +0 -0
  42. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/activity_event.py +0 -0
  43. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/admin.py +0 -0
  44. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/analytics.py +0 -0
  45. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/categories.py +0 -0
  46. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/codemie_guardrails.py +0 -0
  47. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/conversation.py +0 -0
  48. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/files.py +0 -0
  49. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/integration.py +0 -0
  50. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/llm.py +0 -0
  51. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/mermaid.py +0 -0
  52. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/project.py +0 -0
  53. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/skill.py +0 -0
  54. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/task.py +0 -0
  55. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/user.py +0 -0
  56. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/vendor_assistant.py +0 -0
  57. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/vendor_guardrail.py +0 -0
  58. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/vendor_knowledgebase.py +0 -0
  59. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/vendor_runtime.py +0 -0
  60. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/vendor_workflow.py +0 -0
  61. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/webhook.py +0 -0
  62. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/workflow.py +0 -0
  63. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/workflow_execution.py +0 -0
  64. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/services/workflow_execution_state.py +0 -0
  65. {codemie_sdk_python-0.1.520 → codemie_sdk_python-0.1.522}/src/codemie_sdk/utils/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codemie-sdk-python
3
- Version: 0.1.520
3
+ Version: 0.1.522
4
4
  Summary: CodeMie SDK for Python
5
5
  Author: Vadym Vlasenko
6
6
  Author-email: vadym_vlasenko@epam.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "codemie-sdk-python"
3
- version = "0.1.520"
3
+ version = "0.1.522"
4
4
  description = "CodeMie SDK for Python"
5
5
  authors = [
6
6
  "Vadym Vlasenko <vadym_vlasenko@epam.com>",
@@ -152,12 +152,17 @@ from .models.assistant import (
152
152
  BuiltinSubagent,
153
153
  AssistantProjectFeature,
154
154
  AssistantProjectMappingRequest,
155
- AssistantProjectMappingResponse,
155
+ AssistantProjectMappingPagination,
156
+ AssistantProjectMappingListResponse,
156
157
  )
157
158
 
158
159
  __version__ = "0.2.12"
159
160
  __all__ = [
160
161
  "CodeMieClient",
162
+ "AssistantProjectFeature",
163
+ "AssistantProjectMappingRequest",
164
+ "AssistantProjectMappingPagination",
165
+ "AssistantProjectMappingListResponse",
161
166
  "VendorType",
162
167
  "VendorAssistantSetting",
163
168
  "VendorAssistantSettingsResponse",
@@ -269,7 +274,4 @@ __all__ = [
269
274
  "SkillPagination",
270
275
  "SkillService",
271
276
  "BuiltinSubagent",
272
- "AssistantProjectFeature",
273
- "AssistantProjectMappingRequest",
274
- "AssistantProjectMappingResponse",
275
277
  ]
@@ -610,23 +610,50 @@ class ReactionRequest(BaseModel):
610
610
 
611
611
 
612
612
  class AssistantProjectFeature(str, Enum):
613
- """Enum for assistant project feature discriminators."""
613
+ """Feature discriminator for assistant/project mappings (e.g. Teams bot).
614
614
 
615
- teams = "teams"
615
+ This enum is expected to grow over time on the backend; treat unrecognized
616
+ wire values defensively rather than assuming this is the complete set.
617
+ """
618
+
619
+ TEAMS = "teams"
616
620
 
617
621
 
618
622
  class AssistantProjectMappingRequest(BaseModel):
619
- """Request body for enabling an assistant for a project feature."""
623
+ """Request body for POST /v1/assistants/{assistant_id}/projects/mapping."""
620
624
 
621
625
  model_config = ConfigDict(extra="ignore", use_enum_values=True)
622
626
 
623
- project_name: str = Field(description="Project identifier")
624
- feature: AssistantProjectFeature = Field(description="Feature discriminator")
627
+ project_name: str = Field(description="Project (application) name")
628
+ feature: AssistantProjectFeature = Field(
629
+ description="Feature discriminator this mapping is for, e.g. 'teams'"
630
+ )
631
+
632
+
633
+ class AssistantProjectMappingPagination(BaseModel):
634
+ """Pagination metadata returned by GET /v1/assistants/projects/mapping."""
635
+
636
+ model_config = ConfigDict(extra="ignore")
637
+
638
+ page: int = Field(description="Current page, 0-indexed")
639
+ per_page: int = Field(description="Items per page")
640
+ total: int = Field(description="Total matching assistants across all pages")
625
641
 
626
642
 
627
- class AssistantProjectMappingResponse(BaseModel):
628
- """Response for assistant project mapping operations."""
643
+ class AssistantProjectMappingListResponse(BaseModel):
644
+ """Response for GET /v1/assistants/projects/mapping.
645
+
646
+ List items are intentionally typed as ``dict[str, Any]`` rather than
647
+ ``Assistant``/``AssistantBase``. The backend contract documents this
648
+ endpoint as returning "the same shape as GET /v1/assistants", but that
649
+ endpoint's own shape is parameterized by a ``minimal_response`` flag that
650
+ this new endpoint does not expose, and the exact per-item fields returned
651
+ here are not otherwise confirmed. Rather than guess the wire format,
652
+ callers get the raw dict and can assert on whichever fields they need
653
+ (e.g. ``item["id"]``).
654
+ """
629
655
 
630
656
  model_config = ConfigDict(extra="ignore")
631
657
 
632
- message: str = Field(description="Operation result message")
658
+ data: list[dict[str, Any]] = Field(default_factory=list)
659
+ pagination: AssistantProjectMappingPagination
@@ -30,9 +30,10 @@ from ..models.assistant import (
30
30
  ReactionRequest,
31
31
  AssistantProjectFeature,
32
32
  AssistantProjectMappingRequest,
33
- AssistantProjectMappingResponse,
33
+ AssistantProjectMappingListResponse,
34
34
  )
35
35
  from ..models.common import PaginationParams
36
+ from ..models.conversation import BaseResponse
36
37
  from ..utils import ApiRequestHandler, TokenSource
37
38
 
38
39
 
@@ -613,78 +614,92 @@ class AssistantService:
613
614
 
614
615
  def list_project_mapping(
615
616
  self,
616
- feature: Union[AssistantProjectFeature, str],
617
- project: str,
617
+ project_name: str,
618
+ feature: AssistantProjectFeature = AssistantProjectFeature.TEAMS,
618
619
  page: int = 0,
619
620
  per_page: int = 12,
620
- ) -> list[Assistant]:
621
- """List assistants enabled for a project feature.
621
+ ) -> AssistantProjectMappingListResponse:
622
+ """List assistants enabled for a project feature (e.g. Teams bot).
623
+
624
+ Accessible to any member of ``project_name``, not just project admins.
622
625
 
623
626
  Args:
624
- feature: Feature discriminator (e.g. "teams")
625
- project: Project name (application name)
626
- page: 0-indexed page number
627
- per_page: Items per page (max 100)
627
+ project_name: Project (application) name to list mappings for
628
+ feature: Feature discriminator, currently only "teams"
629
+ page: Page number, 0-indexed
630
+ per_page: Items per page (default 12, max 10000)
628
631
 
629
632
  Returns:
630
- List of assistants mapped to the project feature
633
+ Paginated list of assistants enabled for the project feature
631
634
  """
632
- params = {
633
- "feature": feature if isinstance(feature, str) else feature.value,
634
- "project": project,
635
- "page": page,
636
- "per_page": per_page,
637
- }
635
+ feature_value = (
636
+ feature.value if isinstance(feature, AssistantProjectFeature) else feature
637
+ )
638
+ params = PaginationParams(page=page, per_page=per_page).to_dict()
639
+ params["feature"] = feature_value
640
+ params["project"] = project_name
638
641
  return self._api.get(
639
- "/v1/assistants/projects/mapping", list[Assistant], params=params
642
+ "/v1/assistants/projects/mapping",
643
+ AssistantProjectMappingListResponse,
644
+ params=params,
645
+ wrap_response=False,
640
646
  )
641
647
 
642
- def enable_project_mapping(
648
+ def enable_for_project(
643
649
  self,
644
650
  assistant_id: str,
645
- request: AssistantProjectMappingRequest,
646
- ) -> AssistantProjectMappingResponse:
647
- """Enable an assistant for a project feature.
651
+ project_name: str,
652
+ feature: AssistantProjectFeature = AssistantProjectFeature.TEAMS,
653
+ ) -> BaseResponse:
654
+ """Enable an assistant for a project feature (e.g. Teams bot).
648
655
 
649
- Idempotent: returns 200 whether the mapping already existed or not.
656
+ Idempotent calling this when the mapping already exists returns 200
657
+ with no error. Requires the caller to be a project admin/maintainer
658
+ (or application admin) for ``project_name``.
650
659
 
651
660
  Args:
652
- assistant_id: UUID of the assistant
653
- request: Mapping request with project_name and feature
661
+ assistant_id: ID of the assistant to enable
662
+ project_name: Project (application) name to enable the mapping for
663
+ feature: Feature discriminator, currently only "teams"
654
664
 
655
665
  Returns:
656
- AssistantProjectMappingResponse with confirmation message
666
+ Response confirming the assistant was enabled
657
667
  """
668
+ request = AssistantProjectMappingRequest(
669
+ project_name=project_name, feature=feature
670
+ )
658
671
  return self._api.post(
659
672
  f"/v1/assistants/{assistant_id}/projects/mapping",
660
- AssistantProjectMappingResponse,
673
+ BaseResponse,
661
674
  json_data=request.model_dump(exclude_none=True),
662
- wrap_response=False,
663
675
  )
664
676
 
665
- def disable_project_mapping(
677
+ def disable_for_project(
666
678
  self,
667
679
  assistant_id: str,
668
- project: str,
669
- feature: Union[AssistantProjectFeature, str],
670
- ) -> AssistantProjectMappingResponse:
671
- """Disable an assistant for a project feature.
680
+ project_name: str,
681
+ feature: AssistantProjectFeature = AssistantProjectFeature.TEAMS,
682
+ ) -> BaseResponse:
683
+ """Disable an assistant for a project feature (e.g. Teams bot).
684
+
685
+ Raises an HTTP error (404) if the mapping does not exist. Requires the
686
+ caller to be a project admin/maintainer (or application admin) for
687
+ ``project_name``.
672
688
 
673
689
  Args:
674
- assistant_id: UUID of the assistant
675
- project: Project name
676
- feature: Feature discriminator (e.g. "teams")
690
+ assistant_id: ID of the assistant to disable
691
+ project_name: Project (application) name to disable the mapping for
692
+ feature: Feature discriminator, currently only "teams"
677
693
 
678
694
  Returns:
679
- AssistantProjectMappingResponse with confirmation message
695
+ Response confirming the assistant was disabled
680
696
  """
681
- params = {
682
- "project": project,
683
- "feature": feature if isinstance(feature, str) else feature.value,
684
- }
697
+ feature_value = (
698
+ feature.value if isinstance(feature, AssistantProjectFeature) else feature
699
+ )
700
+ params = {"project": project_name, "feature": feature_value}
685
701
  return self._api.delete(
686
702
  f"/v1/assistants/{assistant_id}/projects/mapping",
687
- AssistantProjectMappingResponse,
703
+ BaseResponse,
688
704
  params=params,
689
- wrap_response=False,
690
705
  )
@@ -60,26 +60,20 @@ class DatasourceService:
60
60
  json_data=request.model_dump(by_alias=True, exclude_none=True),
61
61
  )
62
62
 
63
- def create_file_datasource(
64
- self,
65
- request: FileDataSourceRequest,
63
+ @staticmethod
64
+ def _build_file_uploads(
66
65
  files: list[str | Tuple[str, bytes, str]],
67
- ) -> dict:
68
- """Create a new file datasource with file uploads.
66
+ ) -> list[tuple[str, tuple[str, bytes, str]]]:
67
+ """Build multipart file tuples from file paths or (filename, content, mime_type) tuples.
69
68
 
70
69
  Args:
71
- request: File datasource creation request
72
70
  files: List of files to upload. Each item can be:
73
71
  - str: file path (will read file and detect MIME type)
74
72
  - Tuple[str, bytes, str]: (filename, content, mime_type)
75
73
 
76
74
  Returns:
77
- dict: Response from the server containing operation status
75
+ list: Multipart-ready ("files", (filename, content, mime_type)) tuples
78
76
  """
79
- endpoint = "/v1/index/knowledge_base/file"
80
-
81
- # Prepare multipart form data
82
- params = request.model_dump(by_alias=True, exclude_none=True)
83
77
  file_uploads = []
84
78
 
85
79
  for file_item in files:
@@ -106,15 +100,47 @@ class DatasourceService:
106
100
  "Each file must be either a file path (str) or a tuple of (filename, content, mime_type)"
107
101
  )
108
102
 
103
+ return file_uploads
104
+
105
+ def create_file_datasource(
106
+ self,
107
+ request: FileDataSourceRequest,
108
+ files: list[str | Tuple[str, bytes, str]],
109
+ ) -> dict:
110
+ """Create a new file datasource with file uploads.
111
+
112
+ Args:
113
+ request: File datasource creation request
114
+ files: List of files to upload. Each item can be:
115
+ - str: file path (will read file and detect MIME type)
116
+ - Tuple[str, bytes, str]: (filename, content, mime_type)
117
+
118
+ Returns:
119
+ dict: Response from the server containing operation status
120
+ """
121
+ endpoint = "/v1/index/knowledge_base/file"
122
+
123
+ # Prepare multipart form data
124
+ params = request.model_dump(by_alias=True, exclude_none=True)
125
+ file_uploads = self._build_file_uploads(files)
126
+
109
127
  return self._api.post_multipart(
110
128
  endpoint, dict, params=params, files=file_uploads
111
129
  )
112
130
 
113
- def update(self, datasource_id: str, request: BaseUpdateDataSourceRequest) -> dict:
131
+ def update(
132
+ self,
133
+ datasource_id: str,
134
+ request: BaseUpdateDataSourceRequest,
135
+ files: list[str | Tuple[str, bytes, str]] | None = None,
136
+ ) -> dict:
114
137
  """Update an existing datasource.
115
138
 
116
139
  Args:
117
140
  request: Update datasource request
141
+ files: Optional list of files to add to a File datasource. Each item
142
+ can be a file path (str) or a (filename, content, mime_type)
143
+ tuple. Only supported for UpdateFileDataSourceRequest.
118
144
 
119
145
  Returns:
120
146
  dict: Response from the server containing operation status
@@ -140,6 +166,11 @@ class DatasourceService:
140
166
  # PUT /index/knowledge_base/file now uses Depends() — all fields are query params
141
167
  if isinstance(request, UpdateFileDataSourceRequest):
142
168
  params.update(data)
169
+ if files:
170
+ file_uploads = self._build_file_uploads(files)
171
+ return self._api.put_multipart(
172
+ endpoint, dict, params=params, files=file_uploads
173
+ )
143
174
  return self._api.put(endpoint, dict, {}, params=params)
144
175
 
145
176
  return self._api.put(endpoint, dict, params=params, json_data=data)
@@ -274,6 +274,40 @@ class ApiRequestHandler:
274
274
 
275
275
  return self._parse_response(response, response_model, wrap_response)
276
276
 
277
+ @log_request
278
+ def put_multipart(
279
+ self,
280
+ endpoint: str,
281
+ response_model: Type[T],
282
+ params: dict[str, Any] | None = None,
283
+ files: list | None = None,
284
+ wrap_response: bool = True,
285
+ ) -> T:
286
+ """Makes a PUT multipart/form-data request and parses the response.
287
+
288
+ Args:
289
+ endpoint: API endpoint path
290
+ response_model: Pydantic model class or list[Model] for response
291
+ params: Url parameters
292
+ files: List of file tuples for upload
293
+ wrap_response: Whether response is wrapped in 'data' field
294
+
295
+ Returns:
296
+ Parsed response object or list of objects
297
+ """
298
+ response = requests.put(
299
+ url=f"{self._base_url}{endpoint}",
300
+ headers=self._get_headers(
301
+ exclude_content_type=True
302
+ ), # Let requests set multipart content-type
303
+ params=params,
304
+ files=files,
305
+ verify=self._verify_ssl,
306
+ )
307
+ response.raise_for_status()
308
+
309
+ return self._parse_response(response, response_model, wrap_response)
310
+
277
311
  @log_request
278
312
  def put(
279
313
  self,