singlestoredb 1.12.4__py3-none-any.whl → 1.13.1__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.
Potentially problematic release.
This version of singlestoredb might be problematic. Click here for more details.
- singlestoredb/__init__.py +1 -1
- singlestoredb/ai/__init__.py +1 -0
- singlestoredb/ai/chat.py +26 -0
- singlestoredb/ai/embeddings.py +18 -15
- singlestoredb/apps/__init__.py +1 -0
- singlestoredb/apps/_config.py +6 -0
- singlestoredb/apps/_connection_info.py +8 -0
- singlestoredb/apps/_python_udfs.py +85 -0
- singlestoredb/config.py +14 -2
- singlestoredb/functions/__init__.py +15 -1
- singlestoredb/functions/decorator.py +102 -252
- singlestoredb/functions/dtypes.py +545 -198
- singlestoredb/functions/ext/asgi.py +421 -129
- singlestoredb/functions/ext/json.py +29 -36
- singlestoredb/functions/ext/mmap.py +1 -1
- singlestoredb/functions/ext/rowdat_1.py +50 -70
- singlestoredb/functions/signature.py +816 -144
- singlestoredb/functions/typing.py +41 -0
- singlestoredb/functions/utils.py +421 -0
- singlestoredb/http/connection.py +3 -1
- singlestoredb/management/inference_api.py +101 -0
- singlestoredb/management/manager.py +6 -1
- singlestoredb/management/organization.py +17 -0
- singlestoredb/management/utils.py +2 -2
- singlestoredb/tests/ext_funcs/__init__.py +476 -237
- singlestoredb/tests/test_ext_func.py +192 -3
- singlestoredb/tests/test_management.py +5 -5
- singlestoredb/tests/test_udf.py +101 -131
- singlestoredb/tests/test_udf_returns.py +459 -0
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/METADATA +2 -1
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/RECORD +35 -29
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/LICENSE +0 -0
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/WHEEL +0 -0
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/entry_points.txt +0 -0
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/top_level.txt +0 -0
|
@@ -1,183 +1,113 @@
|
|
|
1
|
-
import dataclasses
|
|
2
|
-
import datetime
|
|
3
1
|
import functools
|
|
4
2
|
import inspect
|
|
5
3
|
from typing import Any
|
|
6
4
|
from typing import Callable
|
|
7
|
-
from typing import Dict
|
|
8
5
|
from typing import List
|
|
9
6
|
from typing import Optional
|
|
10
|
-
from typing import
|
|
7
|
+
from typing import Type
|
|
11
8
|
from typing import Union
|
|
12
9
|
|
|
13
|
-
from . import
|
|
14
|
-
from .dtypes import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if
|
|
39
|
-
return
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return out, names
|
|
99
|
-
|
|
100
|
-
elif has_pydantic and inspect.isclass(params) \
|
|
101
|
-
and issubclass(params, pydantic.BaseModel):
|
|
102
|
-
names = []
|
|
103
|
-
out = []
|
|
104
|
-
for name, item in params.model_fields.items():
|
|
105
|
-
typ, nullable = process_annotation(item.annotation)
|
|
106
|
-
sql_type = process_types(typ)[0]
|
|
107
|
-
if not nullable:
|
|
108
|
-
sql_type = sql_type.replace('NULL', 'NOT NULL')
|
|
109
|
-
out.append(sql_type)
|
|
110
|
-
names.append(name)
|
|
111
|
-
return out, names
|
|
112
|
-
|
|
113
|
-
elif params in python_type_map:
|
|
114
|
-
return python_type_map[params](), []
|
|
115
|
-
|
|
116
|
-
elif callable(params):
|
|
117
|
-
return params(), []
|
|
118
|
-
|
|
119
|
-
elif isinstance(params, str):
|
|
120
|
-
return params, []
|
|
121
|
-
|
|
122
|
-
raise TypeError(f'unrecognized data type for args: {params}')
|
|
10
|
+
from . import utils
|
|
11
|
+
from .dtypes import SQLString
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
ParameterType = Union[
|
|
15
|
+
str,
|
|
16
|
+
Callable[..., SQLString],
|
|
17
|
+
List[Union[str, Callable[..., SQLString]]],
|
|
18
|
+
Type[Any],
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
ReturnType = ParameterType
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def is_valid_type(obj: Any) -> bool:
|
|
25
|
+
"""Check if the object is a valid type for a schema definition."""
|
|
26
|
+
if not inspect.isclass(obj):
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
if utils.is_typeddict(obj):
|
|
30
|
+
return True
|
|
31
|
+
|
|
32
|
+
if utils.is_namedtuple(obj):
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
if utils.is_dataclass(obj):
|
|
36
|
+
return True
|
|
37
|
+
|
|
38
|
+
# We don't want to import pydantic here, so we check if
|
|
39
|
+
# the class is a subclass
|
|
40
|
+
if utils.is_pydantic(obj):
|
|
41
|
+
return True
|
|
42
|
+
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def is_valid_callable(obj: Any) -> bool:
|
|
47
|
+
"""Check if the object is a valid callable for a parameter type."""
|
|
48
|
+
if not callable(obj):
|
|
49
|
+
return False
|
|
50
|
+
|
|
51
|
+
returns = utils.get_annotations(obj).get('return', None)
|
|
52
|
+
|
|
53
|
+
if inspect.isclass(returns) and issubclass(returns, str):
|
|
54
|
+
return True
|
|
55
|
+
|
|
56
|
+
raise TypeError(
|
|
57
|
+
f'callable {obj} must return a str, '
|
|
58
|
+
f'but got {returns}',
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def expand_types(args: Any) -> Optional[Union[List[str], Type[Any]]]:
|
|
63
|
+
"""Expand the types for the function arguments / return values."""
|
|
64
|
+
if args is None:
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
# SQL string
|
|
68
|
+
if isinstance(args, str):
|
|
69
|
+
return [args]
|
|
70
|
+
|
|
71
|
+
# General way of accepting pydantic.BaseModel, NamedTuple, TypedDict
|
|
72
|
+
elif is_valid_type(args):
|
|
73
|
+
return args
|
|
74
|
+
|
|
75
|
+
# List of SQL strings or callables
|
|
76
|
+
elif isinstance(args, list):
|
|
77
|
+
new_args = []
|
|
78
|
+
for arg in args:
|
|
79
|
+
if isinstance(arg, str):
|
|
80
|
+
new_args.append(arg)
|
|
81
|
+
elif callable(arg):
|
|
82
|
+
new_args.append(arg())
|
|
83
|
+
else:
|
|
84
|
+
raise TypeError(f'unrecognized type for parameter: {arg}')
|
|
85
|
+
return new_args
|
|
86
|
+
|
|
87
|
+
# Callable that returns a SQL string
|
|
88
|
+
elif is_valid_callable(args):
|
|
89
|
+
out = args()
|
|
90
|
+
if not isinstance(out, str):
|
|
91
|
+
raise TypeError(f'unrecognized type for parameter: {args}')
|
|
92
|
+
return [out]
|
|
93
|
+
|
|
94
|
+
raise TypeError(f'unrecognized type for parameter: {args}')
|
|
123
95
|
|
|
124
96
|
|
|
125
97
|
def _func(
|
|
126
98
|
func: Optional[Callable[..., Any]] = None,
|
|
127
99
|
*,
|
|
128
100
|
name: Optional[str] = None,
|
|
129
|
-
args: Optional[
|
|
130
|
-
|
|
131
|
-
DataType,
|
|
132
|
-
List[DataType],
|
|
133
|
-
Dict[str, DataType],
|
|
134
|
-
'pydantic.BaseModel',
|
|
135
|
-
type,
|
|
136
|
-
]
|
|
137
|
-
] = None,
|
|
138
|
-
returns: Optional[
|
|
139
|
-
Union[
|
|
140
|
-
str,
|
|
141
|
-
List[DataType],
|
|
142
|
-
List[type],
|
|
143
|
-
'pydantic.BaseModel',
|
|
144
|
-
type,
|
|
145
|
-
]
|
|
146
|
-
] = None,
|
|
147
|
-
data_format: Optional[str] = None,
|
|
148
|
-
include_masks: bool = False,
|
|
149
|
-
function_type: str = 'udf',
|
|
150
|
-
output_fields: Optional[List[str]] = None,
|
|
101
|
+
args: Optional[ParameterType] = None,
|
|
102
|
+
returns: Optional[ReturnType] = None,
|
|
151
103
|
) -> Callable[..., Any]:
|
|
152
104
|
"""Generic wrapper for UDF and TVF decorators."""
|
|
153
|
-
args, _ = process_types(args)
|
|
154
|
-
returns, fields = process_types(returns)
|
|
155
|
-
|
|
156
|
-
if not output_fields and fields:
|
|
157
|
-
output_fields = fields
|
|
158
|
-
|
|
159
|
-
if isinstance(returns, list) \
|
|
160
|
-
and isinstance(output_fields, list) \
|
|
161
|
-
and len(output_fields) != len(returns):
|
|
162
|
-
raise ValueError(
|
|
163
|
-
'The number of output fields must match the number of return types',
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
if include_masks and data_format == 'python':
|
|
167
|
-
raise RuntimeError(
|
|
168
|
-
'include_masks is only valid when using '
|
|
169
|
-
'vectors for input parameters',
|
|
170
|
-
)
|
|
171
105
|
|
|
172
106
|
_singlestoredb_attrs = { # type: ignore
|
|
173
107
|
k: v for k, v in dict(
|
|
174
108
|
name=name,
|
|
175
|
-
args=args,
|
|
176
|
-
returns=returns,
|
|
177
|
-
data_format=data_format,
|
|
178
|
-
include_masks=include_masks,
|
|
179
|
-
function_type=function_type,
|
|
180
|
-
output_fields=output_fields or None,
|
|
109
|
+
args=expand_types(args),
|
|
110
|
+
returns=expand_types(returns),
|
|
181
111
|
).items() if v is not None
|
|
182
112
|
}
|
|
183
113
|
|
|
@@ -186,10 +116,14 @@ def _func(
|
|
|
186
116
|
# in at that time.
|
|
187
117
|
if func is None:
|
|
188
118
|
def decorate(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
119
|
+
|
|
189
120
|
def wrapper(*args: Any, **kwargs: Any) -> Callable[..., Any]:
|
|
190
121
|
return func(*args, **kwargs) # type: ignore
|
|
122
|
+
|
|
191
123
|
wrapper._singlestoredb_attrs = _singlestoredb_attrs # type: ignore
|
|
124
|
+
|
|
192
125
|
return functools.wraps(func)(wrapper)
|
|
126
|
+
|
|
193
127
|
return decorate
|
|
194
128
|
|
|
195
129
|
def wrapper(*args: Any, **kwargs: Any) -> Callable[..., Any]:
|
|
@@ -204,13 +138,11 @@ def udf(
|
|
|
204
138
|
func: Optional[Callable[..., Any]] = None,
|
|
205
139
|
*,
|
|
206
140
|
name: Optional[str] = None,
|
|
207
|
-
args: Optional[
|
|
208
|
-
returns: Optional[
|
|
209
|
-
data_format: Optional[str] = None,
|
|
210
|
-
include_masks: bool = False,
|
|
141
|
+
args: Optional[ParameterType] = None,
|
|
142
|
+
returns: Optional[ReturnType] = None,
|
|
211
143
|
) -> Callable[..., Any]:
|
|
212
144
|
"""
|
|
213
|
-
|
|
145
|
+
Define a user-defined function (UDF).
|
|
214
146
|
|
|
215
147
|
Parameters
|
|
216
148
|
----------
|
|
@@ -218,71 +150,7 @@ def udf(
|
|
|
218
150
|
The UDF to apply parameters to
|
|
219
151
|
name : str, optional
|
|
220
152
|
The name to use for the UDF in the database
|
|
221
|
-
args : str |
|
|
222
|
-
Specifies the data types of the function arguments. Typically,
|
|
223
|
-
the function data types are derived from the function parameter
|
|
224
|
-
annotations. These annotations can be overridden. If the function
|
|
225
|
-
takes a single type for all parameters, `args` can be set to a
|
|
226
|
-
SQL string describing all parameters. If the function takes more
|
|
227
|
-
than one parameter and all of the parameters are being manually
|
|
228
|
-
defined, a list of SQL strings may be used (one for each parameter).
|
|
229
|
-
A dictionary of SQL strings may be used to specify a parameter type
|
|
230
|
-
for a subset of parameters; the keys are the names of the
|
|
231
|
-
function parameters. Callables may also be used for datatypes. This
|
|
232
|
-
is primarily for using the functions in the ``dtypes`` module that
|
|
233
|
-
are associated with SQL types with all default options (e.g., ``dt.FLOAT``).
|
|
234
|
-
returns : str, optional
|
|
235
|
-
Specifies the return data type of the function. If not specified,
|
|
236
|
-
the type annotation from the function is used.
|
|
237
|
-
data_format : str, optional
|
|
238
|
-
The data format of each parameter: python, pandas, arrow, polars
|
|
239
|
-
include_masks : bool, optional
|
|
240
|
-
Should boolean masks be included with each input parameter to indicate
|
|
241
|
-
which elements are NULL? This is only used when a input parameters are
|
|
242
|
-
configured to a vector type (numpy, pandas, polars, arrow).
|
|
243
|
-
|
|
244
|
-
Returns
|
|
245
|
-
-------
|
|
246
|
-
Callable
|
|
247
|
-
|
|
248
|
-
"""
|
|
249
|
-
return _func(
|
|
250
|
-
func=func,
|
|
251
|
-
name=name,
|
|
252
|
-
args=args,
|
|
253
|
-
returns=returns,
|
|
254
|
-
data_format=data_format,
|
|
255
|
-
include_masks=include_masks,
|
|
256
|
-
function_type='udf',
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
udf.pandas = functools.partial(udf, data_format='pandas') # type: ignore
|
|
261
|
-
udf.polars = functools.partial(udf, data_format='polars') # type: ignore
|
|
262
|
-
udf.arrow = functools.partial(udf, data_format='arrow') # type: ignore
|
|
263
|
-
udf.numpy = functools.partial(udf, data_format='numpy') # type: ignore
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
def tvf(
|
|
267
|
-
func: Optional[Callable[..., Any]] = None,
|
|
268
|
-
*,
|
|
269
|
-
name: Optional[str] = None,
|
|
270
|
-
args: Optional[Union[DataType, List[DataType], Dict[str, DataType]]] = None,
|
|
271
|
-
returns: Optional[Union[str, List[DataType], List[type]]] = None,
|
|
272
|
-
data_format: Optional[str] = None,
|
|
273
|
-
include_masks: bool = False,
|
|
274
|
-
output_fields: Optional[List[str]] = None,
|
|
275
|
-
) -> Callable[..., Any]:
|
|
276
|
-
"""
|
|
277
|
-
Apply attributes to a TVF.
|
|
278
|
-
|
|
279
|
-
Parameters
|
|
280
|
-
----------
|
|
281
|
-
func : callable, optional
|
|
282
|
-
The TVF to apply parameters to
|
|
283
|
-
name : str, optional
|
|
284
|
-
The name to use for the TVF in the database
|
|
285
|
-
args : str | Callable | List[str | Callable] | Dict[str, str | Callable], optional
|
|
153
|
+
args : str | Type | Callable | List[str | Callable], optional
|
|
286
154
|
Specifies the data types of the function arguments. Typically,
|
|
287
155
|
the function data types are derived from the function parameter
|
|
288
156
|
annotations. These annotations can be overridden. If the function
|
|
@@ -295,18 +163,10 @@ def tvf(
|
|
|
295
163
|
function parameters. Callables may also be used for datatypes. This
|
|
296
164
|
is primarily for using the functions in the ``dtypes`` module that
|
|
297
165
|
are associated with SQL types with all default options (e.g., ``dt.FLOAT``).
|
|
298
|
-
returns : str, optional
|
|
299
|
-
Specifies the return data type of the function.
|
|
300
|
-
the
|
|
301
|
-
|
|
302
|
-
The data format of each parameter: python, pandas, arrow, polars
|
|
303
|
-
include_masks : bool, optional
|
|
304
|
-
Should boolean masks be included with each input parameter to indicate
|
|
305
|
-
which elements are NULL? This is only used when a input parameters are
|
|
306
|
-
configured to a vector type (numpy, pandas, polars, arrow).
|
|
307
|
-
output_fields : List[str], optional
|
|
308
|
-
The names of the output fields for the TVF. If not specified, the
|
|
309
|
-
names are generated.
|
|
166
|
+
returns : str | Type | Callable | List[str | Callable] | Table, optional
|
|
167
|
+
Specifies the return data type of the function. This parameter
|
|
168
|
+
works the same way as `args`. If the function is a table-valued
|
|
169
|
+
function, the return type should be a `Table` object.
|
|
310
170
|
|
|
311
171
|
Returns
|
|
312
172
|
-------
|
|
@@ -318,14 +178,4 @@ def tvf(
|
|
|
318
178
|
name=name,
|
|
319
179
|
args=args,
|
|
320
180
|
returns=returns,
|
|
321
|
-
data_format=data_format,
|
|
322
|
-
include_masks=include_masks,
|
|
323
|
-
function_type='tvf',
|
|
324
|
-
output_fields=output_fields,
|
|
325
181
|
)
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
tvf.pandas = functools.partial(tvf, data_format='pandas') # type: ignore
|
|
329
|
-
tvf.polars = functools.partial(tvf, data_format='polars') # type: ignore
|
|
330
|
-
tvf.arrow = functools.partial(tvf, data_format='arrow') # type: ignore
|
|
331
|
-
tvf.numpy = functools.partial(tvf, data_format='numpy') # type: ignore
|