elasticsearch9 9.0.0__py3-none-any.whl

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 (160) hide show
  1. elasticsearch9/__init__.py +98 -0
  2. elasticsearch9/_async/__init__.py +16 -0
  3. elasticsearch9/_async/client/__init__.py +6531 -0
  4. elasticsearch9/_async/client/_base.py +430 -0
  5. elasticsearch9/_async/client/async_search.py +637 -0
  6. elasticsearch9/_async/client/autoscaling.py +252 -0
  7. elasticsearch9/_async/client/cat.py +2995 -0
  8. elasticsearch9/_async/client/ccr.py +1043 -0
  9. elasticsearch9/_async/client/cluster.py +1223 -0
  10. elasticsearch9/_async/client/connector.py +1978 -0
  11. elasticsearch9/_async/client/dangling_indices.py +192 -0
  12. elasticsearch9/_async/client/enrich.py +291 -0
  13. elasticsearch9/_async/client/eql.py +359 -0
  14. elasticsearch9/_async/client/esql.py +490 -0
  15. elasticsearch9/_async/client/features.py +130 -0
  16. elasticsearch9/_async/client/fleet.py +658 -0
  17. elasticsearch9/_async/client/graph.py +113 -0
  18. elasticsearch9/_async/client/ilm.py +668 -0
  19. elasticsearch9/_async/client/indices.py +5582 -0
  20. elasticsearch9/_async/client/inference.py +2247 -0
  21. elasticsearch9/_async/client/ingest.py +766 -0
  22. elasticsearch9/_async/client/license.py +400 -0
  23. elasticsearch9/_async/client/logstash.py +176 -0
  24. elasticsearch9/_async/client/migration.py +160 -0
  25. elasticsearch9/_async/client/ml.py +5835 -0
  26. elasticsearch9/_async/client/monitoring.py +100 -0
  27. elasticsearch9/_async/client/nodes.py +543 -0
  28. elasticsearch9/_async/client/query_rules.py +485 -0
  29. elasticsearch9/_async/client/rollup.py +616 -0
  30. elasticsearch9/_async/client/search_application.py +574 -0
  31. elasticsearch9/_async/client/searchable_snapshots.py +313 -0
  32. elasticsearch9/_async/client/security.py +4688 -0
  33. elasticsearch9/_async/client/shutdown.py +268 -0
  34. elasticsearch9/_async/client/simulate.py +145 -0
  35. elasticsearch9/_async/client/slm.py +559 -0
  36. elasticsearch9/_async/client/snapshot.py +1338 -0
  37. elasticsearch9/_async/client/sql.py +469 -0
  38. elasticsearch9/_async/client/ssl.py +76 -0
  39. elasticsearch9/_async/client/synonyms.py +413 -0
  40. elasticsearch9/_async/client/tasks.py +295 -0
  41. elasticsearch9/_async/client/text_structure.py +664 -0
  42. elasticsearch9/_async/client/transform.py +922 -0
  43. elasticsearch9/_async/client/utils.py +48 -0
  44. elasticsearch9/_async/client/watcher.py +894 -0
  45. elasticsearch9/_async/client/xpack.py +134 -0
  46. elasticsearch9/_async/helpers.py +596 -0
  47. elasticsearch9/_otel.py +110 -0
  48. elasticsearch9/_sync/__init__.py +16 -0
  49. elasticsearch9/_sync/client/__init__.py +6529 -0
  50. elasticsearch9/_sync/client/_base.py +430 -0
  51. elasticsearch9/_sync/client/async_search.py +637 -0
  52. elasticsearch9/_sync/client/autoscaling.py +252 -0
  53. elasticsearch9/_sync/client/cat.py +2995 -0
  54. elasticsearch9/_sync/client/ccr.py +1043 -0
  55. elasticsearch9/_sync/client/cluster.py +1223 -0
  56. elasticsearch9/_sync/client/connector.py +1978 -0
  57. elasticsearch9/_sync/client/dangling_indices.py +192 -0
  58. elasticsearch9/_sync/client/enrich.py +291 -0
  59. elasticsearch9/_sync/client/eql.py +359 -0
  60. elasticsearch9/_sync/client/esql.py +490 -0
  61. elasticsearch9/_sync/client/features.py +130 -0
  62. elasticsearch9/_sync/client/fleet.py +658 -0
  63. elasticsearch9/_sync/client/graph.py +113 -0
  64. elasticsearch9/_sync/client/ilm.py +668 -0
  65. elasticsearch9/_sync/client/indices.py +5582 -0
  66. elasticsearch9/_sync/client/inference.py +2247 -0
  67. elasticsearch9/_sync/client/ingest.py +766 -0
  68. elasticsearch9/_sync/client/license.py +400 -0
  69. elasticsearch9/_sync/client/logstash.py +176 -0
  70. elasticsearch9/_sync/client/migration.py +160 -0
  71. elasticsearch9/_sync/client/ml.py +5835 -0
  72. elasticsearch9/_sync/client/monitoring.py +100 -0
  73. elasticsearch9/_sync/client/nodes.py +543 -0
  74. elasticsearch9/_sync/client/query_rules.py +485 -0
  75. elasticsearch9/_sync/client/rollup.py +616 -0
  76. elasticsearch9/_sync/client/search_application.py +574 -0
  77. elasticsearch9/_sync/client/searchable_snapshots.py +313 -0
  78. elasticsearch9/_sync/client/security.py +4688 -0
  79. elasticsearch9/_sync/client/shutdown.py +268 -0
  80. elasticsearch9/_sync/client/simulate.py +145 -0
  81. elasticsearch9/_sync/client/slm.py +559 -0
  82. elasticsearch9/_sync/client/snapshot.py +1338 -0
  83. elasticsearch9/_sync/client/sql.py +469 -0
  84. elasticsearch9/_sync/client/ssl.py +76 -0
  85. elasticsearch9/_sync/client/synonyms.py +413 -0
  86. elasticsearch9/_sync/client/tasks.py +295 -0
  87. elasticsearch9/_sync/client/text_structure.py +664 -0
  88. elasticsearch9/_sync/client/transform.py +922 -0
  89. elasticsearch9/_sync/client/utils.py +475 -0
  90. elasticsearch9/_sync/client/watcher.py +894 -0
  91. elasticsearch9/_sync/client/xpack.py +134 -0
  92. elasticsearch9/_utils.py +34 -0
  93. elasticsearch9/_version.py +18 -0
  94. elasticsearch9/client.py +126 -0
  95. elasticsearch9/compat.py +79 -0
  96. elasticsearch9/dsl/__init__.py +203 -0
  97. elasticsearch9/dsl/_async/__init__.py +16 -0
  98. elasticsearch9/dsl/_async/document.py +522 -0
  99. elasticsearch9/dsl/_async/faceted_search.py +50 -0
  100. elasticsearch9/dsl/_async/index.py +639 -0
  101. elasticsearch9/dsl/_async/mapping.py +49 -0
  102. elasticsearch9/dsl/_async/search.py +237 -0
  103. elasticsearch9/dsl/_async/update_by_query.py +47 -0
  104. elasticsearch9/dsl/_sync/__init__.py +16 -0
  105. elasticsearch9/dsl/_sync/document.py +514 -0
  106. elasticsearch9/dsl/_sync/faceted_search.py +50 -0
  107. elasticsearch9/dsl/_sync/index.py +597 -0
  108. elasticsearch9/dsl/_sync/mapping.py +49 -0
  109. elasticsearch9/dsl/_sync/search.py +230 -0
  110. elasticsearch9/dsl/_sync/update_by_query.py +45 -0
  111. elasticsearch9/dsl/aggs.py +3734 -0
  112. elasticsearch9/dsl/analysis.py +341 -0
  113. elasticsearch9/dsl/async_connections.py +37 -0
  114. elasticsearch9/dsl/connections.py +142 -0
  115. elasticsearch9/dsl/document.py +20 -0
  116. elasticsearch9/dsl/document_base.py +444 -0
  117. elasticsearch9/dsl/exceptions.py +32 -0
  118. elasticsearch9/dsl/faceted_search.py +28 -0
  119. elasticsearch9/dsl/faceted_search_base.py +489 -0
  120. elasticsearch9/dsl/field.py +4392 -0
  121. elasticsearch9/dsl/function.py +180 -0
  122. elasticsearch9/dsl/index.py +23 -0
  123. elasticsearch9/dsl/index_base.py +178 -0
  124. elasticsearch9/dsl/mapping.py +19 -0
  125. elasticsearch9/dsl/mapping_base.py +219 -0
  126. elasticsearch9/dsl/query.py +2822 -0
  127. elasticsearch9/dsl/response/__init__.py +388 -0
  128. elasticsearch9/dsl/response/aggs.py +100 -0
  129. elasticsearch9/dsl/response/hit.py +53 -0
  130. elasticsearch9/dsl/search.py +20 -0
  131. elasticsearch9/dsl/search_base.py +1053 -0
  132. elasticsearch9/dsl/serializer.py +34 -0
  133. elasticsearch9/dsl/types.py +6453 -0
  134. elasticsearch9/dsl/update_by_query.py +19 -0
  135. elasticsearch9/dsl/update_by_query_base.py +149 -0
  136. elasticsearch9/dsl/utils.py +687 -0
  137. elasticsearch9/dsl/wrappers.py +144 -0
  138. elasticsearch9/exceptions.py +133 -0
  139. elasticsearch9/helpers/__init__.py +41 -0
  140. elasticsearch9/helpers/actions.py +875 -0
  141. elasticsearch9/helpers/errors.py +40 -0
  142. elasticsearch9/helpers/vectorstore/__init__.py +62 -0
  143. elasticsearch9/helpers/vectorstore/_async/__init__.py +16 -0
  144. elasticsearch9/helpers/vectorstore/_async/_utils.py +39 -0
  145. elasticsearch9/helpers/vectorstore/_async/embedding_service.py +89 -0
  146. elasticsearch9/helpers/vectorstore/_async/strategies.py +487 -0
  147. elasticsearch9/helpers/vectorstore/_async/vectorstore.py +421 -0
  148. elasticsearch9/helpers/vectorstore/_sync/__init__.py +16 -0
  149. elasticsearch9/helpers/vectorstore/_sync/_utils.py +39 -0
  150. elasticsearch9/helpers/vectorstore/_sync/embedding_service.py +89 -0
  151. elasticsearch9/helpers/vectorstore/_sync/strategies.py +487 -0
  152. elasticsearch9/helpers/vectorstore/_sync/vectorstore.py +421 -0
  153. elasticsearch9/helpers/vectorstore/_utils.py +116 -0
  154. elasticsearch9/py.typed +0 -0
  155. elasticsearch9/serializer.py +250 -0
  156. elasticsearch9-9.0.0.dist-info/METADATA +175 -0
  157. elasticsearch9-9.0.0.dist-info/RECORD +160 -0
  158. elasticsearch9-9.0.0.dist-info/WHEEL +4 -0
  159. elasticsearch9-9.0.0.dist-info/licenses/LICENSE +176 -0
  160. elasticsearch9-9.0.0.dist-info/licenses/NOTICE +2 -0
