singlestoredb 1.0.3__tar.gz → 1.1.0__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 (124) hide show
  1. {singlestoredb-1.0.3/singlestoredb.egg-info → singlestoredb-1.1.0}/PKG-INFO +1 -1
  2. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/accel.c +126 -28
  3. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/setup.cfg +3 -2
  4. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/__init__.py +1 -1
  5. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/config.py +125 -0
  6. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/functions/dtypes.py +5 -198
  7. singlestoredb-1.1.0/singlestoredb/functions/ext/__init__.py +1 -0
  8. singlestoredb-1.1.0/singlestoredb/functions/ext/asgi.py +1173 -0
  9. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/functions/ext/json.py +2 -2
  10. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/functions/ext/mmap.py +174 -67
  11. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/functions/ext/rowdat_1.py +2 -2
  12. singlestoredb-1.1.0/singlestoredb/functions/ext/utils.py +169 -0
  13. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/fusion/handler.py +109 -9
  14. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/fusion/handlers/stage.py +150 -0
  15. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/fusion/handlers/workspace.py +265 -4
  16. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/fusion/registry.py +69 -1
  17. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/http/connection.py +40 -2
  18. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/management/utils.py +30 -0
  19. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/management/workspace.py +209 -35
  20. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/connection.py +69 -0
  21. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/cursors.py +176 -4
  22. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test.sql +210 -0
  23. singlestoredb-1.1.0/singlestoredb/tests/test_connection.py +2882 -0
  24. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_ext_func.py +2 -2
  25. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_ext_func_data.py +1 -1
  26. singlestoredb-1.1.0/singlestoredb/utils/dtypes.py +205 -0
  27. singlestoredb-1.1.0/singlestoredb/utils/results.py +581 -0
  28. {singlestoredb-1.0.3 → singlestoredb-1.1.0/singlestoredb.egg-info}/PKG-INFO +1 -1
  29. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb.egg-info/SOURCES.txt +2 -0
  30. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb.egg-info/requires.txt +3 -0
  31. singlestoredb-1.0.3/singlestoredb/functions/ext/__init__.py +0 -2
  32. singlestoredb-1.0.3/singlestoredb/functions/ext/asgi.py +0 -661
  33. singlestoredb-1.0.3/singlestoredb/tests/test_connection.py +0 -1474
  34. singlestoredb-1.0.3/singlestoredb/utils/results.py +0 -228
  35. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/LICENSE +0 -0
  36. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/README.md +0 -0
  37. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/setup.py +0 -0
  38. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/alchemy/__init__.py +0 -0
  39. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/auth.py +0 -0
  40. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/connection.py +0 -0
  41. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/converters.py +0 -0
  42. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/exceptions.py +0 -0
  43. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/functions/__init__.py +0 -0
  44. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/functions/decorator.py +0 -0
  45. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/functions/ext/arrow.py +0 -0
  46. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/functions/signature.py +0 -0
  47. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/fusion/__init__.py +0 -0
  48. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/fusion/graphql.py +0 -0
  49. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/fusion/handlers/__init__.py +0 -0
  50. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/fusion/handlers/utils.py +0 -0
  51. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/fusion/result.py +0 -0
  52. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/http/__init__.py +0 -0
  53. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/management/__init__.py +0 -0
  54. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/management/billing_usage.py +0 -0
  55. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/management/cluster.py +0 -0
  56. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/management/manager.py +0 -0
  57. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/management/organization.py +0 -0
  58. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/management/region.py +0 -0
  59. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/__init__.py +0 -0
  60. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/_auth.py +0 -0
  61. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/charset.py +0 -0
  62. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/constants/CLIENT.py +0 -0
  63. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/constants/COMMAND.py +0 -0
  64. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/constants/CR.py +0 -0
  65. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/constants/ER.py +0 -0
  66. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/constants/FIELD_TYPE.py +0 -0
  67. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/constants/FLAG.py +0 -0
  68. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/constants/SERVER_STATUS.py +0 -0
  69. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/constants/__init__.py +0 -0
  70. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/converters.py +0 -0
  71. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/err.py +0 -0
  72. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/optionfile.py +0 -0
  73. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/protocol.py +0 -0
  74. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/__init__.py +0 -0
  75. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/base.py +0 -0
  76. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/conftest.py +0 -0
  77. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_DictCursor.py +0 -0
  78. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_SSCursor.py +0 -0
  79. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_basic.py +0 -0
  80. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_connection.py +0 -0
  81. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_converters.py +0 -0
  82. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_cursor.py +0 -0
  83. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_err.py +0 -0
  84. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_issues.py +0 -0
  85. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_load_local.py +0 -0
  86. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_nextset.py +0 -0
  87. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/test_optionfile.py +0 -0
  88. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/thirdparty/__init__.py +0 -0
  89. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +0 -0
  90. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +0 -0
  91. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +0 -0
  92. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +0 -0
  93. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +0 -0
  94. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +0 -0
  95. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/mysql/times.py +0 -0
  96. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/pytest.py +0 -0
  97. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/__init__.py +0 -0
  98. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/empty.sql +0 -0
  99. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/ext_funcs/__init__.py +0 -0
  100. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/local_infile.csv +0 -0
  101. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test2.sql +0 -0
  102. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_basics.py +0 -0
  103. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_config.py +0 -0
  104. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_dbapi.py +0 -0
  105. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_exceptions.py +0 -0
  106. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_fusion.py +0 -0
  107. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_http.py +0 -0
  108. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_management.py +0 -0
  109. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_plugin.py +0 -0
  110. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_results.py +0 -0
  111. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_types.py +0 -0
  112. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_udf.py +0 -0
  113. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/test_xdict.py +0 -0
  114. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/tests/utils.py +0 -0
  115. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/types.py +0 -0
  116. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/utils/__init__.py +0 -0
  117. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/utils/config.py +0 -0
  118. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/utils/convert_rows.py +0 -0
  119. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/utils/debug.py +0 -0
  120. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/utils/mogrify.py +0 -0
  121. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb/utils/xdict.py +0 -0
  122. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb.egg-info/dependency_links.txt +0 -0
  123. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/singlestoredb.egg-info/entry_points.txt +0 -0
  124. {singlestoredb-1.0.3 → singlestoredb-1.1.0}/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.0.3
