singlestoredb 1.11.0__tar.gz → 1.12.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 (155) hide show
  1. {singlestoredb-1.11.0/singlestoredb.egg-info → singlestoredb-1.12.1}/PKG-INFO +2 -1
  2. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/accel.c +18 -0
  3. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/setup.cfg +4 -2
  4. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/__init__.py +1 -1
  5. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/config.py +6 -0
  6. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/connection.py +7 -0
  7. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/converters.py +5 -5
  8. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/__init__.py +1 -0
  9. singlestoredb-1.12.1/singlestoredb/functions/decorator.py +331 -0
  10. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/ext/asgi.py +121 -27
  11. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/signature.py +100 -9
  12. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/handlers/export.py +58 -2
  13. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/handlers/files.py +6 -6
  14. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/handlers/utils.py +14 -8
  15. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/result.py +1 -1
  16. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/http/connection.py +4 -0
  17. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/export.py +30 -7
  18. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/files.py +7 -8
  19. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/workspace.py +5 -6
  20. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/connection.py +24 -19
  21. singlestoredb-1.12.1/singlestoredb/server/docker.py +455 -0
  22. singlestoredb-1.12.1/singlestoredb/server/free_tier.py +267 -0
  23. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_management.py +50 -2
  24. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_udf.py +84 -32
  25. singlestoredb-1.12.1/singlestoredb/utils/__init__.py +0 -0
  26. {singlestoredb-1.11.0 → singlestoredb-1.12.1/singlestoredb.egg-info}/PKG-INFO +2 -1
  27. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb.egg-info/SOURCES.txt +3 -0
  28. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb.egg-info/requires.txt +3 -0
  29. singlestoredb-1.11.0/singlestoredb/functions/decorator.py +0 -142
  30. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/LICENSE +0 -0
  31. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/README.md +0 -0
  32. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/setup.py +0 -0
  33. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/ai/__init__.py +0 -0
  34. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/ai/embeddings.py +0 -0
  35. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/alchemy/__init__.py +0 -0
  36. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/apps/__init__.py +0 -0
  37. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/apps/_cloud_functions.py +0 -0
  38. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/apps/_config.py +0 -0
  39. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/apps/_connection_info.py +0 -0
  40. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/apps/_dashboards.py +0 -0
  41. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/apps/_process.py +0 -0
  42. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/apps/_stdout_supress.py +0 -0
  43. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/apps/_uvicorn_util.py +0 -0
  44. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/auth.py +0 -0
  45. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/exceptions.py +0 -0
  46. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/dtypes.py +0 -0
  47. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/ext/__init__.py +0 -0
  48. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/ext/arrow.py +0 -0
  49. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/ext/json.py +0 -0
  50. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/ext/mmap.py +0 -0
  51. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/ext/rowdat_1.py +0 -0
  52. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/functions/ext/utils.py +0 -0
  53. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/__init__.py +0 -0
  54. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/graphql.py +0 -0
  55. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/handler.py +0 -0
  56. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/handlers/__init__.py +0 -0
  57. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/handlers/job.py +0 -0
  58. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/handlers/models.py +0 -0
  59. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/handlers/stage.py +0 -0
  60. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/handlers/workspace.py +0 -0
  61. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/fusion/registry.py +0 -0
  62. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/http/__init__.py +0 -0
  63. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/magics/__init__.py +0 -0
  64. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/magics/run_personal.py +0 -0
  65. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/magics/run_shared.py +0 -0
  66. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/__init__.py +0 -0
  67. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/billing_usage.py +0 -0
  68. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/cluster.py +0 -0
  69. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/job.py +0 -0
  70. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/manager.py +0 -0
  71. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/organization.py +0 -0
  72. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/region.py +0 -0
  73. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/management/utils.py +0 -0
  74. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/__init__.py +0 -0
  75. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/_auth.py +0 -0
  76. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/charset.py +0 -0
  77. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/CLIENT.py +0 -0
  78. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/COMMAND.py +0 -0
  79. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/CR.py +0 -0
  80. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/ER.py +0 -0
  81. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/EXTENDED_TYPE.py +0 -0
  82. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/FIELD_TYPE.py +0 -0
  83. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/FLAG.py +0 -0
  84. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/SERVER_STATUS.py +0 -0
  85. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/VECTOR_TYPE.py +0 -0
  86. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/constants/__init__.py +0 -0
  87. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/converters.py +0 -0
  88. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/cursors.py +0 -0
  89. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/err.py +0 -0
  90. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/optionfile.py +0 -0
  91. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/protocol.py +0 -0
  92. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/__init__.py +0 -0
  93. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/base.py +0 -0
  94. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/conftest.py +0 -0
  95. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_DictCursor.py +0 -0
  96. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_SSCursor.py +0 -0
  97. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_basic.py +0 -0
  98. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_connection.py +0 -0
  99. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_converters.py +0 -0
  100. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_cursor.py +0 -0
  101. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_err.py +0 -0
  102. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_issues.py +0 -0
  103. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_load_local.py +0 -0
  104. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_nextset.py +0 -0
  105. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/test_optionfile.py +0 -0
  106. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/thirdparty/__init__.py +0 -0
  107. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +0 -0
  108. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +0 -0
  109. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +0 -0
  110. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +0 -0
  111. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +0 -0
  112. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +0 -0
  113. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/mysql/times.py +0 -0
  114. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/notebook/__init__.py +0 -0
  115. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/notebook/_objects.py +0 -0
  116. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/notebook/_portal.py +0 -0
  117. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/py.typed +0 -0
  118. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/pytest.py +0 -0
  119. {singlestoredb-1.11.0/singlestoredb/tests → singlestoredb-1.12.1/singlestoredb/server}/__init__.py +0 -0
  120. {singlestoredb-1.11.0/singlestoredb/utils → singlestoredb-1.12.1/singlestoredb/tests}/__init__.py +0 -0
  121. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/empty.sql +0 -0
  122. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/ext_funcs/__init__.py +0 -0
  123. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/local_infile.csv +0 -0
  124. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test.ipynb +0 -0
  125. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test.sql +0 -0
  126. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test2.ipynb +0 -0
  127. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test2.sql +0 -0
  128. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_basics.py +0 -0
  129. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_config.py +0 -0
  130. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_connection.py +0 -0
  131. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_dbapi.py +0 -0
  132. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_exceptions.py +0 -0
  133. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_ext_func.py +0 -0
  134. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_ext_func_data.py +0 -0
  135. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_fusion.py +0 -0
  136. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_http.py +0 -0
  137. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_plugin.py +0 -0
  138. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_results.py +0 -0
  139. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_types.py +0 -0
  140. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/test_xdict.py +0 -0
  141. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/tests/utils.py +0 -0
  142. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/types.py +0 -0
  143. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/utils/config.py +0 -0
  144. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/utils/convert_rows.py +0 -0
  145. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/utils/debug.py +0 -0
  146. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/utils/dtypes.py +0 -0
  147. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/utils/events.py +0 -0
  148. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/utils/mogrify.py +0 -0
  149. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/utils/results.py +0 -0
  150. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb/utils/xdict.py +0 -0
  151. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb.egg-info/dependency_links.txt +0 -0
  152. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb.egg-info/entry_points.txt +0 -0
  153. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/singlestoredb.egg-info/top_level.txt +0 -0
  154. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/sqlx/__init__.py +0 -0
  155. {singlestoredb-1.11.0 → singlestoredb-1.12.1}/sqlx/magic.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: singlestoredb
