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.

Files changed (128) hide show
  1. {singlestoredb-1.4.0/singlestoredb.egg-info → singlestoredb-1.4.1}/PKG-INFO +1 -1
  2. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/accel.c +19 -9
  3. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/setup.cfg +1 -1
  4. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/__init__.py +1 -1
  5. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/connection.py +4 -0
  6. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/signature.py +4 -2
  7. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/__init__.py +1 -1
  8. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/cluster.py +4 -3
  9. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/manager.py +1 -2
  10. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/utils.py +68 -21
  11. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/workspace.py +5 -4
  12. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/connection.py +33 -4
  13. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/notebook/__init__.py +1 -0
  14. singlestoredb-1.4.1/singlestoredb/notebook/_portal.py +281 -0
  15. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_connection.py +24 -20
  16. singlestoredb-1.4.1/singlestoredb/utils/events.py +49 -0
  17. {singlestoredb-1.4.0 → singlestoredb-1.4.1/singlestoredb.egg-info}/PKG-INFO +1 -1
  18. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/SOURCES.txt +2 -0
  19. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/LICENSE +0 -0
  20. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/README.md +0 -0
  21. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/setup.py +0 -0
  22. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/ai/__init__.py +0 -0
  23. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/ai/embeddings.py +0 -0
  24. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/alchemy/__init__.py +0 -0
  25. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/auth.py +0 -0
  26. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/config.py +0 -0
  27. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/converters.py +0 -0
  28. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/exceptions.py +0 -0
  29. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/__init__.py +0 -0
  30. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/decorator.py +0 -0
  31. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/dtypes.py +0 -0
  32. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/__init__.py +0 -0
  33. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/arrow.py +0 -0
  34. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/asgi.py +0 -0
  35. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/json.py +0 -0
  36. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/mmap.py +0 -0
  37. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/rowdat_1.py +0 -0
  38. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/functions/ext/utils.py +0 -0
  39. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/__init__.py +0 -0
  40. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/graphql.py +0 -0
  41. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handler.py +0 -0
  42. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handlers/__init__.py +0 -0
  43. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handlers/stage.py +0 -0
  44. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handlers/utils.py +0 -0
  45. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/handlers/workspace.py +0 -0
  46. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/registry.py +0 -0
  47. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/fusion/result.py +0 -0
  48. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/http/__init__.py +0 -0
  49. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/http/connection.py +0 -0
  50. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/billing_usage.py +0 -0
  51. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/organization.py +0 -0
  52. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/management/region.py +0 -0
  53. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/__init__.py +0 -0
  54. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/_auth.py +0 -0
  55. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/charset.py +0 -0
  56. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/CLIENT.py +0 -0
  57. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/COMMAND.py +0 -0
  58. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/CR.py +0 -0
  59. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/ER.py +0 -0
  60. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/EXTENDED_TYPE.py +0 -0
  61. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/FIELD_TYPE.py +0 -0
  62. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/FLAG.py +0 -0
  63. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/SERVER_STATUS.py +0 -0
  64. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/VECTOR_TYPE.py +0 -0
  65. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/constants/__init__.py +0 -0
  66. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/converters.py +0 -0
  67. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/cursors.py +0 -0
  68. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/err.py +0 -0
  69. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/optionfile.py +0 -0
  70. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/protocol.py +0 -0
  71. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/__init__.py +0 -0
  72. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/base.py +0 -0
  73. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/conftest.py +0 -0
  74. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_DictCursor.py +0 -0
  75. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_SSCursor.py +0 -0
  76. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_basic.py +0 -0
  77. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_connection.py +0 -0
  78. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_converters.py +0 -0
  79. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_cursor.py +0 -0
  80. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_err.py +0 -0
  81. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_issues.py +0 -0
  82. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_load_local.py +0 -0
  83. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_nextset.py +0 -0
  84. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/test_optionfile.py +0 -0
  85. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/__init__.py +0 -0
  86. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +0 -0
  87. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +0 -0
  88. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +0 -0
  89. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +0 -0
  90. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +0 -0
  91. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +0 -0
  92. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/mysql/times.py +0 -0
  93. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/notebook/_objects.py +0 -0
  94. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/pytest.py +0 -0
  95. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/__init__.py +0 -0
  96. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/empty.sql +0 -0
  97. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/ext_funcs/__init__.py +0 -0
  98. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/local_infile.csv +0 -0
  99. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test.sql +0 -0
  100. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test2.sql +0 -0
  101. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_basics.py +0 -0
  102. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_config.py +0 -0
  103. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_dbapi.py +0 -0
  104. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_exceptions.py +0 -0
  105. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_ext_func.py +0 -0
  106. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_ext_func_data.py +0 -0
  107. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_fusion.py +0 -0
  108. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_http.py +0 -0
  109. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_management.py +0 -0
  110. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_plugin.py +0 -0
  111. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_results.py +0 -0
  112. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_types.py +0 -0
  113. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_udf.py +0 -0
  114. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/test_xdict.py +0 -0
  115. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/tests/utils.py +0 -0
  116. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/types.py +0 -0
  117. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/__init__.py +0 -0
  118. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/config.py +0 -0
  119. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/convert_rows.py +0 -0
  120. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/debug.py +0 -0
  121. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/dtypes.py +0 -0
  122. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/mogrify.py +0 -0
  123. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/results.py +0 -0
  124. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb/utils/xdict.py +0 -0
  125. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/dependency_links.txt +0 -0
  126. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/entry_points.txt +0 -0
  127. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/requires.txt +0 -0
  128. {singlestoredb-1.4.0 → singlestoredb-1.4.1}/singlestoredb.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: singlestoredb