3
+ Version: 1.1.0
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
@@ -16,6 +16,10 @@
16
16
  #define ACCEL_OUT_STRUCTSEQUENCES 1
17
17
  #define ACCEL_OUT_DICTS 2
18
18
  #define ACCEL_OUT_NAMEDTUPLES 3
19
+ #define ACCEL_OUT_NUMPY 4
20
+ #define ACCEL_OUT_PANDAS 5
21
+ #define ACCEL_OUT_POLARS 6
22
+ #define ACCEL_OUT_ARROW 7
19
23
 
20
24
  #define NUMPY_BOOL 1
21
25
  #define NUMPY_INT8 2
@@ -389,6 +393,9 @@ typedef struct {
389
393
  PyObject *Series;
390
394
  PyObject *array;
391
395
  PyObject *vectorize;
396
+ PyObject *DataFrame;
397
+ PyObject *Table;
398
+ PyObject *from_pylist;
392
399
  } PyStrings;
393
400
 
394
401
  static PyStrings PyStr = {0};
@@ -406,6 +413,10 @@ typedef struct {
406
413
  PyObject *collections_namedtuple;
407
414
  PyObject *numpy_array;
408
415
  PyObject *numpy_vectorize;
416
+ PyObject *pandas_DataFrame;
417
+ PyObject *polars_DataFrame;
418
+ PyObject *pyarrow_Table;
419
+ PyObject *pyarrow_Table_from_pylist;
409
420
  } PyFunctions;
410
421
 
411
422
  static PyFunctions PyFunc = {0};
@@ -466,10 +477,88 @@ typedef struct {
466
477
  char *encoding_errors;
467
478
  } StateObject;
468
479
 
469
- static void read_options(MySQLAccelOptions *options, PyObject *dict);
480
+ static int read_options(MySQLAccelOptions *options, PyObject *dict);
470
481
 
471
482
  #define DESTROY(x) do { if (x) { free((void*)x); (x) = NULL; } } while (0)
472
483
 
