singlestoredb 1.16.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.
- singlestoredb/__init__.py +75 -0
- singlestoredb/ai/__init__.py +2 -0
- singlestoredb/ai/chat.py +139 -0
- singlestoredb/ai/embeddings.py +128 -0
- singlestoredb/alchemy/__init__.py +90 -0
- singlestoredb/apps/__init__.py +3 -0
- singlestoredb/apps/_cloud_functions.py +90 -0
- singlestoredb/apps/_config.py +72 -0
- singlestoredb/apps/_connection_info.py +18 -0
- singlestoredb/apps/_dashboards.py +47 -0
- singlestoredb/apps/_process.py +32 -0
- singlestoredb/apps/_python_udfs.py +100 -0
- singlestoredb/apps/_stdout_supress.py +30 -0
- singlestoredb/apps/_uvicorn_util.py +36 -0
- singlestoredb/auth.py +245 -0
- singlestoredb/config.py +484 -0
- singlestoredb/connection.py +1487 -0
- singlestoredb/converters.py +950 -0
- singlestoredb/docstring/__init__.py +33 -0
- singlestoredb/docstring/attrdoc.py +126 -0
- singlestoredb/docstring/common.py +230 -0
- singlestoredb/docstring/epydoc.py +267 -0
- singlestoredb/docstring/google.py +412 -0
- singlestoredb/docstring/numpydoc.py +562 -0
- singlestoredb/docstring/parser.py +100 -0
- singlestoredb/docstring/py.typed +1 -0
- singlestoredb/docstring/rest.py +256 -0
- singlestoredb/docstring/tests/__init__.py +1 -0
- singlestoredb/docstring/tests/_pydoctor.py +21 -0
- singlestoredb/docstring/tests/test_epydoc.py +729 -0
- singlestoredb/docstring/tests/test_google.py +1007 -0
- singlestoredb/docstring/tests/test_numpydoc.py +1100 -0
- singlestoredb/docstring/tests/test_parse_from_object.py +109 -0
- singlestoredb/docstring/tests/test_parser.py +248 -0
- singlestoredb/docstring/tests/test_rest.py +547 -0
- singlestoredb/docstring/tests/test_util.py +70 -0
- singlestoredb/docstring/util.py +141 -0
- singlestoredb/exceptions.py +120 -0
- singlestoredb/functions/__init__.py +16 -0
- singlestoredb/functions/decorator.py +201 -0
- singlestoredb/functions/dtypes.py +1793 -0
- singlestoredb/functions/ext/__init__.py +1 -0
- singlestoredb/functions/ext/arrow.py +375 -0
- singlestoredb/functions/ext/asgi.py +2133 -0
- singlestoredb/functions/ext/json.py +420 -0
- singlestoredb/functions/ext/mmap.py +413 -0
- singlestoredb/functions/ext/rowdat_1.py +724 -0
- singlestoredb/functions/ext/timer.py +89 -0
- singlestoredb/functions/ext/utils.py +218 -0
- singlestoredb/functions/signature.py +1578 -0
- singlestoredb/functions/typing/__init__.py +41 -0
- singlestoredb/functions/typing/numpy.py +20 -0
- singlestoredb/functions/typing/pandas.py +2 -0
- singlestoredb/functions/typing/polars.py +2 -0
- singlestoredb/functions/typing/pyarrow.py +2 -0
- singlestoredb/functions/utils.py +421 -0
- singlestoredb/fusion/__init__.py +11 -0
- singlestoredb/fusion/graphql.py +213 -0
- singlestoredb/fusion/handler.py +916 -0
- singlestoredb/fusion/handlers/__init__.py +0 -0
- singlestoredb/fusion/handlers/export.py +525 -0
- singlestoredb/fusion/handlers/files.py +690 -0
- singlestoredb/fusion/handlers/job.py +660 -0
- singlestoredb/fusion/handlers/models.py +250 -0
- singlestoredb/fusion/handlers/stage.py +502 -0
- singlestoredb/fusion/handlers/utils.py +324 -0
- singlestoredb/fusion/handlers/workspace.py +956 -0
- singlestoredb/fusion/registry.py +249 -0
- singlestoredb/fusion/result.py +399 -0
- singlestoredb/http/__init__.py +27 -0
- singlestoredb/http/connection.py +1267 -0
- singlestoredb/magics/__init__.py +34 -0
- singlestoredb/magics/run_personal.py +137 -0
- singlestoredb/magics/run_shared.py +134 -0
- singlestoredb/management/__init__.py +9 -0
- singlestoredb/management/billing_usage.py +148 -0
- singlestoredb/management/cluster.py +462 -0
- singlestoredb/management/export.py +295 -0
- singlestoredb/management/files.py +1102 -0
- singlestoredb/management/inference_api.py +105 -0
- singlestoredb/management/job.py +887 -0
- singlestoredb/management/manager.py +373 -0
- singlestoredb/management/organization.py +226 -0
- singlestoredb/management/region.py +169 -0
- singlestoredb/management/utils.py +423 -0
- singlestoredb/management/workspace.py +1927 -0
- singlestoredb/mysql/__init__.py +177 -0
- singlestoredb/mysql/_auth.py +298 -0
- singlestoredb/mysql/charset.py +214 -0
- singlestoredb/mysql/connection.py +2032 -0
- singlestoredb/mysql/constants/CLIENT.py +38 -0
- singlestoredb/mysql/constants/COMMAND.py +32 -0
- singlestoredb/mysql/constants/CR.py +78 -0
- singlestoredb/mysql/constants/ER.py +474 -0
- singlestoredb/mysql/constants/EXTENDED_TYPE.py +3 -0
- singlestoredb/mysql/constants/FIELD_TYPE.py +48 -0
- singlestoredb/mysql/constants/FLAG.py +15 -0
- singlestoredb/mysql/constants/SERVER_STATUS.py +10 -0
- singlestoredb/mysql/constants/VECTOR_TYPE.py +6 -0
- singlestoredb/mysql/constants/__init__.py +0 -0
- singlestoredb/mysql/converters.py +271 -0
- singlestoredb/mysql/cursors.py +896 -0
- singlestoredb/mysql/err.py +92 -0
- singlestoredb/mysql/optionfile.py +20 -0
- singlestoredb/mysql/protocol.py +450 -0
- singlestoredb/mysql/tests/__init__.py +19 -0
- singlestoredb/mysql/tests/base.py +126 -0
- singlestoredb/mysql/tests/conftest.py +37 -0
- singlestoredb/mysql/tests/test_DictCursor.py +132 -0
- singlestoredb/mysql/tests/test_SSCursor.py +141 -0
- singlestoredb/mysql/tests/test_basic.py +452 -0
- singlestoredb/mysql/tests/test_connection.py +851 -0
- singlestoredb/mysql/tests/test_converters.py +58 -0
- singlestoredb/mysql/tests/test_cursor.py +141 -0
- singlestoredb/mysql/tests/test_err.py +16 -0
- singlestoredb/mysql/tests/test_issues.py +514 -0
- singlestoredb/mysql/tests/test_load_local.py +75 -0
- singlestoredb/mysql/tests/test_nextset.py +88 -0
- singlestoredb/mysql/tests/test_optionfile.py +27 -0
- singlestoredb/mysql/tests/thirdparty/__init__.py +6 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +9 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +323 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +865 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +110 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +224 -0
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +101 -0
- singlestoredb/mysql/times.py +23 -0
- singlestoredb/notebook/__init__.py +16 -0
- singlestoredb/notebook/_objects.py +213 -0
- singlestoredb/notebook/_portal.py +352 -0
- singlestoredb/py.typed +0 -0
- singlestoredb/pytest.py +352 -0
- singlestoredb/server/__init__.py +0 -0
- singlestoredb/server/docker.py +452 -0
- singlestoredb/server/free_tier.py +267 -0
- singlestoredb/tests/__init__.py +0 -0
- singlestoredb/tests/alltypes.sql +307 -0
- singlestoredb/tests/alltypes_no_nulls.sql +208 -0
- singlestoredb/tests/empty.sql +0 -0
- singlestoredb/tests/ext_funcs/__init__.py +702 -0
- singlestoredb/tests/local_infile.csv +3 -0
- singlestoredb/tests/test.ipynb +18 -0
- singlestoredb/tests/test.sql +680 -0
- singlestoredb/tests/test2.ipynb +18 -0
- singlestoredb/tests/test2.sql +1 -0
- singlestoredb/tests/test_basics.py +1332 -0
- singlestoredb/tests/test_config.py +318 -0
- singlestoredb/tests/test_connection.py +3103 -0
- singlestoredb/tests/test_dbapi.py +27 -0
- singlestoredb/tests/test_exceptions.py +45 -0
- singlestoredb/tests/test_ext_func.py +1472 -0
- singlestoredb/tests/test_ext_func_data.py +1101 -0
- singlestoredb/tests/test_fusion.py +1527 -0
- singlestoredb/tests/test_http.py +288 -0
- singlestoredb/tests/test_management.py +1599 -0
- singlestoredb/tests/test_plugin.py +33 -0
- singlestoredb/tests/test_results.py +171 -0
- singlestoredb/tests/test_types.py +132 -0
- singlestoredb/tests/test_udf.py +737 -0
- singlestoredb/tests/test_udf_returns.py +459 -0
- singlestoredb/tests/test_vectorstore.py +51 -0
- singlestoredb/tests/test_xdict.py +333 -0
- singlestoredb/tests/utils.py +141 -0
- singlestoredb/types.py +373 -0
- singlestoredb/utils/__init__.py +0 -0
- singlestoredb/utils/config.py +950 -0
- singlestoredb/utils/convert_rows.py +69 -0
- singlestoredb/utils/debug.py +13 -0
- singlestoredb/utils/dtypes.py +205 -0
- singlestoredb/utils/events.py +65 -0
- singlestoredb/utils/mogrify.py +151 -0
- singlestoredb/utils/results.py +585 -0
- singlestoredb/utils/xdict.py +425 -0
- singlestoredb/vectorstore.py +192 -0
- singlestoredb/warnings.py +5 -0
- singlestoredb-1.16.1.dist-info/METADATA +165 -0
- singlestoredb-1.16.1.dist-info/RECORD +183 -0
- singlestoredb-1.16.1.dist-info/WHEEL +5 -0
- singlestoredb-1.16.1.dist-info/entry_points.txt +2 -0
- singlestoredb-1.16.1.dist-info/licenses/LICENSE +201 -0
- singlestoredb-1.16.1.dist-info/top_level.txt +3 -0
- sqlx/__init__.py +4 -0
- sqlx/magic.py +113 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""Utility functions for working with docstrings."""
|
|
2
|
+
import typing as T
|
|
3
|
+
from collections import ChainMap
|
|
4
|
+
from inspect import Signature
|
|
5
|
+
from itertools import chain
|
|
6
|
+
|
|
7
|
+
from .common import DocstringMeta
|
|
8
|
+
from .common import DocstringParam
|
|
9
|
+
from .common import DocstringReturns # noqa: F401
|
|
10
|
+
from .common import DocstringStyle
|
|
11
|
+
from .common import RenderingStyle
|
|
12
|
+
from .parser import compose
|
|
13
|
+
from .parser import parse
|
|
14
|
+
|
|
15
|
+
_Func = T.Callable[..., T.Any]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def combine_docstrings(
|
|
19
|
+
*others: _Func,
|
|
20
|
+
exclude: T.Iterable[T.Type[DocstringMeta]] = (),
|
|
21
|
+
style: DocstringStyle = DocstringStyle.AUTO,
|
|
22
|
+
rendering_style: RenderingStyle = RenderingStyle.COMPACT,
|
|
23
|
+
) -> _Func:
|
|
24
|
+
"""A function decorator that parses the docstrings from `others`,
|
|
25
|
+
programmatically combines them with the parsed docstring of the decorated
|
|
26
|
+
function, and replaces the docstring of the decorated function with the
|
|
27
|
+
composed result. Only parameters that are part of the decorated functions
|
|
28
|
+
signature are included in the combined docstring. When multiple sources for
|
|
29
|
+
a parameter or docstring metadata exists then the decorator will first
|
|
30
|
+
default to the wrapped function's value (when available) and otherwise use
|
|
31
|
+
the rightmost definition from ``others``.
|
|
32
|
+
|
|
33
|
+
The following example illustrates its usage:
|
|
34
|
+
|
|
35
|
+
>>> def fun1(a, b, c, d):
|
|
36
|
+
... '''short_description: fun1
|
|
37
|
+
...
|
|
38
|
+
... :param a: fun1
|
|
39
|
+
... :param b: fun1
|
|
40
|
+
... :return: fun1
|
|
41
|
+
... '''
|
|
42
|
+
>>> def fun2(b, c, d, e):
|
|
43
|
+
... '''short_description: fun2
|
|
44
|
+
...
|
|
45
|
+
... long_description: fun2
|
|
46
|
+
...
|
|
47
|
+
... :param b: fun2
|
|
48
|
+
... :param c: fun2
|
|
49
|
+
... :param e: fun2
|
|
50
|
+
... '''
|
|
51
|
+
>>> @combine_docstrings(fun1, fun2)
|
|
52
|
+
>>> def decorated(a, b, c, d, e, f):
|
|
53
|
+
... '''
|
|
54
|
+
... :param e: decorated
|
|
55
|
+
... :param f: decorated
|
|
56
|
+
... '''
|
|
57
|
+
>>> print(decorated.__doc__)
|
|
58
|
+
short_description: fun2
|
|
59
|
+
<BLANKLINE>
|
|
60
|
+
long_description: fun2
|
|
61
|
+
<BLANKLINE>
|
|
62
|
+
:param a: fun1
|
|
63
|
+
:param b: fun1
|
|
64
|
+
:param c: fun2
|
|
65
|
+
:param e: fun2
|
|
66
|
+
:param f: decorated
|
|
67
|
+
:returns: fun1
|
|
68
|
+
>>> @combine_docstrings(fun1, fun2, exclude=[DocstringReturns])
|
|
69
|
+
>>> def decorated(a, b, c, d, e, f): pass
|
|
70
|
+
>>> print(decorated.__doc__)
|
|
71
|
+
short_description: fun2
|
|
72
|
+
<BLANKLINE>
|
|
73
|
+
long_description: fun2
|
|
74
|
+
<BLANKLINE>
|
|
75
|
+
:param a: fun1
|
|
76
|
+
:param b: fun1
|
|
77
|
+
:param c: fun2
|
|
78
|
+
:param e: fun2
|
|
79
|
+
|
|
80
|
+
:param others: callables from which to parse docstrings.
|
|
81
|
+
:param exclude: an iterable of ``DocstringMeta`` subclasses to exclude when
|
|
82
|
+
combining docstrings.
|
|
83
|
+
:param style: style composed docstring. The default will infer the style
|
|
84
|
+
from the decorated function.
|
|
85
|
+
:param rendering_style: The rendering style used to compose a docstring.
|
|
86
|
+
:return: the decorated function with a modified docstring.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
def wrapper(func: _Func) -> _Func:
|
|
90
|
+
sig = Signature.from_callable(func)
|
|
91
|
+
|
|
92
|
+
comb_doc = parse(func.__doc__ or '')
|
|
93
|
+
docs = [parse(other.__doc__ or '') for other in others] + [comb_doc]
|
|
94
|
+
params = dict(
|
|
95
|
+
ChainMap(
|
|
96
|
+
*(
|
|
97
|
+
{param.arg_name: param for param in doc.params}
|
|
98
|
+
for doc in docs
|
|
99
|
+
),
|
|
100
|
+
),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
for doc in reversed(docs):
|
|
104
|
+
if not doc.short_description:
|
|
105
|
+
continue
|
|
106
|
+
comb_doc.short_description = doc.short_description
|
|
107
|
+
comb_doc.blank_after_short_description = (
|
|
108
|
+
doc.blank_after_short_description
|
|
109
|
+
)
|
|
110
|
+
break
|
|
111
|
+
|
|
112
|
+
for doc in reversed(docs):
|
|
113
|
+
if not doc.long_description:
|
|
114
|
+
continue
|
|
115
|
+
comb_doc.long_description = doc.long_description
|
|
116
|
+
comb_doc.blank_after_long_description = (
|
|
117
|
+
doc.blank_after_long_description
|
|
118
|
+
)
|
|
119
|
+
break
|
|
120
|
+
|
|
121
|
+
combined: T.Dict[T.Type[DocstringMeta], T.List[DocstringMeta]] = {}
|
|
122
|
+
for doc in docs:
|
|
123
|
+
metas: T.Dict[T.Type[DocstringMeta], T.List[DocstringMeta]] = {}
|
|
124
|
+
for meta in doc.meta:
|
|
125
|
+
meta_type = type(meta)
|
|
126
|
+
if meta_type in exclude:
|
|
127
|
+
continue
|
|
128
|
+
metas.setdefault(meta_type, []).append(meta)
|
|
129
|
+
for meta_type, meta_list in metas.items():
|
|
130
|
+
combined[meta_type] = meta_list
|
|
131
|
+
|
|
132
|
+
combined[DocstringParam] = [
|
|
133
|
+
params[name] for name in sig.parameters if name in params
|
|
134
|
+
]
|
|
135
|
+
comb_doc.meta = list(chain(*combined.values()))
|
|
136
|
+
func.__doc__ = compose(
|
|
137
|
+
comb_doc, style=style, rendering_style=rendering_style,
|
|
138
|
+
)
|
|
139
|
+
return func
|
|
140
|
+
|
|
141
|
+
return wrapper
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Database exeception classes."""
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MySQLError(Exception):
|
|
7
|
+
"""All MySQL-related exceptions."""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Error(MySQLError):
|
|
11
|
+
"""
|
|
12
|
+
Generic database exception.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
errno : int
|
|
17
|
+
Database error code
|
|
18
|
+
msg : str
|
|
19
|
+
Database error message
|
|
20
|
+
sqlstate : str, optional
|
|
21
|
+
SQL engine state code
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self, errno: Optional[int] = None, msg: Optional[str] = None,
|
|
27
|
+
sqlstate: Optional[int] = None,
|
|
28
|
+
):
|
|
29
|
+
self.errno = errno
|
|
30
|
+
self.errmsg = msg
|
|
31
|
+
self.sqlstate = sqlstate
|
|
32
|
+
super(Exception, self).__init__(errno, msg, sqlstate)
|
|
33
|
+
|
|
34
|
+
def __str__(self) -> str:
|
|
35
|
+
"""Return string representation."""
|
|
36
|
+
prefix = []
|
|
37
|
+
if self.errno is not None:
|
|
38
|
+
prefix.append(f'{self.errno}')
|
|
39
|
+
if self.sqlstate is not None:
|
|
40
|
+
prefix.append(f'({self.sqlstate})')
|
|
41
|
+
if prefix and self.errmsg:
|
|
42
|
+
return ' '.join(prefix) + ': ' + self.errmsg
|
|
43
|
+
elif prefix:
|
|
44
|
+
return ' '.join(prefix)
|
|
45
|
+
elif self.errmsg:
|
|
46
|
+
return f'{self.errmsg}'
|
|
47
|
+
return 'Unknown error'
|
|
48
|
+
|
|
49
|
+
def __repr__(self) -> str:
|
|
50
|
+
"""Return string representation."""
|
|
51
|
+
return str(self)
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def msg(self) -> Optional[str]:
|
|
55
|
+
"""Return error message."""
|
|
56
|
+
return self.errmsg
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Warning(Warning, MySQLError): # type: ignore
|
|
60
|
+
"""Exception for important warnings like data truncations, etc."""
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class InterfaceError(Error):
|
|
64
|
+
"""Exception for errors in the database interface rather than the database."""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class DatabaseError(Error):
|
|
68
|
+
"""General exception for errors in the database."""
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class InternalError(DatabaseError):
|
|
72
|
+
"""Exception for internal database errors such as out of sync transactions."""
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class OperationalError(DatabaseError):
|
|
76
|
+
"""Exception for operational errors such as unexpected disconnections."""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class ProgrammingError(DatabaseError):
|
|
80
|
+
"""Exception for programming errors."""
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class IntegrityError(DatabaseError):
|
|
84
|
+
"""Exception for relational integrity errors."""
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class DataError(DatabaseError):
|
|
88
|
+
"""Exception for problems with processed data like division by zero."""
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class NotSupportedError(DatabaseError):
|
|
92
|
+
"""Exception for using unsupported features of the database."""
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ManagementError(Error):
|
|
96
|
+
"""Exception for errors in the management API."""
|
|
97
|
+
|
|
98
|
+
def __init__(
|
|
99
|
+
self, errno: Optional[int] = None, msg: Optional[str] = None,
|
|
100
|
+
response: Optional[str] = None,
|
|
101
|
+
):
|
|
102
|
+
self.errno = errno
|
|
103
|
+
self.errmsg = msg
|
|
104
|
+
self.response = response
|
|
105
|
+
super(Exception, self).__init__(errno, msg)
|
|
106
|
+
|
|
107
|
+
def __str__(self) -> str:
|
|
108
|
+
"""Return string representation."""
|
|
109
|
+
prefix = []
|
|
110
|
+
if self.errno is not None:
|
|
111
|
+
prefix.append(f'{self.errno}')
|
|
112
|
+
if self.response is not None:
|
|
113
|
+
prefix.append(f'({self.response})')
|
|
114
|
+
if prefix and self.errmsg:
|
|
115
|
+
return ' '.join(prefix) + ': ' + self.errmsg
|
|
116
|
+
elif prefix:
|
|
117
|
+
return ' '.join(prefix)
|
|
118
|
+
elif self.errmsg:
|
|
119
|
+
return f'{self.errmsg}'
|
|
120
|
+
return 'Unknown error'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .decorator import udf # noqa: F401
|
|
2
|
+
from .typing import Masked # noqa: F401
|
|
3
|
+
from .typing import Table # noqa: F401
|
|
4
|
+
from .utils import pack_vector # noqa: F401
|
|
5
|
+
from .utils import pack_vectors # noqa: F401
|
|
6
|
+
from .utils import unpack_vector # noqa: F401
|
|
7
|
+
from .utils import unpack_vectors # noqa: F401
|
|
8
|
+
from .utils import VectorTypes
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
F32 = VectorTypes.F32
|
|
12
|
+
F64 = VectorTypes.F64
|
|
13
|
+
I8 = VectorTypes.I8
|
|
14
|
+
I16 = VectorTypes.I16
|
|
15
|
+
I32 = VectorTypes.I32
|
|
16
|
+
I64 = VectorTypes.I64
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import functools
|
|
3
|
+
import inspect
|
|
4
|
+
from typing import Any
|
|
5
|
+
from typing import Callable
|
|
6
|
+
from typing import List
|
|
7
|
+
from typing import Optional
|
|
8
|
+
from typing import Type
|
|
9
|
+
from typing import Union
|
|
10
|
+
|
|
11
|
+
from . import utils
|
|
12
|
+
from .dtypes import SQLString
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
ParameterType = Union[
|
|
16
|
+
str,
|
|
17
|
+
Callable[..., SQLString],
|
|
18
|
+
List[Union[str, Callable[..., SQLString]]],
|
|
19
|
+
Type[Any],
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
ReturnType = ParameterType
|
|
23
|
+
UDFType = Callable[..., Any]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def is_valid_type(obj: Any) -> bool:
|
|
27
|
+
"""Check if the object is a valid type for a schema definition."""
|
|
28
|
+
if not inspect.isclass(obj):
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
if utils.is_typeddict(obj):
|
|
32
|
+
return True
|
|
33
|
+
|
|
34
|
+
if utils.is_namedtuple(obj):
|
|
35
|
+
return True
|
|
36
|
+
|
|
37
|
+
if utils.is_dataclass(obj):
|
|
38
|
+
return True
|
|
39
|
+
|
|
40
|
+
# We don't want to import pydantic here, so we check if
|
|
41
|
+
# the class is a subclass
|
|
42
|
+
if utils.is_pydantic(obj):
|
|
43
|
+
return True
|
|
44
|
+
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def is_sqlstr_callable(obj: Any) -> bool:
|
|
49
|
+
"""Check if the object is a valid callable for a parameter type."""
|
|
50
|
+
if not callable(obj):
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
returns = utils.get_annotations(obj).get('return', None)
|
|
54
|
+
|
|
55
|
+
if inspect.isclass(returns) and issubclass(returns, SQLString):
|
|
56
|
+
return True
|
|
57
|
+
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def expand_types(args: Any) -> Optional[List[Any]]:
|
|
62
|
+
"""Expand the types for the function arguments / return values."""
|
|
63
|
+
if args is None:
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
# SQL string
|
|
67
|
+
if isinstance(args, str):
|
|
68
|
+
return [args]
|
|
69
|
+
|
|
70
|
+
# List of SQL strings or callables
|
|
71
|
+
elif isinstance(args, list):
|
|
72
|
+
new_args: List[Any] = []
|
|
73
|
+
for arg in args:
|
|
74
|
+
if isinstance(arg, str):
|
|
75
|
+
new_args.append(arg)
|
|
76
|
+
elif is_sqlstr_callable(arg):
|
|
77
|
+
new_args.append(arg())
|
|
78
|
+
elif type(arg) is type:
|
|
79
|
+
new_args.append(arg)
|
|
80
|
+
elif is_valid_type(arg):
|
|
81
|
+
new_args.append(arg)
|
|
82
|
+
else:
|
|
83
|
+
raise TypeError(f'unrecognized type for parameter: {arg}')
|
|
84
|
+
return new_args
|
|
85
|
+
|
|
86
|
+
# Callable that returns a SQL string
|
|
87
|
+
elif is_sqlstr_callable(args):
|
|
88
|
+
return [args()]
|
|
89
|
+
|
|
90
|
+
# General way of accepting pydantic.BaseModel, NamedTuple, TypedDict
|
|
91
|
+
elif is_valid_type(args):
|
|
92
|
+
return [args]
|
|
93
|
+
|
|
94
|
+
elif type(args) is type:
|
|
95
|
+
return [args]
|
|
96
|
+
|
|
97
|
+
raise TypeError(f'unrecognized type for parameter: {args}')
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _func(
|
|
101
|
+
func: Optional[Callable[..., Any]] = None,
|
|
102
|
+
*,
|
|
103
|
+
name: Optional[str] = None,
|
|
104
|
+
args: Optional[ParameterType] = None,
|
|
105
|
+
returns: Optional[ReturnType] = None,
|
|
106
|
+
timeout: Optional[int] = None,
|
|
107
|
+
) -> UDFType:
|
|
108
|
+
"""Generic wrapper for UDF and TVF decorators."""
|
|
109
|
+
|
|
110
|
+
_singlestoredb_attrs = { # type: ignore
|
|
111
|
+
k: v for k, v in dict(
|
|
112
|
+
name=name,
|
|
113
|
+
args=expand_types(args),
|
|
114
|
+
returns=expand_types(returns),
|
|
115
|
+
timeout=timeout,
|
|
116
|
+
).items() if v is not None
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# No func was specified, this is an uncalled decorator that will get
|
|
120
|
+
# called later, so the wrapper much be created with the func passed
|
|
121
|
+
# in at that time.
|
|
122
|
+
if func is None:
|
|
123
|
+
def decorate(func: UDFType) -> UDFType:
|
|
124
|
+
|
|
125
|
+
if asyncio.iscoroutinefunction(func):
|
|
126
|
+
async def async_wrapper(*args: Any, **kwargs: Any) -> UDFType:
|
|
127
|
+
return await func(*args, **kwargs) # type: ignore
|
|
128
|
+
async_wrapper._singlestoredb_attrs = _singlestoredb_attrs # type: ignore
|
|
129
|
+
return functools.wraps(func)(async_wrapper)
|
|
130
|
+
|
|
131
|
+
else:
|
|
132
|
+
def wrapper(*args: Any, **kwargs: Any) -> UDFType:
|
|
133
|
+
return func(*args, **kwargs) # type: ignore
|
|
134
|
+
wrapper._singlestoredb_attrs = _singlestoredb_attrs # type: ignore
|
|
135
|
+
return functools.wraps(func)(wrapper)
|
|
136
|
+
|
|
137
|
+
return decorate
|
|
138
|
+
|
|
139
|
+
if asyncio.iscoroutinefunction(func):
|
|
140
|
+
async def async_wrapper(*args: Any, **kwargs: Any) -> UDFType:
|
|
141
|
+
return await func(*args, **kwargs) # type: ignore
|
|
142
|
+
async_wrapper._singlestoredb_attrs = _singlestoredb_attrs # type: ignore
|
|
143
|
+
return functools.wraps(func)(async_wrapper)
|
|
144
|
+
|
|
145
|
+
else:
|
|
146
|
+
def wrapper(*args: Any, **kwargs: Any) -> UDFType:
|
|
147
|
+
return func(*args, **kwargs) # type: ignore
|
|
148
|
+
wrapper._singlestoredb_attrs = _singlestoredb_attrs # type: ignore
|
|
149
|
+
return functools.wraps(func)(wrapper)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def udf(
|
|
153
|
+
func: Optional[Callable[..., Any]] = None,
|
|
154
|
+
*,
|
|
155
|
+
name: Optional[str] = None,
|
|
156
|
+
args: Optional[ParameterType] = None,
|
|
157
|
+
returns: Optional[ReturnType] = None,
|
|
158
|
+
timeout: Optional[int] = None,
|
|
159
|
+
) -> UDFType:
|
|
160
|
+
"""
|
|
161
|
+
Define a user-defined function (UDF).
|
|
162
|
+
|
|
163
|
+
Parameters
|
|
164
|
+
----------
|
|
165
|
+
func : callable, optional
|
|
166
|
+
The UDF to apply parameters to
|
|
167
|
+
name : str, optional
|
|
168
|
+
The name to use for the UDF in the database
|
|
169
|
+
args : str | Type | Callable | List[str | Callable], optional
|
|
170
|
+
Specifies the data types of the function arguments. Typically,
|
|
171
|
+
the function data types are derived from the function parameter
|
|
172
|
+
annotations. These annotations can be overridden. If the function
|
|
173
|
+
takes a single type for all parameters, `args` can be set to a
|
|
174
|
+
SQL string describing all parameters. If the function takes more
|
|
175
|
+
than one parameter and all of the parameters are being manually
|
|
176
|
+
defined, a list of SQL strings may be used (one for each parameter).
|
|
177
|
+
A dictionary of SQL strings may be used to specify a parameter type
|
|
178
|
+
for a subset of parameters; the keys are the names of the
|
|
179
|
+
function parameters. Callables may also be used for datatypes. This
|
|
180
|
+
is primarily for using the functions in the ``dtypes`` module that
|
|
181
|
+
are associated with SQL types with all default options (e.g., ``dt.FLOAT``).
|
|
182
|
+
returns : str | Type | Callable | List[str | Callable] | Table, optional
|
|
183
|
+
Specifies the return data type of the function. This parameter
|
|
184
|
+
works the same way as `args`. If the function is a table-valued
|
|
185
|
+
function, the return type should be a `Table` object.
|
|
186
|
+
timeout : int, optional
|
|
187
|
+
The timeout in seconds for the UDF execution. If not specified,
|
|
188
|
+
the global default timeout is used.
|
|
189
|
+
|
|
190
|
+
Returns
|
|
191
|
+
-------
|
|
192
|
+
Callable
|
|
193
|
+
|
|
194
|
+
"""
|
|
195
|
+
return _func(
|
|
196
|
+
func=func,
|
|
197
|
+
name=name,
|
|
198
|
+
args=args,
|
|
199
|
+
returns=returns,
|
|
200
|
+
timeout=timeout,
|
|
201
|
+
)
|