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.
- singlestoredb/__init__.py +33 -1
- singlestoredb/alchemy/__init__.py +90 -0
- singlestoredb/auth.py +5 -1
- singlestoredb/config.py +116 -14
- singlestoredb/connection.py +483 -516
- singlestoredb/converters.py +238 -135
- singlestoredb/exceptions.py +30 -2
- singlestoredb/functions/__init__.py +1 -0
- singlestoredb/functions/decorator.py +142 -0
- singlestoredb/functions/dtypes.py +1639 -0
- singlestoredb/functions/ext/__init__.py +2 -0
- singlestoredb/functions/ext/arrow.py +375 -0
- singlestoredb/functions/ext/asgi.py +661 -0
- singlestoredb/functions/ext/json.py +427 -0
- singlestoredb/functions/ext/mmap.py +306 -0
- singlestoredb/functions/ext/rowdat_1.py +744 -0
- singlestoredb/functions/signature.py +673 -0
- singlestoredb/fusion/__init__.py +11 -0
- singlestoredb/fusion/graphql.py +213 -0
- singlestoredb/fusion/handler.py +621 -0
- singlestoredb/fusion/handlers/stage.py +257 -0
- singlestoredb/fusion/handlers/utils.py +162 -0
- singlestoredb/fusion/handlers/workspace.py +412 -0
- singlestoredb/fusion/registry.py +164 -0
- singlestoredb/fusion/result.py +399 -0
- singlestoredb/http/__init__.py +27 -0
- singlestoredb/{http.py → http/connection.py} +555 -154
- singlestoredb/management/__init__.py +3 -0
- singlestoredb/management/billing_usage.py +148 -0
- singlestoredb/management/cluster.py +14 -6
- singlestoredb/management/manager.py +100 -38
- singlestoredb/management/organization.py +188 -0
- singlestoredb/management/region.py +5 -5
- singlestoredb/management/utils.py +281 -2
- singlestoredb/management/workspace.py +1344 -49
- singlestoredb/{clients/pymysqlsv → mysql}/__init__.py +16 -21
- singlestoredb/{clients/pymysqlsv → mysql}/_auth.py +39 -8
- singlestoredb/{clients/pymysqlsv → mysql}/charset.py +26 -23
- singlestoredb/{clients/pymysqlsv/connections.py → mysql/connection.py} +532 -165
- singlestoredb/{clients/pymysqlsv → mysql}/constants/CLIENT.py +0 -1
- singlestoredb/{clients/pymysqlsv → mysql}/constants/COMMAND.py +0 -1
- singlestoredb/{clients/pymysqlsv → mysql}/constants/CR.py +0 -2
- singlestoredb/{clients/pymysqlsv → mysql}/constants/ER.py +0 -1
- singlestoredb/{clients/pymysqlsv → mysql}/constants/FIELD_TYPE.py +1 -1
- singlestoredb/{clients/pymysqlsv → mysql}/constants/FLAG.py +0 -1
- singlestoredb/{clients/pymysqlsv → mysql}/constants/SERVER_STATUS.py +0 -1
- singlestoredb/mysql/converters.py +271 -0
- singlestoredb/{clients/pymysqlsv → mysql}/cursors.py +228 -112
- singlestoredb/mysql/err.py +92 -0
- singlestoredb/{clients/pymysqlsv → mysql}/optionfile.py +5 -4
- singlestoredb/{clients/pymysqlsv → mysql}/protocol.py +49 -20
- singlestoredb/mysql/tests/__init__.py +19 -0
- singlestoredb/{clients/pymysqlsv → mysql}/tests/base.py +32 -12
- singlestoredb/mysql/tests/conftest.py +37 -0
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_DictCursor.py +11 -7
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_SSCursor.py +17 -12
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_basic.py +32 -24
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_connection.py +130 -119
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_converters.py +9 -7
- singlestoredb/mysql/tests/test_cursor.py +141 -0
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_err.py +3 -2
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_issues.py +35 -27
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_load_local.py +13 -11
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_nextset.py +7 -3
- singlestoredb/{clients/pymysqlsv → mysql}/tests/test_optionfile.py +2 -1
- singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/__init__.py +1 -1
- singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +9 -0
- singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/capabilities.py +19 -17
- singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/dbapi20.py +31 -22
- singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +3 -4
- singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +24 -20
- singlestoredb/{clients/pymysqlsv → mysql}/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +4 -4
- singlestoredb/{clients/pymysqlsv → mysql}/times.py +3 -4
- singlestoredb/pytest.py +283 -0
- singlestoredb/tests/empty.sql +0 -0
- singlestoredb/tests/ext_funcs/__init__.py +385 -0
- singlestoredb/tests/test.sql +210 -0
- singlestoredb/tests/test2.sql +1 -0
- singlestoredb/tests/test_basics.py +482 -115
- singlestoredb/tests/test_config.py +13 -13
- singlestoredb/tests/test_connection.py +241 -305
- singlestoredb/tests/test_dbapi.py +27 -0
- singlestoredb/tests/test_ext_func.py +1193 -0
- singlestoredb/tests/test_ext_func_data.py +1101 -0
- singlestoredb/tests/test_fusion.py +465 -0
- singlestoredb/tests/test_http.py +32 -26
- singlestoredb/tests/test_management.py +588 -8
- singlestoredb/tests/test_plugin.py +33 -0
- singlestoredb/tests/test_results.py +11 -12
- singlestoredb/tests/test_udf.py +687 -0
- singlestoredb/tests/utils.py +3 -2
- singlestoredb/utils/config.py +58 -0
- singlestoredb/utils/debug.py +13 -0
- singlestoredb/utils/mogrify.py +151 -0
- singlestoredb/utils/results.py +4 -1
- singlestoredb-1.0.4.dist-info/METADATA +139 -0
- singlestoredb-1.0.4.dist-info/RECORD +112 -0
- {singlestoredb-0.4.0.dist-info → singlestoredb-1.0.4.dist-info}/WHEEL +1 -1
- singlestoredb-1.0.4.dist-info/entry_points.txt +2 -0
- singlestoredb/clients/pymysqlsv/converters.py +0 -365
- singlestoredb/clients/pymysqlsv/err.py +0 -144
- singlestoredb/clients/pymysqlsv/tests/__init__.py +0 -19
- singlestoredb/clients/pymysqlsv/tests/test_cursor.py +0 -133
- singlestoredb/clients/pymysqlsv/tests/thirdparty/test_MySQLdb/__init__.py +0 -9
- singlestoredb/drivers/__init__.py +0 -45
- singlestoredb/drivers/base.py +0 -198
- singlestoredb/drivers/cymysql.py +0 -38
- singlestoredb/drivers/http.py +0 -47
- singlestoredb/drivers/mariadb.py +0 -40
- singlestoredb/drivers/mysqlconnector.py +0 -49
- singlestoredb/drivers/mysqldb.py +0 -60
- singlestoredb/drivers/pymysql.py +0 -37
- singlestoredb/drivers/pymysqlsv.py +0 -35
- singlestoredb/drivers/pyodbc.py +0 -65
- singlestoredb-0.4.0.dist-info/METADATA +0 -111
- singlestoredb-0.4.0.dist-info/RECORD +0 -86
- /singlestoredb/{clients → fusion/handlers}/__init__.py +0 -0
- /singlestoredb/{clients/pymysqlsv → mysql}/constants/__init__.py +0 -0
- {singlestoredb-0.4.0.dist-info → singlestoredb-1.0.4.dist-info}/LICENSE +0 -0
- {singlestoredb-0.4.0.dist-info → singlestoredb-1.0.4.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# type: ignore
|
|
2
1
|
"""
|
|
3
2
|
PyMySQL: A pure-Python MySQL client library.
|
|
4
3
|
|
|
@@ -23,6 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
23
22
|
THE SOFTWARE.
|
|
24
23
|
"""
|
|
25
24
|
import sys
|
|
25
|
+
from typing import Any
|
|
26
|
+
from typing import FrozenSet
|
|
26
27
|
|
|
27
28
|
from .constants import FIELD_TYPE
|
|
28
29
|
from .err import DatabaseError
|
|
@@ -44,32 +45,28 @@ from .times import Timestamp
|
|
|
44
45
|
from .times import TimestampFromTicks
|
|
45
46
|
|
|
46
47
|
|
|
47
|
-
VERSION = (1, 0, 2, None)
|
|
48
|
-
if VERSION[3] is not None:
|
|
49
|
-
VERSION_STRING = '%d.%d.%d_%s' % VERSION
|
|
50
|
-
else:
|
|
51
|
-
VERSION_STRING = '%d.%d.%d' % VERSION[:3]
|
|
52
48
|
threadsafety = 1
|
|
53
49
|
apilevel = '2.0'
|
|
54
50
|
paramstyle = 'pyformat'
|
|
55
51
|
|
|
56
|
-
from . import
|
|
52
|
+
from . import connection # noqa: E402
|
|
57
53
|
|
|
58
54
|
|
|
59
|
-
class DBAPISet(
|
|
60
|
-
|
|
55
|
+
class DBAPISet(FrozenSet[Any]):
|
|
56
|
+
|
|
57
|
+
def __ne__(self, other: Any) -> bool:
|
|
61
58
|
if isinstance(other, set):
|
|
62
59
|
return frozenset.__ne__(self, other)
|
|
63
60
|
else:
|
|
64
61
|
return other not in self
|
|
65
62
|
|
|
66
|
-
def __eq__(self, other):
|
|
63
|
+
def __eq__(self, other: Any) -> bool:
|
|
67
64
|
if isinstance(other, frozenset):
|
|
68
65
|
return frozenset.__eq__(self, other)
|
|
69
66
|
else:
|
|
70
67
|
return other in self
|
|
71
68
|
|
|
72
|
-
def __hash__(self):
|
|
69
|
+
def __hash__(self) -> int:
|
|
73
70
|
return frozenset.__hash__(self)
|
|
74
71
|
|
|
75
72
|
|
|
@@ -101,19 +98,17 @@ DATETIME = TIMESTAMP
|
|
|
101
98
|
ROWID = DBAPISet()
|
|
102
99
|
|
|
103
100
|
|
|
104
|
-
def Binary(x):
|
|
101
|
+
def Binary(x: Any) -> bytes:
|
|
105
102
|
"""Return x as a binary type."""
|
|
106
103
|
return bytes(x)
|
|
107
104
|
|
|
108
105
|
|
|
109
|
-
Connect = connect = Connection =
|
|
106
|
+
Connect = connect = Connection = connection.Connection # type: ignore
|
|
110
107
|
|
|
111
108
|
|
|
112
|
-
def get_client_info(): # for MySQLdb compatibility
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
version = VERSION[:3]
|
|
116
|
-
return '.'.join(map(str, version))
|
|
109
|
+
def get_client_info() -> str: # for MySQLdb compatibility
|
|
110
|
+
from .. import __version__
|
|
111
|
+
return __version__
|
|
117
112
|
|
|
118
113
|
|
|
119
114
|
# we include a doctored version_info here for MySQLdb compatibility
|
|
@@ -124,11 +119,11 @@ NULL = 'NULL'
|
|
|
124
119
|
__version__ = get_client_info()
|
|
125
120
|
|
|
126
121
|
|
|
127
|
-
def thread_safe():
|
|
122
|
+
def thread_safe() -> bool:
|
|
128
123
|
return True # match MySQLdb.thread_safe()
|
|
129
124
|
|
|
130
125
|
|
|
131
|
-
def install_as_MySQLdb():
|
|
126
|
+
def install_as_MySQLdb() -> None:
|
|
132
127
|
"""
|
|
133
128
|
After this function is called, any application that imports MySQLdb or
|
|
134
129
|
_mysql will unwittingly actually use pymysql.
|
|
@@ -169,7 +164,7 @@ __all__ = [
|
|
|
169
164
|
'Warning',
|
|
170
165
|
'apilevel',
|
|
171
166
|
'connect',
|
|
172
|
-
'
|
|
167
|
+
'connection',
|
|
173
168
|
'constants',
|
|
174
169
|
'converters',
|
|
175
170
|
'cursors',
|
|
@@ -4,7 +4,6 @@ Implements auth methods
|
|
|
4
4
|
"""
|
|
5
5
|
from .err import OperationalError
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
try:
|
|
9
8
|
from cryptography.hazmat.backends import default_backend
|
|
10
9
|
from cryptography.hazmat.primitives import serialization, hashes
|
|
@@ -17,8 +16,10 @@ except ImportError:
|
|
|
17
16
|
from functools import partial
|
|
18
17
|
import hashlib
|
|
19
18
|
|
|
19
|
+
from ..config import get_option
|
|
20
|
+
|
|
20
21
|
|
|
21
|
-
DEBUG =
|
|
22
|
+
DEBUG = get_option('debug.connection')
|
|
22
23
|
SCRAMBLE_LENGTH = 20
|
|
23
24
|
sha1_new = partial(hashlib.new, 'sha1')
|
|
24
25
|
|
|
@@ -28,7 +29,7 @@ sha1_new = partial(hashlib.new, 'sha1')
|
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def scramble_native_password(password, message):
|
|
31
|
-
"""Scramble used for mysql_native_password"""
|
|
32
|
+
"""Scramble used for mysql_native_password."""
|
|
32
33
|
if not password:
|
|
33
34
|
return b''
|
|
34
35
|
|
|
@@ -76,9 +77,11 @@ def _scalar_clamp(s32):
|
|
|
76
77
|
|
|
77
78
|
|
|
78
79
|
def ed25519_password(password, scramble):
|
|
79
|
-
"""
|
|
80
|
+
"""
|
|
81
|
+
Sign a random scramble with elliptic curve Ed25519.
|
|
80
82
|
|
|
81
83
|
Secret and public key are derived from password.
|
|
84
|
+
|
|
82
85
|
"""
|
|
83
86
|
# variable names based on rfc8032 section-5.1.6
|
|
84
87
|
#
|
|
@@ -125,7 +128,8 @@ def _roundtrip(conn, send_data):
|
|
|
125
128
|
|
|
126
129
|
def _xor_password(password, salt):
|
|
127
130
|
# Trailing NUL character will be added in Auth Switch Request.
|
|
128
|
-
# See https://github.com/mysql/mysql-server/blob/
|
|
131
|
+
# See https://github.com/mysql/mysql-server/blob/
|
|
132
|
+
# 7d10c82196c8e45554f27c00681474a9fb86d137/sql/auth/sha2_password.cc#L939-L945
|
|
129
133
|
salt = salt[:SCRAMBLE_LENGTH]
|
|
130
134
|
password_bytes = bytearray(password)
|
|
131
135
|
# salt = bytearray(salt) # for PY2 compat.
|
|
@@ -136,13 +140,16 @@ def _xor_password(password, salt):
|
|
|
136
140
|
|
|
137
141
|
|
|
138
142
|
def sha2_rsa_encrypt(password, salt, public_key):
|
|
139
|
-
"""
|
|
143
|
+
"""
|
|
144
|
+
Encrypt password with salt and public_key.
|
|
140
145
|
|
|
141
146
|
Used for sha256_password and caching_sha2_password.
|
|
147
|
+
|
|
142
148
|
"""
|
|
143
149
|
if not _have_cryptography:
|
|
144
150
|
raise RuntimeError(
|
|
145
|
-
"'cryptography' package is required for sha256_password or
|
|
151
|
+
"'cryptography' package is required for sha256_password or "
|
|
152
|
+
'caching_sha2_password auth methods',
|
|
146
153
|
)
|
|
147
154
|
message = _xor_password(password + b'\0', salt)
|
|
148
155
|
rsa_key = serialization.load_pem_public_key(public_key, default_backend())
|
|
@@ -189,9 +196,11 @@ def sha256_password_auth(conn, pkt):
|
|
|
189
196
|
|
|
190
197
|
def scramble_caching_sha2(password, nonce):
|
|
191
198
|
# (bytes, bytes) -> bytes
|
|
192
|
-
"""
|
|
199
|
+
"""
|
|
200
|
+
Scramble algorithm used in cached_sha2_password fast path.
|
|
193
201
|
|
|
194
202
|
XOR(SHA256(password), SHA256(SHA256(SHA256(password)), nonce))
|
|
203
|
+
|
|
195
204
|
"""
|
|
196
205
|
if not password:
|
|
197
206
|
return b''
|
|
@@ -265,3 +274,25 @@ def caching_sha2_password_auth(conn, pkt):
|
|
|
265
274
|
|
|
266
275
|
data = sha2_rsa_encrypt(conn.password, conn.salt, conn.server_public_key)
|
|
267
276
|
pkt = _roundtrip(conn, data)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def gssapi_auth(data):
|
|
280
|
+
try:
|
|
281
|
+
import gssapi.raw
|
|
282
|
+
except ImportError:
|
|
283
|
+
raise ImportError(
|
|
284
|
+
'The `gssapi` package must be '
|
|
285
|
+
'installed for Kerberos authentication',
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
ctx = None
|
|
289
|
+
try:
|
|
290
|
+
ctx = gssapi.raw.init_sec_context(
|
|
291
|
+
gssapi.raw.import_name(data, gssapi.raw.NameType.user),
|
|
292
|
+
flags=[0], lifetime=0,
|
|
293
|
+
)
|
|
294
|
+
return ctx.token
|
|
295
|
+
|
|
296
|
+
finally:
|
|
297
|
+
if ctx is not None:
|
|
298
|
+
gssapi.raw.delete_sec_context(ctx.context)
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
from typing import Dict
|
|
2
|
+
from typing import Optional
|
|
2
3
|
|
|
3
4
|
MBLENGTH = {8: 1, 33: 3, 88: 2, 91: 2}
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class Charset:
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
def __init__(self, id: int, name: str, collation: str, is_default: str):
|
|
8
10
|
self.id, self.name, self.collation = id, name, collation
|
|
9
11
|
self.is_default = is_default == 'Yes'
|
|
10
12
|
|
|
11
|
-
def __repr__(self):
|
|
13
|
+
def __repr__(self) -> str:
|
|
12
14
|
return 'Charset(id=%s, name=%r, collation=%r)' % (
|
|
13
15
|
self.id,
|
|
14
16
|
self.name,
|
|
@@ -16,7 +18,7 @@ class Charset:
|
|
|
16
18
|
)
|
|
17
19
|
|
|
18
20
|
@property
|
|
19
|
-
def encoding(self):
|
|
21
|
+
def encoding(self) -> str:
|
|
20
22
|
name = self.name
|
|
21
23
|
if name in ('utf8mb4', 'utf8mb3'):
|
|
22
24
|
return 'utf8'
|
|
@@ -29,40 +31,41 @@ class Charset:
|
|
|
29
31
|
return name
|
|
30
32
|
|
|
31
33
|
@property
|
|
32
|
-
def is_binary(self):
|
|
34
|
+
def is_binary(self) -> bool:
|
|
33
35
|
return self.id == 63
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
class Charsets:
|
|
37
|
-
def __init__(self):
|
|
38
|
-
self._by_id = {}
|
|
39
|
-
self._by_name = {}
|
|
40
39
|
|
|
41
|
-
def
|
|
40
|
+
def __init__(self) -> None:
|
|
41
|
+
self._by_id: Dict[int, Charset] = {}
|
|
42
|
+
self._by_name: Dict[str, Charset] = {}
|
|
43
|
+
|
|
44
|
+
def add(self, c: Charset) -> None:
|
|
42
45
|
self._by_id[c.id] = c
|
|
43
46
|
if c.is_default:
|
|
44
47
|
self._by_name[c.name] = c
|
|
45
48
|
|
|
46
|
-
def by_id(self, id):
|
|
49
|
+
def by_id(self, id: int) -> Charset:
|
|
47
50
|
return self._by_id[id]
|
|
48
51
|
|
|
49
|
-
def by_name(self, name):
|
|
52
|
+
def by_name(self, name: str) -> Optional[Charset]:
|
|
50
53
|
return self._by_name.get(name.lower())
|
|
51
54
|
|
|
52
55
|
|
|
53
56
|
_charsets = Charsets()
|
|
54
|
-
|
|
55
|
-
Generated with:
|
|
56
|
-
|
|
57
|
-
mysql -N -s -e "select id, character_set_name, collation_name, is_default
|
|
58
|
-
from information_schema.collations order by id;" | python -c "import sys
|
|
59
|
-
for l in sys.stdin.readlines():
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
|
|
58
|
+
# Generated with:
|
|
59
|
+
#
|
|
60
|
+
# mysql -N -s -e "select id, character_set_name, collation_name, is_default
|
|
61
|
+
# from information_schema.collations order by id;" | python -c "import sys
|
|
62
|
+
# for l in sys.stdin.readlines():
|
|
63
|
+
# id, name, collation, is_default = l.split(chr(9))
|
|
64
|
+
# print '_charsets.add(Charset(%s, \'%s\', \'%s\', \'%s\'))' \
|
|
65
|
+
# % (id, name, collation, is_default.strip())
|
|
66
|
+
# "
|
|
67
|
+
#
|
|
68
|
+
#
|
|
66
69
|
_charsets.add(Charset(1, 'big5', 'big5_chinese_ci', 'Yes'))
|
|
67
70
|
_charsets.add(Charset(2, 'latin2', 'latin2_czech_cs', ''))
|
|
68
71
|
_charsets.add(Charset(3, 'dec8', 'dec8_swedish_ci', 'Yes'))
|