Skip to content

Release 9.0.0 #2918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 50 additions & 3 deletions docs/release-notes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,57 @@ 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 <https://github.com/elastic/elasticsearch-dsl-py/>`_ 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 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
* 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]
### Fixes [elasticsearch-python-client-900-fixes]
2 changes: 1 addition & 1 deletion elasticsearch/_async/client/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion elasticsearch/_sync/client/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion elasticsearch/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
# specific language governing permissions and limitations
# under the License.

__versionstr__ = "8.17.2"
__versionstr__ = "9.0.0"
10 changes: 5 additions & 5 deletions test_elasticsearch/test_async/test_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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
},
Expand Down Expand Up @@ -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,
},
Expand All @@ -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,
},
Expand Down Expand Up @@ -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,
},
Expand Down
34 changes: 17 additions & 17 deletions test_elasticsearch/test_client/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
}
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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")
Expand All @@ -325,15 +325,15 @@ 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")
call = calls[("GET", "/3")][0]

assert call["headers"] == {
"key": "val2",
"accept": "application/vnd.elasticsearch+json; compatible-with=8",
"accept": "application/vnd.elasticsearch+json; compatible-with=9",
}

client = Elasticsearch(
Expand All @@ -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(
Expand All @@ -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):
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
}
Expand All @@ -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,
Expand Down
18 changes: 9 additions & 9 deletions test_elasticsearch/test_client/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,38 @@ 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
self.client.cat.nodes()
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
Expand All @@ -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"])
Expand Down
8 changes: 4 additions & 4 deletions test_elasticsearch/test_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading
Loading