From 7d7b9321f818559993bf90cd96e63e98e715db19 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 31 Jan 2024 16:19:57 +0400 Subject: [PATCH] Fix but deprecate parameter aliases in body parameter --- elasticsearch/_sync/client/utils.py | 28 ++++++++++++-- .../test_client/test_rewrite_parameters.py | 37 ++++++++++++++++++- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/elasticsearch/_sync/client/utils.py b/elasticsearch/_sync/client/utils.py index 4febb0352..1d1a983ac 100644 --- a/elasticsearch/_sync/client/utils.py +++ b/elasticsearch/_sync/client/utils.py @@ -298,7 +298,8 @@ def _merge_kwargs_no_duplicates(kwargs: Dict[str, Any], values: Dict[str, Any]) def _merge_body_fields_no_duplicates( body: _TYPE_BODY, kwargs: Dict[str, Any], body_fields: Tuple[str, ...] -) -> None: +) -> bool: + mixed_body_and_params = False for key in list(kwargs.keys()): if key in body_fields: if isinstance(body, (str, bytes)): @@ -315,11 +316,13 @@ def _merge_body_fields_no_duplicates( warnings.warn( f"Received '{key}' via a specific parameter in the presence of a " "'body' parameter, which is deprecated and will be removed in a future " - "version. Instead, use only 'body' or only specific paremeters.", + "version. Instead, use only 'body' or only specific parameters.", category=DeprecationWarning, stacklevel=warn_stacklevel(), ) body[key] = kwargs.pop(key) + mixed_body_and_params = True + return mixed_body_and_params def _rewrite_parameters( @@ -401,6 +404,7 @@ def wrapped(*args: Any, **kwargs: Any) -> Any: not ignore_deprecated_options or "body" not in ignore_deprecated_options ): body: Optional[_TYPE_BODY] = kwargs.pop("body") + mixed_body_and_params = False if body is not None: if body_name: if body_name in kwargs: @@ -411,11 +415,27 @@ def wrapped(*args: Any, **kwargs: Any) -> Any: "issues/1698 for more information" ) kwargs[body_name] = body - elif body_fields is not None: - _merge_body_fields_no_duplicates(body, kwargs, body_fields) + mixed_body_and_params = _merge_body_fields_no_duplicates( + body, kwargs, body_fields + ) kwargs["body"] = body + if parameter_aliases and not isinstance(body, (str, bytes)): + for alias, rename_to in parameter_aliases.items(): + if rename_to in body: + body[alias] = body.pop(rename_to) + # If body and params are mixed, the alias may come from a param, + # in which case the warning below will not make sense. + if not mixed_body_and_params: + warnings.warn( + f"Using '{rename_to}' alias in 'body' is deprecated and will be removed " + f"in a future version of elasticsearch-py. Use '{alias}' directly instead. " + "See https://github.com/elastic/elasticsearch-py/issues/1698 for more information", + category=DeprecationWarning, + stacklevel=2, + ) + if parameter_aliases: for alias, rename_to in parameter_aliases.items(): try: diff --git a/test_elasticsearch/test_client/test_rewrite_parameters.py b/test_elasticsearch/test_client/test_rewrite_parameters.py index 262180408..50a232563 100644 --- a/test_elasticsearch/test_client/test_rewrite_parameters.py +++ b/test_elasticsearch/test_client/test_rewrite_parameters.py @@ -191,7 +191,7 @@ def test_body_fields_merge(self): assert str(w[0].message) == ( "Received 'source' via a specific parameter in the presence of a " "'body' parameter, which is deprecated and will be removed in a future " - "version. Instead, use only 'body' or only specific paremeters." + "version. Instead, use only 'body' or only specific parameters." ) def test_body_fields_conflict(self): @@ -238,6 +238,41 @@ def test_parameter_aliases(self): self.wrapped_func_aliases(source=["key3"]) assert self.calls[-1] == ((), {"source": ["key3"]}) + def test_parameter_aliases_body(self): + with pytest.warns( + DeprecationWarning, + match=( + "Using 'source' alias in 'body' is deprecated and will be removed in a future version of elasticsearch-py. " + "Use '_source' directly instead." + ), + ): + self.wrapped_func_aliases(body={"source": ["key4"]}) + + # using the correct name does not warn + with warnings.catch_warnings(): + warnings.simplefilter("error") + self.wrapped_func_aliases(body={"_source": ["key4"]}) + + def test_parameter_aliases_body_param(self): + with pytest.warns( + DeprecationWarning, + match=( + "Received 'source' via a specific parameter in the presence of a " + "'body' parameter, which is deprecated and will be removed in a future " + "version. Instead, use only 'body' or only specific parameters." + ), + ): + self.wrapped_func_aliases( + source=["key4"], body={"query": {"match_all": {}}} + ) + + # using the correct name does not warn + with warnings.catch_warnings(): + warnings.simplefilter("error") + self.wrapped_func_aliases( + body={"query": {"match_all": {}}, "_source": ["key4"]} + ) + @pytest.mark.parametrize("client_cls", [Elasticsearch, AsyncElasticsearch]) def test_positional_argument_error(self, client_cls): client = client_cls("https://localhost:9200")