singlestoredb 0.4.0__py3-none-any.whl → 1.0.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of singlestoredb might be problematic. Click here for more details.

Files changed (120) hide show
  1. singlestoredb/__init__.py +33 -1
  2. singlestoredb/alchemy/__init__.py +90 -0
  3. singlestoredb/auth.py +5 -1
  4. singlestoredb/config.py +116 -14
  5. singlestoredb/connection.py +483 -516
  6. singlestoredb/converters.py +238 -135
  7. singlestoredb/exceptions.py +30 -2
  8. singlestoredb/functions/__init__.py +1 -0
  9. singlestoredb/functions/decorator.py +142 -0
  10. singlestoredb/functions/dtypes.py +1639 -0
  11. singlestoredb/functions/ext/__init__.py +2 -0
  12. singlestoredb/functions/ext/arrow.py +375 -0
  13. singlestoredb/functions/ext/asgi.py +661 -0
  14. singlestoredb/functions/ext/json.py +427 -0
  15. singlestoredb/functions/ext/mmap.py +306 -0
  16. singlestoredb/functions/ext/rowdat_1.py +744 -0
  17. singlestoredb/functions/signature.py +673 -0
  18. singlestoredb/fusion/__init__.py +11 -0
  19. singlestoredb/fusion/graphql.py +213 -0
  20. singlestoredb/fusion/handler.py +621 -0
  21. singlestoredb/fusion/handlers/stage.py +257 -0
  22. singlestoredb/fusion/handlers/utils.py +162 -0
  23. singlestoredb/fusion/handlers/workspace.py +412 -0
  24. singlestoredb/fusion/registry.py +164 -0
  25. singlestoredb/fusion/result.py +399 -0
  26. singlestoredb/http/__init__.py +27 -0
  27. singlestoredb/{http.py → http/connection.py} +555 -154
  28. singlestoredb/management/__init__.py +3 -0
  29. singlestoredb/management/billing_usage.py +148 -0
  30. singlestoredb/management/cluster.py +14 -6
  31. singlestoredb/management/manager.py +100 -38
  32. singlestoredb/management/organization.py +188 -0
  33. singlestoredb/management/region.py +5 -5
  34. singlestoredb/management/utils.py +281 -2
  35. singlestoredb/management/workspace.py +1344 -49
  36. singlestoredb/{clients/pymysqlsv → mysql}/__init__.py +16 -21
  37. singlestoredb/{clients/pymysqlsv → mysql}/_auth.py +39 -8
  38. singlestoredb/{clients/pymysqlsv → mysql}/charset.py +26 -23
  39. singlestoredb/{clients/pymysqlsv/connections.py → mysql/connection.py} +532 -165
  40. singlestoredb/{clients/pymysqlsv → mysql}/constants/CLIENT.py +0 -1
  41. singlestoredb/{clients/pymysqlsv → mysql}/constants/COMMAND.py +0 -1
  42. singlestoredb/{clients/pymysqlsv → mysql}/constants/CR.py +0 -2
  43. singlestoredb/{clients/pymysqlsv → mysql}/constants/ER.py +0 -1
  44. singlestoredb/{clients/pymysqlsv → mysql}/constants/FIELD_TYPE.py +1 -1
  45. singlestoredb/{clients/pymysqlsv → mysql}/constants/FLAG.py +0 -1
  46. singlestoredb/{clients/pymysqlsv → mysql}/constants/SERVER_STATUS.py +0 -1
  47. singlestoredb/mysql/converters.py +271 -0
  48. singlestoredb/{clients/pymysqlsv → mysql}/cursors.py +228 -112
  49. singlestoredb/mysql/err.py +92 -0
  50. singlestoredb/{clients/pymysqlsv → mysql}/optionfile.py +5 -4
  51. singlestoredb/{clients/pymysqlsv → mysql}/protocol.py +49 -20
  52. singlestoredb/mysql/tests/__init__.py +19 -0
  53. singlestoredb/{clients/pymysqlsv → mysql}/tests/base.py +32 -12
  54. singlestoredb/mysql/tests/conftest.py +37 -0
  55. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_DictCursor.py +11 -7
  56. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_SSCursor.py +17 -12
  57. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_basic.py +32 -24
  58. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_connection.py +130 -119
  59. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_converters.py +9 -7
  60. singlestoredb/mysql/tests/test_cursor.py +141 -0
  61. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_err.py +3 -2
  62. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_issues.py +35 -27
  63. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_load_local.py +13 -11
  64. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_nextset.py +7 -3
  65. singlestoredb/{clients/pymysqlsv → mysql}/tests/test_optionfile.py +2 -1
  66. singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/__init__.py +1 -1
  67. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +9 -0
  68. singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/capabilities.py +19 -17
  69. singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/dbapi20.py +31 -22
  70. singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +3 -4
  71. singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +24 -20
  72. singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +4 -4
  73. singlestoredb/{clients/pymysqlsv → mysql}/times.py +3 -4
  74. singlestoredb/pytest.py +283 -0
  75. singlestoredb/tests/empty.sql +0 -0
  76. singlestoredb/tests/ext_funcs/__init__.py +385 -0
  77. singlestoredb/tests/test.sql +210 -0
  78. singlestoredb/tests/test2.sql +1 -0
  79. singlestoredb/tests/test_basics.py +482 -115
  80. singlestoredb/tests/test_config.py +13 -13
  81. singlestoredb/tests/test_connection.py +241 -305
  82. singlestoredb/tests/test_dbapi.py +27 -0
  83. singlestoredb/tests/test_ext_func.py +1193 -0
  84. singlestoredb/tests/test_ext_func_data.py +1101 -0
  85. singlestoredb/tests/test_fusion.py +465 -0
  86. singlestoredb/tests/test_http.py +32 -26
  87. singlestoredb/tests/test_management.py +588 -8
  88. singlestoredb/tests/test_plugin.py +33 -0
  89. singlestoredb/tests/test_results.py +11 -12
  90. singlestoredb/tests/test_udf.py +687 -0
  91. singlestoredb/tests/utils.py +3 -2
  92. singlestoredb/utils/config.py +58 -0
  93. singlestoredb/utils/debug.py +13 -0
  94. singlestoredb/utils/mogrify.py +151 -0
  95. singlestoredb/utils/results.py +4 -1
  96. singlestoredb-1.0.4.dist-info/METADATA +139 -0
  97. singlestoredb-1.0.4.dist-info/RECORD +112 -0
  98. {singlestoredb-0.4.0.dist-info → singlestoredb-1.0.4.dist-info}/WHEEL +1 -1
  99. singlestoredb-1.0.4.dist-info/entry_points.txt +2 -0
  100. singlestoredb/clients/pymysqlsv/converters.py +0 -365
  101. singlestoredb/clients/pymysqlsv/err.py +0 -144
  102. singlestoredb/clients/pymysqlsv/tests/__init__.py +0 -19
  103. singlestoredb/clients/pymysqlsv/tests/test_cursor.py +0 -133
  104. singlestoredb/clients/pymysqlsv/tests/thirdparty/test_MySQLdb/__init__.py +0 -9
  105. singlestoredb/drivers/__init__.py +0 -45
  106. singlestoredb/drivers/base.py +0 -198
  107. singlestoredb/drivers/cymysql.py +0 -38
  108. singlestoredb/drivers/http.py +0 -47
  109. singlestoredb/drivers/mariadb.py +0 -40
  110. singlestoredb/drivers/mysqlconnector.py +0 -49
  111. singlestoredb/drivers/mysqldb.py +0 -60
  112. singlestoredb/drivers/pymysql.py +0 -37
  113. singlestoredb/drivers/pymysqlsv.py +0 -35
  114. singlestoredb/drivers/pyodbc.py +0 -65
  115. singlestoredb-0.4.0.dist-info/METADATA +0 -111
  116. singlestoredb-0.4.0.dist-info/RECORD +0 -86
  117. /singlestoredb/{clients → fusion/handlers}/__init__.py +0 -0
  118. /singlestoredb/{clients/pymysqlsv → mysql}/constants/__init__.py +0 -0
  119. {singlestoredb-0.4.0.dist-info → singlestoredb-1.0.4.dist-info}/LICENSE +0 -0
  120. {singlestoredb-0.4.0.dist-info → singlestoredb-1.0.4.dist-info}/top_level.txt +0 -0