@@ -0,0 +1,430 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ import re
19
+ import warnings
20
+ from typing import (
21
+ Any,
22
+ Callable,
23
+ Collection,
24
+ Dict,
25
+ Iterable,
26
+ List,
27
+ Mapping,
28
+ Optional,
29
+ Tuple,
30
+ Union,
31
+ )
32
+
33
+ from elastic_transport import (
34
+ ApiResponse,
35
+ BinaryApiResponse,
36
+ HeadApiResponse,
37
+ HttpHeaders,
38
+ ListApiResponse,
39
+ NodeConfig,
40
+ ObjectApiResponse,
41
+ OpenTelemetrySpan,
42
+ SniffOptions,
43
+ TextApiResponse,
44
+ Transport,
45
+ )
46
+ from elastic_transport.client_utils import DEFAULT, DefaultType
47
+
48
+ from ..._otel import OpenTelemetry
49
+ from ..._version import __versionstr__
50
+ from ...compat import warn_stacklevel
51
+ from ...exceptions import (
52
+ HTTP_EXCEPTIONS,
53
+ ApiError,
54
+ ConnectionError,
55
+ ElasticsearchWarning,
56
+ SerializationError,
57
+ UnsupportedProductError,
58
+ )
59
+ from .utils import _TYPE_SYNC_SNIFF_CALLBACK, _base64_auth_header, _quote_query
60
+
61
+ _WARNING_RE = re.compile(r"\"([^\"]*)\"")
62
+ _COMPAT_MIMETYPE_TEMPLATE = "application/vnd.elasticsearch+%s; compatible-with=" + str(
63
+ __versionstr__.partition(".")[0]
64
+ )
65
+ _COMPAT_MIMETYPE_RE = re.compile(r"application/(json|x-ndjson|vnd\.mapbox-vector-tile)")
66
+ _COMPAT_MIMETYPE_SUB = _COMPAT_MIMETYPE_TEMPLATE % (r"\g<1>",)
67
+
68
+
69
+ def resolve_auth_headers(
70
+ headers: Optional[Mapping[str, str]],
71
+ http_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
72
+ api_key: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
73
+ basic_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT,
74
+ bearer_auth: Union[DefaultType, None, str] = DEFAULT,
75
+ ) -> HttpHeaders:
76
+ if headers is None:
77
+ headers = HttpHeaders()
78
+ elif not isinstance(headers, HttpHeaders):
79
+ headers = HttpHeaders(headers)
80
+
81
+ resolved_http_auth = http_auth if http_auth is not DEFAULT else None
82
+ resolved_basic_auth = basic_auth if basic_auth is not DEFAULT else None
83
+ if resolved_http_auth is not None:
84
+ if resolved_basic_auth is not None:
85
+ raise ValueError(
86
+ "Can't specify both 'http_auth' and 'basic_auth', "
87
+ "instead only specify 'basic_auth'"
88
+ )
89
+ if isinstance(http_auth, str) or (
90
+ isinstance(resolved_http_auth, (list, tuple))
91
+ and all(isinstance(x, str) for x in resolved_http_auth)
92
+ ):
93
+ resolved_basic_auth = resolved_http_auth
94
+ else:
95
+ raise TypeError(
96
+ "The deprecated 'http_auth' parameter must be either 'Tuple[str, str]' or 'str'. "
97
+ "Use either the 'basic_auth' parameter instead"
98
+ )
99
+
100
+ warnings.warn(
101
+ "The 'http_auth' parameter is deprecated. "
102
+ "Use 'basic_auth' or 'bearer_auth' parameters instead",
103
+ category=DeprecationWarning,
104
+ stacklevel=warn_stacklevel(),
105
+ )
106
+
107
+ resolved_api_key = api_key if api_key is not DEFAULT else None
108
+ resolved_bearer_auth = bearer_auth if bearer_auth is not DEFAULT else None
109
+ if resolved_api_key or resolved_basic_auth or resolved_bearer_auth:
110
+ if (
111
+ sum(
112
+ x is not None
113
+ for x in (
114
+ resolved_api_key,
115
+ resolved_basic_auth,
116
+ resolved_bearer_auth,
117
+ )
118
+ )
119
+ > 1
120
+ ):
121
+ raise ValueError(
122
+ "Can only set one of 'api_key', 'basic_auth', and 'bearer_auth'"
123
+ )
124
+ if headers and headers.get("authorization", None) is not None:
125
+ raise ValueError(
126
+ "Can't set 'Authorization' HTTP header with other authentication options"
127
+ )
128
+ if resolved_api_key:
129
+ headers["authorization"] = f"ApiKey {_base64_auth_header(resolved_api_key)}"
130
+ if resolved_basic_auth:
131
+ headers["authorization"] = (
132
+ f"Basic {_base64_auth_header(resolved_basic_auth)}"
133
+ )
134
+ if resolved_bearer_auth:
135
+ headers["authorization"] = f"Bearer {resolved_bearer_auth}"
136
+
137
+ return headers
138
+
139
+
140
+ def create_sniff_callback(
141
+ host_info_callback: Optional[
142
+ Callable[[Dict[str, Any], Dict[str, Any]], Optional[Dict[str, Any]]]
143
+ ] = None,
144
+ sniffed_node_callback: Optional[
145
+ Callable[[Dict[str, Any], NodeConfig], Optional[NodeConfig]]
146
+ ] = None,
147
+ ) -> _TYPE_SYNC_SNIFF_CALLBACK:
148
+ assert (host_info_callback is None) != (sniffed_node_callback is None)
149
+
150
+ # Wrap the deprecated 'host_info_callback' into 'sniffed_node_callback'
151
+ if host_info_callback is not None:
152
+
153
+ def _sniffed_node_callback(
154
+ node_info: Dict[str, Any], node_config: NodeConfig
155
+ ) -> Optional[NodeConfig]:
156
+ assert host_info_callback is not None
157
+ if (
158
+ host_info_callback( # type ignore[misc]
159
+ node_info, {"host": node_config.host, "port": node_config.port}
160
+ )
161
+ is None
162
+ ):
163
+ return None
164
+ return node_config
165
+
166
+ sniffed_node_callback = _sniffed_node_callback
167
+
168
+ def sniff_callback(
169
+ transport: Transport, sniff_options: SniffOptions
170
+ ) -> List[NodeConfig]:
171
+ for _ in transport.node_pool.all():
172
+ try:
173
+ meta, node_infos = transport.perform_request(
174
+ "GET",
175
+ "/_nodes/_all/http",
176
+ headers={
177
+ "accept": "application/vnd.elasticsearch+json; compatible-with=9"
178
+ },
179
+ request_timeout=(
180
+ sniff_options.sniff_timeout
181
+ if not sniff_options.is_initial_sniff
182
+ else None
183
+ ),
184
+ )
185
+ except (SerializationError, ConnectionError):
186
+ continue
187
+
188
+ if not 200 <= meta.status <= 299:
189
+ continue
190
+
191
+ node_configs = []
192
+ for node_info in node_infos.get("nodes", {}).values():
193
+ address = node_info.get("http", {}).get("publish_address")
194
+ if not address or ":" not in address:
195
+ continue
196
+
197
+ if "/" in address:
198
+ # Support 7.x host/ip:port behavior where http.publish_host has been set.
199
+ fqdn, ipaddress = address.split("/", 1)
200
+ host = fqdn
201
+ _, port_str = ipaddress.rsplit(":", 1)
202
+ port = int(port_str)
203
+ else:
204
+ host, port_str = address.rsplit(":", 1)
205
+ port = int(port_str)
206
+
207
+ assert sniffed_node_callback is not None
208
+ sniffed_node = sniffed_node_callback(
209
+ node_info, meta.node.replace(host=host, port=port)
210
+ )
211
+ if sniffed_node is None:
212
+ continue
213
+
214
+ # Use the node which was able to make the request as a base.
215
+ node_configs.append(sniffed_node)
216
+
217
+ if node_configs:
218
+ return node_configs
219
+
220
+ return []
221
+
222
+ return sniff_callback
223
+
224
+
225
+ def _default_sniffed_node_callback(
226
+ node_info: Dict[str, Any], node_config: NodeConfig
227
+ ) -> Optional[NodeConfig]:
228
+ if node_info.get("roles", []) == ["master"]:
229
+ return None
230
+ return node_config
231
+
232
+
233
+ default_sniff_callback = create_sniff_callback(
234
+ sniffed_node_callback=_default_sniffed_node_callback
235
+ )
236
+
237
+
238
+ class BaseClient:
239
+ def __init__(self, _transport: Transport) -> None:
240
+ self._transport = _transport
241
+ self._client_meta: Union[DefaultType, Tuple[Tuple[str, str], ...]] = DEFAULT
242
+ self._headers = HttpHeaders()
243
+ self._request_timeout: Union[DefaultType, Optional[float]] = DEFAULT
244
+ self._ignore_status: Union[DefaultType, Collection[int]] = DEFAULT
245
+ self._max_retries: Union[DefaultType, int] = DEFAULT
246
+ self._retry_on_timeout: Union[DefaultType, bool] = DEFAULT
247
+ self._retry_on_status: Union[DefaultType, Collection[int]] = DEFAULT
248
+ self._verified_elasticsearch = False
249
+ self._otel = OpenTelemetry()
250
+
251
+ @property
252
+ def transport(self) -> Transport:
253
+ return self._transport
254
+
255
+ def perform_request(
256
+ self,
257
+ method: str,
258
+ path: str,
259
+ *,
260
+ params: Optional[Mapping[str, Any]] = None,
261
+ headers: Optional[Mapping[str, str]] = None,
262
+ body: Optional[Any] = None,
263
+ endpoint_id: Optional[str] = None,
264
+ path_parts: Optional[Mapping[str, Any]] = None,
265
+ ) -> ApiResponse[Any]:
266
+ with self._otel.span(
267
+ method,
268
+ endpoint_id=endpoint_id,
269
+ path_parts=path_parts or {},
270
+ ) as otel_span:
271
+ response = self._perform_request(
272
+ method,
273
+ path,
274
+ params=params,
275
+ headers=headers,
276
+ body=body,
277
+ otel_span=otel_span,
278
+ )
279
+ otel_span.set_elastic_cloud_metadata(response.meta.headers)
280
+ return response
281
+
282
+ def _perform_request(
283
+ self,
284
+ method: str,
285
+ path: str,
286
+ *,
287
+ params: Optional[Mapping[str, Any]] = None,
288
+ headers: Optional[Mapping[str, str]] = None,
289
+ body: Optional[Any] = None,
290
+ otel_span: OpenTelemetrySpan,
291
+ ) -> ApiResponse[Any]:
292
+ if headers:
293
+ request_headers = self._headers.copy()
294
+ request_headers.update(headers)
295
+ else:
296
+ request_headers = self._headers
297
+
298
+ def mimetype_header_to_compat(header: str) -> None:
299
+ # Converts all parts of a Accept/Content-Type headers
300
+ # from application/X -> application/vnd.elasticsearch+X
301
+ mimetype = request_headers.get(header, None)
302
+ if mimetype:
303
+ request_headers[header] = _COMPAT_MIMETYPE_RE.sub(
304
+ _COMPAT_MIMETYPE_SUB, mimetype
305
+ )
306
+
307
+ mimetype_header_to_compat("Accept")
308
+ mimetype_header_to_compat("Content-Type")
309
+
310
+ if params:
311
+ target = f"{path}?{_quote_query(params)}"
312
+ else:
313
+ target = path
314
+
315
+ meta, resp_body = self.transport.perform_request(
316
+ method,
317
+ target,
318
+ headers=request_headers,
319
+ body=body,
320
+ request_timeout=self._request_timeout,
321
+ max_retries=self._max_retries,
322
+ retry_on_status=self._retry_on_status,
323
+ retry_on_timeout=self._retry_on_timeout,
324
+ client_meta=self._client_meta,
325
+ otel_span=otel_span,
326
+ )
327
+
328
+ # HEAD with a 404 is returned as a normal response
329
+ # since this is used as an 'exists' functionality.
330
+ if not (method == "HEAD" and meta.status == 404) and (
331
+ not 200 <= meta.status < 299
332
+ and (
333
+ self._ignore_status is DEFAULT
334
+ or self._ignore_status is None
335
+ or meta.status not in self._ignore_status
336
+ )
337
+ ):
338
+ message = str(resp_body)
339
+
340
+ # If the response is an error response try parsing
341
+ # the raw Elasticsearch error before raising.
342
+ if isinstance(resp_body, dict):
343
+ try:
344
+ error = resp_body.get("error", message)
345
+ if isinstance(error, dict) and "type" in error:
346
+ error = error["type"]
347
+ message = error
348
+ except (ValueError, KeyError, TypeError):
349
+ pass
350
+
351
+ raise HTTP_EXCEPTIONS.get(meta.status, ApiError)(
352
+ message=message, meta=meta, body=resp_body
353
+ )
354
+
355
+ # 'X-Elastic-Product: Elasticsearch' should be on every 2XX response.
356
+ if not self._verified_elasticsearch:
357
+ # If the header is set we mark the server as verified.
358
+ if meta.headers.get("x-elastic-product", "") == "Elasticsearch":
359
+ self._verified_elasticsearch = True
360
+ # Otherwise we only raise an error on 2XX responses.
361
+ elif meta.status >= 200 and meta.status < 300:
362
+ raise UnsupportedProductError(
363
+ message=(
364
+ "The client noticed that the server is not Elasticsearch "
365
+ "and we do not support this unknown product"
366
+ ),
367
+ meta=meta,
368
+ body=resp_body,
369
+ )
370
+
371
+ # 'Warning' headers should be reraised as 'ElasticsearchWarning'
372
+ if "warning" in meta.headers:
373
+ warning_header = (meta.headers.get("warning") or "").strip()
374
+ warning_messages: Iterable[str] = _WARNING_RE.findall(warning_header) or (
375
+ warning_header,
376
+ )
377
+ stacklevel = warn_stacklevel()
378
+ for warning_message in warning_messages:
379
+ warnings.warn(
380
+ warning_message,
381
+ category=ElasticsearchWarning,
382
+ stacklevel=stacklevel,
383
+ )
384
+
385
+ if method == "HEAD":
386
+ response = HeadApiResponse(meta=meta)
387
+ elif isinstance(resp_body, dict):
388
+ response = ObjectApiResponse(body=resp_body, meta=meta) # type: ignore[assignment]
389
+ elif isinstance(resp_body, list):
390
+ response = ListApiResponse(body=resp_body, meta=meta) # type: ignore[assignment]
391
+ elif isinstance(resp_body, str):
392
+ response = TextApiResponse( # type: ignore[assignment]
393
+ body=resp_body,
394
+ meta=meta,
395
+ )
396
+ elif isinstance(resp_body, bytes):
397
+ response = BinaryApiResponse(body=resp_body, meta=meta) # type: ignore[assignment]
398
+ else:
399
+ response = ApiResponse(body=resp_body, meta=meta) # type: ignore[assignment]
400
+
401
+ return response
402
+
403
+
404
+ class NamespacedClient(BaseClient):
405
+ def __init__(self, client: "BaseClient") -> None:
406
+ self._client = client
407
+ super().__init__(self._client.transport)
408
+
409
+ def perform_request(
410
+ self,
411
+ method: str,
412
+ path: str,
413
+ *,
414
+ params: Optional[Mapping[str, Any]] = None,
415
+ headers: Optional[Mapping[str, str]] = None,
416
+ body: Optional[Any] = None,
417
+ endpoint_id: Optional[str] = None,
418
+ path_parts: Optional[Mapping[str, Any]] = None,
419
+ ) -> ApiResponse[Any]:
420
+ # Use the internal clients .perform_request() implementation
421
+ # so we take advantage of their transport options.
422
+ return self._client.perform_request(
423
+ method,
424
+ path,
425
+ params=params,
426
+ headers=headers,
427
+ body=body,
428
+ endpoint_id=endpoint_id,
429
+ path_parts=path_parts,
430
+ )