From e29da9412fe0c6d1757dfa6c4e2686f300bdc771 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Fri, 8 Nov 2024 07:03:08 +0400 Subject: [PATCH] Emit Python warnings for beta and tech preview APIs (#96) --- .../_async/client/__init__.py | 3 ++ .../_async/client/connector.py | 32 +++++++++++- .../_async/client/inference.py | 12 ++++- elasticsearch_serverless/_async/client/ml.py | 9 +++- .../_async/client/search_application.py | 16 +++++- .../_async/client/tasks.py | 9 +++- .../_async/client/utils.py | 4 ++ .../_sync/client/__init__.py | 3 ++ .../_sync/client/connector.py | 32 +++++++++++- .../_sync/client/inference.py | 12 ++++- elasticsearch_serverless/_sync/client/ml.py | 9 +++- .../_sync/client/search_application.py | 16 +++++- .../_sync/client/tasks.py | 9 +++- .../_sync/client/utils.py | 41 ++++++++++++++++ elasticsearch_serverless/exceptions.py | 4 ++ .../test_client/test_utils.py | 49 +++++++++++++++++-- 16 files changed, 247 insertions(+), 13 deletions(-) diff --git a/elasticsearch_serverless/_async/client/__init__.py b/elasticsearch_serverless/_async/client/__init__.py index 127bf8a..fdf058b 100644 --- a/elasticsearch_serverless/_async/client/__init__.py +++ b/elasticsearch_serverless/_async/client/__init__.py @@ -59,8 +59,10 @@ _TYPE_HOST, CLIENT_META_SERVICE, SKIP_IN_PATH, + Stability, _quote, _rewrite_parameters, + _stability_warning, client_node_config, is_requests_http_auth, is_requests_node_class, @@ -3070,6 +3072,7 @@ async def render_search_template( @_rewrite_parameters( body_fields=("context", "context_setup", "script"), ) + @_stability_warning(Stability.EXPERIMENTAL) async def scripts_painless_execute( self, *, diff --git a/elasticsearch_serverless/_async/client/connector.py b/elasticsearch_serverless/_async/client/connector.py index 28186bc..79ffd7d 100644 --- a/elasticsearch_serverless/_async/client/connector.py +++ b/elasticsearch_serverless/_async/client/connector.py @@ -20,12 +20,19 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class ConnectorClient(NamespacedClient): @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) async def check_in( self, *, @@ -67,6 +74,7 @@ async def check_in( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) async def delete( self, *, @@ -115,6 +123,7 @@ async def delete( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) async def get( self, *, @@ -157,6 +166,7 @@ async def get( @_rewrite_parameters( parameter_aliases={"from": "from_"}, ) + @_stability_warning(Stability.BETA) async def list( self, *, @@ -230,6 +240,7 @@ async def list( "service_type", ), ) + @_stability_warning(Stability.BETA) async def post( self, *, @@ -311,6 +322,7 @@ async def post( "service_type", ), ) + @_stability_warning(Stability.BETA) async def put( self, *, @@ -387,6 +399,7 @@ async def put( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) async def sync_job_cancel( self, *, @@ -434,6 +447,7 @@ async def sync_job_cancel( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) async def sync_job_delete( self, *, @@ -478,6 +492,7 @@ async def sync_job_delete( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) async def sync_job_get( self, *, @@ -522,6 +537,7 @@ async def sync_job_get( @_rewrite_parameters( parameter_aliases={"from": "from_"}, ) + @_stability_warning(Stability.BETA) async def sync_job_list( self, *, @@ -601,6 +617,7 @@ async def sync_job_list( @_rewrite_parameters( body_fields=("id", "job_type", "trigger_method"), ) + @_stability_warning(Stability.BETA) async def sync_job_post( self, *, @@ -660,6 +677,7 @@ async def sync_job_post( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) async def update_active_filtering( self, *, @@ -703,6 +721,7 @@ async def update_active_filtering( @_rewrite_parameters( body_fields=("api_key_id", "api_key_secret_id"), ) + @_stability_warning(Stability.BETA) async def update_api_key_id( self, *, @@ -761,6 +780,7 @@ async def update_api_key_id( @_rewrite_parameters( body_fields=("configuration", "values"), ) + @_stability_warning(Stability.BETA) async def update_configuration( self, *, @@ -816,6 +836,7 @@ async def update_configuration( @_rewrite_parameters( body_fields=("error",), ) + @_stability_warning(Stability.EXPERIMENTAL) async def update_error( self, *, @@ -871,6 +892,7 @@ async def update_error( @_rewrite_parameters( body_fields=("advanced_snippet", "filtering", "rules"), ) + @_stability_warning(Stability.BETA) async def update_filtering( self, *, @@ -932,6 +954,7 @@ async def update_filtering( @_rewrite_parameters( body_fields=("validation",), ) + @_stability_warning(Stability.EXPERIMENTAL) async def update_filtering_validation( self, *, @@ -985,6 +1008,7 @@ async def update_filtering_validation( @_rewrite_parameters( body_fields=("index_name",), ) + @_stability_warning(Stability.BETA) async def update_index_name( self, *, @@ -1038,6 +1062,7 @@ async def update_index_name( @_rewrite_parameters( body_fields=("description", "name"), ) + @_stability_warning(Stability.BETA) async def update_name( self, *, @@ -1092,6 +1117,7 @@ async def update_name( @_rewrite_parameters( body_fields=("is_native",), ) + @_stability_warning(Stability.BETA) async def update_native( self, *, @@ -1144,6 +1170,7 @@ async def update_native( @_rewrite_parameters( body_fields=("pipeline",), ) + @_stability_warning(Stability.BETA) async def update_pipeline( self, *, @@ -1197,6 +1224,7 @@ async def update_pipeline( @_rewrite_parameters( body_fields=("scheduling",), ) + @_stability_warning(Stability.BETA) async def update_scheduling( self, *, @@ -1249,6 +1277,7 @@ async def update_scheduling( @_rewrite_parameters( body_fields=("service_type",), ) + @_stability_warning(Stability.BETA) async def update_service_type( self, *, @@ -1301,6 +1330,7 @@ async def update_service_type( @_rewrite_parameters( body_fields=("status",), ) + @_stability_warning(Stability.EXPERIMENTAL) async def update_status( self, *, diff --git a/elasticsearch_serverless/_async/client/inference.py b/elasticsearch_serverless/_async/client/inference.py index b7fd1b7..29906c0 100644 --- a/elasticsearch_serverless/_async/client/inference.py +++ b/elasticsearch_serverless/_async/client/inference.py @@ -20,12 +20,19 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class InferenceClient(NamespacedClient): @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) async def delete( self, *, @@ -93,6 +100,7 @@ async def delete( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) async def get( self, *, @@ -151,6 +159,7 @@ async def get( @_rewrite_parameters( body_fields=("input", "query", "task_settings"), ) + @_stability_warning(Stability.EXPERIMENTAL) async def inference( self, *, @@ -237,6 +246,7 @@ async def inference( @_rewrite_parameters( body_name="inference_config", ) + @_stability_warning(Stability.EXPERIMENTAL) async def put( self, *, diff --git a/elasticsearch_serverless/_async/client/ml.py b/elasticsearch_serverless/_async/client/ml.py index cc36142..51af55c 100644 --- a/elasticsearch_serverless/_async/client/ml.py +++ b/elasticsearch_serverless/_async/client/ml.py @@ -20,7 +20,13 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class MlClient(NamespacedClient): @@ -3919,6 +3925,7 @@ async def update_job( @_rewrite_parameters( body_fields=("number_of_allocations",), ) + @_stability_warning(Stability.BETA) async def update_trained_model_deployment( self, *, diff --git a/elasticsearch_serverless/_async/client/search_application.py b/elasticsearch_serverless/_async/client/search_application.py index f35714b..d5a3d15 100644 --- a/elasticsearch_serverless/_async/client/search_application.py +++ b/elasticsearch_serverless/_async/client/search_application.py @@ -20,12 +20,19 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class SearchApplicationClient(NamespacedClient): @_rewrite_parameters() + @_stability_warning(Stability.BETA) async def delete( self, *, @@ -67,6 +74,7 @@ async def delete( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) async def delete_behavioral_analytics( self, *, @@ -108,6 +116,7 @@ async def delete_behavioral_analytics( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) async def get( self, *, @@ -148,6 +157,7 @@ async def get( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) async def get_behavioral_analytics( self, *, @@ -193,6 +203,7 @@ async def get_behavioral_analytics( @_rewrite_parameters( parameter_aliases={"from": "from_"}, ) + @_stability_warning(Stability.BETA) async def list( self, *, @@ -243,6 +254,7 @@ async def list( @_rewrite_parameters( body_name="search_application", ) + @_stability_warning(Stability.BETA) async def put( self, *, @@ -299,6 +311,7 @@ async def put( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) async def put_behavioral_analytics( self, *, @@ -342,6 +355,7 @@ async def put_behavioral_analytics( body_fields=("params",), ignore_deprecated_options={"params"}, ) + @_stability_warning(Stability.BETA) async def search( self, *, diff --git a/elasticsearch_serverless/_async/client/tasks.py b/elasticsearch_serverless/_async/client/tasks.py index cb85eec..c3e9843 100644 --- a/elasticsearch_serverless/_async/client/tasks.py +++ b/elasticsearch_serverless/_async/client/tasks.py @@ -20,12 +20,19 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class TasksClient(NamespacedClient): @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) async def get( self, *, diff --git a/elasticsearch_serverless/_async/client/utils.py b/elasticsearch_serverless/_async/client/utils.py index 2f062de..60366c7 100644 --- a/elasticsearch_serverless/_async/client/utils.py +++ b/elasticsearch_serverless/_async/client/utils.py @@ -19,10 +19,12 @@ _TYPE_HOST, CLIENT_META_SERVICE, SKIP_IN_PATH, + Stability, _base64_auth_header, _quote, _quote_query, _rewrite_parameters, + _stability_warning, client_node_config, is_requests_http_auth, is_requests_node_class, @@ -35,8 +37,10 @@ "_quote_query", "_TYPE_HOST", "SKIP_IN_PATH", + "Stability", "client_node_config", "_rewrite_parameters", + "_stability_warning", "is_requests_http_auth", "is_requests_node_class", ] diff --git a/elasticsearch_serverless/_sync/client/__init__.py b/elasticsearch_serverless/_sync/client/__init__.py index 46d8d1d..6790b51 100644 --- a/elasticsearch_serverless/_sync/client/__init__.py +++ b/elasticsearch_serverless/_sync/client/__init__.py @@ -59,8 +59,10 @@ _TYPE_HOST, CLIENT_META_SERVICE, SKIP_IN_PATH, + Stability, _quote, _rewrite_parameters, + _stability_warning, client_node_config, is_requests_http_auth, is_requests_node_class, @@ -3068,6 +3070,7 @@ def render_search_template( @_rewrite_parameters( body_fields=("context", "context_setup", "script"), ) + @_stability_warning(Stability.EXPERIMENTAL) def scripts_painless_execute( self, *, diff --git a/elasticsearch_serverless/_sync/client/connector.py b/elasticsearch_serverless/_sync/client/connector.py index 1ade6ac..1f30c53 100644 --- a/elasticsearch_serverless/_sync/client/connector.py +++ b/elasticsearch_serverless/_sync/client/connector.py @@ -20,12 +20,19 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class ConnectorClient(NamespacedClient): @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) def check_in( self, *, @@ -67,6 +74,7 @@ def check_in( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) def delete( self, *, @@ -115,6 +123,7 @@ def delete( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) def get( self, *, @@ -157,6 +166,7 @@ def get( @_rewrite_parameters( parameter_aliases={"from": "from_"}, ) + @_stability_warning(Stability.BETA) def list( self, *, @@ -230,6 +240,7 @@ def list( "service_type", ), ) + @_stability_warning(Stability.BETA) def post( self, *, @@ -311,6 +322,7 @@ def post( "service_type", ), ) + @_stability_warning(Stability.BETA) def put( self, *, @@ -387,6 +399,7 @@ def put( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) def sync_job_cancel( self, *, @@ -434,6 +447,7 @@ def sync_job_cancel( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) def sync_job_delete( self, *, @@ -478,6 +492,7 @@ def sync_job_delete( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) def sync_job_get( self, *, @@ -522,6 +537,7 @@ def sync_job_get( @_rewrite_parameters( parameter_aliases={"from": "from_"}, ) + @_stability_warning(Stability.BETA) def sync_job_list( self, *, @@ -601,6 +617,7 @@ def sync_job_list( @_rewrite_parameters( body_fields=("id", "job_type", "trigger_method"), ) + @_stability_warning(Stability.BETA) def sync_job_post( self, *, @@ -660,6 +677,7 @@ def sync_job_post( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) def update_active_filtering( self, *, @@ -703,6 +721,7 @@ def update_active_filtering( @_rewrite_parameters( body_fields=("api_key_id", "api_key_secret_id"), ) + @_stability_warning(Stability.BETA) def update_api_key_id( self, *, @@ -761,6 +780,7 @@ def update_api_key_id( @_rewrite_parameters( body_fields=("configuration", "values"), ) + @_stability_warning(Stability.BETA) def update_configuration( self, *, @@ -816,6 +836,7 @@ def update_configuration( @_rewrite_parameters( body_fields=("error",), ) + @_stability_warning(Stability.EXPERIMENTAL) def update_error( self, *, @@ -871,6 +892,7 @@ def update_error( @_rewrite_parameters( body_fields=("advanced_snippet", "filtering", "rules"), ) + @_stability_warning(Stability.BETA) def update_filtering( self, *, @@ -932,6 +954,7 @@ def update_filtering( @_rewrite_parameters( body_fields=("validation",), ) + @_stability_warning(Stability.EXPERIMENTAL) def update_filtering_validation( self, *, @@ -985,6 +1008,7 @@ def update_filtering_validation( @_rewrite_parameters( body_fields=("index_name",), ) + @_stability_warning(Stability.BETA) def update_index_name( self, *, @@ -1038,6 +1062,7 @@ def update_index_name( @_rewrite_parameters( body_fields=("description", "name"), ) + @_stability_warning(Stability.BETA) def update_name( self, *, @@ -1092,6 +1117,7 @@ def update_name( @_rewrite_parameters( body_fields=("is_native",), ) + @_stability_warning(Stability.BETA) def update_native( self, *, @@ -1144,6 +1170,7 @@ def update_native( @_rewrite_parameters( body_fields=("pipeline",), ) + @_stability_warning(Stability.BETA) def update_pipeline( self, *, @@ -1197,6 +1224,7 @@ def update_pipeline( @_rewrite_parameters( body_fields=("scheduling",), ) + @_stability_warning(Stability.BETA) def update_scheduling( self, *, @@ -1249,6 +1277,7 @@ def update_scheduling( @_rewrite_parameters( body_fields=("service_type",), ) + @_stability_warning(Stability.BETA) def update_service_type( self, *, @@ -1301,6 +1330,7 @@ def update_service_type( @_rewrite_parameters( body_fields=("status",), ) + @_stability_warning(Stability.EXPERIMENTAL) def update_status( self, *, diff --git a/elasticsearch_serverless/_sync/client/inference.py b/elasticsearch_serverless/_sync/client/inference.py index 2fc2a8d..780db0a 100644 --- a/elasticsearch_serverless/_sync/client/inference.py +++ b/elasticsearch_serverless/_sync/client/inference.py @@ -20,12 +20,19 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class InferenceClient(NamespacedClient): @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) def delete( self, *, @@ -93,6 +100,7 @@ def delete( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) def get( self, *, @@ -151,6 +159,7 @@ def get( @_rewrite_parameters( body_fields=("input", "query", "task_settings"), ) + @_stability_warning(Stability.EXPERIMENTAL) def inference( self, *, @@ -237,6 +246,7 @@ def inference( @_rewrite_parameters( body_name="inference_config", ) + @_stability_warning(Stability.EXPERIMENTAL) def put( self, *, diff --git a/elasticsearch_serverless/_sync/client/ml.py b/elasticsearch_serverless/_sync/client/ml.py index 7db7748..ff876ca 100644 --- a/elasticsearch_serverless/_sync/client/ml.py +++ b/elasticsearch_serverless/_sync/client/ml.py @@ -20,7 +20,13 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class MlClient(NamespacedClient): @@ -3919,6 +3925,7 @@ def update_job( @_rewrite_parameters( body_fields=("number_of_allocations",), ) + @_stability_warning(Stability.BETA) def update_trained_model_deployment( self, *, diff --git a/elasticsearch_serverless/_sync/client/search_application.py b/elasticsearch_serverless/_sync/client/search_application.py index 69a186e..d13093f 100644 --- a/elasticsearch_serverless/_sync/client/search_application.py +++ b/elasticsearch_serverless/_sync/client/search_application.py @@ -20,12 +20,19 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class SearchApplicationClient(NamespacedClient): @_rewrite_parameters() + @_stability_warning(Stability.BETA) def delete( self, *, @@ -67,6 +74,7 @@ def delete( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) def delete_behavioral_analytics( self, *, @@ -108,6 +116,7 @@ def delete_behavioral_analytics( ) @_rewrite_parameters() + @_stability_warning(Stability.BETA) def get( self, *, @@ -148,6 +157,7 @@ def get( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) def get_behavioral_analytics( self, *, @@ -193,6 +203,7 @@ def get_behavioral_analytics( @_rewrite_parameters( parameter_aliases={"from": "from_"}, ) + @_stability_warning(Stability.BETA) def list( self, *, @@ -243,6 +254,7 @@ def list( @_rewrite_parameters( body_name="search_application", ) + @_stability_warning(Stability.BETA) def put( self, *, @@ -299,6 +311,7 @@ def put( ) @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) def put_behavioral_analytics( self, *, @@ -342,6 +355,7 @@ def put_behavioral_analytics( body_fields=("params",), ignore_deprecated_options={"params"}, ) + @_stability_warning(Stability.BETA) def search( self, *, diff --git a/elasticsearch_serverless/_sync/client/tasks.py b/elasticsearch_serverless/_sync/client/tasks.py index a35acf7..6f149b4 100644 --- a/elasticsearch_serverless/_sync/client/tasks.py +++ b/elasticsearch_serverless/_sync/client/tasks.py @@ -20,12 +20,19 @@ from elastic_transport import ObjectApiResponse from ._base import NamespacedClient -from .utils import SKIP_IN_PATH, _quote, _rewrite_parameters +from .utils import ( + SKIP_IN_PATH, + Stability, + _quote, + _rewrite_parameters, + _stability_warning, +) class TasksClient(NamespacedClient): @_rewrite_parameters() + @_stability_warning(Stability.EXPERIMENTAL) def get( self, *, diff --git a/elasticsearch_serverless/_sync/client/utils.py b/elasticsearch_serverless/_sync/client/utils.py index 980870d..34b9336 100644 --- a/elasticsearch_serverless/_sync/client/utils.py +++ b/elasticsearch_serverless/_sync/client/utils.py @@ -19,6 +19,7 @@ import inspect import warnings from datetime import date, datetime +from enum import Enum, auto from functools import wraps from typing import ( TYPE_CHECKING, @@ -46,6 +47,8 @@ url_to_node_config, ) +from elasticsearch_serverless.exceptions import GeneralAvailabilityWarning + from ..._version import __versionstr__ from ...compat import to_bytes, to_str, warn_stacklevel @@ -62,6 +65,13 @@ USER_AGENT = create_user_agent("elasticsearch-py", __versionstr__) ELASTIC_API_VERSION = "2023-10-31" + +class Stability(Enum): + STABLE = auto() + BETA = auto() + EXPERIMENTAL = auto() + + _TYPE_HOST = Union[str, Mapping[str, Union[str, int]], NodeConfig] _TYPE_BODY = Union[bytes, str, Dict[str, Any]] @@ -420,6 +430,37 @@ def wrapped(*args: Any, **kwargs: Any) -> Any: return wrapper +def _stability_warning( + stability: Stability, + version: Optional[str] = None, + message: Optional[str] = None, +) -> Callable[[F], F]: + def wrapper(api: F) -> F: + @wraps(api) + def wrapped(*args: Any, **kwargs: Any) -> Any: + if stability == Stability.BETA: + warnings.warn( + "This API is in beta and is subject to change. " + "The design and code is less mature than official GA features and is being provided as-is with no warranties. " + "Beta features are not subject to the support SLA of official GA features.", + category=GeneralAvailabilityWarning, + stacklevel=warn_stacklevel(), + ) + elif stability == Stability.EXPERIMENTAL: + warnings.warn( + "This API is in technical preview and may be changed or removed in a future release. " + "Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.", + category=GeneralAvailabilityWarning, + stacklevel=warn_stacklevel(), + ) + + return api(*args, **kwargs) + + return wrapped # type: ignore[return-value] + + return wrapper + + def is_requests_http_auth(http_auth: Any) -> bool: """Detect if an http_auth value is a custom Requests auth object""" try: diff --git a/elasticsearch_serverless/exceptions.py b/elasticsearch_serverless/exceptions.py index f587067..dc410ae 100644 --- a/elasticsearch_serverless/exceptions.py +++ b/elasticsearch_serverless/exceptions.py @@ -115,6 +115,10 @@ class ElasticsearchWarning(TransportWarning): """ +class GeneralAvailabilityWarning(TransportWarning): + """Warning that is raised when a feature is not yet GA.""" + + # Aliases for backwards compatibility ElasticsearchDeprecationWarning = ElasticsearchWarning RequestError = BadRequestError diff --git a/test_elasticsearch_serverless/test_client/test_utils.py b/test_elasticsearch_serverless/test_client/test_utils.py index 32c56bd..180615e 100644 --- a/test_elasticsearch_serverless/test_client/test_utils.py +++ b/test_elasticsearch_serverless/test_client/test_utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Licensed to Elasticsearch B.V. under one or more contributor # license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright @@ -16,9 +15,17 @@ # specific language governing permissions and limitations # under the License. -from __future__ import unicode_literals -from elasticsearch_serverless._sync.client.utils import _quote +import warnings + +import pytest + +from elasticsearch_serverless._sync.client.utils import ( + Stability, + _quote, + _stability_warning, +) +from elasticsearch_serverless.exceptions import GeneralAvailabilityWarning def test_handles_ascii(): @@ -38,3 +45,39 @@ def test_handles_unicode(): def test_handles_unicode2(): string = "中*文," assert "%E4%B8%AD*%E6%96%87," == _quote(string) + + +class TestStabilityWarning: + def test_default(self): + + @_stability_warning(stability=Stability.STABLE) + def func_default(*args, **kwargs): + pass + + with warnings.catch_warnings(): + warnings.simplefilter("error") + func_default() + + def test_beta(self, recwarn): + + @_stability_warning(stability=Stability.BETA) + def func_beta(*args, **kwargs): + pass + + with pytest.warns( + GeneralAvailabilityWarning, + match="This API is in beta and is subject to change.", + ): + func_beta() + + def test_experimental(self, recwarn): + + @_stability_warning(stability=Stability.EXPERIMENTAL) + def func_experimental(*args, **kwargs): + pass + + with pytest.warns( + GeneralAvailabilityWarning, + match="This API is in technical preview and may be changed or removed in a future release.", + ): + func_experimental()