@@ -1,45 +0,0 @@
1
- import re
2
- from typing import Any
3
- from typing import Dict
4
-
5
- from . import base
6
- from .cymysql import CyMySQLDriver
7
- from .http import HTTPDriver
8
- from .http import HTTPSDriver
9
- from .mariadb import MariaDBDriver
10
- from .mysqlconnector import MySQLConnectorDriver
11
- from .mysqldb import MySQLdbDriver
12
- from .pymysql import PyMySQLDriver
13
- from .pymysqlsv import PyMySQLsvDriver
14
- from .pyodbc import PyODBCDriver
15
-
16
-
17
- def get_driver(name: str, params: Dict[str, Any]) -> base.Driver:
18
- """
19
- Return the driver with the given name.
20
-
21
- Parameters
22
- ----------
23
- name : str
24
- Name of the driver. All non-letters/digits will be removed
25
- from the name when matching. For example, 'mysqlconnector'
26
- will match 'mysql.connector' or 'mysqlconnector'. Matches
27
- are also case-insensitive.
28
- params : dict
29
- Dictionary of connection parameters
30
-
31
- Returns
32
- -------
33
- Driver
34
-
35
- """
36
- rm_symbols = re.compile(r'[^A-Z0-9]', flags=re.I)
37
- new_name = rm_symbols.sub(r'', name).lower()
38
- for item in globals().values():
39
- if type(item) is not type:
40
- continue
41
- if not issubclass(item, base.Driver):
42
- continue
43
- if new_name == rm_symbols.sub(r'', item.name.lower()):
44
- return item(**params)
45
- raise RuntimeError("Could not locate driver with name '{}'".format(name))
@@ -1,198 +0,0 @@
1
- import sys
2
- from typing import Any
3
- from typing import Callable
4
- from typing import Dict
5
- from typing import Optional
6
-
7
- from .. import exceptions
8
-
9
-
10
- def wrap_converter(
11
- outer: Optional[Callable[[Any], Any]],
12
- conv: Optional[Callable[[Any], Any]],
13
- ) -> Optional[Callable[[Any], Any]]:
14
- """Create a pipeline from two functions."""
15
- if outer is None:
16
- return conv
17
-
18
- if conv is None:
19
- return outer
20
-
21
- def converter(value: Any) -> Any:
22
- return outer(conv(value)) # type: ignore
23
-
24
- return converter
25
-
26
-
27
- class Driver(object):
28
- """Base driver class."""
29
-
30
- # Name of driver used in connections
31
- name: str = ''
32
-
33
- # Name of package to import
34
- pkg_name: str = ''
35
-
36
- # Name of the package on PyPI.org
37
- pypi: str = ''
38
-
39
- # Name of the package on Anaconda.org
40
- anaconda: str = ''
41
-
42
- # Does the driver return bytes for all data values?
43
- # If true and flags are available in the description to deterimine
44
- # if a character field is text or binary, the text will be automatically
45
- # decoded before conversion functions are run.
46
- returns_bytes: bool = False
47
-
48
- def __init__(self, **kwargs: Any):
49
- self._params = kwargs
50
-
51
- # These converters get applied after the driver does its own
52
- # conversions. This allows each driver to decide which conversions
53
- # get handled internally and which get applied by this framework.
54
- self.converters: Dict[int, Callable[[Any], Any]] = {}
55
-
56
- def connect(self) -> Any:
57
- """Create a new connection."""
58
- params = {
59
- k: v for k, v in self.remap_params(self._params).items() if v is not None
60
- }
61
- conn = self.dbapi.connect(**params)
62
- self.after_connect(conn, self._params)
63
- return conn
64
-
65
- def merge_converters(
66
- self,
67
- user_converters: Dict[int, Callable[[Any], Any]],
68
- driver_converters: Dict[int, Callable[[Any], Any]],
69
- ) -> Dict[int, Callable[[Any], Any]]:
70
- """Merge two sets of converters into pipelines as needed."""
71
- out = dict(driver_converters)
72
- for key, value in user_converters.items():
73
- func = wrap_converter(value, out.get(key))
74
- if func is not None:
75
- out[key] = func
76
- return out
77
-
78
- def after_connect(self, conn: Any, params: Dict[str, Any]) -> None:
79
- """
80
- Callback for immediately after making a connection.
81
-
82
- Parameters
83
- ----------
84
- conn : Connection
85
- Connection object
86
- params : dict
87
- Original connection parameters
88
-
89
- """
90
- return
91
-
92
- def is_connected(self, conn: Any, reconnect: bool = False) -> bool:
93
- """
94
- Determine if the server is still connected.
95
-
96
- Parameters
97
- ----------
98
- conn : Connection
99
- Connection object to test
100
- reconnect : bool, optional
101
- If the server is not connected, should a reconnection be attempted?
102
-
103
- Returns
104
- -------
105
- bool
106
-
107
- """
108
- raise NotImplementedError
109
-
110
- def remap_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
111
- """
112
- Map generalized parameters to package-specific parameters.
113
-
114
- Parameters
115
- ----------
116
- params : dict
117
- Dictionary of connection parameters.
118
-
119
- Returns
120
- -------
121
- dict
122
-
123
- """
124
- return params
125
-
126
- def convert_exception(self, exc: Exception) -> Exception:
127
- """Convert driver-specific exception to SingleStoreDB exception."""
128
- dbapi = self.dbapi
129
- if not isinstance(exc, (dbapi.Error, dbapi.Warning)):
130
- return exc
131
- new_exc: Optional[type] = None
132
- if isinstance(exc, dbapi.NotSupportedError):
133
- new_exc = exceptions.NotSupportedError
134
- elif isinstance(exc, dbapi.ProgrammingError):
135
- new_exc = exceptions.ProgrammingError
136
- elif isinstance(exc, dbapi.InternalError):
137
- new_exc = exceptions.InternalError
138
- elif isinstance(exc, dbapi.IntegrityError):
139
- new_exc = exceptions.IntegrityError
140
- elif isinstance(exc, dbapi.OperationalError):
141
- new_exc = exceptions.OperationalError
142
- elif isinstance(exc, dbapi.DataError):
143
- new_exc = exceptions.DataError
144
- elif isinstance(exc, dbapi.DatabaseError):
145
- new_exc = exceptions.DatabaseError
146
- elif isinstance(exc, dbapi.InterfaceError):
147
- new_exc = exceptions.InterfaceError
148
- elif isinstance(exc, dbapi.Error):
149
- new_exc = exceptions.Error
150
- elif isinstance(exc, dbapi.Warning):
151
- new_exc = exceptions.Warning
152
- if new_exc is None:
153
- return exc
154
-
155
- # Check for exceptions with errno / msg first
156
- errno = getattr(exc, 'errno', None)
157
- msg = getattr(exc, 'msg', None)
158
- if msg:
159
- return new_exc(
160
- errno=errno, msg=msg,
161
- sqlstate=getattr(exc, 'sqlstate', None),
162
- )
163
-
164
- # Check for exceptions with just args
165
- args = getattr(exc, 'args', [])
166
- if len(args) > 1:
167
- return new_exc(args[0], args[1])
168
- if len(args):
169
- return new_exc(args[0])
170
-
171
- # Don't know what type it is
172
- raise ValueError(f'Unrecognized exception format: {exc}')
173
-
174
- @property
175
- def dbapi(self) -> Any:
176
- """Return imported DB-API-compatible module."""
177
- if not type(self).pkg_name:
178
- raise ValueError('No package name defined in driver.')
179
- try:
180
- return __import__(type(self).pkg_name, {}, {}, ['connect'])
181
- except ModuleNotFoundError:
182
- msg = []
183
- msg.append('{} is not available.'.format(type(self).pkg_name))
184
- msg.append(" Use 'pip install {}'".format(type(self).pypi))
185
- if type(self).anaconda:
186
- if '::' in type(self).anaconda:
187
- msg.append(
188
- " or 'conda install -c {} {}' (for Anaconda)"
189
- .format(*type(self).anaconda.split('::', 1)),
190
- )
191
- else:
192
- msg.append(
193
- " or 'conda install {}' (for Anaconda)"
194
- .format(type(self).anaconda),
195
- )
196
- msg.append(' to install it.')
197
- print(''.join(msg), file=sys.stderr)
198
- raise
@@ -1,38 +0,0 @@
1
- from typing import Any
2
- from typing import Dict
3
-
4
- try:
5
- from cymysql.converters import encoders
6
- except ImportError:
7
- encoders = {}
8
-
9
- from .base import Driver
10
- from ..converters import converters
11
-
12
-
13
- converters = dict(converters)
14
- converters.update(encoders)
15
-
16
-
17
- class CyMySQLDriver(Driver):
18
-
19
- name = 'CyMySQL'
20
-
21
- pkg_name = 'cymysql'
22
- pypi = 'cymysql'
23
- anaconda = 'cymysql'
24
-
25
- def remap_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
26
- params.pop('driver', None)
27
- params.pop('pure_python', None)
28
- params.pop('odbc_driver', None)
29
- params.pop('credential_type', None)
30
- params['port'] = params['port'] or 3306
31
- params['db'] = params.pop('database', None)
32
- params['passwd'] = params.pop('password', None)
33
- params['conv'] = self.merge_converters(params.pop('converters', {}), converters)
34
- params['ssl'] = dict(cipher=params.pop('ssl_cipher'))
35
- return params
36
-
37
- def is_connected(self, conn: Any, reconnect: bool = False) -> bool:
38
- return conn.ping(reconnect=reconnect)
@@ -1,47 +0,0 @@
1
- import warnings
2
- from typing import Any
3
- from typing import Dict
4
-
5
- from .base import Driver
6
-
7
-
8
- class HTTPDriver(Driver):
9
-
10
- name = 'http'
11
-
12
- pkg_name = 'singlestoredb.http'
13
- pypi = 'singlestoredb'
14
- anaconda = 'singlestore::singlestoredb'
15
-
16
- def remap_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
17
- params.pop('pure_python', False)
18
- params.pop('charset', None)
19
- params.pop('odbc_driver', None)
20
- params.pop('credential_type', None)
21
- params.pop('autocommit', None)
22
- params.pop('ssl_cipher', None)
23
-
24
- params['protocol'] = params.pop('driver', '').replace(
25
- 'singlestoredb+', '',
26
- ) or None
27
-
28
- if params.pop('local_infile', False):
29
- warnings.warn('The HTTP driver does not support file uploads.')
30
-
31
- if params['port'] is None:
32
- if type(self).name == 'https':
33
- params['port'] = 443
34
- else:
35
- params['port'] = 80
36
-
37
- self.converters = params.pop('converters', {})
38
-
39
- return params
40
-
41
- def is_connected(self, conn: Any, reconnect: bool = False) -> bool:
42
- return conn.is_connected()
43
-
44
-
45
- class HTTPSDriver(HTTPDriver):
46
-
47
- name = 'https'
@@ -1,40 +0,0 @@
1
- import json
2
- from typing import Any
3
- from typing import Dict
4
-
5
- from .base import Driver
6
-
7
-
8
- converters = {245: json.loads}
9
-
10
-
11
- class MariaDBDriver(Driver):
12
-
13
- name = 'mariadb'
14
-
15
- pkg_name = 'mariadb'
16
- pypi = 'mariadb-connector-python'
17
- anaconda = 'mariadb-connector-python'
18
-
19
- def remap_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
20
- params.pop('driver', None)
21
- params.pop('charset', None)
22
- params.pop('odbc_driver', None)
23
- params.pop('pure_python', None)
24
- params.pop('credential_type', None)
25
- params['converter'] = self.merge_converters(
26
- params.pop('converters', {}),
27
- dict(converters),
28
- )
29
- if params.pop('ssl_disabled', False):
30
- params['ssl'] = False
31
- params['ssl_verify_cert'] = False
32
-
33
- return params
34
-
35
- def is_connected(self, conn: Any, reconnect: bool = False) -> bool:
36
- try:
37
- conn.ping()
38
- return True
39
- except conn.InterfaceError:
40
- return False
@@ -1,49 +0,0 @@
1
- from typing import Any
2
- from typing import Dict
3
-
4
- from .. import auth
5
- from ..converters import converters
6
- from .base import Driver
7
-
8
-
9
- class MySQLConnectorDriver(Driver):
10
-
11
- name = 'mysqlconnector'
12
-
13
- pkg_name = 'mysql.connector'
14
- pypi = 'mysql-connector-python'
15
- anaconda = 'mysql-connector-python'
16
-
17
- # This flag lets the connection do the decoding of text / binary accordingly
18
- returns_bytes = True
19
-
20
- def remap_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
21
- params.pop('driver', None)
22
- params.pop('odbc_driver', None)
23
- params.pop('ssl_cipher', None)
24
- if params.pop('pure_python', False):
25
- params['use_pure'] = True
26
- params['port'] = params['port'] or 3306
27
- params['allow_local_infile'] = params.pop('local_infile')
28
-
29
- # Always use raw, we're doing the conversions ourselves
30
- params['raw'] = True
31
-
32
- convs = params.pop('converters', {})
33
- self.converters = self.merge_converters(convs, converters)
34
-
35
- # Check authentication method
36
- cred = params.pop('credential_type', None)
37
- if cred in [auth.BROWSER_SSO, auth.JWT] and not params.get('use_pure', False):
38
- # params['auth_plugin'] = 'mysql_clear_password'
39
- params['ssl_verify_identity'] = True
40
- params['ssl_verify_cert'] = True
41
-
42
- return params
43
-
44
- def is_connected(self, conn: Any, reconnect: bool = False) -> bool:
45
- try:
46
- conn.ping(reconnect=reconnect)
47
- return True
48
- except conn.InterfaceError:
49
- return False
@@ -1,60 +0,0 @@
1
- from typing import Any
2
- from typing import Dict
3
-
4
- from ..converters import converters
5
- from .base import Driver
6
-
7
-
8
- class MySQLdbDriver(Driver):
9
-
10
- name = 'MySQLdb'
11
-
12
- pkg_name = 'MySQLdb'
13
- pypi = 'mysqlclient'
14
- anaconda = 'mysqlclient'
15
-
16
- def remap_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
17
- params.pop('driver', None)
18
- params.pop('pure_python', None)
19
- params.pop('odbc_driver', None)
20
- params.pop('credential_type', None)
21
-
22
- params['conv'] = dict(converters)
23
-
24
- ssl = dict()
25
-
26
- if params.get('ssl_key', None):
27
- ssl['key'] = params.get('ssl_key')
28
- if params.get('ssl_cert', None):
29
- ssl['cert'] = params.get('ssl_cert')
30
- if params.get('ssl_ca', None):
31
- ssl['ca'] = params.get('ssl_ca')
32
- if params.get('ssl_cipher', None):
33
- ssl['cipher'] = params.get('ssl_cipher')
34
-
35
- params.pop('ssl_key', None)
36
- params.pop('ssl_cert', None)
37
- params.pop('ssl_ca', None)
38
- params.pop('ssl_cipher', None)
39
-
40
- if ssl:
41
- params['ssl'] = dict(ssl=ssl)
42
-
43
- if params.pop('ssl_disabled', False):
44
- params['ssl_mode'] = 'DISABLED'
45
-
46
- self.converters = params.pop('converters', {})
47
-
48
- return params
49
-
50
- def after_connect(self, conn: Any, params: Dict[str, Any]) -> None:
51
- # This must be done afterward because use_unicode= whacks the
52
- # json converter if you try to put it in earlier.
53
- conn.converter[245] = converters[245]
54
-
55
- def is_connected(self, conn: Any, reconnect: bool = False) -> bool:
56
- try:
57
- conn.ping(reconnect)
58
- return True
59
- except conn.InterfaceError:
60
- return False
@@ -1,37 +0,0 @@
1
- from typing import Any
2
- from typing import Callable
3
- from typing import Dict
4
-
5
- try:
6
- from pymysql.converters import encoders
7
- except ImportError:
8
- encoders = {}
9
-
10
- from .base import Driver
11
- from ..converters import converters as convs
12
-
13
- converters: Dict[Any, Callable[..., Any]] = dict(convs)
14
- converters.update(encoders)
15
-
16
-
17
- class PyMySQLDriver(Driver):
18
-
19
- name = 'PyMySQL'
20
-
21
- pkg_name = 'pymysql'
22
- pypi = 'pymysql'
23
- anaconda = 'pymysql'
24
-
25
- def remap_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
26
- params.pop('driver', None)
27
- params.pop('odbc_driver', None)
28
- params.pop('pure_python', None)
29
- params.pop('credential_type', None)
30
- # The cipher must be set to this level for SingleStoreDB Cloud.
31
- params['ssl'] = dict(cipher=params.pop('ssl_cipher'))
32
- params['port'] = params['port'] or 3306
33
- params['conv'] = self.merge_converters(params.pop('converters', {}), converters)
34
- return params
35
-
36
- def is_connected(self, conn: Any, reconnect: bool = False) -> bool:
37
- return conn.open
@@ -1,35 +0,0 @@
1
- from typing import Any
2
- from typing import Callable
3
- from typing import Dict
4
-
5
- try:
6
- from ..clients.pymysqlsv.converters import encoders # type: ignore
7
- except (ImportError, ModuleNotFoundError):
8
- encoders = {}
9
-
10
- from .base import Driver
11
- from ..converters import converters as convs
12
-
13
- converters: Dict[Any, Callable[..., Any]] = dict(convs)
14
- converters.update(encoders)
15
-
16
-
17
- class PyMySQLsvDriver(Driver):
18
-
19
- name = 'PyMySQLsv'
20
-
21
- pkg_name = 'singlestoredb.clients.pymysqlsv'
22
-
23
- def remap_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
24
- params.pop('driver', None)
25
- params.pop('odbc_driver', None)
26
- params.pop('pure_python', None)
27
- params.pop('credential_type', None)
28
- # The cipher must be set to this level for SingleStoreDB Cloud.
29
- params['ssl'] = dict(cipher=params.pop('ssl_cipher'))
30
- params['port'] = params['port'] or 3306
31
- params['conv'] = self.merge_converters(params.pop('converters', {}), converters)
32
- return params
33
-
34
- def is_connected(self, conn: Any, reconnect: bool = False) -> bool:
35
- return conn.open
@@ -1,65 +0,0 @@
1
- import datetime
2
- import json
3
- from typing import Any
4
- from typing import Dict
5
- from typing import Optional
6
-
7
- from .base import Driver
8
-
9
-
10
- datetime_min = datetime.datetime.min
11
- date_min = datetime.date.min
12
- datetime_combine = datetime.datetime.combine
13
-
14
-
15
- def convert_time(value: Optional[datetime.time]) -> Optional[datetime.timedelta]:
16
- """Convert time to timedelta."""
17
- if value is None:
18
- return None
19
- return datetime_combine(date_min, value) - datetime_min
20
-
21
-
22
- def convert_json(value: Optional[str]) -> Optional[Dict[str, Any]]:
23
- """Convert JSON str to dict."""
24
- if value is None:
25
- return None
26
- return json.loads(value)
27
-
28
-
29
- class PyODBCDriver(Driver):
30
-
31
- name = 'pyodbc'
32
-
33
- pkg_name = 'pyodbc'
34
- pypi = 'pyodbc'
35
- anaconda = 'pyodbc'
36
-
37
- def remap_params(self, params: Dict[str, Any]) -> Dict[str, Any]:
38
- out = {
39
- k: v for k, v in dict(
40
- server=params.get('host', '127.0.0.1'),
41
- port=params.get('port', 0) or 3306,
42
- database=params.get('database'),
43
- uid=params.get('user'),
44
- pwd=params.get('password'),
45
- charset=params.get('charset'),
46
- driver=params.get('odbc_driver'),
47
- ).items() if v is not None
48
- }
49
-
50
- convs = params.pop('converters', {})
51
- self.converters = self.merge_converters(
52
- convs, {
53
- 11: convert_time,
54
- 245: convert_json,
55
- },
56
- )
57
-
58
- return out
59
-
60
- def after_connect(self, conn: Any, params: Dict[str, Any]) -> None:
61
- if params.get('autocommit'):
62
- conn.autocommit(True)
63
-
64
- def is_connected(self, conn: Any, reconnect: bool = False) -> bool:
65
- return not conn.closed