google-genai 0.8.0__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google/genai/_api_client.py +24 -21
- google/genai/_automatic_function_calling_util.py +19 -20
- google/genai/_common.py +22 -0
- google/genai/_extra_utils.py +12 -6
- google/genai/_replay_api_client.py +2 -0
- google/genai/_transformers.py +32 -14
- google/genai/errors.py +4 -0
- google/genai/files.py +21 -15
- google/genai/live.py +5 -0
- google/genai/models.py +341 -38
- google/genai/tunings.py +288 -61
- google/genai/types.py +86 -67
- google/genai/version.py +1 -1
- {google_genai-0.8.0.dist-info → google_genai-1.0.0.dist-info}/METADATA +87 -46
- google_genai-1.0.0.dist-info/RECORD +27 -0
- google_genai-0.8.0.dist-info/RECORD +0 -27
- {google_genai-0.8.0.dist-info → google_genai-1.0.0.dist-info}/LICENSE +0 -0
- {google_genai-0.8.0.dist-info → google_genai-1.0.0.dist-info}/WHEEL +0 -0
- {google_genai-0.8.0.dist-info → google_genai-1.0.0.dist-info}/top_level.txt +0 -0
google/genai/_api_client.py
CHANGED
@@ -99,6 +99,19 @@ class HttpRequest:
|
|
99
99
|
timeout: Optional[float] = None
|
100
100
|
|
101
101
|
|
102
|
+
# TODO(b/394358912): Update this class to use a SDKResponse class that can be
|
103
|
+
# generated and used for all languages.
|
104
|
+
@dataclass
|
105
|
+
class BaseResponse:
|
106
|
+
http_headers: dict[str, str]
|
107
|
+
|
108
|
+
@property
|
109
|
+
def dict(self) -> dict[str, Any]:
|
110
|
+
if isinstance(self, dict):
|
111
|
+
return self
|
112
|
+
return {'httpHeaders': self.http_headers}
|
113
|
+
|
114
|
+
|
102
115
|
class HttpResponse:
|
103
116
|
|
104
117
|
def __init__(
|
@@ -434,18 +447,12 @@ class ApiClient:
|
|
434
447
|
http_method, path, request_dict, http_options
|
435
448
|
)
|
436
449
|
response = self._request(http_request, stream=False)
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
elif (
|
444
|
-
isinstance(http_options, dict)
|
445
|
-
and 'deprecated_response_payload' in http_options
|
446
|
-
):
|
447
|
-
response._copy_to_dict(http_options['deprecated_response_payload'])
|
448
|
-
return response.json
|
450
|
+
json_response = response.json
|
451
|
+
if not json_response:
|
452
|
+
base_response = BaseResponse(response.headers).dict
|
453
|
+
return base_response
|
454
|
+
|
455
|
+
return json_response
|
449
456
|
|
450
457
|
def request_streamed(
|
451
458
|
self,
|
@@ -459,10 +466,6 @@ class ApiClient:
|
|
459
466
|
)
|
460
467
|
|
461
468
|
session_response = self._request(http_request, stream=True)
|
462
|
-
if http_options and 'deprecated_response_payload' in http_options:
|
463
|
-
session_response._copy_to_dict(
|
464
|
-
http_options['deprecated_response_payload']
|
465
|
-
)
|
466
469
|
for chunk in session_response.segments():
|
467
470
|
yield chunk
|
468
471
|
|
@@ -478,9 +481,11 @@ class ApiClient:
|
|
478
481
|
)
|
479
482
|
|
480
483
|
result = await self._async_request(http_request=http_request, stream=False)
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
+
json_response = result.json
|
485
|
+
if not json_response:
|
486
|
+
base_response = BaseResponse(result.headers).dict
|
487
|
+
return base_response
|
488
|
+
return json_response
|
484
489
|
|
485
490
|
async def async_request_streamed(
|
486
491
|
self,
|
@@ -495,8 +500,6 @@ class ApiClient:
|
|
495
500
|
|
496
501
|
response = await self._async_request(http_request=http_request, stream=True)
|
497
502
|
|
498
|
-
if http_options and 'deprecated_response_payload' in http_options:
|
499
|
-
response._copy_to_dict(http_options['deprecated_response_payload'])
|
500
503
|
async def async_generator():
|
501
504
|
async for chunk in response:
|
502
505
|
yield chunk
|
@@ -17,14 +17,18 @@ import inspect
|
|
17
17
|
import sys
|
18
18
|
import types as builtin_types
|
19
19
|
import typing
|
20
|
-
from typing import Any, Callable,
|
20
|
+
from typing import _GenericAlias, Any, Callable, get_args, get_origin, Literal, Union
|
21
|
+
|
21
22
|
import pydantic
|
23
|
+
|
24
|
+
from . import _extra_utils
|
22
25
|
from . import types
|
23
26
|
|
27
|
+
|
24
28
|
if sys.version_info >= (3, 10):
|
25
|
-
|
29
|
+
VersionedUnionType = builtin_types.UnionType
|
26
30
|
else:
|
27
|
-
|
31
|
+
VersionedUnionType = typing._UnionGenericAlias
|
28
32
|
|
29
33
|
_py_builtin_type_to_schema_type = {
|
30
34
|
str: 'STRING',
|
@@ -45,7 +49,8 @@ def _is_builtin_primitive_or_compound(
|
|
45
49
|
def _raise_for_any_of_if_mldev(schema: types.Schema):
|
46
50
|
if schema.any_of:
|
47
51
|
raise ValueError(
|
48
|
-
'AnyOf is not supported in function declaration schema for
|
52
|
+
'AnyOf is not supported in function declaration schema for'
|
53
|
+
' the Gemini API.'
|
49
54
|
)
|
50
55
|
|
51
56
|
|
@@ -53,15 +58,7 @@ def _raise_for_default_if_mldev(schema: types.Schema):
|
|
53
58
|
if schema.default is not None:
|
54
59
|
raise ValueError(
|
55
60
|
'Default value is not supported in function declaration schema for'
|
56
|
-
'
|
57
|
-
)
|
58
|
-
|
59
|
-
|
60
|
-
def _raise_for_nullable_if_mldev(schema: types.Schema):
|
61
|
-
if schema.nullable:
|
62
|
-
raise ValueError(
|
63
|
-
'Nullable is not supported in function declaration schema for'
|
64
|
-
' Google AI.'
|
61
|
+
' the Gemini API.'
|
65
62
|
)
|
66
63
|
|
67
64
|
|
@@ -69,7 +66,6 @@ def _raise_if_schema_unsupported(client, schema: types.Schema):
|
|
69
66
|
if not client.vertexai:
|
70
67
|
_raise_for_any_of_if_mldev(schema)
|
71
68
|
_raise_for_default_if_mldev(schema)
|
72
|
-
_raise_for_nullable_if_mldev(schema)
|
73
69
|
|
74
70
|
|
75
71
|
def _is_default_value_compatible(
|
@@ -82,10 +78,10 @@ def _is_default_value_compatible(
|
|
82
78
|
if (
|
83
79
|
isinstance(annotation, _GenericAlias)
|
84
80
|
or isinstance(annotation, builtin_types.GenericAlias)
|
85
|
-
or isinstance(annotation,
|
81
|
+
or isinstance(annotation, VersionedUnionType)
|
86
82
|
):
|
87
83
|
origin = get_origin(annotation)
|
88
|
-
if origin in (Union,
|
84
|
+
if origin in (Union, VersionedUnionType):
|
89
85
|
return any(
|
90
86
|
_is_default_value_compatible(default_value, arg)
|
91
87
|
for arg in get_args(annotation)
|
@@ -141,7 +137,7 @@ def _parse_schema_from_parameter(
|
|
141
137
|
_raise_if_schema_unsupported(client, schema)
|
142
138
|
return schema
|
143
139
|
if (
|
144
|
-
isinstance(param.annotation,
|
140
|
+
isinstance(param.annotation, VersionedUnionType)
|
145
141
|
# only parse simple UnionType, example int | str | float | bool
|
146
142
|
# complex UnionType will be invoked in raise branch
|
147
143
|
and all(
|
@@ -229,7 +225,11 @@ def _parse_schema_from_parameter(
|
|
229
225
|
schema.type = 'OBJECT'
|
230
226
|
unique_types = set()
|
231
227
|
for arg in args:
|
232
|
-
|
228
|
+
# The first check is for NoneType in Python 3.9, since the __name__
|
229
|
+
# attribute is not available in Python 3.9
|
230
|
+
if type(arg) is type(None) or (
|
231
|
+
hasattr(arg, '__name__') and arg.__name__ == 'NoneType'
|
232
|
+
): # Optional type
|
233
233
|
schema.nullable = True
|
234
234
|
continue
|
235
235
|
schema_in_any_of = _parse_schema_from_parameter(
|
@@ -272,9 +272,8 @@ def _parse_schema_from_parameter(
|
|
272
272
|
return schema
|
273
273
|
# all other generic alias will be invoked in raise branch
|
274
274
|
if (
|
275
|
-
inspect.isclass(param.annotation)
|
276
275
|
# for user defined class, we only support pydantic model
|
277
|
-
|
276
|
+
_extra_utils.is_annotation_pydantic_model(param.annotation)
|
278
277
|
):
|
279
278
|
if (
|
280
279
|
param.default is not inspect.Parameter.empty
|
google/genai/_common.py
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
import base64
|
19
19
|
import datetime
|
20
20
|
import enum
|
21
|
+
import functools
|
21
22
|
import typing
|
22
23
|
from typing import Union
|
23
24
|
import uuid
|
@@ -27,6 +28,7 @@ import pydantic
|
|
27
28
|
from pydantic import alias_generators
|
28
29
|
|
29
30
|
from . import _api_client
|
31
|
+
from . import errors
|
30
32
|
|
31
33
|
|
32
34
|
def set_value_by_path(data, keys, value):
|
@@ -273,3 +275,23 @@ def encode_unserializable_types(data: dict[str, object]) -> dict[str, object]:
|
|
273
275
|
else:
|
274
276
|
processed_data[key] = value
|
275
277
|
return processed_data
|
278
|
+
|
279
|
+
|
280
|
+
def experimental_warning(message: str):
|
281
|
+
"""Experimental warning, only warns once."""
|
282
|
+
def decorator(func):
|
283
|
+
warning_done = False
|
284
|
+
@functools.wraps(func)
|
285
|
+
def wrapper(*args, **kwargs):
|
286
|
+
nonlocal warning_done
|
287
|
+
if not warning_done:
|
288
|
+
warning_done = True
|
289
|
+
warnings.warn(
|
290
|
+
message=message,
|
291
|
+
category=errors.ExperimentalWarning,
|
292
|
+
stacklevel=2,
|
293
|
+
)
|
294
|
+
return func(*args, **kwargs)
|
295
|
+
return wrapper
|
296
|
+
return decorator
|
297
|
+
|
google/genai/_extra_utils.py
CHANGED
@@ -108,16 +108,22 @@ def convert_number_values_for_function_call_args(
|
|
108
108
|
return args
|
109
109
|
|
110
110
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
111
|
+
def is_annotation_pydantic_model(annotation: Any) -> bool:
|
112
|
+
try:
|
113
|
+
return inspect.isclass(annotation) and issubclass(
|
114
|
+
annotation, pydantic.BaseModel
|
115
|
+
)
|
116
|
+
# for python 3.10 and below, inspect.isclass(annotation) has inconsistent
|
117
|
+
# results with versions above. for example, inspect.isclass(dict[str, int]) is
|
118
|
+
# True in 3.10 and below but False in 3.11 and above.
|
119
|
+
except TypeError:
|
120
|
+
return False
|
115
121
|
|
116
122
|
|
117
123
|
def convert_if_exist_pydantic_model(
|
118
124
|
value: Any, annotation: Any, param_name: str, func_name: str
|
119
125
|
) -> Any:
|
120
|
-
if isinstance(value, dict) and
|
126
|
+
if isinstance(value, dict) and is_annotation_pydantic_model(annotation):
|
121
127
|
try:
|
122
128
|
return annotation(**value)
|
123
129
|
except pydantic.ValidationError as e:
|
@@ -146,7 +152,7 @@ def convert_if_exist_pydantic_model(
|
|
146
152
|
if (
|
147
153
|
(get_args(arg) and get_origin(arg) is list)
|
148
154
|
or isinstance(value, arg)
|
149
|
-
or (isinstance(value, dict) and
|
155
|
+
or (isinstance(value, dict) and is_annotation_pydantic_model(arg))
|
150
156
|
):
|
151
157
|
try:
|
152
158
|
return convert_if_exist_pydantic_model(
|
@@ -362,6 +362,8 @@ class ReplayApiClient(ApiClient):
|
|
362
362
|
if self._should_update_replay():
|
363
363
|
if isinstance(response_model, list):
|
364
364
|
response_model = response_model[0]
|
365
|
+
if response_model and 'http_headers' in response_model.model_fields:
|
366
|
+
response_model.http_headers.pop('Date', None)
|
365
367
|
interaction.response.sdk_response_segments.append(
|
366
368
|
response_model.model_dump(exclude_none=True)
|
367
369
|
)
|
google/genai/_transformers.py
CHANGED
@@ -34,10 +34,12 @@ import pydantic
|
|
34
34
|
from . import _api_client
|
35
35
|
from . import types
|
36
36
|
|
37
|
-
if sys.version_info >= (3,
|
38
|
-
|
37
|
+
if sys.version_info >= (3, 10):
|
38
|
+
VersionedUnionType = typing.types.UnionType
|
39
|
+
_UNION_TYPES = (typing.Union, typing.types.UnionType)
|
39
40
|
else:
|
40
|
-
|
41
|
+
VersionedUnionType = typing._UnionGenericAlias
|
42
|
+
_UNION_TYPES = (typing.Union,)
|
41
43
|
|
42
44
|
|
43
45
|
def _resource_name(
|
@@ -225,6 +227,7 @@ PartType = Union[types.Part, types.PartDict, str, 'PIL.Image.Image']
|
|
225
227
|
def t_part(client: _api_client.ApiClient, part: PartType) -> types.Part:
|
226
228
|
try:
|
227
229
|
import PIL.Image
|
230
|
+
|
228
231
|
PIL_Image = PIL.Image.Image
|
229
232
|
except ImportError:
|
230
233
|
PIL_Image = None
|
@@ -342,7 +345,7 @@ def handle_null_fields(schema: dict[str, Any]):
|
|
342
345
|
"type": "null"
|
343
346
|
}
|
344
347
|
],
|
345
|
-
"default":
|
348
|
+
"default": None,
|
346
349
|
"title": "Total Area Sq Mi"
|
347
350
|
}
|
348
351
|
}
|
@@ -356,16 +359,12 @@ def handle_null_fields(schema: dict[str, Any]):
|
|
356
359
|
"total_area_sq_mi": {
|
357
360
|
"type": "integer",
|
358
361
|
"nullable": true,
|
359
|
-
"default":
|
362
|
+
"default": None,
|
360
363
|
"title": "Total Area Sq Mi"
|
361
364
|
}
|
362
365
|
}
|
363
366
|
"""
|
364
|
-
if (
|
365
|
-
isinstance(schema, dict)
|
366
|
-
and 'type' in schema
|
367
|
-
and schema['type'] == 'null'
|
368
|
-
):
|
367
|
+
if schema.get('type', None) == 'null':
|
369
368
|
schema['nullable'] = True
|
370
369
|
del schema['type']
|
371
370
|
elif 'anyOf' in schema:
|
@@ -445,6 +444,11 @@ def process_schema(
|
|
445
444
|
if client and not client.vertexai:
|
446
445
|
schema.pop('title', None)
|
447
446
|
|
447
|
+
if schema.get('default') is not None:
|
448
|
+
raise ValueError(
|
449
|
+
'Default value is not supported in the response schema for the Gemmini API.'
|
450
|
+
)
|
451
|
+
|
448
452
|
if defs is None:
|
449
453
|
defs = schema.pop('$defs', {})
|
450
454
|
for _, sub_schema in defs.items():
|
@@ -454,8 +458,19 @@ def process_schema(
|
|
454
458
|
|
455
459
|
any_of = schema.get('anyOf', None)
|
456
460
|
if any_of is not None:
|
461
|
+
if not client.vertexai:
|
462
|
+
raise ValueError(
|
463
|
+
'AnyOf is not supported in the response schema for the Gemini API.'
|
464
|
+
)
|
457
465
|
for sub_schema in any_of:
|
458
|
-
|
466
|
+
# $ref is present in any_of if the schema is a union of Pydantic classes
|
467
|
+
ref_key = sub_schema.get('$ref', None)
|
468
|
+
if ref_key is None:
|
469
|
+
process_schema(sub_schema, client, defs)
|
470
|
+
else:
|
471
|
+
ref = defs[ref_key.split('defs/')[-1]]
|
472
|
+
any_of.append(ref)
|
473
|
+
schema['anyOf'] = [item for item in any_of if '$ref' not in item]
|
459
474
|
return
|
460
475
|
|
461
476
|
schema_type = schema.get('type', None)
|
@@ -526,15 +541,18 @@ def t_schema(
|
|
526
541
|
if (
|
527
542
|
# in Python 3.9 Generic alias list[int] counts as a type,
|
528
543
|
# and breaks issubclass because it's not a class.
|
529
|
-
not isinstance(origin, GenericAlias) and
|
530
|
-
isinstance(origin, type) and
|
544
|
+
not isinstance(origin, GenericAlias) and
|
545
|
+
isinstance(origin, type) and
|
531
546
|
issubclass(origin, pydantic.BaseModel)
|
532
547
|
):
|
533
548
|
schema = origin.model_json_schema()
|
534
549
|
process_schema(schema, client)
|
535
550
|
return types.Schema.model_validate(schema)
|
536
551
|
elif (
|
537
|
-
|
552
|
+
isinstance(origin, GenericAlias)
|
553
|
+
or isinstance(origin, type)
|
554
|
+
or isinstance(origin, VersionedUnionType)
|
555
|
+
or typing.get_origin(origin) in _UNION_TYPES
|
538
556
|
):
|
539
557
|
class Placeholder(pydantic.BaseModel):
|
540
558
|
placeholder: origin
|
google/genai/errors.py
CHANGED
google/genai/files.py
CHANGED
@@ -19,7 +19,7 @@ import io
|
|
19
19
|
import mimetypes
|
20
20
|
import os
|
21
21
|
import pathlib
|
22
|
-
from typing import Optional, Union
|
22
|
+
from typing import Any, Optional, Union
|
23
23
|
from urllib.parse import urlencode
|
24
24
|
from . import _api_module
|
25
25
|
from . import _common
|
@@ -351,12 +351,12 @@ def _DeleteFileParameters_to_vertex(
|
|
351
351
|
return to_object
|
352
352
|
|
353
353
|
|
354
|
-
def _FileState_to_vertex_enum_validate(enum_value:
|
354
|
+
def _FileState_to_vertex_enum_validate(enum_value: Any):
|
355
355
|
if enum_value in set(['STATE_UNSPECIFIED', 'PROCESSING', 'ACTIVE', 'FAILED']):
|
356
356
|
raise ValueError(f'{enum_value} enum value is not supported in Vertex AI.')
|
357
357
|
|
358
358
|
|
359
|
-
def _FileSource_to_vertex_enum_validate(enum_value:
|
359
|
+
def _FileSource_to_vertex_enum_validate(enum_value: Any):
|
360
360
|
if enum_value in set(['SOURCE_UNSPECIFIED', 'UPLOADED', 'GENERATED']):
|
361
361
|
raise ValueError(f'{enum_value} enum value is not supported in Vertex AI.')
|
362
362
|
|
@@ -494,6 +494,8 @@ def _CreateFileResponse_from_mldev(
|
|
494
494
|
parent_object: dict = None,
|
495
495
|
) -> dict:
|
496
496
|
to_object = {}
|
497
|
+
if getv(from_object, ['httpHeaders']) is not None:
|
498
|
+
setv(to_object, ['http_headers'], getv(from_object, ['httpHeaders']))
|
497
499
|
|
498
500
|
return to_object
|
499
501
|
|
@@ -504,6 +506,8 @@ def _CreateFileResponse_from_vertex(
|
|
504
506
|
parent_object: dict = None,
|
505
507
|
) -> dict:
|
506
508
|
to_object = {}
|
509
|
+
if getv(from_object, ['httpHeaders']) is not None:
|
510
|
+
setv(to_object, ['http_headers'], getv(from_object, ['httpHeaders']))
|
507
511
|
|
508
512
|
return to_object
|
509
513
|
|
@@ -840,7 +844,7 @@ class Files(_api_module.BaseModule):
|
|
840
844
|
'Unknown mime type: Could not determine the mimetype for your'
|
841
845
|
' file\n please set the `mime_type` argument'
|
842
846
|
)
|
843
|
-
|
847
|
+
|
844
848
|
if config_model and config_model.http_options:
|
845
849
|
http_options = config_model.http_options
|
846
850
|
else:
|
@@ -853,19 +857,20 @@ class Files(_api_module.BaseModule):
|
|
853
857
|
'X-Goog-Upload-Header-Content-Length': f'{file_obj.size_bytes}',
|
854
858
|
'X-Goog-Upload-Header-Content-Type': f'{file_obj.mime_type}',
|
855
859
|
},
|
856
|
-
'deprecated_response_payload': response,
|
857
860
|
}
|
858
|
-
self._create(
|
861
|
+
response = self._create(
|
862
|
+
file=file_obj, config={'http_options': http_options}
|
863
|
+
)
|
859
864
|
|
860
865
|
if (
|
861
|
-
|
862
|
-
or 'X-Goog-Upload-URL' not in response
|
866
|
+
response.http_headers is None
|
867
|
+
or 'X-Goog-Upload-URL' not in response.http_headers
|
863
868
|
):
|
864
869
|
raise KeyError(
|
865
870
|
'Failed to create file. Upload URL did not returned from the create'
|
866
871
|
' file request.'
|
867
872
|
)
|
868
|
-
upload_url = response['
|
873
|
+
upload_url = response.http_headers['X-Goog-Upload-URL']
|
869
874
|
|
870
875
|
if isinstance(file, io.IOBase):
|
871
876
|
return_file = self._api_client.upload_file(
|
@@ -1272,7 +1277,6 @@ class AsyncFiles(_api_module.BaseModule):
|
|
1272
1277
|
' file\n please set the `mime_type` argument'
|
1273
1278
|
)
|
1274
1279
|
|
1275
|
-
response = {}
|
1276
1280
|
if config_model and config_model.http_options:
|
1277
1281
|
http_options = config_model.http_options
|
1278
1282
|
else:
|
@@ -1285,18 +1289,20 @@ class AsyncFiles(_api_module.BaseModule):
|
|
1285
1289
|
'X-Goog-Upload-Header-Content-Length': f'{file_obj.size_bytes}',
|
1286
1290
|
'X-Goog-Upload-Header-Content-Type': f'{file_obj.mime_type}',
|
1287
1291
|
},
|
1288
|
-
'deprecated_response_payload': response,
|
1289
1292
|
}
|
1290
|
-
await self._create(
|
1293
|
+
response = await self._create(
|
1294
|
+
file=file_obj, config={'http_options': http_options}
|
1295
|
+
)
|
1296
|
+
|
1291
1297
|
if (
|
1292
|
-
|
1293
|
-
or 'X-Goog-Upload-URL' not in response
|
1298
|
+
response.http_headers is None
|
1299
|
+
or 'X-Goog-Upload-URL' not in response.http_headers
|
1294
1300
|
):
|
1295
1301
|
raise KeyError(
|
1296
1302
|
'Failed to create file. Upload URL did not returned from the create'
|
1297
1303
|
' file request.'
|
1298
1304
|
)
|
1299
|
-
upload_url = response['
|
1305
|
+
upload_url = response.http_headers['X-Goog-Upload-URL']
|
1300
1306
|
|
1301
1307
|
if isinstance(file, io.IOBase):
|
1302
1308
|
return_file = await self._api_client.async_upload_file(
|
google/genai/live.py
CHANGED
@@ -29,8 +29,10 @@ from . import _api_module
|
|
29
29
|
from . import _common
|
30
30
|
from . import _transformers as t
|
31
31
|
from . import client
|
32
|
+
from . import errors
|
32
33
|
from . import types
|
33
34
|
from ._api_client import ApiClient
|
35
|
+
from ._common import experimental_warning
|
34
36
|
from ._common import get_value_by_path as getv
|
35
37
|
from ._common import set_value_by_path as setv
|
36
38
|
from .models import _Content_from_mldev
|
@@ -633,6 +635,9 @@ class AsyncLive(_api_module.BaseModule):
|
|
633
635
|
return_value['setup'].update(to_object)
|
634
636
|
return return_value
|
635
637
|
|
638
|
+
@experimental_warning(
|
639
|
+
"The live API is experimental and may change in future versions.",
|
640
|
+
)
|
636
641
|
@contextlib.asynccontextmanager
|
637
642
|
async def connect(
|
638
643
|
self,
|