From ce7a121c7dc81bfbb7a6a847a4009d8b76a46f54 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Mon, 14 Apr 2025 18:27:46 +0400 Subject: [PATCH 1/4] Release 9.0.0 --- docs/release-notes/index.md | 50 ++++++++++++++++++- elasticsearch/_async/client/_base.py | 2 +- elasticsearch/_sync/client/_base.py | 2 +- elasticsearch/_version.py | 2 +- .../test_async/test_transport.py | 10 ++-- .../test_client/test_options.py | 34 ++++++------- .../test_client/test_serializers.py | 18 +++---- test_elasticsearch/test_serializer.py | 8 +-- test_elasticsearch/test_transport.py | 10 ++-- 9 files changed, 92 insertions(+), 44 deletions(-) diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index d2dccfd8a..58a0b9982 100644 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -18,7 +18,55 @@ To check for security updates, go to [Security announcements for the Elastic sta % * % ### Fixes [elasticsearch-python-client-next-fixes] -% * +## 9.0.0 (2025-04-14) + +* Remove deprecated `Elasticsearch()` options ([#2840](https://github.com/elastic/elasticsearch-py/pull/2840)) +* Remove deprecated `url_prefix` and `use_ssl` options ([#2797](https://github.com/elastic/elasticsearch-py/pull/2797)) +* Merge `Elasticsearch-DSL `_ package ([#2736](https://github.com/elastic/elasticsearch-py/pull/2736)) +* Add Python DSL documentation ([#2761](https://github.com/elastic/elasticsearch-py/pull/2761)) +* Autogenerate DSL field classes from schema ([#2780](https://github.com/elastic/elasticsearch-py/pull/2780)) +* Improve DSL documentation examples with class-based queries and type hints ([#2857](https://github.com/elastic/elasticsearch-py/pull/2857)) +* Document the use of `param()` in Python DSL methods ([#2861](https://github.com/elastic/elasticsearch-py/pull/2861)) +* Migrate documentation from AsciiDoc to Markdown format ([#2806](https://github.com/elastic/elasticsearch-py/pull/2806)) +* Document use of sub-clients ([#2798](https://github.com/elastic/elasticsearch-py/pull/2798)) +* Document how to making API calls ([#2843](https://github.com/elastic/elasticsearch-py/pull/2843)) +* Fix `simulate` sub-client documentation ([#2749](https://github.com/elastic/elasticsearch-py/pull/2749)) +* Update APIs + * Remove Unfreeze an index API + * Remove min_compatible_shard_node from Search and Async Search Submit APIs + * Remove local parameter from cat alias, Alias exists, and Get alias APIs + * Remove `verbose` from Index segments API + * Remove `include_model_definition` from Get trained model configuration info API + * Remove `wait_for_active_shards` from experimental Get field usage stats API + * Support soft-deletes in connectors: + * Add `hard` to Delete connector API + * Add `include_deleted` to Get and List Connector APIs + * Add `master_timeout` to Migrate to data tiers routing APIs + * Add `master_timeout` to the Alias exists and Get alias APIs. + * Add `expand_wildcards` to Create snapshot API + * Rename incorrect `access_token` to `token` in Logout of OpenID Connect API + * Add inference APIs: Alibaba Cloud AI Search, Amazon Bedrock, Anthropic, Azure AI Studio, Azure OpenAI, Cohere, Elastic Inference Service (EIS), Elasticsearch, ELSER, Google AI Studio, Google Vertex AI, Hugging Face, Jina AI, Mistral, OpenAI, and Voyage AI + * Add Elastic Inference Service (EIS) chat completion API + * Add Reindex legacy backing indices APIs + * Add Create an index from a source index API + * Add `include_source_on_error` to Create, Index, Update and Bulk APIs + * Add Stop async ES|QL query API + * Add `timeout` to Resolve Cluster API + * Add `adaptive_allocations` body field to Start and Update a trained model deployment API + * Rename `index_template_subtitutions` to `index_template_substitutions` in Simulate data ingestion API* Add `if_primary_term`, `if_seq_no`, `op_type`, `require_alias` and `require_data_stream` to Create API + * Add `max_concurrent_shard_requests` to Open point in time API + * Add `local` and `flat_settings` to Check index templates API + * Add `reopen` to Update index settings API + * Add `resource` to Reload search analyzer API + * Add `lazy` to Roll over to a new index API + * Add `cause` and `create` to Simulate index template APIs + * Add Elastic Inference Service (EIS) chat completion + * Add inference APIs: Alibaba Cloud AI Search, Amazon Bedrock, Anthropic, Azure AI Studio, Azure OpenAI, Cohere, Elastic Inference Service (EIS), Elasticsearch, ELSER, Google AI Studio, Google Vertex AI, Hugging Face, Jina AI, Mistral, OpenAI, and Voyage AI +* Update DSL + * Add `ignore_malformed`, `script`, `on_script_error` and `time_series_dimension` to Boolean field + * Add `index` to GeoShape field + * Add `search_inference_id` to SemanticText field + ## 9.0.0 [elasticsearch-python-client-900-release-notes] diff --git a/elasticsearch/_async/client/_base.py b/elasticsearch/_async/client/_base.py index cc090671c..4e49e7156 100644 --- a/elasticsearch/_async/client/_base.py +++ b/elasticsearch/_async/client/_base.py @@ -174,7 +174,7 @@ async def sniff_callback( "GET", "/_nodes/_all/http", headers={ - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, request_timeout=( sniff_options.sniff_timeout diff --git a/elasticsearch/_sync/client/_base.py b/elasticsearch/_sync/client/_base.py index 868b71073..9ee9c3d1b 100644 --- a/elasticsearch/_sync/client/_base.py +++ b/elasticsearch/_sync/client/_base.py @@ -174,7 +174,7 @@ def sniff_callback( "GET", "/_nodes/_all/http", headers={ - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, request_timeout=( sniff_options.sniff_timeout diff --git a/elasticsearch/_version.py b/elasticsearch/_version.py index 00e2789aa..f0ae401fc 100644 --- a/elasticsearch/_version.py +++ b/elasticsearch/_version.py @@ -15,4 +15,4 @@ # specific language governing permissions and limitations # under the License. -__versionstr__ = "8.17.2" +__versionstr__ = "9.0.0" diff --git a/test_elasticsearch/test_async/test_transport.py b/test_elasticsearch/test_async/test_transport.py index baebc0671..ef52ca85c 100644 --- a/test_elasticsearch/test_async/test_transport.py +++ b/test_elasticsearch/test_async/test_transport.py @@ -256,7 +256,7 @@ async def test_client_meta_header_not_sent(self): calls = client.transport.node_pool.get().calls assert 1 == len(calls) assert calls[0][1]["headers"] == { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } async def test_body_surrogates_replaced_encoded_into_bytes(self): @@ -426,7 +426,7 @@ async def test_sniff_on_start_ignores_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, "request_timeout": None, # <-- Should be None instead of 12 }, @@ -454,7 +454,7 @@ async def test_sniff_uses_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "request_timeout": DEFAULT, }, @@ -464,7 +464,7 @@ async def test_sniff_uses_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, "request_timeout": 12, }, @@ -681,7 +681,7 @@ async def test_unsupported_product_error(headers): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "request_timeout": DEFAULT, }, diff --git a/test_elasticsearch/test_client/test_options.py b/test_elasticsearch/test_client/test_options.py index c2050d186..4c719edb0 100644 --- a/test_elasticsearch/test_client/test_options.py +++ b/test_elasticsearch/test_client/test_options.py @@ -156,7 +156,7 @@ def test_options_passed_to_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, } @@ -175,7 +175,7 @@ def test_options_passed_to_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -201,7 +201,7 @@ def test_options_passed_to_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -229,7 +229,7 @@ async def test_options_passed_to_async_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, } @@ -248,7 +248,7 @@ async def test_options_passed_to_async_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -274,7 +274,7 @@ async def test_options_passed_to_async_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -316,7 +316,7 @@ def test_http_headers_overrides(self): assert call["headers"] == { "key": "val", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client.options(headers={"key1": "val"}).indices.get(index="2") @@ -325,7 +325,7 @@ def test_http_headers_overrides(self): assert call["headers"] == { "key": "val", "key1": "val", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client.options(headers={"key": "val2"}).indices.get(index="3") @@ -333,7 +333,7 @@ def test_http_headers_overrides(self): assert call["headers"] == { "key": "val2", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client = Elasticsearch( @@ -360,14 +360,14 @@ def test_user_agent_override(self): call = calls[("GET", "/1")][0] assert call["headers"] == { "user-agent": "custom1", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client.indices.get(index="2", headers={"user-agent": "custom2"}) call = calls[("GET", "/2")][0] assert call["headers"] == { "user-agent": "custom2", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client = Elasticsearch( @@ -381,14 +381,14 @@ def test_user_agent_override(self): call = calls[("GET", "/1")][0] assert call["headers"] == { "user-agent": "custom3", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client.indices.get(index="2", headers={"user-agent": "custom4"}) call = calls[("GET", "/2")][0] assert call["headers"] == { "user-agent": "custom4", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } def test_options_timeout_parameters(self): @@ -410,7 +410,7 @@ def test_options_timeout_parameters(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -440,7 +440,7 @@ def test_options_timeout_parameters(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 2, @@ -465,7 +465,7 @@ def test_options_timeout_parameters(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, } @@ -487,7 +487,7 @@ def test_options_timeout_parameters(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, diff --git a/test_elasticsearch/test_client/test_serializers.py b/test_elasticsearch/test_client/test_serializers.py index 986160b92..192c561f8 100644 --- a/test_elasticsearch/test_client/test_serializers.py +++ b/test_elasticsearch/test_client/test_serializers.py @@ -46,22 +46,22 @@ def test_compat_mode_on_by_default(self): self.client.get(index="test0", id="1") assert len(calls) == 1 assert calls[("GET", "/test0/_doc/1")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+json; compatible-with=8" + "Accept": "application/vnd.elasticsearch+json; compatible-with=9" } # Search with body self.client.search(index="test1", query={"match_all": {}}) assert len(calls) == 2 assert calls[("POST", "/test1/_search")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+json; compatible-with=8", - "Content-Type": "application/vnd.elasticsearch+json; compatible-with=8", + "Accept": "application/vnd.elasticsearch+json; compatible-with=9", + "Content-Type": "application/vnd.elasticsearch+json; compatible-with=9", } # Search without body self.client.search(index="test2") assert len(calls) == 3 assert calls[("POST", "/test2/_search")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+json; compatible-with=8", + "Accept": "application/vnd.elasticsearch+json; compatible-with=9", } # Multiple mimetypes in Accept @@ -69,15 +69,15 @@ def test_compat_mode_on_by_default(self): assert len(calls) == 4 assert calls[("GET", "/_cat/nodes")][0]["headers"] == { # text/plain isn't modified. - "Accept": "text/plain,application/vnd.elasticsearch+json; compatible-with=8", + "Accept": "text/plain,application/vnd.elasticsearch+json; compatible-with=9", } # Bulk uses x-ndjson self.client.bulk(operations=[]) assert len(calls) == 5 assert calls[("PUT", "/_bulk")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+json; compatible-with=8", - "Content-Type": "application/vnd.elasticsearch+x-ndjson; compatible-with=8", + "Accept": "application/vnd.elasticsearch+json; compatible-with=9", + "Content-Type": "application/vnd.elasticsearch+x-ndjson; compatible-with=9", } # Mapbox vector tiles @@ -91,8 +91,8 @@ def test_compat_mode_on_by_default(self): ) assert len(calls) == 6 assert calls[("POST", "/test3/_mvt/field/z/x/y")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+vnd.mapbox-vector-tile; compatible-with=8", - "Content-Type": "application/vnd.elasticsearch+json; compatible-with=8", + "Accept": "application/vnd.elasticsearch+vnd.mapbox-vector-tile; compatible-with=9", + "Content-Type": "application/vnd.elasticsearch+json; compatible-with=9", } @pytest.mark.parametrize("mime_subtype", ["json", "x-ndjson"]) diff --git a/test_elasticsearch/test_serializer.py b/test_elasticsearch/test_serializer.py index 21c6b94b5..311605c3a 100644 --- a/test_elasticsearch/test_serializer.py +++ b/test_elasticsearch/test_serializer.py @@ -223,10 +223,10 @@ def test_deserializes_text_with_correct_ct(self, data): def test_deserialize_compatibility_header(self): for content_type in ( - "application/vnd.elasticsearch+json;compatible-with=7", - "application/vnd.elasticsearch+json; compatible-with=7", "application/vnd.elasticsearch+json;compatible-with=8", "application/vnd.elasticsearch+json; compatible-with=8", + "application/vnd.elasticsearch+json;compatible-with=9", + "application/vnd.elasticsearch+json; compatible-with=9", ): assert {"some": "data"} == self.serializers.loads( '{"some":"data"}', content_type @@ -236,10 +236,10 @@ def test_deserialize_compatibility_header(self): ) for content_type in ( - "application/vnd.elasticsearch+x-ndjson;compatible-with=7", - "application/vnd.elasticsearch+x-ndjson; compatible-with=7", "application/vnd.elasticsearch+x-ndjson;compatible-with=8", "application/vnd.elasticsearch+x-ndjson; compatible-with=8", + "application/vnd.elasticsearch+x-ndjson;compatible-with=9", + "application/vnd.elasticsearch+x-ndjson; compatible-with=9", ): assert b'{"some":"data"}\n{"some":"data"}\n' == self.serializers.dumps( ['{"some":"data"}', {"some": "data"}], content_type diff --git a/test_elasticsearch/test_transport.py b/test_elasticsearch/test_transport.py index 4978d52fc..237f21ac1 100644 --- a/test_elasticsearch/test_transport.py +++ b/test_elasticsearch/test_transport.py @@ -267,7 +267,7 @@ def test_client_meta_header_not_sent(self): calls = client.transport.node_pool.get().calls assert 1 == len(calls) assert calls[0][1]["headers"] == { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } def test_meta_header_type_error(self): @@ -428,7 +428,7 @@ def test_sniff_on_start_ignores_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, "request_timeout": None, # <-- Should be None instead of 12 }, @@ -452,7 +452,7 @@ def test_sniff_uses_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, "request_timeout": 12, }, @@ -462,7 +462,7 @@ def test_sniff_uses_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "request_timeout": DEFAULT, }, @@ -592,7 +592,7 @@ def test_unsupported_product_error(headers): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "request_timeout": DEFAULT, }, From 278caa90a98440558532db9a5629ec685ea9b2fc Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Mon, 14 Apr 2025 18:29:23 +0400 Subject: [PATCH 2/4] Release 9.0.0 --- docs/release-notes/index.md | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index 58a0b9982..682d706a3 100644 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -68,6 +68,54 @@ To check for security updates, go to [Security announcements for the Elastic sta * Add `search_inference_id` to SemanticText field +* Remove deprecated `Elasticsearch()` options ([#2840](https://github.com/elastic/elasticsearch-py/pull/2840)) +* Remove deprecated `url_prefix` and `use_ssl` options ([#2797](https://github.com/elastic/elasticsearch-py/pull/2797)) +* Merge `Elasticsearch-DSL `_ package ([#2736](https://github.com/elastic/elasticsearch-py/pull/2736)) +* Add Python DSL documentation ([#2761](https://github.com/elastic/elasticsearch-py/pull/2761)) +* Autogenerate DSL field classes from schema ([#2780](https://github.com/elastic/elasticsearch-py/pull/2780)) +* Improve DSL documentation examples with class-based queries and type hints ([#2857](https://github.com/elastic/elasticsearch-py/pull/2857)) +* Document the use of `param()` in Python DSL methods ([#2861](https://github.com/elastic/elasticsearch-py/pull/2861)) +* Migrate documentation from AsciiDoc to Markdown format ([#2806](https://github.com/elastic/elasticsearch-py/pull/2806)) +* Document use of sub-clients ([#2798](https://github.com/elastic/elasticsearch-py/pull/2798)) +* Document how to making API calls ([#2843](https://github.com/elastic/elasticsearch-py/pull/2843)) +* Fix `simulate` sub-client documentation ([#2749](https://github.com/elastic/elasticsearch-py/pull/2749)) +* Update APIs + * Remove Unfreeze an index API + * Remove min_compatible_shard_node from Search and Async Search Submit APIs + * Remove local parameter from cat alias, Alias exists, and Get alias APIs + * Remove `verbose` from Index segments API + * Remove `include_model_definition` from Get trained model configuration info API + * Remove `wait_for_active_shards` from experimental Get field usage stats API + * Support soft-deletes in connectors: + * Add `hard` to Delete connector API + * Add `include_deleted` to Get and List Connector APIs + * Add `master_timeout` to Migrate to data tiers routing APIs + * Add `master_timeout` to the Alias exists and Get alias APIs. + * Add `expand_wildcards` to Create snapshot API + * Rename incorrect `access_token` to `token` in Logout of OpenID Connect API + * Add inference APIs: Alibaba Cloud AI Search, Amazon Bedrock, Anthropic, Azure AI Studio, Azure OpenAI, Cohere, Elastic Inference Service (EIS), Elasticsearch, ELSER, Google AI Studio, Google Vertex AI, Hugging Face, Jina AI, Mistral, OpenAI, and Voyage AI + * Add Elastic Inference Service (EIS) chat completion API + * Add Reindex legacy backing indices APIs + * Add Create an index from a source index API + * Add `include_source_on_error` to Create, Index, Update and Bulk APIs + * Add Stop async ES|QL query API + * Add `timeout` to Resolve Cluster API + * Add `adaptive_allocations` body field to Start and Update a trained model deployment API + * Rename `index_template_subtitutions` to `index_template_substitutions` in Simulate data ingestion API* Add `if_primary_term`, `if_seq_no`, `op_type`, `require_alias` and `require_data_stream` to Create API + * Add `max_concurrent_shard_requests` to Open point in time API + * Add `local` and `flat_settings` to Check index templates API + * Add `reopen` to Update index settings API + * Add `resource` to Reload search analyzer API + * Add `lazy` to Roll over to a new index API + * Add `cause` and `create` to Simulate index template APIs + * Add Elastic Inference Service (EIS) chat completion + * Add inference APIs: Alibaba Cloud AI Search, Amazon Bedrock, Anthropic, Azure AI Studio, Azure OpenAI, Cohere, Elastic Inference Service (EIS), Elasticsearch, ELSER, Google AI Studio, Google Vertex AI, Hugging Face, Jina AI, Mistral, OpenAI, and Voyage AI +* Update DSL + * Add `ignore_malformed`, `script`, `on_script_error` and `time_series_dimension` to Boolean field + * Add `index` to GeoShape field + * Add `search_inference_id` to SemanticText field + + ## 9.0.0 [elasticsearch-python-client-900-release-notes] ### Features and enhancements [elasticsearch-python-client-900-features-enhancements] From dd69235261f109bdc58619f0748783047a32a2ac Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Mon, 14 Apr 2025 18:27:46 +0400 Subject: [PATCH 3/4] Release 9.0.0 --- docs/release-notes/index.md | 52 +++++++++++++++++-- elasticsearch/_async/client/_base.py | 2 +- elasticsearch/_sync/client/_base.py | 2 +- elasticsearch/_version.py | 2 +- .../test_async/test_transport.py | 10 ++-- .../test_client/test_options.py | 34 ++++++------ .../test_client/test_serializers.py | 18 +++---- test_elasticsearch/test_serializer.py | 8 +-- test_elasticsearch/test_transport.py | 10 ++-- 9 files changed, 92 insertions(+), 46 deletions(-) diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index d2dccfd8a..7a9d229e0 100644 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -18,10 +18,56 @@ To check for security updates, go to [Security announcements for the Elastic sta % * % ### Fixes [elasticsearch-python-client-next-fixes] -% * -## 9.0.0 [elasticsearch-python-client-900-release-notes] +## 9.0.0 (2025-04-15) [elasticsearch-python-client-900-release-notes] + +* Remove deprecated `Elasticsearch()` options ([#2840](https://github.com/elastic/elasticsearch-py/pull/2840)) +* Remove deprecated `url_prefix` and `use_ssl` options ([#2797](https://github.com/elastic/elasticsearch-py/pull/2797)) +* Merge `Elasticsearch-DSL `_ package ([#2736](https://github.com/elastic/elasticsearch-py/pull/2736)) +* Add Python DSL documentation ([#2761](https://github.com/elastic/elasticsearch-py/pull/2761)) +* Autogenerate DSL field classes from schema ([#2780](https://github.com/elastic/elasticsearch-py/pull/2780)) +* Improve DSL documentation examples with class-based queries and type hints ([#2857](https://github.com/elastic/elasticsearch-py/pull/2857)) +* Document the use of `param()` in Python DSL methods ([#2861](https://github.com/elastic/elasticsearch-py/pull/2861)) +* Migrate documentation from AsciiDoc to Markdown format ([#2806](https://github.com/elastic/elasticsearch-py/pull/2806)) +* Document use of sub-clients ([#2798](https://github.com/elastic/elasticsearch-py/pull/2798)) +* Document how to making API calls ([#2843](https://github.com/elastic/elasticsearch-py/pull/2843)) +* Fix `simulate` sub-client documentation ([#2749](https://github.com/elastic/elasticsearch-py/pull/2749)) +* Update APIs + * Remove Unfreeze an index API + * Remove min_compatible_shard_node from Search and Async Search Submit APIs + * Remove local parameter from cat alias, Alias exists, and Get alias APIs + * Remove `verbose` from Index segments API + * Remove `include_model_definition` from Get trained model configuration info API + * Remove `wait_for_active_shards` from experimental Get field usage stats API + * Support soft-deletes in connectors: + * Add `hard` to Delete connector API + * Add `include_deleted` to Get and List Connector APIs + * Add `master_timeout` to Migrate to data tiers routing APIs + * Add `master_timeout` to the Alias exists and Get alias APIs. + * Add `expand_wildcards` to Create snapshot API + * Rename incorrect `access_token` to `token` in Logout of OpenID Connect API + * Add inference APIs: Alibaba Cloud AI Search, Amazon Bedrock, Anthropic, Azure AI Studio, Azure OpenAI, Cohere, Elastic Inference Service (EIS), Elasticsearch, ELSER, Google AI Studio, Google Vertex AI, Hugging Face, Jina AI, Mistral, OpenAI, and Voyage AI + * Add Elastic Inference Service (EIS) chat completion API + * Add Reindex legacy backing indices APIs + * Add Create an index from a source index API + * Add `include_source_on_error` to Create, Index, Update and Bulk APIs + * Add Stop async ES|QL query API + * Add `timeout` to Resolve Cluster API + * Add `adaptive_allocations` body field to Start and Update a trained model deployment API + * Rename `index_template_subtitutions` to `index_template_substitutions` in Simulate data ingestion API* Add `if_primary_term`, `if_seq_no`, `op_type`, `require_alias` and `require_data_stream` to Create API + * Add `max_concurrent_shard_requests` to Open point in time API + * Add `local` and `flat_settings` to Check index templates API + * Add `reopen` to Update index settings API + * Add `resource` to Reload search analyzer API + * Add `lazy` to Roll over to a new index API + * Add `cause` and `create` to Simulate index template APIs + * Add Elastic Inference Service (EIS) chat completion + * Add inference APIs: Alibaba Cloud AI Search, Amazon Bedrock, Anthropic, Azure AI Studio, Azure OpenAI, Cohere, Elastic Inference Service (EIS), Elasticsearch, ELSER, Google AI Studio, Google Vertex AI, Hugging Face, Jina AI, Mistral, OpenAI, and Voyage AI +* Update DSL + * Add `ignore_malformed`, `script`, `on_script_error` and `time_series_dimension` to Boolean field + * Add `index` to GeoShape field + * Add `search_inference_id` to SemanticText field ### Features and enhancements [elasticsearch-python-client-900-features-enhancements] -### Fixes [elasticsearch-python-client-900-fixes] \ No newline at end of file +### Fixes [elasticsearch-python-client-900-fixes] diff --git a/elasticsearch/_async/client/_base.py b/elasticsearch/_async/client/_base.py index cc090671c..4e49e7156 100644 --- a/elasticsearch/_async/client/_base.py +++ b/elasticsearch/_async/client/_base.py @@ -174,7 +174,7 @@ async def sniff_callback( "GET", "/_nodes/_all/http", headers={ - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, request_timeout=( sniff_options.sniff_timeout diff --git a/elasticsearch/_sync/client/_base.py b/elasticsearch/_sync/client/_base.py index 868b71073..9ee9c3d1b 100644 --- a/elasticsearch/_sync/client/_base.py +++ b/elasticsearch/_sync/client/_base.py @@ -174,7 +174,7 @@ def sniff_callback( "GET", "/_nodes/_all/http", headers={ - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, request_timeout=( sniff_options.sniff_timeout diff --git a/elasticsearch/_version.py b/elasticsearch/_version.py index 00e2789aa..f0ae401fc 100644 --- a/elasticsearch/_version.py +++ b/elasticsearch/_version.py @@ -15,4 +15,4 @@ # specific language governing permissions and limitations # under the License. -__versionstr__ = "8.17.2" +__versionstr__ = "9.0.0" diff --git a/test_elasticsearch/test_async/test_transport.py b/test_elasticsearch/test_async/test_transport.py index baebc0671..ef52ca85c 100644 --- a/test_elasticsearch/test_async/test_transport.py +++ b/test_elasticsearch/test_async/test_transport.py @@ -256,7 +256,7 @@ async def test_client_meta_header_not_sent(self): calls = client.transport.node_pool.get().calls assert 1 == len(calls) assert calls[0][1]["headers"] == { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } async def test_body_surrogates_replaced_encoded_into_bytes(self): @@ -426,7 +426,7 @@ async def test_sniff_on_start_ignores_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, "request_timeout": None, # <-- Should be None instead of 12 }, @@ -454,7 +454,7 @@ async def test_sniff_uses_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "request_timeout": DEFAULT, }, @@ -464,7 +464,7 @@ async def test_sniff_uses_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, "request_timeout": 12, }, @@ -681,7 +681,7 @@ async def test_unsupported_product_error(headers): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "request_timeout": DEFAULT, }, diff --git a/test_elasticsearch/test_client/test_options.py b/test_elasticsearch/test_client/test_options.py index c2050d186..4c719edb0 100644 --- a/test_elasticsearch/test_client/test_options.py +++ b/test_elasticsearch/test_client/test_options.py @@ -156,7 +156,7 @@ def test_options_passed_to_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, } @@ -175,7 +175,7 @@ def test_options_passed_to_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -201,7 +201,7 @@ def test_options_passed_to_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -229,7 +229,7 @@ async def test_options_passed_to_async_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, } @@ -248,7 +248,7 @@ async def test_options_passed_to_async_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -274,7 +274,7 @@ async def test_options_passed_to_async_perform_request(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -316,7 +316,7 @@ def test_http_headers_overrides(self): assert call["headers"] == { "key": "val", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client.options(headers={"key1": "val"}).indices.get(index="2") @@ -325,7 +325,7 @@ def test_http_headers_overrides(self): assert call["headers"] == { "key": "val", "key1": "val", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client.options(headers={"key": "val2"}).indices.get(index="3") @@ -333,7 +333,7 @@ def test_http_headers_overrides(self): assert call["headers"] == { "key": "val2", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client = Elasticsearch( @@ -360,14 +360,14 @@ def test_user_agent_override(self): call = calls[("GET", "/1")][0] assert call["headers"] == { "user-agent": "custom1", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client.indices.get(index="2", headers={"user-agent": "custom2"}) call = calls[("GET", "/2")][0] assert call["headers"] == { "user-agent": "custom2", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client = Elasticsearch( @@ -381,14 +381,14 @@ def test_user_agent_override(self): call = calls[("GET", "/1")][0] assert call["headers"] == { "user-agent": "custom3", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } client.indices.get(index="2", headers={"user-agent": "custom4"}) call = calls[("GET", "/2")][0] assert call["headers"] == { "user-agent": "custom4", - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } def test_options_timeout_parameters(self): @@ -410,7 +410,7 @@ def test_options_timeout_parameters(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, @@ -440,7 +440,7 @@ def test_options_timeout_parameters(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 2, @@ -465,7 +465,7 @@ def test_options_timeout_parameters(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, } @@ -487,7 +487,7 @@ def test_options_timeout_parameters(self): assert isinstance(call.pop("otel_span"), OpenTelemetrySpan) assert call == { "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "body": None, "request_timeout": 1, diff --git a/test_elasticsearch/test_client/test_serializers.py b/test_elasticsearch/test_client/test_serializers.py index 986160b92..192c561f8 100644 --- a/test_elasticsearch/test_client/test_serializers.py +++ b/test_elasticsearch/test_client/test_serializers.py @@ -46,22 +46,22 @@ def test_compat_mode_on_by_default(self): self.client.get(index="test0", id="1") assert len(calls) == 1 assert calls[("GET", "/test0/_doc/1")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+json; compatible-with=8" + "Accept": "application/vnd.elasticsearch+json; compatible-with=9" } # Search with body self.client.search(index="test1", query={"match_all": {}}) assert len(calls) == 2 assert calls[("POST", "/test1/_search")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+json; compatible-with=8", - "Content-Type": "application/vnd.elasticsearch+json; compatible-with=8", + "Accept": "application/vnd.elasticsearch+json; compatible-with=9", + "Content-Type": "application/vnd.elasticsearch+json; compatible-with=9", } # Search without body self.client.search(index="test2") assert len(calls) == 3 assert calls[("POST", "/test2/_search")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+json; compatible-with=8", + "Accept": "application/vnd.elasticsearch+json; compatible-with=9", } # Multiple mimetypes in Accept @@ -69,15 +69,15 @@ def test_compat_mode_on_by_default(self): assert len(calls) == 4 assert calls[("GET", "/_cat/nodes")][0]["headers"] == { # text/plain isn't modified. - "Accept": "text/plain,application/vnd.elasticsearch+json; compatible-with=8", + "Accept": "text/plain,application/vnd.elasticsearch+json; compatible-with=9", } # Bulk uses x-ndjson self.client.bulk(operations=[]) assert len(calls) == 5 assert calls[("PUT", "/_bulk")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+json; compatible-with=8", - "Content-Type": "application/vnd.elasticsearch+x-ndjson; compatible-with=8", + "Accept": "application/vnd.elasticsearch+json; compatible-with=9", + "Content-Type": "application/vnd.elasticsearch+x-ndjson; compatible-with=9", } # Mapbox vector tiles @@ -91,8 +91,8 @@ def test_compat_mode_on_by_default(self): ) assert len(calls) == 6 assert calls[("POST", "/test3/_mvt/field/z/x/y")][0]["headers"] == { - "Accept": "application/vnd.elasticsearch+vnd.mapbox-vector-tile; compatible-with=8", - "Content-Type": "application/vnd.elasticsearch+json; compatible-with=8", + "Accept": "application/vnd.elasticsearch+vnd.mapbox-vector-tile; compatible-with=9", + "Content-Type": "application/vnd.elasticsearch+json; compatible-with=9", } @pytest.mark.parametrize("mime_subtype", ["json", "x-ndjson"]) diff --git a/test_elasticsearch/test_serializer.py b/test_elasticsearch/test_serializer.py index 21c6b94b5..311605c3a 100644 --- a/test_elasticsearch/test_serializer.py +++ b/test_elasticsearch/test_serializer.py @@ -223,10 +223,10 @@ def test_deserializes_text_with_correct_ct(self, data): def test_deserialize_compatibility_header(self): for content_type in ( - "application/vnd.elasticsearch+json;compatible-with=7", - "application/vnd.elasticsearch+json; compatible-with=7", "application/vnd.elasticsearch+json;compatible-with=8", "application/vnd.elasticsearch+json; compatible-with=8", + "application/vnd.elasticsearch+json;compatible-with=9", + "application/vnd.elasticsearch+json; compatible-with=9", ): assert {"some": "data"} == self.serializers.loads( '{"some":"data"}', content_type @@ -236,10 +236,10 @@ def test_deserialize_compatibility_header(self): ) for content_type in ( - "application/vnd.elasticsearch+x-ndjson;compatible-with=7", - "application/vnd.elasticsearch+x-ndjson; compatible-with=7", "application/vnd.elasticsearch+x-ndjson;compatible-with=8", "application/vnd.elasticsearch+x-ndjson; compatible-with=8", + "application/vnd.elasticsearch+x-ndjson;compatible-with=9", + "application/vnd.elasticsearch+x-ndjson; compatible-with=9", ): assert b'{"some":"data"}\n{"some":"data"}\n' == self.serializers.dumps( ['{"some":"data"}', {"some": "data"}], content_type diff --git a/test_elasticsearch/test_transport.py b/test_elasticsearch/test_transport.py index 4978d52fc..237f21ac1 100644 --- a/test_elasticsearch/test_transport.py +++ b/test_elasticsearch/test_transport.py @@ -267,7 +267,7 @@ def test_client_meta_header_not_sent(self): calls = client.transport.node_pool.get().calls assert 1 == len(calls) assert calls[0][1]["headers"] == { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", } def test_meta_header_type_error(self): @@ -428,7 +428,7 @@ def test_sniff_on_start_ignores_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, "request_timeout": None, # <-- Should be None instead of 12 }, @@ -452,7 +452,7 @@ def test_sniff_uses_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8" + "accept": "application/vnd.elasticsearch+json; compatible-with=9" }, "request_timeout": 12, }, @@ -462,7 +462,7 @@ def test_sniff_uses_sniff_timeout(self): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "request_timeout": DEFAULT, }, @@ -592,7 +592,7 @@ def test_unsupported_product_error(headers): { "body": None, "headers": { - "accept": "application/vnd.elasticsearch+json; compatible-with=8", + "accept": "application/vnd.elasticsearch+json; compatible-with=9", }, "request_timeout": DEFAULT, }, From 6af701858307fb06b15a44b8795ca6be4d7582d9 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Mon, 14 Apr 2025 21:43:17 +0400 Subject: [PATCH 4/4] Add knn_search removal to release notes --- docs/release-notes/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index 7a9d229e0..5d47dd45b 100644 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -33,6 +33,7 @@ To check for security updates, go to [Security announcements for the Elastic sta * Document how to making API calls ([#2843](https://github.com/elastic/elasticsearch-py/pull/2843)) * Fix `simulate` sub-client documentation ([#2749](https://github.com/elastic/elasticsearch-py/pull/2749)) * Update APIs + * Remove deprecated `/_knn_search` API * Remove Unfreeze an index API * Remove min_compatible_shard_node from Search and Async Search Submit APIs * Remove local parameter from cat alias, Alias exists, and Get alias APIs