singlestoredb 1.4.0__tar.gz → 1.4.1__tar.gz
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-1.4.0/singlestoredb.egg-info → singlestoredb-1.4.1}/PKG-INFO +1 -1
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/accel.c +19 -9
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/setup.cfg +1 -1
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/__init__.py +1 -1
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/connection.py +4 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/signature.py +4 -2
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/__init__.py +1 -1
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/cluster.py +4 -3
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/manager.py +1 -2
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/utils.py +68 -21
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/workspace.py +5 -4
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/connection.py +33 -4
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/notebook/__init__.py +1 -0
- singlestoredb-1.4.1/singlestoredb/notebook/_portal.py +281 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_connection.py +24 -20
- singlestoredb-1.4.1/singlestoredb/utils/events.py +49 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1/singlestoredb.egg-info}/PKG-INFO +1 -1
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/SOURCES.txt +2 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/LICENSE +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/README.md +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/setup.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/ai/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/ai/embeddings.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/alchemy/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/auth.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/config.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/converters.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/exceptions.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/decorator.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/dtypes.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/arrow.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/asgi.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/json.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/mmap.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/rowdat_1.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/utils.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/graphql.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handler.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handlers/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handlers/stage.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handlers/utils.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handlers/workspace.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/registry.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/result.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/http/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/http/connection.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/billing_usage.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/organization.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/region.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/_auth.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/charset.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/CLIENT.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/COMMAND.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/CR.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/ER.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/EXTENDED_TYPE.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/FIELD_TYPE.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/FLAG.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/SERVER_STATUS.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/VECTOR_TYPE.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/converters.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/cursors.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/err.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/optionfile.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/protocol.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/base.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/conftest.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_DictCursor.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_SSCursor.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_basic.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_connection.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_converters.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_cursor.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_err.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_issues.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_load_local.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_nextset.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_optionfile.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/times.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/notebook/_objects.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/pytest.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/empty.sql +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/ext_funcs/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/local_infile.csv +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test.sql +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test2.sql +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_basics.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_config.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_dbapi.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_exceptions.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_ext_func.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_ext_func_data.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_fusion.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_http.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_management.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_plugin.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_results.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_types.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_udf.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_xdict.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/utils.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/types.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/__init__.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/config.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/convert_rows.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/debug.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/dtypes.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/mogrify.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/results.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/xdict.py +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/dependency_links.txt +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/entry_points.txt +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/requires.txt +0 -0
- {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/top_level.txt +0 -0
|
@@ -421,6 +421,7 @@ typedef struct {
|
|
|
421
421
|
PyObject *float64;
|
|
422
422
|
PyObject *unpack;
|
|
423
423
|
PyObject *decode;
|
|
424
|
+
PyObject *frombuffer;
|
|
424
425
|
} PyStrings;
|
|
425
426
|
|
|
426
427
|
static PyStrings PyStr = {0};
|
|
@@ -437,6 +438,7 @@ typedef struct {
|
|
|
437
438
|
PyObject *datetime_datetime;
|
|
438
439
|
PyObject *collections_namedtuple;
|
|
439
440
|
PyObject *numpy_array;
|
|
441
|
+
PyObject *numpy_frombuffer;
|
|
440
442
|
PyObject *numpy_vectorize;
|
|
441
443
|
PyObject *pandas_DataFrame;
|
|
442
444
|
PyObject *polars_DataFrame;
|
|
@@ -521,6 +523,9 @@ int ensure_numpy() {
|
|
|
521
523
|
PyFunc.numpy_array = PyObject_GetAttr(numpy_mod, PyStr.array);
|
|
522
524
|
if (!PyFunc.numpy_array) goto error;
|
|
523
525
|
|
|
526
|
+
PyFunc.numpy_frombuffer = PyObject_GetAttr(numpy_mod, PyStr.frombuffer);
|
|
527
|
+
if (!PyFunc.numpy_frombuffer) goto error;
|
|
528
|
+
|
|
524
529
|
PyFunc.numpy_vectorize = PyObject_GetAttr(numpy_mod, PyStr.vectorize);
|
|
525
530
|
if (!PyFunc.numpy_vectorize) goto error;
|
|
526
531
|
|
|
@@ -1476,7 +1481,7 @@ static PyObject *read_row_from_packet(
|
|
|
1476
1481
|
PyObject *py_str = NULL;
|
|
1477
1482
|
PyObject *py_memview = NULL;
|
|
1478
1483
|
char end = '\0';
|
|
1479
|
-
char *cast_type_codes[] = {"", "f", "d", "b", "h", "
|
|
1484
|
+
char *cast_type_codes[] = {"", "f", "d", "b", "h", "i", "q"};
|
|
1480
1485
|
int item_type_lengths[] = {0, 4, 8, 1, 2, 4, 8};
|
|
1481
1486
|
|
|
1482
1487
|
int sign = 1;
|
|
@@ -1773,17 +1778,20 @@ static PyObject *read_row_from_packet(
|
|
|
1773
1778
|
case MYSQL_TYPE_INT16_VECTOR:
|
|
1774
1779
|
case MYSQL_TYPE_INT32_VECTOR:
|
|
1775
1780
|
case MYSQL_TYPE_INT64_VECTOR:
|
|
1781
|
+
{
|
|
1782
|
+
int type_idx = py_state->type_codes[i] % 1000;
|
|
1783
|
+
|
|
1776
1784
|
if (ensure_numpy() == 0) {
|
|
1777
|
-
py_memview =
|
|
1785
|
+
py_memview = PyBytes_FromStringAndSize(out, out_l);
|
|
1778
1786
|
if (!py_memview) goto error;
|
|
1779
1787
|
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1788
|
+
CHECKRC(PyTuple_SetItem(PyObj.create_numpy_array_args, 0, py_memview));
|
|
1789
|
+
|
|
1790
|
+
py_item = PyObject_Call(
|
|
1791
|
+
PyFunc.numpy_frombuffer,
|
|
1792
|
+
PyObj.create_numpy_array_args,
|
|
1793
|
+
PyObj.create_numpy_array_kwargs_vector[type_idx]
|
|
1785
1794
|
);
|
|
1786
|
-
Py_CLEAR(py_memview);
|
|
1787
1795
|
if (!py_item) goto error;
|
|
1788
1796
|
|
|
1789
1797
|
} else {
|
|
@@ -1791,7 +1799,7 @@ static PyObject *read_row_from_packet(
|
|
|
1791
1799
|
if (!py_memview) goto error;
|
|
1792
1800
|
|
|
1793
1801
|
CHECKRC(PyTuple_SetItem(PyObj.struct_unpack_args, 0,
|
|
1794
|
-
PyUnicode_FromFormat("<%
|
|
1802
|
+
PyUnicode_FromFormat("<%ld%s", out_l / item_type_lengths[type_idx], cast_type_codes[type_idx])));
|
|
1795
1803
|
CHECKRC(PyTuple_SetItem(PyObj.struct_unpack_args, 1, py_memview));
|
|
1796
1804
|
|
|
1797
1805
|
py_item = PyObject_Call(
|
|
@@ -1803,6 +1811,7 @@ static PyObject *read_row_from_packet(
|
|
|
1803
1811
|
}
|
|
1804
1812
|
|
|
1805
1813
|
break;
|
|
1814
|
+
}
|
|
1806
1815
|
|
|
1807
1816
|
case MYSQL_TYPE_BSON:
|
|
1808
1817
|
py_item = PyBytes_FromStringAndSize(out, out_l);
|
|
@@ -4614,6 +4623,7 @@ PyMODINIT_FUNC PyInit__singlestoredb_accel(void) {
|
|
|
4614
4623
|
PyStr.float64 = PyUnicode_FromString("float64");
|
|
4615
4624
|
PyStr.unpack = PyUnicode_FromString("unpack");
|
|
4616
4625
|
PyStr.decode = PyUnicode_FromString("decode");
|
|
4626
|
+
PyStr.frombuffer = PyUnicode_FromString("frombuffer");
|
|
4617
4627
|
|
|
4618
4628
|
PyObject *decimal_mod = PyImport_ImportModule("decimal");
|
|
4619
4629
|
if (!decimal_mod) goto error;
|
|
@@ -1359,6 +1359,10 @@ def connect(
|
|
|
1359
1359
|
results_type : str, optional
|
|
1360
1360
|
The form of the query results: tuples, namedtuples, dicts,
|
|
1361
1361
|
numpy, polars, pandas, arrow
|
|
1362
|
+
buffered : bool, optional
|
|
1363
|
+
Should the entire query result be buffered in memory? This is the default
|
|
1364
|
+
behavior which allows full cursor control of the result, but does consume
|
|
1365
|
+
more memory.
|
|
1362
1366
|
results_format : str, optional
|
|
1363
1367
|
Deprecated. This option has been renamed to results_type.
|
|
1364
1368
|
program_name : str, optional
|
|
@@ -45,15 +45,17 @@ if has_numpy:
|
|
|
45
45
|
np.uint8: 'uint8',
|
|
46
46
|
np.longlong: 'uint64',
|
|
47
47
|
np.ulonglong: 'uint64',
|
|
48
|
-
np.unicode_: 'str',
|
|
49
48
|
np.str_: 'str',
|
|
50
49
|
np.bytes_: 'bytes',
|
|
51
|
-
np.float_: 'float64',
|
|
52
50
|
np.float64: 'float64',
|
|
53
51
|
np.float32: 'float32',
|
|
54
52
|
np.float16: 'float16',
|
|
55
53
|
np.double: 'float64',
|
|
56
54
|
}
|
|
55
|
+
if hasattr(np, 'unicode_'):
|
|
56
|
+
numpy_type_map[np.unicode_] = 'str'
|
|
57
|
+
if hasattr(np, 'float_'):
|
|
58
|
+
numpy_type_map[np.float_] = 'float64'
|
|
57
59
|
else:
|
|
58
60
|
array_types = (Sequence,)
|
|
59
61
|
numpy_type_map = {}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
from .cluster import manage_cluster
|
|
3
|
-
from .manager import get_organization
|
|
4
3
|
from .manager import get_token
|
|
4
|
+
from .workspace import get_organization
|
|
5
5
|
from .workspace import get_secret
|
|
6
6
|
from .workspace import get_stage
|
|
7
7
|
from .workspace import manage_workspaces
|
|
@@ -8,6 +8,7 @@ from typing import List
|
|
|
8
8
|
from typing import Optional
|
|
9
9
|
from typing import Union
|
|
10
10
|
|
|
11
|
+
from .. import config
|
|
11
12
|
from .. import connection
|
|
12
13
|
from ..exceptions import ManagementError
|
|
13
14
|
from .manager import Manager
|
|
@@ -332,7 +333,7 @@ class ClusterManager(Manager):
|
|
|
332
333
|
default_version = 'v0beta'
|
|
333
334
|
|
|
334
335
|
#: Base URL if none is specified.
|
|
335
|
-
default_base_url = '
|
|
336
|
+
default_base_url = config.get_option('management.base_url')
|
|
336
337
|
|
|
337
338
|
#: Object type
|
|
338
339
|
obj_type = 'cluster'
|
|
@@ -425,8 +426,8 @@ class ClusterManager(Manager):
|
|
|
425
426
|
|
|
426
427
|
def manage_cluster(
|
|
427
428
|
access_token: Optional[str] = None,
|
|
428
|
-
version: str =
|
|
429
|
-
base_url: str =
|
|
429
|
+
version: Optional[str] = None,
|
|
430
|
+
base_url: Optional[str] = None,
|
|
430
431
|
*,
|
|
431
432
|
organization_id: Optional[str] = None,
|
|
432
433
|
) -> ClusterManager:
|
|
@@ -15,7 +15,6 @@ import requests
|
|
|
15
15
|
|
|
16
16
|
from .. import config
|
|
17
17
|
from ..exceptions import ManagementError
|
|
18
|
-
from .utils import get_organization
|
|
19
18
|
from .utils import get_token
|
|
20
19
|
|
|
21
20
|
|
|
@@ -24,7 +23,7 @@ def set_organization(kwargs: Dict[str, Any]) -> None:
|
|
|
24
23
|
if kwargs.get('params', {}).get('organizationID', None):
|
|
25
24
|
return
|
|
26
25
|
|
|
27
|
-
org =
|
|
26
|
+
org = os.environ.get('SINGLESTOREDB_ORGANIZATION')
|
|
28
27
|
if org:
|
|
29
28
|
if 'params' not in kwargs:
|
|
30
29
|
kwargs['params'] = {}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"""SingleStoreDB Cluster Management."""
|
|
3
3
|
import datetime
|
|
4
4
|
import functools
|
|
5
|
+
import itertools
|
|
5
6
|
import os
|
|
6
7
|
import re
|
|
7
8
|
import sys
|
|
@@ -12,6 +13,7 @@ from typing import List
|
|
|
12
13
|
from typing import Mapping
|
|
13
14
|
from typing import Optional
|
|
14
15
|
from typing import SupportsIndex
|
|
16
|
+
from typing import Tuple
|
|
15
17
|
from typing import TypeVar
|
|
16
18
|
from typing import Union
|
|
17
19
|
from urllib.parse import urlparse
|
|
@@ -20,6 +22,7 @@ import jwt
|
|
|
20
22
|
|
|
21
23
|
from .. import converters
|
|
22
24
|
from ..config import get_option
|
|
25
|
+
from ..utils import events
|
|
23
26
|
|
|
24
27
|
JSON = Union[str, List[str], Dict[str, 'JSON']]
|
|
25
28
|
JSONObj = Dict[str, JSON]
|
|
@@ -117,6 +120,66 @@ class NamedList(List[T]):
|
|
|
117
120
|
raise
|
|
118
121
|
|
|
119
122
|
|
|
123
|
+
def _setup_authentication_info_handler() -> Callable[..., Dict[str, Any]]:
|
|
124
|
+
"""Setup authentication info event handler."""
|
|
125
|
+
|
|
126
|
+
authentication_info: List[Tuple[str, Any]] = []
|
|
127
|
+
|
|
128
|
+
def handle_authentication_info(msg: Dict[str, Any]) -> None:
|
|
129
|
+
"""Handle authentication info events."""
|
|
130
|
+
nonlocal authentication_info
|
|
131
|
+
if msg.get('name', '') != 'singlestore.portal.authentication_updated':
|
|
132
|
+
return
|
|
133
|
+
authentication_info = list(msg.get('data', {}).items())
|
|
134
|
+
|
|
135
|
+
events.subscribe(handle_authentication_info)
|
|
136
|
+
|
|
137
|
+
def handle_connection_info(msg: Dict[str, Any]) -> None:
|
|
138
|
+
"""Handle connection info events."""
|
|
139
|
+
nonlocal authentication_info
|
|
140
|
+
if msg.get('name', '') != 'singlestore.portal.connection_updated':
|
|
141
|
+
return
|
|
142
|
+
data = msg.get('data', {})
|
|
143
|
+
out = {}
|
|
144
|
+
if 'user' in data:
|
|
145
|
+
out['user'] = data['user']
|
|
146
|
+
if 'password' in data:
|
|
147
|
+
out['password'] = data['password']
|
|
148
|
+
authentication_info = list(out.items())
|
|
149
|
+
|
|
150
|
+
events.subscribe(handle_authentication_info)
|
|
151
|
+
|
|
152
|
+
def get_env() -> List[Tuple[str, Any]]:
|
|
153
|
+
conn = {}
|
|
154
|
+
url = os.environ.get('SINGLESTOREDB_URL') or get_option('host')
|
|
155
|
+
if url:
|
|
156
|
+
urlp = urlparse(url, scheme='singlestoredb', allow_fragments=True)
|
|
157
|
+
conn = dict(
|
|
158
|
+
user=urlp.username or None,
|
|
159
|
+
password=urlp.password or None,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
return [
|
|
163
|
+
x for x in dict(
|
|
164
|
+
**conn,
|
|
165
|
+
).items() if x[1] is not None
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
def get_authentication_info(include_env: bool = True) -> Dict[str, Any]:
|
|
169
|
+
"""Return authentication info from event."""
|
|
170
|
+
return dict(
|
|
171
|
+
itertools.chain(
|
|
172
|
+
(get_env() if include_env else []),
|
|
173
|
+
authentication_info,
|
|
174
|
+
),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return get_authentication_info
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
get_authentication_info = _setup_authentication_info_handler()
|
|
181
|
+
|
|
182
|
+
|
|
120
183
|
def get_token() -> Optional[str]:
|
|
121
184
|
"""Return the token for the Management API."""
|
|
122
185
|
# See if an API key is configured
|
|
@@ -124,18 +187,11 @@ def get_token() -> Optional[str]:
|
|
|
124
187
|
if tok:
|
|
125
188
|
return tok
|
|
126
189
|
|
|
127
|
-
|
|
128
|
-
if
|
|
129
|
-
# See if the connection URL contains a JWT
|
|
130
|
-
url = get_option('host')
|
|
131
|
-
if not url:
|
|
132
|
-
return None
|
|
133
|
-
|
|
134
|
-
urlp = urlparse(url, scheme='singlestoredb', allow_fragments=True)
|
|
135
|
-
if urlp.password:
|
|
190
|
+
tok = get_authentication_info(include_env=True).get('password')
|
|
191
|
+
if tok:
|
|
136
192
|
try:
|
|
137
|
-
jwt.decode(
|
|
138
|
-
return
|
|
193
|
+
jwt.decode(tok, options={'verify_signature': False})
|
|
194
|
+
return tok
|
|
139
195
|
except jwt.DecodeError:
|
|
140
196
|
pass
|
|
141
197
|
|
|
@@ -143,15 +199,6 @@ def get_token() -> Optional[str]:
|
|
|
143
199
|
return None
|
|
144
200
|
|
|
145
201
|
|
|
146
|
-
def get_organization() -> Optional[str]:
|
|
147
|
-
"""Return the organization for the current token or environment."""
|
|
148
|
-
org = os.environ.get('SINGLESTOREDB_ORGANIZATION')
|
|
149
|
-
if org:
|
|
150
|
-
return org
|
|
151
|
-
|
|
152
|
-
return None
|
|
153
|
-
|
|
154
|
-
|
|
155
202
|
def enable_http_tracing() -> None:
|
|
156
203
|
"""Enable tracing of HTTP requests."""
|
|
157
204
|
import logging
|
|
@@ -269,7 +316,7 @@ def snake_to_camel(s: Optional[str], cap_first: bool = False) -> Optional[str]:
|
|
|
269
316
|
"""Convert snake-case to camel-case."""
|
|
270
317
|
if s is None:
|
|
271
318
|
return None
|
|
272
|
-
out = re.sub(r'_[A-Za-z]', _upper_match, s.lower())
|
|
319
|
+
out = re.sub(r'_([A-Za-z])', _upper_match, s.lower())
|
|
273
320
|
if cap_first and out:
|
|
274
321
|
return out[0].upper() + out[1:]
|
|
275
322
|
return out
|
|
@@ -17,6 +17,7 @@ from typing import Optional
|
|
|
17
17
|
from typing import TextIO
|
|
18
18
|
from typing import Union
|
|
19
19
|
|
|
20
|
+
from .. import config
|
|
20
21
|
from .. import connection
|
|
21
22
|
from ..exceptions import ManagementError
|
|
22
23
|
from .billing_usage import BillingUsageItem
|
|
@@ -1690,10 +1691,10 @@ class WorkspaceManager(Manager):
|
|
|
1690
1691
|
"""
|
|
1691
1692
|
|
|
1692
1693
|
#: Workspace management API version if none is specified.
|
|
1693
|
-
default_version = '
|
|
1694
|
+
default_version = config.get_option('management.version')
|
|
1694
1695
|
|
|
1695
1696
|
#: Base URL if none is specified.
|
|
1696
|
-
default_base_url = '
|
|
1697
|
+
default_base_url = config.get_option('management.base_url')
|
|
1697
1698
|
|
|
1698
1699
|
#: Object type
|
|
1699
1700
|
obj_type = 'workspace'
|
|
@@ -1906,8 +1907,8 @@ class WorkspaceManager(Manager):
|
|
|
1906
1907
|
|
|
1907
1908
|
def manage_workspaces(
|
|
1908
1909
|
access_token: Optional[str] = None,
|
|
1909
|
-
version: str =
|
|
1910
|
-
base_url: str =
|
|
1910
|
+
version: Optional[str] = None,
|
|
1911
|
+
base_url: Optional[str] = None,
|
|
1911
1912
|
*,
|
|
1912
1913
|
organization_id: Optional[str] = None,
|
|
1913
1914
|
) -> WorkspaceManager:
|
|
@@ -13,6 +13,8 @@ import struct
|
|
|
13
13
|
import sys
|
|
14
14
|
import traceback
|
|
15
15
|
import warnings
|
|
16
|
+
from typing import Any
|
|
17
|
+
from typing import Dict
|
|
16
18
|
from typing import Iterable
|
|
17
19
|
|
|
18
20
|
try:
|
|
@@ -21,6 +23,7 @@ except (ImportError, ModuleNotFoundError):
|
|
|
21
23
|
_singlestoredb_accel = None
|
|
22
24
|
|
|
23
25
|
from . import _auth
|
|
26
|
+
from ..utils import events
|
|
24
27
|
|
|
25
28
|
from .charset import charset_by_name, charset_by_id
|
|
26
29
|
from .constants import CLIENT, COMMAND, CR, ER, FIELD_TYPE, SERVER_STATUS
|
|
@@ -100,6 +103,19 @@ TEXT_TYPES = {
|
|
|
100
103
|
FIELD_TYPE.VAR_STRING,
|
|
101
104
|
FIELD_TYPE.VARCHAR,
|
|
102
105
|
FIELD_TYPE.GEOMETRY,
|
|
106
|
+
FIELD_TYPE.BSON,
|
|
107
|
+
FIELD_TYPE.FLOAT32_VECTOR_JSON,
|
|
108
|
+
FIELD_TYPE.FLOAT64_VECTOR_JSON,
|
|
109
|
+
FIELD_TYPE.INT8_VECTOR_JSON,
|
|
110
|
+
FIELD_TYPE.INT16_VECTOR_JSON,
|
|
111
|
+
FIELD_TYPE.INT32_VECTOR_JSON,
|
|
112
|
+
FIELD_TYPE.INT64_VECTOR_JSON,
|
|
113
|
+
FIELD_TYPE.FLOAT32_VECTOR,
|
|
114
|
+
FIELD_TYPE.FLOAT64_VECTOR,
|
|
115
|
+
FIELD_TYPE.INT8_VECTOR,
|
|
116
|
+
FIELD_TYPE.INT16_VECTOR,
|
|
117
|
+
FIELD_TYPE.INT32_VECTOR,
|
|
118
|
+
FIELD_TYPE.INT64_VECTOR,
|
|
103
119
|
}
|
|
104
120
|
|
|
105
121
|
UNSET = 'unset'
|
|
@@ -614,15 +630,22 @@ class Connection(BaseConnection):
|
|
|
614
630
|
if k not in self._connect_attrs:
|
|
615
631
|
self._connect_attrs[k] = v
|
|
616
632
|
|
|
633
|
+
self._is_committable = True
|
|
617
634
|
self._in_sync = False
|
|
618
635
|
self._track_env = bool(track_env) or self.host == 'singlestore.com'
|
|
619
636
|
self._enable_extended_data_types = enable_extended_data_types
|
|
637
|
+
self._connection_info = {}
|
|
638
|
+
events.subscribe(self._handle_event)
|
|
620
639
|
|
|
621
640
|
if defer_connect or self._track_env:
|
|
622
641
|
self._sock = None
|
|
623
642
|
else:
|
|
624
643
|
self.connect()
|
|
625
644
|
|
|
645
|
+
def _handle_event(self, data: Dict[str, Any]) -> None:
|
|
646
|
+
if data.get('name', '') == 'singlestore.portal.connection_updated':
|
|
647
|
+
self._connection_info = dict(data)
|
|
648
|
+
|
|
626
649
|
@property
|
|
627
650
|
def messages(self):
|
|
628
651
|
# TODO
|
|
@@ -766,7 +789,8 @@ class Connection(BaseConnection):
|
|
|
766
789
|
|
|
767
790
|
"""
|
|
768
791
|
log_query('COMMIT')
|
|
769
|
-
if self.host == 'singlestore.com':
|
|
792
|
+
if not self._is_committable or self.host == 'singlestore.com':
|
|
793
|
+
self._is_committable = True
|
|
770
794
|
return
|
|
771
795
|
self._execute_command(COMMAND.COM_QUERY, 'COMMIT')
|
|
772
796
|
self._read_ok_packet()
|
|
@@ -780,7 +804,8 @@ class Connection(BaseConnection):
|
|
|
780
804
|
|
|
781
805
|
"""
|
|
782
806
|
log_query('ROLLBACK')
|
|
783
|
-
if self.host == 'singlestore.com':
|
|
807
|
+
if not self._is_committable or self.host == 'singlestore.com':
|
|
808
|
+
self._is_committable = True
|
|
784
809
|
return
|
|
785
810
|
self._execute_command(COMMAND.COM_QUERY, 'ROLLBACK')
|
|
786
811
|
self._read_ok_packet()
|
|
@@ -858,9 +883,11 @@ class Connection(BaseConnection):
|
|
|
858
883
|
# print("DEBUG: sending query:", sql)
|
|
859
884
|
handler = fusion.get_handler(sql)
|
|
860
885
|
if handler is not None:
|
|
886
|
+
self._is_committable = False
|
|
861
887
|
self._result = fusion.execute(self, sql, handler=handler)
|
|
862
888
|
self._affected_rows = self._result.affected_rows
|
|
863
889
|
else:
|
|
890
|
+
self._is_committable = True
|
|
864
891
|
if isinstance(sql, str):
|
|
865
892
|
sql = sql.encode(self.encoding, 'surrogateescape')
|
|
866
893
|
self._local_infile_stream = infile_stream
|
|
@@ -973,9 +1000,11 @@ class Connection(BaseConnection):
|
|
|
973
1000
|
if not self._track_env:
|
|
974
1001
|
return
|
|
975
1002
|
|
|
976
|
-
url =
|
|
1003
|
+
url = self._connection_info.get('connection_url')
|
|
977
1004
|
if not url:
|
|
978
|
-
|
|
1005
|
+
url = os.environ.get('SINGLESTOREDB_URL')
|
|
1006
|
+
if not url:
|
|
1007
|
+
return
|
|
979
1008
|
|
|
980
1009
|
out = {}
|
|
981
1010
|
urlp = connection._parse_url(url)
|
|
@@ -7,6 +7,7 @@ from ._objects import secrets # noqa: F401
|
|
|
7
7
|
from ._objects import stage # noqa: F401
|
|
8
8
|
from ._objects import workspace # noqa: F401
|
|
9
9
|
from ._objects import workspace_group # noqa: F401
|
|
10
|
+
from ._portal import portal # noqa: F401
|
|
10
11
|
|
|
11
12
|
if 'SINGLESTOREDB_ORGANIZATION' not in _os.environ:
|
|
12
13
|
_warnings.warn(
|