3
- Version: 1.4.0
3
+ Version: 1.4.1
4
4
  Summary: Interface to the SingleStoreDB database and workspace management APIs
5
5
  Home-page: https://github.com/singlestore-labs/singlestoredb-python
6
6
  Author: SingleStore
@@ -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", "l", "q"};
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 = PyMemoryView_FromMemory(out, out_l, PyBUF_WRITE);
1785
+ py_memview = PyBytes_FromStringAndSize(out, out_l);
1778
1786
  if (!py_memview) goto error;
1779
1787
 
1780
- py_item = create_numpy_array(
1781
- py_memview,
1782
- cast_type_codes[py_state->type_codes[i] % 1000],
1783
- py_state->type_codes[i],
1784
- NULL
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("<%l%s", out_l / item_type_lengths[i], cast_type_codes[i])));
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;
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = singlestoredb
3
- version = 1.4.0
3
+ version = 1.4.1
4
4
  description = Interface to the SingleStoreDB database and workspace management APIs
5
5
  long_description = file: README.md
6
6
  long_description_content_type = text/markdown
@@ -13,7 +13,7 @@ Examples
13
13
 
14
14
  """
15
15
 
16
- __version__ = '1.4.0'
16
+ __version__ = '1.4.1'
17
17
 
18
18
  from typing import Any
19
19
 
@@ -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 = 'https://api.singlestore.com'
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 = ClusterManager.default_version,
429
- base_url: str = ClusterManager.default_base_url,
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 = get_organization()
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
- url = os.environ.get('SINGLESTOREDB_URL')
128
- if not url:
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(urlp.password, options={'verify_signature': False})
138
- return urlp.password
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 = 'v1'
1694
+ default_version = config.get_option('management.version')
1694
1695
 
1695
1696
  #: Base URL if none is specified.
1696
- default_base_url = 'https://api.singlestore.com'
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 = WorkspaceManager.default_version,
1910
- base_url: str = WorkspaceManager.default_base_url,
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 = os.environ.get('SINGLESTOREDB_URL')
1003
+ url = self._connection_info.get('connection_url')
977
1004
  if not url:
978
- return
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(