diff --git a/elasticsearch/_async/client/__init__.py b/elasticsearch/_async/client/__init__.py index 3e520f8c4..2ad9a5959 100644 --- a/elasticsearch/_async/client/__init__.py +++ b/elasticsearch/_async/client/__init__.py @@ -168,6 +168,7 @@ def __init__( ] = None, sniffer_timeout=DEFAULT, sniff_on_connection_fail=DEFAULT, + http_auth=DEFAULT, # Internal use only _transport: Optional[AsyncTransport] = None, ) -> None: @@ -346,6 +347,7 @@ def __init__( self._headers["x-opaque-id"] = opaque_id self._headers = resolve_auth_headers( self._headers, + http_auth=http_auth, api_key=api_key, basic_auth=basic_auth, bearer_auth=bearer_auth, diff --git a/elasticsearch/_async/client/_base.py b/elasticsearch/_async/client/_base.py index 015775caf..2dd0d2984 100644 --- a/elasticsearch/_async/client/_base.py +++ b/elasticsearch/_async/client/_base.py @@ -53,6 +53,7 @@ def resolve_auth_headers( headers: Optional[Mapping[str, str]], + http_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT, api_key: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT, basic_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT, bearer_auth: Union[DefaultType, None, str] = DEFAULT, @@ -63,8 +64,33 @@ def resolve_auth_headers( elif not isinstance(headers, HttpHeaders): headers = HttpHeaders(headers) - resolved_api_key = resolve_default(api_key, None) + resolved_http_auth = resolve_default(http_auth, None) resolved_basic_auth = resolve_default(basic_auth, None) + if resolved_http_auth is not None: + if resolved_basic_auth is not None: + raise ValueError( + "Can't specify both 'http_auth' and 'basic_auth', " + "instead only specify 'basic_auth'" + ) + if isinstance(http_auth, str) or ( + isinstance(resolved_http_auth, (list, tuple)) + and all(isinstance(x, str) for x in resolved_http_auth) + ): + resolved_basic_auth = resolved_http_auth + else: + raise TypeError( + "The deprecated 'http_auth' parameter must be either 'Tuple[str, str]' or 'str'. " + "Use either the 'basic_auth' parameter instead" + ) + + warnings.warn( + "The 'http_auth' parameter is deprecated. " + "Use 'basic_auth' or 'bearer_auth' parameters instead", + category=DeprecationWarning, + stacklevel=warn_stacklevel(), + ) + + resolved_api_key = resolve_default(api_key, None) resolved_bearer_auth = resolve_default(bearer_auth, None) if resolved_api_key or resolved_basic_auth or resolved_bearer_auth: if ( diff --git a/elasticsearch/_sync/client/__init__.py b/elasticsearch/_sync/client/__init__.py index 1450ef082..6730f6641 100644 --- a/elasticsearch/_sync/client/__init__.py +++ b/elasticsearch/_sync/client/__init__.py @@ -168,6 +168,7 @@ def __init__( ] = None, sniffer_timeout=DEFAULT, sniff_on_connection_fail=DEFAULT, + http_auth=DEFAULT, # Internal use only _transport: Optional[Transport] = None, ) -> None: @@ -346,6 +347,7 @@ def __init__( self._headers["x-opaque-id"] = opaque_id self._headers = resolve_auth_headers( self._headers, + http_auth=http_auth, api_key=api_key, basic_auth=basic_auth, bearer_auth=bearer_auth, diff --git a/elasticsearch/_sync/client/_base.py b/elasticsearch/_sync/client/_base.py index ebaa82bdc..c0aed6047 100644 --- a/elasticsearch/_sync/client/_base.py +++ b/elasticsearch/_sync/client/_base.py @@ -53,6 +53,7 @@ def resolve_auth_headers( headers: Optional[Mapping[str, str]], + http_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT, api_key: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT, basic_auth: Union[DefaultType, None, Tuple[str, str], str] = DEFAULT, bearer_auth: Union[DefaultType, None, str] = DEFAULT, @@ -63,8 +64,33 @@ def resolve_auth_headers( elif not isinstance(headers, HttpHeaders): headers = HttpHeaders(headers) - resolved_api_key = resolve_default(api_key, None) + resolved_http_auth = resolve_default(http_auth, None) resolved_basic_auth = resolve_default(basic_auth, None) + if resolved_http_auth is not None: + if resolved_basic_auth is not None: + raise ValueError( + "Can't specify both 'http_auth' and 'basic_auth', " + "instead only specify 'basic_auth'" + ) + if isinstance(http_auth, str) or ( + isinstance(resolved_http_auth, (list, tuple)) + and all(isinstance(x, str) for x in resolved_http_auth) + ): + resolved_basic_auth = resolved_http_auth + else: + raise TypeError( + "The deprecated 'http_auth' parameter must be either 'Tuple[str, str]' or 'str'. " + "Use either the 'basic_auth' parameter instead" + ) + + warnings.warn( + "The 'http_auth' parameter is deprecated. " + "Use 'basic_auth' or 'bearer_auth' parameters instead", + category=DeprecationWarning, + stacklevel=warn_stacklevel(), + ) + + resolved_api_key = resolve_default(api_key, None) resolved_bearer_auth = resolve_default(bearer_auth, None) if resolved_api_key or resolved_basic_auth or resolved_bearer_auth: if ( diff --git a/test_elasticsearch/test_client/test_deprecated_options.py b/test_elasticsearch/test_client/test_deprecated_options.py index d7037521d..5c4458ec0 100644 --- a/test_elasticsearch/test_client/test_deprecated_options.py +++ b/test_elasticsearch/test_client/test_deprecated_options.py @@ -17,6 +17,8 @@ import warnings +import pytest + from elasticsearch import Elasticsearch @@ -30,6 +32,17 @@ def test_sniff_on_connection_fail(): "The 'sniff_on_connection_fail' parameter is deprecated in favor of 'sniff_on_node_failure'" ) + with pytest.raises(ValueError) as e: + Elasticsearch( + "http://localhost:9200", + sniff_on_connection_fail=True, + sniff_on_node_failure=True, + ) + assert ( + str(e.value) + == "Can't specify both 'sniff_on_connection_fail' and 'sniff_on_node_failure', instead only specify 'sniff_on_node_failure'" + ) + def test_sniffer_timeout(): with warnings.catch_warnings(record=True) as w: @@ -41,6 +54,15 @@ def test_sniffer_timeout(): "The 'sniffer_timeout' parameter is deprecated in favor of 'min_delay_between_sniffing'" ) + with pytest.raises(ValueError) as e: + Elasticsearch( + "http://localhost:9200", sniffer_timeout=1, min_delay_between_sniffing=1 + ) + assert ( + str(e.value) + == "Can't specify both 'sniffer_timeout' and 'min_delay_between_sniffing', instead only specify 'min_delay_between_sniffing'" + ) + def test_randomize_hosts(): with warnings.catch_warnings(record=True) as w: @@ -50,3 +72,38 @@ def test_randomize_hosts(): assert str(w[0].message) == ( "The 'randomize_hosts' parameter is deprecated in favor of 'randomize_nodes_in_pool'" ) + + with pytest.raises(ValueError) as e: + Elasticsearch( + "http://localhost:9200", randomize_hosts=True, randomize_nodes_in_pool=True + ) + assert ( + str(e.value) + == "Can't specify both 'randomize_hosts' and 'randomize_nodes_in_pool', instead only specify 'randomize_nodes_in_pool'" + ) + + +def test_http_auth(): + with warnings.catch_warnings(record=True) as w: + client = Elasticsearch( + "http://localhost:9200", http_auth=("username", "password") + ) + + assert len(w) == 1 + assert w[0].category == DeprecationWarning + assert ( + str(w[0].message) + == "The 'http_auth' parameter is deprecated. Use 'basic_auth' or 'bearer_auth' parameters instead" + ) + assert client._headers["Authorization"] == "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" + + with pytest.raises(ValueError) as e: + Elasticsearch( + "http://localhost:9200", + http_auth=("username", "password"), + basic_auth=("username", "password"), + ) + assert ( + str(e.value) + == "Can't specify both 'http_auth' and 'basic_auth', instead only specify 'basic_auth'" + )