3
- Version: 1.11.0
3
+ Version: 1.12.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
@@ -15,6 +15,7 @@ Requires-Python: >=3.8
15
15
  Description-Content-Type: text/markdown
16
16
  Provides-Extra: dataframe
17
17
  Provides-Extra: dbt
18
+ Provides-Extra: docker
18
19
  Provides-Extra: ed22519
19
20
  Provides-Extra: gssapi
20
21
  Provides-Extra: ibis
@@ -1533,6 +1533,15 @@ static PyObject *read_row_from_packet(
1533
1533
  if (!py_str) goto error;
1534
1534
  } else {
1535
1535
  py_str = PyUnicode_Decode(out, out_l, py_state->encodings[i], py_state->encoding_errors);
1536
+ if (PyErr_Occurred()) {
1537
+ PyErr_Clear();
1538
+ PyErr_Format(
1539
+ PyExc_UnicodeDecodeError,
1540
+ "failed to decode string value in column '%S' using encoding '%s'; "
1541
+ "use the 'encoding_errors' option on the connection to specify how to handle this error",
1542
+ py_state->py_names[i], py_state->encodings[i]
1543
+ );
1544
+ }
1536
1545
  if (!py_str) goto error;
1537
1546
  }
1538
1547
  if (py_state->py_converters[i] == Py_None) {
@@ -1740,6 +1749,15 @@ static PyObject *read_row_from_packet(
1740
1749
  }
1741
1750
 
1742
1751
  py_item = PyUnicode_Decode(out, out_l, py_state->encodings[i], py_state->encoding_errors);
1752
+ if (PyErr_Occurred()) {
1753
+ PyErr_Clear();
1754
+ PyErr_Format(
1755
+ PyExc_UnicodeDecodeError,
1756
+ "failed to decode string value in column '%S' using encoding '%s'; "
1757
+ "use the 'encoding_errors' option on the connection to specify how to handle this error",
1758
+ py_state->py_names[i], py_state->encodings[i]
1759
+ );
1760
+ }
1743
1761
  if (!py_item) goto error;
1744
1762
 
1745
1763
  // Parse JSON string.
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = singlestoredb
3
- version = 1.11.0
3
+ version = 1.12.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
@@ -50,6 +50,8 @@ dataframe =
50
50
  ibis-singlestoredb
51
51
  dbt =
52
52
  dbt-singlestore
53
+ docker =
54
+ docker
53
55
  ed22519 =
54
56
  PyNaCl>=1.4.0
55
57
  gssapi =
@@ -81,7 +83,7 @@ exclude =
81
83
  docs/*
82
84
  resources/*
83
85
  licenses/*
84
- max-complexity = 35
86
+ max-complexity = 45
85
87
  max-line-length = 90
86
88
  per-file-ignores =
87
89
  singlestoredb/__init__.py:F401
@@ -13,7 +13,7 @@ Examples
13
13
 
14
14
  """
15
15
 
16
- __version__ = '1.11.0'
16
+ __version__ = '1.12.1'
17
17
 
18
18
  from typing import Any
19
19
 
@@ -201,6 +201,12 @@ register_option(
201
201
  environ='SINGLESTOREDB_BUFFERED',
202
202
  )
203
203
 
204
+ register_option(
205
+ 'parse_json', 'bool', check_bool, True,
206
+ 'Parse JSON values into Python objects?',
207
+ environ='SINGLESTOREDB_PARSE_JSON',
208
+ )
209
+
204
210
  register_option(
205
211
  'connect_timeout', 'int', check_int, 10,
206
212
  'The timeout for connecting to the database in seconds. '
@@ -541,10 +541,16 @@ class Cursor(metaclass=abc.ABCMeta):
541
541
 
542
542
  Examples
543
543
  --------
544
+ Query with no parameters
545
+
544
546
  >>> cur.execute('select * from mytable')
545
547
 
548
+ Query with positional parameters
549
+
546
550
  >>> cur.execute('select * from mytable where id < %s', [100])
547
551
 
552
+ Query with named parameters
553
+
548
554
  >>> cur.execute('select * from mytable where id < %(max)s', dict(max=100))
549
555
 
550
556
  Returns
@@ -1317,6 +1323,7 @@ def connect(
1317
1323
  track_env: Optional[bool] = None,
1318
1324
  enable_extended_data_types: Optional[bool] = None,
1319
1325
  vector_data_format: Optional[str] = None,
1326
+ parse_json: Optional[bool] = None,
1320
1327
  ) -> Connection:
1321
1328
  """
1322
1329
  Return a SingleStoreDB connection.
@@ -594,7 +594,7 @@ def float32_vector_or_none(x: Optional[bytes]) -> Optional[Any]:
594
594
  if has_numpy:
595
595
  return numpy.frombuffer(x, dtype=numpy.float32)
596
596
 
597
- return struct.unpack(f'<{len(x)/4}f', x)
597
+ return struct.unpack(f'<{len(x)//4}f', x)
598
598
 
599
599
 
600
600
  def float64_vector_json_or_none(x: Optional[str]) -> Optional[Any]:
@@ -650,7 +650,7 @@ def float64_vector_or_none(x: Optional[bytes]) -> Optional[Any]:
650
650
  if has_numpy:
651
651
  return numpy.frombuffer(x, dtype=numpy.float64)
652
652
 
653
- return struct.unpack(f'<{len(x)/8}d', x)
653
+ return struct.unpack(f'<{len(x)//8}d', x)
654
654
 
655
655
 
656
656
  def int8_vector_json_or_none(x: Optional[str]) -> Optional[Any]:
@@ -762,7 +762,7 @@ def int16_vector_or_none(x: Optional[bytes]) -> Optional[Any]:
762
762
  if has_numpy:
763
763
  return numpy.frombuffer(x, dtype=numpy.int16)
764
764
 
765
- return struct.unpack(f'<{len(x)/2}h', x)
765
+ return struct.unpack(f'<{len(x)//2}h', x)
766
766
 
767
767
 
768
768
  def int32_vector_json_or_none(x: Optional[str]) -> Optional[Any]:
@@ -818,7 +818,7 @@ def int32_vector_or_none(x: Optional[bytes]) -> Optional[Any]:
818
818
  if has_numpy:
819
819
  return numpy.frombuffer(x, dtype=numpy.int32)
820
820
 
821
- return struct.unpack(f'<{len(x)/4}l', x)
821
+ return struct.unpack(f'<{len(x)//4}l', x)
822
822
 
823
823
 
824
824
  def int64_vector_json_or_none(x: Optional[str]) -> Optional[Any]:
@@ -875,7 +875,7 @@ def int64_vector_or_none(x: Optional[bytes]) -> Optional[Any]:
875
875
  if has_numpy:
876
876
  return numpy.frombuffer(x, dtype=numpy.int64)
877
877
 
878
- return struct.unpack(f'<{len(x)/8}l', x)
878
+ return struct.unpack(f'<{len(x)//8}l', x)
879
879
 
880
880
 
881
881
  def bson_or_none(x: Optional[bytes]) -> Optional[Any]:
@@ -1 +1,2 @@
1
+ from .decorator import tvf # noqa: F401
1
2
  from .decorator import udf # noqa: F401
@@ -0,0 +1,331 @@
1
+ import dataclasses
2
+ import datetime
3
+ import functools
4
+ import inspect
5
+ from typing import Any
6
+ from typing import Callable
7
+ from typing import Dict
8
+ from typing import List
9
+ from typing import Optional
10
+ from typing import Tuple
11
+ from typing import Union
12
+
13
+ from . import dtypes
14
+ from .dtypes import DataType
15
+ from .signature import simplify_dtype
16
+
17
+ try:
18
+ import pydantic
19
+ has_pydantic = True
20
+ except ImportError:
21
+ has_pydantic = False
22
+
23
+ python_type_map: Dict[Any, Callable[..., str]] = {
24
+ str: dtypes.TEXT,
25
+ int: dtypes.BIGINT,
26
+ float: dtypes.DOUBLE,
27
+ bool: dtypes.BOOL,
28
+ bytes: dtypes.BINARY,
29
+ bytearray: dtypes.BINARY,
30
+ datetime.datetime: dtypes.DATETIME,
31
+ datetime.date: dtypes.DATE,
32
+ datetime.timedelta: dtypes.TIME,
33
+ }
34
+
35
+
36
+ def listify(x: Any) -> List[Any]:
37
+ """Make sure sure value is a list."""
38
+ if x is None:
39
+ return []
40
+ if isinstance(x, (list, tuple, set)):
41
+ return list(x)
42
+ return [x]
43
+
44
+
45
+ def process_annotation(annotation: Any) -> Tuple[Any, bool]:
46
+ types = simplify_dtype(annotation)
47
+ if isinstance(types, list):
48
+ nullable = False
49
+ if type(None) in types:
50
+ nullable = True
51
+ types = [x for x in types if x is not type(None)]
52
+ if len(types) > 1:
53
+ raise ValueError(f'multiple types not supported: {annotation}')
54
+ return types[0], nullable
55
+ return types, True
56
+
57
+
58
+ def process_types(params: Any) -> Any:
59
+ if params is None:
60
+ return params, []
61
+
62
+ elif isinstance(params, (list, tuple)):
63
+ params = list(params)
64
+ for i, item in enumerate(params):
65
+ if params[i] in python_type_map:
66
+ params[i] = python_type_map[params[i]]()
67
+ elif callable(item):
68
+ params[i] = item()
69
+ for item in params:
70
+ if not isinstance(item, str):
71
+ raise TypeError(f'unrecognized type for parameter: {item}')
72
+ return params, []
73
+
74
+ elif isinstance(params, dict):
75
+ names = []
76
+ params = dict(params)
77
+ for k, v in list(params.items()):
78
+ names.append(k)
79
+ if params[k] in python_type_map:
80
+ params[k] = python_type_map[params[k]]()
81
+ elif callable(v):
82
+ params[k] = v()
83
+ for item in params.values():
84
+ if not isinstance(item, str):
85
+ raise TypeError(f'unrecognized type for parameter: {item}')
86
+ return params, names
87
+
88
+ elif dataclasses.is_dataclass(params):
89
+ names = []
90
+ out = []
91
+ for item in dataclasses.fields(params):
92
+ typ, nullable = process_annotation(item.type)
93
+ sql_type = process_types(typ)[0]
94
+ if not nullable:
95
+ sql_type = sql_type.replace('NULL', 'NOT NULL')
96
+ out.append(sql_type)
97
+ names.append(item.name)
98
+ return out, names
99
+
100
+ elif has_pydantic and inspect.isclass(params) \
101
+ and issubclass(params, pydantic.BaseModel):
102
+ names = []
103
+ out = []
104
+ for name, item in params.model_fields.items():
105
+ typ, nullable = process_annotation(item.annotation)
106
+ sql_type = process_types(typ)[0]
107
+ if not nullable:
108
+ sql_type = sql_type.replace('NULL', 'NOT NULL')
109
+ out.append(sql_type)
110
+ names.append(name)
111
+ return out, names
112
+
113
+ elif params in python_type_map:
114
+ return python_type_map[params](), []
115
+
116
+ elif callable(params):
117
+ return params(), []
118
+
119
+ elif isinstance(params, str):
120
+ return params, []
121
+
122
+ raise TypeError(f'unrecognized data type for args: {params}')
123
+
124
+
125
+ def _func(
126
+ func: Optional[Callable[..., Any]] = None,
127
+ *,
128
+ name: Optional[str] = None,
129
+ args: Optional[
130
+ Union[
131
+ DataType,
132
+ List[DataType],
133
+ Dict[str, DataType],
134
+ 'pydantic.BaseModel',
135
+ type,
136
+ ]
137
+ ] = None,
138
+ returns: Optional[
139
+ Union[
140
+ str,
141
+ List[DataType],
142
+ List[type],
143
+ 'pydantic.BaseModel',
144
+ type,
145
+ ]
146
+ ] = None,
147
+ data_format: Optional[str] = None,
148
+ include_masks: bool = False,
149
+ function_type: str = 'udf',
150
+ output_fields: Optional[List[str]] = None,
151
+ ) -> Callable[..., Any]:
152
+ """Generic wrapper for UDF and TVF decorators."""
153
+ args, _ = process_types(args)
154
+ returns, fields = process_types(returns)
155
+
156
+ if not output_fields and fields:
157
+ output_fields = fields
158
+
159
+ if isinstance(returns, list) \
160
+ and isinstance(output_fields, list) \
161
+ and len(output_fields) != len(returns):
162
+ raise ValueError(
163
+ 'The number of output fields must match the number of return types',
164
+ )
165
+
166
+ if include_masks and data_format == 'python':
167
+ raise RuntimeError(
168
+ 'include_masks is only valid when using '
169
+ 'vectors for input parameters',
170
+ )
171
+
172
+ _singlestoredb_attrs = { # type: ignore
173
+ k: v for k, v in dict(
174
+ name=name,
175
+ args=args,
176
+ returns=returns,
177
+ data_format=data_format,
178
+ include_masks=include_masks,
179
+ function_type=function_type,
180
+ output_fields=output_fields or None,
181
+ ).items() if v is not None
182
+ }
183
+
184
+ # No func was specified, this is an uncalled decorator that will get
185
+ # called later, so the wrapper much be created with the func passed
186
+ # in at that time.
187
+ if func is None:
188
+ def decorate(func: Callable[..., Any]) -> Callable[..., Any]:
189
+ def wrapper(*args: Any, **kwargs: Any) -> Callable[..., Any]:
190
+ return func(*args, **kwargs) # type: ignore
191
+ wrapper._singlestoredb_attrs = _singlestoredb_attrs # type: ignore
192
+ return functools.wraps(func)(wrapper)
193
+ return decorate
194
+
195
+ def wrapper(*args: Any, **kwargs: Any) -> Callable[..., Any]:
196
+ return func(*args, **kwargs) # type: ignore
197
+
198
+ wrapper._singlestoredb_attrs = _singlestoredb_attrs # type: ignore
199
+
200
+ return functools.wraps(func)(wrapper)
201
+
202
+
203
+ def udf(
204
+ func: Optional[Callable[..., Any]] = None,
205
+ *,
206
+ name: Optional[str] = None,
207
+ args: Optional[Union[DataType, List[DataType], Dict[str, DataType]]] = None,
208
+ returns: Optional[Union[str, List[DataType], List[type]]] = None,
209
+ data_format: Optional[str] = None,
210
+ include_masks: bool = False,
211
+ ) -> Callable[..., Any]:
212
+ """
213
+ Apply attributes to a UDF.
214
+
215
+ Parameters
216
+ ----------
217
+ func : callable, optional
218
+ The UDF to apply parameters to
219
+ name : str, optional
220
+ The name to use for the UDF in the database
221
+ args : str | Callable | List[str | Callable] | Dict[str, str | Callable], optional
222
+ Specifies the data types of the function arguments. Typically,
223
+ the function data types are derived from the function parameter
224
+ annotations. These annotations can be overridden. If the function
225
+ takes a single type for all parameters, `args` can be set to a
226
+ SQL string describing all parameters. If the function takes more
227
+ than one parameter and all of the parameters are being manually
228
+ defined, a list of SQL strings may be used (one for each parameter).
229
+ A dictionary of SQL strings may be used to specify a parameter type
230
+ for a subset of parameters; the keys are the names of the
231
+ function parameters. Callables may also be used for datatypes. This
232
+ is primarily for using the functions in the ``dtypes`` module that
233
+ are associated with SQL types with all default options (e.g., ``dt.FLOAT``).
234
+ returns : str, optional
235
+ Specifies the return data type of the function. If not specified,
236
+ the type annotation from the function is used.
237
+ data_format : str, optional
238
+ The data format of each parameter: python, pandas, arrow, polars
239
+ include_masks : bool, optional
240
+ Should boolean masks be included with each input parameter to indicate
241
+ which elements are NULL? This is only used when a input parameters are
242
+ configured to a vector type (numpy, pandas, polars, arrow).
243
+
244
+ Returns
245
+ -------
246
+ Callable
247
+
248
+ """
249
+ return _func(
250
+ func=func,
251
+ name=name,
252
+ args=args,
253
+ returns=returns,
254
+ data_format=data_format,
255
+ include_masks=include_masks,
256
+ function_type='udf',
257
+ )
258
+
259
+
260
+ udf.pandas = functools.partial(udf, data_format='pandas') # type: ignore
261
+ udf.polars = functools.partial(udf, data_format='polars') # type: ignore
262
+ udf.arrow = functools.partial(udf, data_format='arrow') # type: ignore
263
+ udf.numpy = functools.partial(udf, data_format='numpy') # type: ignore
264
+
265
+
266
+ def tvf(
267
+ func: Optional[Callable[..., Any]] = None,
268
+ *,
269
+ name: Optional[str] = None,
270
+ args: Optional[Union[DataType, List[DataType], Dict[str, DataType]]] = None,
271
+ returns: Optional[Union[str, List[DataType], List[type]]] = None,
272
+ data_format: Optional[str] = None,
273
+ include_masks: bool = False,
274
+ output_fields: Optional[List[str]] = None,
275
+ ) -> Callable[..., Any]:
276
+ """
277
+ Apply attributes to a TVF.
278
+
279
+ Parameters
280
+ ----------
281
+ func : callable, optional
282
+ The TVF to apply parameters to
283
+ name : str, optional
284
+ The name to use for the TVF in the database
285
+ args : str | Callable | List[str | Callable] | Dict[str, str | Callable], optional
286
+ Specifies the data types of the function arguments. Typically,
287
+ the function data types are derived from the function parameter
288
+ annotations. These annotations can be overridden. If the function
289
+ takes a single type for all parameters, `args` can be set to a
290
+ SQL string describing all parameters. If the function takes more
291
+ than one parameter and all of the parameters are being manually
292
+ defined, a list of SQL strings may be used (one for each parameter).
293
+ A dictionary of SQL strings may be used to specify a parameter type
294
+ for a subset of parameters; the keys are the names of the
295
+ function parameters. Callables may also be used for datatypes. This
296
+ is primarily for using the functions in the ``dtypes`` module that
297
+ are associated with SQL types with all default options (e.g., ``dt.FLOAT``).
298
+ returns : str, optional
299
+ Specifies the return data type of the function. If not specified,
300
+ the type annotation from the function is used.
301
+ data_format : str, optional
302
+ The data format of each parameter: python, pandas, arrow, polars
303
+ include_masks : bool, optional
304
+ Should boolean masks be included with each input parameter to indicate
305
+ which elements are NULL? This is only used when a input parameters are
306
+ configured to a vector type (numpy, pandas, polars, arrow).
307
+ output_fields : List[str], optional
308
+ The names of the output fields for the TVF. If not specified, the
309
+ names are generated.
310
+
311
+ Returns
312
+ -------
313
+ Callable
314
+
315
+ """
316
+ return _func(
317
+ func=func,
318
+ name=name,
319
+ args=args,
320
+ returns=returns,
321
+ data_format=data_format,
322
+ include_masks=include_masks,
323
+ function_type='tvf',
324
+ output_fields=output_fields,
325
+ )
326
+
327
+
328
+ tvf.pandas = functools.partial(tvf, data_format='pandas') # type: ignore
329
+ tvf.polars = functools.partial(tvf, data_format='polars') # type: ignore
330
+ tvf.arrow = functools.partial(tvf, data_format='arrow') # type: ignore
331
+ tvf.numpy = functools.partial(tvf, data_format='numpy') # type: ignore