484
+ int ensure_numpy() {
485
+ if (PyFunc.numpy_array && PyFunc.numpy_vectorize) goto exit;
486
+
487
+ // Import numpy if it exists
488
+ PyObject *numpy_mod = PyImport_ImportModule("numpy");
489
+ if (!numpy_mod) goto error;
490
+
491
+ PyFunc.numpy_array = PyObject_GetAttr(numpy_mod, PyStr.array);
492
+ if (!PyFunc.numpy_array) goto error;
493
+
494
+ PyFunc.numpy_vectorize = PyObject_GetAttr(numpy_mod, PyStr.vectorize);
495
+ if (!PyFunc.numpy_vectorize) goto error;
496
+
497
+ exit:
498
+ return 0;
499
+
500
+ error:
501
+ return -1;
502
+ }
503
+
504
+
505
+ int ensure_pandas() {
506
+ if (PyFunc.pandas_DataFrame) goto exit;
507
+
508
+ // Import pandas if it exists
509
+ PyObject *pandas_mod = PyImport_ImportModule("pandas");
510
+ if (!pandas_mod) goto error;
511
+
512
+ PyFunc.pandas_DataFrame = PyObject_GetAttr(pandas_mod, PyStr.DataFrame);
513
+ if (!PyFunc.pandas_DataFrame) goto error;
514
+
515
+ exit:
516
+ return 0;
517
+
518
+ error:
519
+ return -1;
520
+ }
521
+
522
+
523
+ int ensure_polars() {
524
+ if (PyFunc.polars_DataFrame) goto exit;
525
+
526
+ // Import polars if it exists
527
+ PyObject *polars_mod = PyImport_ImportModule("polars");
528
+ if (!polars_mod) goto error;
529
+
530
+ PyFunc.polars_DataFrame = PyObject_GetAttr(polars_mod, PyStr.DataFrame);
531
+ if (!PyFunc.polars_DataFrame) goto error;
532
+
533
+ exit:
534
+ return 0;
535
+
536
+ error:
537
+ return -1;
538
+ }
539
+
540
+
541
+ int ensure_pyarrow() {
542
+ if (PyFunc.pyarrow_Table_from_pylist) goto exit;
543
+
544
+ // Import pyarrow if it exists
545
+ PyObject *pyarrow_mod = PyImport_ImportModule("pyarrow");
546
+ if (!pyarrow_mod) goto error;
547
+
548
+ PyFunc.pyarrow_Table = PyObject_GetAttr(pyarrow_mod, PyStr.Table);
549
+ if (!PyFunc.pyarrow_Table) goto error;
550
+
551
+ PyFunc.pyarrow_Table_from_pylist = PyObject_GetAttr(PyFunc.pyarrow_Table, PyStr.from_pylist);
552
+ if (!PyFunc.pyarrow_Table_from_pylist) goto error;
553
+
554
+ exit:
555
+ return 0;
556
+
557
+ error:
558
+ return -1;
559
+ }
560
+
561
+
473
562
  static void State_clear_fields(StateObject *self) {
474
563
  if (!self) return;
475
564
  DESTROY(self->offsets);
@@ -680,7 +769,7 @@ static int State_init(StateObject *self, PyObject *args, PyObject *kwds) {
680
769
  Py_XINCREF(self->py_invalid_values[i]);
681
770
 
682
771
  self->py_converters[i] = (!py_converter
683
- || py_converter == Py_None
772
+ // || py_converter == Py_None
684
773
  || py_converter == py_default_converter) ?
685
774
  NULL : py_converter;
686
775
  Py_XINCREF(self->py_converters[i]);
@@ -709,7 +798,8 @@ static int State_init(StateObject *self, PyObject *args, PyObject *kwds) {
709
798
  Py_XDECREF(py_next_seq_id);
710
799
 
711
800
  if (py_options && PyDict_Check(py_options)) {
712
- read_options(&self->options, py_options);
801
+ rc = read_options(&self->options, py_options);
802
+ if (rc) goto error;
713
803
  }
714
804
 
715
805
  switch (self->options.results_type) {
@@ -825,12 +915,13 @@ static PyType_Spec StateType_spec = {
825
915
  // End State
826
916
  //
827
917
 
828
- static void read_options(MySQLAccelOptions *options, PyObject *dict) {
829
- if (!options || !dict) return;
918
+ static int read_options(MySQLAccelOptions *options, PyObject *dict) {
919
+ if (!options || !dict) return 0;
830
920
 
831
921
  PyObject *key = NULL;
832
922
  PyObject *value = NULL;
833
923
  Py_ssize_t pos = 0;
924
+ int rc = 0;
834
925
 
835
926
  while (PyDict_Next(dict, &pos, &key, &value)) {
836
927
  if (PyUnicode_CompareWithASCIIString(key, "results_type") == 0) {
@@ -846,6 +937,23 @@ static void read_options(MySQLAccelOptions *options, PyObject *dict) {
846
937
  PyUnicode_CompareWithASCIIString(value, "structsequences") == 0) {
847
938
  options->results_type = ACCEL_OUT_STRUCTSEQUENCES;
848
939
  }
940
+ else if (PyUnicode_CompareWithASCIIString(value, "numpy") == 0) {
941
+ options->results_type = ACCEL_OUT_NUMPY;
942
+ rc = ensure_numpy();
943
+ }
944
+ else if (PyUnicode_CompareWithASCIIString(value, "pandas") == 0) {
945
+ options->results_type = ACCEL_OUT_PANDAS;
946
+ rc = ensure_pandas();
947
+ }
948
+ else if (PyUnicode_CompareWithASCIIString(value, "polars") == 0) {
949
+ options->results_type = ACCEL_OUT_POLARS;
950
+ rc = ensure_polars();
951
+ }
952
+ else if (PyUnicode_CompareWithASCIIString(value, "arrow") == 0 ||
953
+ PyUnicode_CompareWithASCIIString(value, "pyarrow") == 0) {
954
+ options->results_type = ACCEL_OUT_ARROW;
955
+ rc = ensure_pyarrow();
956
+ }
849
957
  else {
850
958
  options->results_type = ACCEL_OUT_TUPLES;
851
959
  }
@@ -857,6 +965,8 @@ static void read_options(MySQLAccelOptions *options, PyObject *dict) {
857
965
  }
858
966
  }
859
967
  }
968
+
969
+ return rc;
860
970
  }
861
971
 
862
972
  static void raise_exception(
@@ -1323,6 +1433,7 @@ static PyObject *read_row_from_packet(
1323
1433
 
1324
1434
  switch (py_state->options.results_type) {
1325
1435
  case ACCEL_OUT_DICTS:
1436
+ case ACCEL_OUT_ARROW:
1326
1437
  py_result = PyDict_New();
1327
1438
  break;
1328
1439
  case ACCEL_OUT_STRUCTSEQUENCES: {
@@ -1362,8 +1473,12 @@ static PyObject *read_row_from_packet(
1362
1473
  py_str = PyUnicode_Decode(out, out_l, py_state->encodings[i], py_state->encoding_errors);
1363
1474
  if (!py_str) goto error;
1364
1475
  }
1365
- py_item = PyObject_CallFunctionObjArgs(py_state->py_converters[i], py_str, NULL);
1366
- Py_CLEAR(py_str);
1476
+ if (py_state->py_converters[i] == Py_None) {
1477
+ py_item = py_str;
1478
+ } else {
1479
+ py_item = PyObject_CallFunctionObjArgs(py_state->py_converters[i], py_str, NULL);
1480
+ Py_CLEAR(py_str);
1481
+ }
1367
1482
  if (!py_item) goto error;
1368
1483
  }
1369
1484
 
@@ -1586,6 +1701,7 @@ static PyObject *read_row_from_packet(
1586
1701
  PyStructSequence_SetItem(py_result, i, py_item);
1587
1702
  break;
1588
1703
  case ACCEL_OUT_DICTS:
1704
+ case ACCEL_OUT_ARROW:
1589
1705
  PyDict_SetItem(py_result, py_state->py_names[i], py_item);
1590
1706
  Py_INCREF(py_state->py_names[i]);
1591
1707
  Py_DECREF(py_item);
@@ -1847,27 +1963,6 @@ error:
1847
1963
  }
1848
1964
 
1849
1965
 
1850
- int ensure_numpy() {
1851
- if (PyFunc.numpy_array && PyFunc.numpy_vectorize) goto exit;
1852
-
1853
- // Import numpy if it exists
1854
- PyObject *numpy_mod = PyImport_ImportModule("numpy");
1855
- if (!numpy_mod) goto error;
1856
-
1857
- PyFunc.numpy_array = PyObject_GetAttr(numpy_mod, PyStr.array);
1858
- if (!PyFunc.numpy_array) goto error;
1859
-
1860
- PyFunc.numpy_vectorize = PyObject_GetAttr(numpy_mod, PyStr.vectorize);
1861
- if (!PyFunc.numpy_vectorize) goto error;
1862
-
1863
- exit:
1864
- return 0;
1865
-
1866
- error:
1867
- return -1;
1868
- }
1869
-
1870
-
1871
1966
  static PyObject *load_rowdat_1_numpy(PyObject *self, PyObject *args, PyObject *kwargs) {
1872
1967
  PyObject *py_data = NULL;
1873
1968
  PyObject *py_out = NULL;
@@ -4372,6 +4467,9 @@ PyMODINIT_FUNC PyInit__singlestoredb_accel(void) {
4372
4467
  PyStr.Series = PyUnicode_FromString("Series");
4373
4468
  PyStr.array = PyUnicode_FromString("array");
4374
4469
  PyStr.vectorize = PyUnicode_FromString("vectorize");
4470
+ PyStr.DataFrame = PyUnicode_FromString("DataFrame");
4471
+ PyStr.Table = PyUnicode_FromString("Table");
4472
+ PyStr.from_pylist = PyUnicode_FromString("from_pylist");
4375
4473
 
4376
4474
  PyObject *decimal_mod = PyImport_ImportModule("decimal");
4377
4475
  if (!decimal_mod) goto error;
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = singlestoredb
3
- version = 1.0.3
3
+ version = 1.1.0
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
@@ -26,6 +26,7 @@ install_requires =
26
26
  setuptools
27
27
  sqlparams
28
28
  wheel
29
+ tomli>=1.1.0;python_version < '3.11'
29
30
  python_requires = >=3.8
30
31
  tests_require =
31
32
  coverage
@@ -77,7 +78,7 @@ exclude =
77
78
  docs/*
78
79
  resources/*
79
80
  licenses/*
80
- max-complexity = 30
81
+ max-complexity = 35
81
82
  max-line-length = 90
82
83
  per-file-ignores =
83
84
  singlestoredb/__init__.py:F401
@@ -13,7 +13,7 @@ Examples
13
13
 
14
14
  """
15
15
 
16
- __version__ = '1.0.3'
16
+ __version__ = '1.1.0'
17
17
 
18
18
  from typing import Any
19
19
 
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  """SingleStoreDB package options."""
3
3
  import functools
4
+ import os
4
5
 
5
6
  from . import auth
6
7
  from .utils.config import check_bool # noqa: F401
@@ -230,6 +231,7 @@ register_option(
230
231
  valid_values=[
231
232
  'tuple', 'tuples', 'namedtuple', 'namedtuples',
232
233
  'dict', 'dicts', 'structsequence', 'structsequences',
234
+ 'numpy', 'pandas', 'polars', 'arrow', 'pyarrow',
233
235
  ],
234
236
  ),
235
237
  'tuples',
@@ -266,6 +268,129 @@ register_option(
266
268
  )
267
269
 
268
270
 
271
+ #
272
+ # External function options
273
+ #
274
+ register_option(
275
+ 'external_function.url', 'string', check_str, 'http://localhost:8000/invoke',
276
+ 'Specifies the URL of the external function application.',
277
+ environ=['SINGLESTOREDB_EXT_FUNC_URL'],
278
+ )
279
+
280
+ register_option(
281
+ 'external_function.app_mode', 'string',
282
+ functools.partial(
283
+ check_str,
284
+ valid_values=['remote', 'collocated'],
285
+ ),
286
+ 'remote',
287
+ 'Specifies the mode of operation of the external function application.',
288
+ environ=['SINGLESTOREDB_EXT_FUNC_APP_MODE'],
289
+ )
290
+
291
+ register_option(
292
+ 'external_function.data_format', 'string',
293
+ functools.partial(
294
+ check_str,
295
+ valid_values=['rowdat_1', 'json'],
296
+ ),
297
+ 'rowdat_1',
298
+ 'Specifies the format for the data rows.',
299
+ environ=['SINGLESTOREDB_EXT_FUNC_DATA_FORMAT'],
300
+ )
301
+
302
+ register_option(
303
+ 'external_function.data_version', 'string', check_str, '1.0',
304
+ 'Specifies the version of the data format.',
305
+ environ=['SINGLESTOREDB_EXT_FUNC_DATA_VERSION'],
306
+ )
307
+
308
+ register_option(
309
+ 'external_function.link_name', 'string', check_str, None,
310
+ 'Specifies the link name to use for remote external functions.',
311
+ environ=['SINGLESTOREDB_EXT_FUNC_LINK_NAME'],
312
+ )
313
+
314
+ register_option(
315
+ 'external_function.link_config', 'string', check_str, None,
316
+ 'Specifies the link config in JSON format.',
317
+ environ=['SINGLESTOREDB_EXT_FUNC_LINK_CONFIG'],
318
+ )
319
+
320
+ register_option(
321
+ 'external_function.link_credentials', 'string', check_str, None,
322
+ 'Specifies the link credentials in JSON format.',
323
+ environ=['SINGLESTOREDB_EXT_FUNC_LINK_CREDENTIALS'],
324
+ )
325
+
326
+ register_option(
327
+ 'external_function.replace_existing', 'bool', check_bool, False,
328
+ 'Should existing functions be replaced when registering external functions?',
329
+ environ=['SINGLESTOREDB_EXT_FUNC_REPLACE_EXISTING'],
330
+ )
331
+
332
+ register_option(
333
+ 'external_function.socket_path', 'string', check_str, None,
334
+ 'Specifies the socket path for collocated external functions.',
335
+ environ=['SINGLESTOREDB_EXT_FUNC_SOCKET_PATH'],
336
+ )
337
+
338
+ register_option(
339
+ 'external_function.max_connections', 'int', check_int, 32,
340
+ 'Specifies the maximum connections in a collocated external function ' +
341
+ 'before reusing them.',
342
+ environ=['SINGLESTOREDB_EXT_FUNC_MAX_CONNECTIONS'],
343
+ )
344
+
345
+ register_option(
346
+ 'external_function.process_mode', 'string',
347
+ functools.partial(
348
+ check_str,
349
+ valid_values=['thread', 'subprocess'],
350
+ ),
351
+ 'subprocess',
352
+ 'Specifies the method to use for concurrent handlers in ' +
353
+ 'collocated external functions',
354
+ environ=['SINGLESTOREDB_EXT_FUNC_PROCESS_MODE'],
355
+ )
356
+
357
+ register_option(
358
+ 'external_function.single_thread', 'bool', check_bool, False,
359
+ 'Should the collocated server run in single-thread mode?',
360
+ environ=['SINGLESTOREDB_EXT_FUNC_SINGLE_THREAD'],
361
+ )
362
+
363
+ register_option(
364
+ 'external_function.log_level', 'string',
365
+ functools.partial(
366
+ check_str,
367
+ valid_values=['info', 'debug', 'warning', 'error'],
368
+ ),
369
+ 'info',
370
+ 'Logging level of external function server.',
371
+ environ=['SINGLESTOREDB_EXT_FUNC_LOG_LEVEL'],
372
+ )
373
+
374
+ register_option(
375
+ 'external_function.connection', 'string', check_str,
376
+ os.environ.get('SINGLESTOREDB_URL') or None,
377
+ 'Specifies the connection string for the database to register functions with.',
378
+ environ=['SINGLESTOREDB_EXT_FUNC_CONNECTION'],
379
+ )
380
+
381
+ register_option(
382
+ 'external_function.host', 'string', check_str, '127.0.0.1',
383
+ 'Specifies the host to bind the server to.',
384
+ environ=['SINGLESTOREDB_EXT_FUNC_HOST'],
385
+ )
386
+
387
+ register_option(
388
+ 'external_function.port', 'int', check_int, 8000,
389
+ 'Specifies the port to bind the server to.',
390
+ environ=['SINGLESTOREDB_EXT_FUNC_PORT'],
391
+ )
392
+
393
+
269
394
  #
270
395
  # Debugging options
271
396
  #
@@ -10,24 +10,11 @@ from typing import Union
10
10
 
11
11
  from ..converters import converters
12
12
  from ..mysql.converters import escape_item # type: ignore
13
-
14
- try:
15
- import numpy as np
16
- has_numpy = True
17
- except ImportError:
18
- has_numpy = False
19
-
20
- try:
21
- import polars as pl
22
- has_polars = True
23
- except ImportError:
24
- has_polars = False
25
-
26
- try:
27
- import pyarrow as pa
28
- has_pyarrow = True
29
- except ImportError:
30
- has_pyarrow = False
13
+ from ..utils.dtypes import DEFAULT_VALUES # noqa
14
+ from ..utils.dtypes import NUMPY_TYPE_MAP # noqa
15
+ from ..utils.dtypes import PANDAS_TYPE_MAP # noqa
16
+ from ..utils.dtypes import POLARS_TYPE_MAP # noqa
17
+ from ..utils.dtypes import PYARROW_TYPE_MAP # noqa
31
18
 
32
19
 
33
20
  DataType = Union[str, Callable[..., Any]]
@@ -117,48 +104,6 @@ def bytestr(x: Any) -> Optional[bytes]:
117
104
  return bytes.fromhex(x)
118
105
 
119
106
 
120
- DEFAULT_VALUES = {
121
- 0: 0, # Decimal
122
- 1: 0, # Tiny
123
- -1: 0, # Unsigned Tiny
124
- 2: 0, # Short
125
- -2: 0, # Unsigned Short
126
- 3: 0, # Long
127
- -3: 0, # Unsigned Long
128
- 4: float('nan'), # Float
129
- 5: float('nan'), # Double,
130
- 6: None, # Null,
131
- 7: 0, # Timestamp
132
- 8: 0, # LongLong
133
- -8: 0, # Unsigned Longlong
134
- 9: 0, # Int24
135
- -9: 0, # Unsigned Int24
136
- 10: 0, # Date
137
- 11: 0, # Time
138
- 12: 0, # Datetime
139
- 13: 0, # Year
140
- 15: None, # Varchar
141
- -15: None, # Varbinary
142
- 16: 0, # Bit
143
- 245: None, # JSON
144
- 246: 0, # NewDecimal
145
- 247: None, # Enum
146
- 248: None, # Set
147
- 249: None, # TinyText
148
- -249: None, # TinyBlob
149
- 250: None, # MediumText
150
- -250: None, # MediumBlob
151
- 251: None, # LongText
152
- -251: None, # LongBlob
153
- 252: None, # Text
154
- -252: None, # Blob
155
- 253: None, # VarString
156
- -253: None, # VarBinary
157
- 254: None, # String
158
- -254: None, # Binary
159
- 255: None, # Geometry
160
- }
161
-
162
107
  PYTHON_CONVERTERS = {
163
108
  -1: converters[1],
164
109
  -2: converters[2],
@@ -183,144 +128,6 @@ PYTHON_CONVERTERS = {
183
128
  PYTHON_CONVERTERS = dict(list(converters.items()) + list(PYTHON_CONVERTERS.items()))
184
129
 
185
130
 
186
- if has_numpy:
187
- NUMPY_TYPE_MAP = {
188
- 0: object, # Decimal
189
- 1: np.int8, # Tiny
190
- -1: np.uint8, # Unsigned Tiny
191
- 2: np.int16, # Short
192
- -2: np.uint16, # Unsigned Short
193
- 3: np.int32, # Long
194
- -3: np.uint32, # Unsigned Long
195
- 4: np.single, # Float
196
- 5: np.double, # Double,
197
- 6: object, # Null,
198
- 7: object, # Timestamp
199
- 8: np.int64, # LongLong
200
- -8: np.uint64, # Unsigned LongLong
201
- 9: np.int32, # Int24
202
- -9: np.uint32, # Unsigned Int24
203
- 10: object, # Date
204
- 11: object, # Time
205
- 12: object, # Datetime
206
- 13: np.int16, # Year
207
- 15: object, # Varchar
208
- -15: object, # Varbinary
209
- 16: object, # Bit
210
- 245: object, # JSON
211
- 246: object, # NewDecimal
212
- 247: object, # Enum
213
- 248: object, # Set
214
- 249: object, # TinyText
215
- -249: object, # TinyBlob
216
- 250: object, # MediumText
217
- -250: object, # MediumBlob
218
- 251: object, # LongText
219
- -251: object, # LongBlob
220
- 252: object, # Blob
221
- -252: object, # Text
222
- 253: object, # VarString
223
- -253: object, # VarBlob
224
- 254: object, # String
225
- -254: object, # Binary
226
- 255: object, # Geometry
227
- }
228
- else:
229
- NUMPY_TYPE_MAP = {}
230
-
231
- PANDAS_TYPE_MAP = NUMPY_TYPE_MAP
232
-
233
- if has_pyarrow:
234
- PYARROW_TYPE_MAP = {
235
- 0: pa.string(), # Decimal
236
- 1: pa.int8(), # Tiny
237
- -1: pa.uint8(), # Unsigned Tiny
238
- 2: pa.int16(), # Short
239
- -2: pa.uint16(), # Unsigned Short
240
- 3: pa.int32(), # Long
241
- -3: pa.uint32(), # Unsigned Long
242
- 4: pa.float32(), # Float
243
- 5: pa.float64(), # Double,
244
- 6: pa.null(), # Null,
245
- 7: pa.timestamp('ns'), # Timestamp
246
- 8: pa.int64(), # LongLong
247
- -8: pa.uint64(), # Unsigned LongLong
248
- 9: pa.int32(), # Int24
249
- -9: pa.uint32(), # Unsigned Int24
250
- 10: pa.date64(), # Date
251
- 11: pa.duration('ns'), # Time
252
- 12: pa.timestamp('ns'), # Datetime
253
- 13: pa.int16(), # Year
254
- 15: pa.string(), # Varchar
255
- -15: pa.binary(), # Varbinary
256
- 16: pa.binary(), # Bit
257
- 245: pa.string(), # JSON
258
- 246: pa.string(), # NewDecimal
259
- 247: pa.string(), # Enum
260
- 248: pa.string(), # Set
261
- 249: pa.string(), # TinyText
262
- -249: pa.binary(), # TinyBlob
263
- 250: pa.string(), # MediumText
264
- -250: pa.binary(), # MediumBlob
265
- 251: pa.string(), # LongText
266
- -251: pa.binary(), # LongBlob
267
- 252: pa.string(), # Text
268
- -252: pa.binary(), # Blob
269
- 253: pa.string(), # VarString
270
- -253: pa.binary(), # VarBinary
271
- 254: pa.string(), # String
272
- -254: pa.binary(), # Binary
273
- 255: pa.string(), # Geometry
274
- }
275
- else:
276
- PYARROW_TYPE_MAP = {}
277
-
278
- if has_polars:
279
- POLARS_TYPE_MAP = {
280
- 0: pl.Utf8, # Decimal
281
- 1: pl.Int8, # Tiny
282
- -1: pl.UInt8, # Unsigned Tiny
283
- 2: pl.Int16, # Short
284
- -2: pl.UInt16, # Unsigned Short
285
- 3: pl.Int32, # Long
286
- -3: pl.UInt32, # Unsigned Long
287
- 4: pl.Float32, # Float
288
- 5: pl.Float64, # Double,
289
- 6: pl.Null, # Null,
290
- 7: pl.Datetime, # Timestamp
291
- 8: pl.Int64, # LongLong
292
- -8: pl.UInt64, # Unsigned LongLong
293
- 9: pl.Int32, # Int24
294
- -9: pl.UInt32, # Unsigned Int24
295
- 10: pl.Date, # Date
296
- 11: pl.Time, # Time
297
- 12: pl.Datetime, # Datetime
298
- 13: pl.Int16, # Year
299
- 15: pl.Utf8, # Varchar
300
- -15: pl.Utf8, # Varbinary
301
- 16: pl.Binary, # Bit
302
- 245: pl.Utf8, # JSON
303
- 246: pl.Utf8, # NewDecimal
304
- 247: pl.Utf8, # Enum
305
- 248: pl.Utf8, # Set
306
- 249: pl.Utf8, # TinyText
307
- -249: pl.Utf8, # TinyBlob
308
- 250: pl.Utf8, # MediumBlob
309
- -250: pl.Utf8, # MediumText
310
- 251: pl.Utf8, # LongBlob
311
- -251: pl.Utf8, # LongText
312
- 252: pl.Utf8, # Blob
313
- -252: pl.Utf8, # Text
314
- 253: pl.Utf8, # VarString
315
- -253: pl.Utf8, # VarBinary
316
- 254: pl.Utf8, # String
317
- -254: pl.Utf8, # Binary
318
- 255: pl.Utf8, # Geometry
319
- }
320
- else:
321
- POLARS_TYPE_MAP = {}
322
-
323
-
324
131
  def _modifiers(
325
132
  *,
326
133
  nullable: Optional[bool] = None,
@@ -0,0 +1 @@
1
+ #!/usr/bin/env python3