singlestoredb 1.9.0__cp38-abi3-win_amd64.whl → 1.11.0__cp38-abi3-win_amd64.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_accel.pyd +0 -0
- singlestoredb/__init__.py +1 -1
- singlestoredb/fusion/handler.py +0 -7
- singlestoredb/fusion/handlers/export.py +11 -7
- singlestoredb/fusion/handlers/models.py +250 -0
- singlestoredb/fusion/handlers/utils.py +5 -5
- singlestoredb/magics/__init__.py +34 -0
- singlestoredb/magics/run_personal.py +56 -0
- singlestoredb/magics/run_shared.py +53 -0
- singlestoredb/management/cluster.py +2 -1
- singlestoredb/management/files.py +92 -28
- singlestoredb/management/manager.py +3 -2
- singlestoredb/management/workspace.py +3 -2
- singlestoredb/mysql/connection.py +1 -0
- singlestoredb/utils/events.py +16 -0
- {singlestoredb-1.9.0.dist-info → singlestoredb-1.11.0.dist-info}/METADATA +1 -1
- {singlestoredb-1.9.0.dist-info → singlestoredb-1.11.0.dist-info}/RECORD +21 -17
- {singlestoredb-1.9.0.dist-info → singlestoredb-1.11.0.dist-info}/LICENSE +0 -0
- {singlestoredb-1.9.0.dist-info → singlestoredb-1.11.0.dist-info}/WHEEL +0 -0
- {singlestoredb-1.9.0.dist-info → singlestoredb-1.11.0.dist-info}/entry_points.txt +0 -0
- {singlestoredb-1.9.0.dist-info → singlestoredb-1.11.0.dist-info}/top_level.txt +0 -0
_singlestoredb_accel.pyd
CHANGED
|
Binary file
|
singlestoredb/__init__.py
CHANGED
singlestoredb/fusion/handler.py
CHANGED
|
@@ -641,13 +641,6 @@ class SQLHandler(NodeVisitor):
|
|
|
641
641
|
DummySQLResult
|
|
642
642
|
|
|
643
643
|
"""
|
|
644
|
-
import warnings
|
|
645
|
-
warnings.warn(
|
|
646
|
-
'Fusion SQL is currently a preview feature. '
|
|
647
|
-
'Run `SHOW FUSION COMMANDS` to see all commands.',
|
|
648
|
-
RuntimeWarning,
|
|
649
|
-
)
|
|
650
|
-
|
|
651
644
|
type(self).compile()
|
|
652
645
|
self._handled = set()
|
|
653
646
|
try:
|
|
@@ -55,10 +55,10 @@ class CreateClusterIdentity(SQLHandler):
|
|
|
55
55
|
|
|
56
56
|
CREATE CLUSTER IDENTITY
|
|
57
57
|
CATALOG CONFIG '{
|
|
58
|
-
"
|
|
58
|
+
"catalog_type": "GLUE",
|
|
59
59
|
"table_format": "ICEBERG",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
60
|
+
"catalog_id": "13983498723498",
|
|
61
|
+
"catalog_region": "us-east-1"
|
|
62
62
|
}'
|
|
63
63
|
LINK S3 CONFIG '{
|
|
64
64
|
"region": "us-east-1",
|
|
@@ -78,6 +78,8 @@ class CreateClusterIdentity(SQLHandler):
|
|
|
78
78
|
storage_config = json.loads(params['storage'].get('link_config', '{}') or '{}')
|
|
79
79
|
storage_creds = json.loads(params['storage'].get('link_creds', '{}') or '{}')
|
|
80
80
|
|
|
81
|
+
storage_config['provider'] = 'S3'
|
|
82
|
+
|
|
81
83
|
wsg = get_workspace_group({})
|
|
82
84
|
|
|
83
85
|
if wsg._manager is None:
|
|
@@ -145,12 +147,12 @@ class CreateExport(SQLHandler):
|
|
|
145
147
|
catalog and link configurations. The source table to export is
|
|
146
148
|
named "customer_data"::
|
|
147
149
|
|
|
148
|
-
START EXPORT FROM customer_data
|
|
150
|
+
START EXPORT FROM my_db.customer_data
|
|
149
151
|
CATALOG CONFIG '{
|
|
150
|
-
"
|
|
152
|
+
"catalog_type": "GLUE",
|
|
151
153
|
"table_format": "ICEBERG",
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
+
"catalog_id": "13983498723498",
|
|
155
|
+
"catalog_region": "us-east-1"
|
|
154
156
|
}'
|
|
155
157
|
LINK S3 CONFIG '{
|
|
156
158
|
"region": "us-east-1",
|
|
@@ -177,6 +179,8 @@ class CreateExport(SQLHandler):
|
|
|
177
179
|
storage_config = json.loads(params['storage'].get('link_config', '{}') or '{}')
|
|
178
180
|
storage_creds = json.loads(params['storage'].get('link_creds', '{}') or '{}')
|
|
179
181
|
|
|
182
|
+
storage_config['provider'] = 'S3'
|
|
183
|
+
|
|
180
184
|
wsg = get_workspace_group({})
|
|
181
185
|
|
|
182
186
|
if from_database is None:
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import os
|
|
3
|
+
from typing import Any
|
|
4
|
+
from typing import Dict
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from ..handler import SQLHandler
|
|
8
|
+
from ..result import FusionSQLResult
|
|
9
|
+
from .files import ShowFilesHandler
|
|
10
|
+
from .utils import get_file_space
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ShowModelsHandler(ShowFilesHandler):
|
|
14
|
+
"""
|
|
15
|
+
SHOW MODELS
|
|
16
|
+
[ at_path ] [ <like> ]
|
|
17
|
+
[ <order-by> ]
|
|
18
|
+
[ <limit> ] [ recursive ] [ extended ];
|
|
19
|
+
|
|
20
|
+
# File path to list
|
|
21
|
+
at_path = AT '<path>'
|
|
22
|
+
|
|
23
|
+
# Should the listing be recursive?
|
|
24
|
+
recursive = RECURSIVE
|
|
25
|
+
|
|
26
|
+
# Should extended attributes be shown?
|
|
27
|
+
extended = EXTENDED
|
|
28
|
+
|
|
29
|
+
Description
|
|
30
|
+
-----------
|
|
31
|
+
Displays the list of models in models space.
|
|
32
|
+
|
|
33
|
+
Arguments
|
|
34
|
+
---------
|
|
35
|
+
* ``<path>``: A path in the models space.
|
|
36
|
+
* ``<pattern>``: A pattern similar to SQL LIKE clause.
|
|
37
|
+
Uses ``%`` as the wildcard character.
|
|
38
|
+
|
|
39
|
+
Remarks
|
|
40
|
+
-------
|
|
41
|
+
* Use the ``LIKE`` clause to specify a pattern and return only the
|
|
42
|
+
files that match the specified pattern.
|
|
43
|
+
* The ``LIMIT`` clause limits the number of results to the
|
|
44
|
+
specified number.
|
|
45
|
+
* Use the ``ORDER BY`` clause to sort the results by the specified
|
|
46
|
+
key. By default, the results are sorted in the ascending order.
|
|
47
|
+
* The ``AT PATH`` clause specifies the path in the models
|
|
48
|
+
space to list the files from.
|
|
49
|
+
* To return more information about the files, use the ``EXTENDED``
|
|
50
|
+
clause.
|
|
51
|
+
|
|
52
|
+
Examples
|
|
53
|
+
--------
|
|
54
|
+
The following command lists the models::
|
|
55
|
+
|
|
56
|
+
SHOW MODELS;
|
|
57
|
+
|
|
58
|
+
The following command lists the models with additional information::
|
|
59
|
+
|
|
60
|
+
SHOW MODELS EXTENDED;
|
|
61
|
+
|
|
62
|
+
See Also
|
|
63
|
+
--------
|
|
64
|
+
* ``UPLOAD MODEL model_name FROM path``
|
|
65
|
+
* ``DOWNLOAD MODEL model_name``
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
""" # noqa: E501
|
|
69
|
+
|
|
70
|
+
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
71
|
+
params['file_location'] = 'MODELS'
|
|
72
|
+
|
|
73
|
+
return super().run(params)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
ShowModelsHandler.register(overwrite=True)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class UploadModelHandler(SQLHandler):
|
|
80
|
+
"""
|
|
81
|
+
UPLOAD MODEL model_name
|
|
82
|
+
FROM local_path [ overwrite ];
|
|
83
|
+
|
|
84
|
+
# Model Name
|
|
85
|
+
model_name = '<model-name>'
|
|
86
|
+
|
|
87
|
+
# Path to local file or directory
|
|
88
|
+
local_path = '<local-path>'
|
|
89
|
+
|
|
90
|
+
# Should an existing file be overwritten?
|
|
91
|
+
overwrite = OVERWRITE
|
|
92
|
+
|
|
93
|
+
Description
|
|
94
|
+
-----------
|
|
95
|
+
Uploads a file or folder to models space.
|
|
96
|
+
|
|
97
|
+
Arguments
|
|
98
|
+
---------
|
|
99
|
+
* ``<model-name>``: Model name.
|
|
100
|
+
* ``<local-path>``: The path to the file or folder to upload in the local
|
|
101
|
+
directory.
|
|
102
|
+
|
|
103
|
+
Remarks
|
|
104
|
+
-------
|
|
105
|
+
* If the ``OVERWRITE`` clause is specified, any existing file at the
|
|
106
|
+
specified path in the models space is overwritten.
|
|
107
|
+
|
|
108
|
+
Examples
|
|
109
|
+
--------
|
|
110
|
+
The following command uploads a file to models space and overwrite any
|
|
111
|
+
existing files at the specified path::
|
|
112
|
+
|
|
113
|
+
UPLOAD MODEL model_name
|
|
114
|
+
FROM 'llama3/' OVERWRITE;
|
|
115
|
+
|
|
116
|
+
See Also
|
|
117
|
+
--------
|
|
118
|
+
* ``DOWNLOAD MODEL model_name``
|
|
119
|
+
|
|
120
|
+
""" # noqa: E501
|
|
121
|
+
|
|
122
|
+
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
123
|
+
params['file_location'] = 'MODELS'
|
|
124
|
+
|
|
125
|
+
model_name = params['model_name']
|
|
126
|
+
local_path = params['local_path']
|
|
127
|
+
|
|
128
|
+
file_space = get_file_space(params)
|
|
129
|
+
|
|
130
|
+
if os.path.isdir(local_path):
|
|
131
|
+
file_space.upload_folder(
|
|
132
|
+
local_path=local_path,
|
|
133
|
+
path=os.path.join(model_name, ''),
|
|
134
|
+
overwrite=params['overwrite'],
|
|
135
|
+
)
|
|
136
|
+
else:
|
|
137
|
+
file_space.upload_file(
|
|
138
|
+
local_path=local_path,
|
|
139
|
+
path=os.path.join(model_name, local_path),
|
|
140
|
+
overwrite=params['overwrite'],
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
UploadModelHandler.register(overwrite=True)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class DownloadModelHandler(SQLHandler):
|
|
150
|
+
"""
|
|
151
|
+
DOWNLOAD MODEL model_name
|
|
152
|
+
[ local_path ]
|
|
153
|
+
[ overwrite ];
|
|
154
|
+
|
|
155
|
+
# Model Name
|
|
156
|
+
model_name = '<model-name>'
|
|
157
|
+
|
|
158
|
+
# Path to local directory
|
|
159
|
+
local_path = TO '<local-path>'
|
|
160
|
+
|
|
161
|
+
# Should an existing directory be overwritten?
|
|
162
|
+
overwrite = OVERWRITE
|
|
163
|
+
|
|
164
|
+
Description
|
|
165
|
+
-----------
|
|
166
|
+
Download a model from models space.
|
|
167
|
+
|
|
168
|
+
Arguments
|
|
169
|
+
---------
|
|
170
|
+
* ``<model-name>``: Model name to download in models space.
|
|
171
|
+
* ``<local-path>``: Specifies the path in the local directory
|
|
172
|
+
where the model is downloaded.
|
|
173
|
+
|
|
174
|
+
Remarks
|
|
175
|
+
-------
|
|
176
|
+
* If the ``OVERWRITE`` clause is specified, any existing file or folder at
|
|
177
|
+
the download location is overwritten.
|
|
178
|
+
* If ``<local-path>`` is not specified, the model is downloaded to the current location.
|
|
179
|
+
|
|
180
|
+
Examples
|
|
181
|
+
--------
|
|
182
|
+
The following command displays the contents of the file on the
|
|
183
|
+
standard output::
|
|
184
|
+
|
|
185
|
+
DOWNLOAD MODEL llama3;
|
|
186
|
+
|
|
187
|
+
The following command downloads a model to a specific location and
|
|
188
|
+
overwrites any existing models folder with the name ``local_llama3`` on the local storage::
|
|
189
|
+
|
|
190
|
+
DOWNLOAD MODEL llama3
|
|
191
|
+
TO 'local_llama3' OVERWRITE;
|
|
192
|
+
|
|
193
|
+
See Also
|
|
194
|
+
--------
|
|
195
|
+
* ``UPLOAD MODEL model_name FROM local_path``
|
|
196
|
+
|
|
197
|
+
""" # noqa: E501
|
|
198
|
+
|
|
199
|
+
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
200
|
+
params['file_location'] = 'MODELS'
|
|
201
|
+
|
|
202
|
+
file_space = get_file_space(params)
|
|
203
|
+
|
|
204
|
+
model_name = params['model_name']
|
|
205
|
+
file_space.download_folder(
|
|
206
|
+
path=os.path.join(model_name, ''),
|
|
207
|
+
local_path=params['local_path'] or model_name,
|
|
208
|
+
overwrite=params['overwrite'],
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
DownloadModelHandler.register(overwrite=True)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class DropModelsHandler(SQLHandler):
|
|
218
|
+
"""
|
|
219
|
+
DROP MODEL model_name;
|
|
220
|
+
|
|
221
|
+
# Model Name
|
|
222
|
+
model_name = '<model-name>'
|
|
223
|
+
|
|
224
|
+
Description
|
|
225
|
+
-----------
|
|
226
|
+
Deletes a model from models space.
|
|
227
|
+
|
|
228
|
+
Arguments
|
|
229
|
+
---------
|
|
230
|
+
* ``<model-name>``: Model name to delete in models space.
|
|
231
|
+
|
|
232
|
+
Example
|
|
233
|
+
--------
|
|
234
|
+
The following commands deletes a model from a model space::
|
|
235
|
+
|
|
236
|
+
DROP MODEL llama3;
|
|
237
|
+
|
|
238
|
+
""" # noqa: E501
|
|
239
|
+
|
|
240
|
+
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
241
|
+
params['file_location'] = 'MODELS'
|
|
242
|
+
path = os.path.join(params['model_name'], '')
|
|
243
|
+
|
|
244
|
+
file_space = get_file_space(params)
|
|
245
|
+
file_space.removedirs(path=path)
|
|
246
|
+
|
|
247
|
+
return None
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
DropModelsHandler.register(overwrite=True)
|
|
@@ -11,6 +11,7 @@ from ...management import manage_workspaces
|
|
|
11
11
|
from ...management.files import FilesManager
|
|
12
12
|
from ...management.files import FileSpace
|
|
13
13
|
from ...management.files import manage_files
|
|
14
|
+
from ...management.files import MODELS_SPACE
|
|
14
15
|
from ...management.files import PERSONAL_SPACE
|
|
15
16
|
from ...management.files import SHARED_SPACE
|
|
16
17
|
from ...management.workspace import StarterWorkspace
|
|
@@ -296,15 +297,14 @@ def get_file_space(params: Dict[str, Any]) -> FileSpace:
|
|
|
296
297
|
file_location = params.get('file_location')
|
|
297
298
|
if file_location:
|
|
298
299
|
file_location_lower_case = file_location.lower()
|
|
299
|
-
if (
|
|
300
|
-
file_location_lower_case != PERSONAL_SPACE and
|
|
301
|
-
file_location_lower_case != SHARED_SPACE
|
|
302
|
-
):
|
|
303
|
-
raise ValueError(f'invalid file location: {file_location}')
|
|
304
300
|
|
|
305
301
|
if file_location_lower_case == PERSONAL_SPACE:
|
|
306
302
|
return manager.personal_space
|
|
307
303
|
elif file_location_lower_case == SHARED_SPACE:
|
|
308
304
|
return manager.shared_space
|
|
305
|
+
elif file_location_lower_case == MODELS_SPACE:
|
|
306
|
+
return manager.models_space
|
|
307
|
+
else:
|
|
308
|
+
raise ValueError(f'invalid file location: {file_location}')
|
|
309
309
|
|
|
310
310
|
raise KeyError('no file space was specified')
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from IPython.core.interactiveshell import InteractiveShell
|
|
2
|
+
|
|
3
|
+
from .run_personal import RunPersonalMagic
|
|
4
|
+
from .run_shared import RunSharedMagic
|
|
5
|
+
|
|
6
|
+
# In order to actually use these magics, we must register them with a
|
|
7
|
+
# running IPython.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def load_ipython_extension(ip: InteractiveShell) -> None:
|
|
11
|
+
"""
|
|
12
|
+
Any module file that define a function named `load_ipython_extension`
|
|
13
|
+
can be loaded via `%load_ext module.path` or be configured to be
|
|
14
|
+
autoloaded by IPython at startup time.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# Load jupysql extension
|
|
18
|
+
# This is necessary for jupysql to initialize internal state
|
|
19
|
+
# required to render messages
|
|
20
|
+
assert ip.extension_manager is not None
|
|
21
|
+
result = ip.extension_manager.load_extension('sql')
|
|
22
|
+
if result == 'no load function':
|
|
23
|
+
raise RuntimeError('Could not load sql extension. Is jupysql installed?')
|
|
24
|
+
|
|
25
|
+
# Check if %run magic command is defined
|
|
26
|
+
if ip.find_line_magic('run') is None:
|
|
27
|
+
raise RuntimeError(
|
|
28
|
+
'%run magic command is not defined. '
|
|
29
|
+
'Is it available in your IPython environment?',
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Register run_personal and run_shared
|
|
33
|
+
ip.register_magics(RunPersonalMagic(ip))
|
|
34
|
+
ip.register_magics(RunSharedMagic(ip))
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tempfile
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from IPython.core.interactiveshell import InteractiveShell
|
|
6
|
+
from IPython.core.magic import line_magic
|
|
7
|
+
from IPython.core.magic import Magics
|
|
8
|
+
from IPython.core.magic import magics_class
|
|
9
|
+
from IPython.core.magic import needs_local_scope
|
|
10
|
+
from IPython.core.magic import no_var_expand
|
|
11
|
+
from jinja2 import Template
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@magics_class
|
|
15
|
+
class RunPersonalMagic(Magics):
|
|
16
|
+
def __init__(self, shell: InteractiveShell):
|
|
17
|
+
Magics.__init__(self, shell=shell)
|
|
18
|
+
|
|
19
|
+
@no_var_expand
|
|
20
|
+
@needs_local_scope
|
|
21
|
+
@line_magic('run_personal')
|
|
22
|
+
def run_personal(self, line: str, local_ns: Any = None) -> Any:
|
|
23
|
+
"""
|
|
24
|
+
Downloads a personal file using the %sql magic and then runs it using %run.
|
|
25
|
+
|
|
26
|
+
Examples::
|
|
27
|
+
|
|
28
|
+
# Line usage
|
|
29
|
+
|
|
30
|
+
%run_personal personal_file.ipynb
|
|
31
|
+
|
|
32
|
+
%run_personal {{ sample_notebook_name }}
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
template = Template(line.strip())
|
|
37
|
+
personal_file = template.render(local_ns)
|
|
38
|
+
if not personal_file:
|
|
39
|
+
raise ValueError('No personal file specified.')
|
|
40
|
+
if (personal_file.startswith("'") and personal_file.endswith("'")) or \
|
|
41
|
+
(personal_file.startswith('"') and personal_file.endswith('"')):
|
|
42
|
+
personal_file = personal_file[1:-1]
|
|
43
|
+
if not personal_file:
|
|
44
|
+
raise ValueError('No personal file specified.')
|
|
45
|
+
|
|
46
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
47
|
+
temp_file_path = os.path.join(temp_dir, personal_file)
|
|
48
|
+
sql_command = (
|
|
49
|
+
f"DOWNLOAD PERSONAL FILE '{personal_file}' "
|
|
50
|
+
f"TO '{temp_file_path}'"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Execute the SQL command
|
|
54
|
+
self.shell.run_line_magic('sql', sql_command)
|
|
55
|
+
# Run the downloaded file
|
|
56
|
+
self.shell.run_line_magic('run', f'"{temp_file_path}"')
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tempfile
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from IPython.core.interactiveshell import InteractiveShell
|
|
6
|
+
from IPython.core.magic import line_magic
|
|
7
|
+
from IPython.core.magic import Magics
|
|
8
|
+
from IPython.core.magic import magics_class
|
|
9
|
+
from IPython.core.magic import needs_local_scope
|
|
10
|
+
from IPython.core.magic import no_var_expand
|
|
11
|
+
from jinja2 import Template
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@magics_class
|
|
15
|
+
class RunSharedMagic(Magics):
|
|
16
|
+
def __init__(self, shell: InteractiveShell):
|
|
17
|
+
Magics.__init__(self, shell=shell)
|
|
18
|
+
|
|
19
|
+
@no_var_expand
|
|
20
|
+
@needs_local_scope
|
|
21
|
+
@line_magic('run_shared')
|
|
22
|
+
def run_shared(self, line: str, local_ns: Any = None) -> Any:
|
|
23
|
+
"""
|
|
24
|
+
Downloads a shared file using the %sql magic and then runs it using %run.
|
|
25
|
+
|
|
26
|
+
Examples::
|
|
27
|
+
|
|
28
|
+
# Line usage
|
|
29
|
+
|
|
30
|
+
%run_shared shared_file.ipynb
|
|
31
|
+
|
|
32
|
+
%run_shared {{ sample_notebook_name }}
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
template = Template(line.strip())
|
|
37
|
+
shared_file = template.render(local_ns)
|
|
38
|
+
if not shared_file:
|
|
39
|
+
raise ValueError('No shared file specified.')
|
|
40
|
+
if (shared_file.startswith("'") and shared_file.endswith("'")) or \
|
|
41
|
+
(shared_file.startswith('"') and shared_file.endswith('"')):
|
|
42
|
+
shared_file = shared_file[1:-1]
|
|
43
|
+
if not shared_file:
|
|
44
|
+
raise ValueError('No personal file specified.')
|
|
45
|
+
|
|
46
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
47
|
+
temp_file_path = os.path.join(temp_dir, shared_file)
|
|
48
|
+
sql_command = f"DOWNLOAD SHARED FILE '{shared_file}' TO '{temp_file_path}'"
|
|
49
|
+
|
|
50
|
+
# Execute the SQL command
|
|
51
|
+
self.shell.run_line_magic('sql', sql_command)
|
|
52
|
+
# Run the downloaded file
|
|
53
|
+
self.shell.run_line_magic('run', f'"{temp_file_path}"')
|
|
@@ -333,7 +333,8 @@ class ClusterManager(Manager):
|
|
|
333
333
|
default_version = 'v0beta'
|
|
334
334
|
|
|
335
335
|
#: Base URL if none is specified.
|
|
336
|
-
default_base_url = config.get_option('management.base_url')
|
|
336
|
+
default_base_url = config.get_option('management.base_url') \
|
|
337
|
+
or 'https://api.singlestore.com'
|
|
337
338
|
|
|
338
339
|
#: Object type
|
|
339
340
|
obj_type = 'cluster'
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import datetime
|
|
6
|
+
import glob
|
|
6
7
|
import io
|
|
7
8
|
import os
|
|
8
9
|
import re
|
|
@@ -23,9 +24,9 @@ from .utils import PathLike
|
|
|
23
24
|
from .utils import to_datetime
|
|
24
25
|
from .utils import vars_to_str
|
|
25
26
|
|
|
26
|
-
|
|
27
27
|
PERSONAL_SPACE = 'personal'
|
|
28
28
|
SHARED_SPACE = 'shared'
|
|
29
|
+
MODELS_SPACE = 'models'
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
class FilesObject(object):
|
|
@@ -35,8 +36,8 @@ class FilesObject(object):
|
|
|
35
36
|
It can belong to either a workspace stage or personal/shared space.
|
|
36
37
|
|
|
37
38
|
This object is not instantiated directly. It is used in the results
|
|
38
|
-
of various operations in ``WorkspaceGroup.stage``, ``FilesManager.personal_space
|
|
39
|
-
and ``FilesManager.
|
|
39
|
+
of various operations in ``WorkspaceGroup.stage``, ``FilesManager.personal_space``,
|
|
40
|
+
``FilesManager.shared_space`` and ``FilesManager.models_space`` methods.
|
|
40
41
|
|
|
41
42
|
"""
|
|
42
43
|
|
|
@@ -494,10 +495,11 @@ class FilesManager(Manager):
|
|
|
494
495
|
"""
|
|
495
496
|
|
|
496
497
|
#: Management API version if none is specified.
|
|
497
|
-
default_version = config.get_option('management.version')
|
|
498
|
+
default_version = config.get_option('management.version') or 'v1'
|
|
498
499
|
|
|
499
500
|
#: Base URL if none is specified.
|
|
500
|
-
default_base_url = config.get_option('management.base_url')
|
|
501
|
+
default_base_url = config.get_option('management.base_url') \
|
|
502
|
+
or 'https://api.singlestore.com'
|
|
501
503
|
|
|
502
504
|
#: Object type
|
|
503
505
|
obj_type = 'file'
|
|
@@ -512,6 +514,11 @@ class FilesManager(Manager):
|
|
|
512
514
|
"""Return the shared file space."""
|
|
513
515
|
return FileSpace(SHARED_SPACE, self)
|
|
514
516
|
|
|
517
|
+
@property
|
|
518
|
+
def models_space(self) -> FileSpace:
|
|
519
|
+
"""Return the models file space."""
|
|
520
|
+
return FileSpace(MODELS_SPACE, self)
|
|
521
|
+
|
|
515
522
|
|
|
516
523
|
def manage_files(
|
|
517
524
|
access_token: Optional[str] = None,
|
|
@@ -550,7 +557,8 @@ class FileSpace(FileLocation):
|
|
|
550
557
|
FileSpace manager.
|
|
551
558
|
|
|
552
559
|
This object is not instantiated directly.
|
|
553
|
-
It is returned by ``FilesManager.personal_space
|
|
560
|
+
It is returned by ``FilesManager.personal_space``, ``FilesManager.shared_space``
|
|
561
|
+
or ``FileManger.models_space``.
|
|
554
562
|
|
|
555
563
|
"""
|
|
556
564
|
|
|
@@ -686,10 +694,36 @@ class FileSpace(FileLocation):
|
|
|
686
694
|
ignore all '*.pyc' files in the directory tree
|
|
687
695
|
|
|
688
696
|
"""
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
697
|
+
if not os.path.isdir(local_path):
|
|
698
|
+
raise NotADirectoryError(f'local path is not a directory: {local_path}')
|
|
699
|
+
|
|
700
|
+
if not path:
|
|
701
|
+
path = local_path
|
|
702
|
+
|
|
703
|
+
ignore_files = set()
|
|
704
|
+
if ignore:
|
|
705
|
+
if isinstance(ignore, list):
|
|
706
|
+
for item in ignore:
|
|
707
|
+
ignore_files.update(glob.glob(str(item), recursive=recursive))
|
|
708
|
+
else:
|
|
709
|
+
ignore_files.update(glob.glob(str(ignore), recursive=recursive))
|
|
710
|
+
|
|
711
|
+
for dir_path, _, files in os.walk(str(local_path)):
|
|
712
|
+
for fname in files:
|
|
713
|
+
if ignore_files and fname in ignore_files:
|
|
714
|
+
continue
|
|
715
|
+
|
|
716
|
+
local_file_path = os.path.join(dir_path, fname)
|
|
717
|
+
remote_path = os.path.join(
|
|
718
|
+
path,
|
|
719
|
+
local_file_path.lstrip(str(local_path)),
|
|
720
|
+
)
|
|
721
|
+
self.upload_file(
|
|
722
|
+
local_path=local_file_path,
|
|
723
|
+
path=remote_path,
|
|
724
|
+
overwrite=overwrite,
|
|
725
|
+
)
|
|
726
|
+
return self.info(path)
|
|
693
727
|
|
|
694
728
|
def _upload(
|
|
695
729
|
self,
|
|
@@ -874,15 +908,30 @@ class FileSpace(FileLocation):
|
|
|
874
908
|
return False
|
|
875
909
|
raise
|
|
876
910
|
|
|
877
|
-
def
|
|
911
|
+
def _listdir(self, path: PathLike, *, recursive: bool = False) -> List[str]:
|
|
878
912
|
"""
|
|
879
|
-
Return the names of files in
|
|
913
|
+
Return the names of files in a directory.
|
|
914
|
+
|
|
880
915
|
Parameters
|
|
881
916
|
----------
|
|
917
|
+
path : Path or str
|
|
918
|
+
Path to the folder
|
|
919
|
+
recursive : bool, optional
|
|
920
|
+
Should folders be listed recursively?
|
|
921
|
+
|
|
882
922
|
"""
|
|
883
923
|
res = self._manager._get(
|
|
884
|
-
f'files/fs/{self._location}',
|
|
924
|
+
f'files/fs/{self._location}/{path}',
|
|
885
925
|
).json()
|
|
926
|
+
|
|
927
|
+
if recursive:
|
|
928
|
+
out = []
|
|
929
|
+
for item in res['content'] or []:
|
|
930
|
+
out.append(item['path'])
|
|
931
|
+
if item['type'] == 'directory':
|
|
932
|
+
out.extend(self._listdir(item['path'], recursive=recursive))
|
|
933
|
+
return out
|
|
934
|
+
|
|
886
935
|
return [x['path'] for x in res['content'] or []]
|
|
887
936
|
|
|
888
937
|
def listdir(
|
|
@@ -904,13 +953,17 @@ class FileSpace(FileLocation):
|
|
|
904
953
|
List[str]
|
|
905
954
|
|
|
906
955
|
"""
|
|
907
|
-
|
|
908
|
-
|
|
956
|
+
path = re.sub(r'^(\./|/)+', r'', str(path))
|
|
957
|
+
path = re.sub(r'/+$', r'', path) + '/'
|
|
909
958
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
)
|
|
959
|
+
if not self.is_dir(path):
|
|
960
|
+
raise NotADirectoryError(f'path is not a directory: {path}')
|
|
961
|
+
|
|
962
|
+
out = self._listdir(path, recursive=recursive)
|
|
963
|
+
if path != '/':
|
|
964
|
+
path_n = len(path.split('/')) - 1
|
|
965
|
+
out = ['/'.join(x.split('/')[path_n:]) for x in out]
|
|
966
|
+
return out
|
|
914
967
|
|
|
915
968
|
def download_file(
|
|
916
969
|
self,
|
|
@@ -972,17 +1025,28 @@ class FileSpace(FileLocation):
|
|
|
972
1025
|
Parameters
|
|
973
1026
|
----------
|
|
974
1027
|
path : Path or str
|
|
975
|
-
|
|
1028
|
+
Directory path
|
|
976
1029
|
local_path : Path or str
|
|
977
1030
|
Path to local directory target location
|
|
978
1031
|
overwrite : bool, optional
|
|
979
1032
|
Should an existing directory / files be overwritten if they exist?
|
|
980
1033
|
|
|
981
1034
|
"""
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1035
|
+
|
|
1036
|
+
if local_path is not None and not overwrite and os.path.exists(local_path):
|
|
1037
|
+
raise OSError('target path already exists; use overwrite=True to replace')
|
|
1038
|
+
|
|
1039
|
+
if not self.is_dir(path):
|
|
1040
|
+
raise NotADirectoryError(f'path is not a directory: {path}')
|
|
1041
|
+
|
|
1042
|
+
files = self.listdir(path, recursive=True)
|
|
1043
|
+
for f in files:
|
|
1044
|
+
remote_path = os.path.join(path, f)
|
|
1045
|
+
if self.is_dir(remote_path):
|
|
1046
|
+
continue
|
|
1047
|
+
target = os.path.normpath(os.path.join(local_path, f))
|
|
1048
|
+
os.makedirs(os.path.dirname(target), exist_ok=True)
|
|
1049
|
+
self.download_file(remote_path, target, overwrite=overwrite)
|
|
986
1050
|
|
|
987
1051
|
def remove(self, path: PathLike) -> None:
|
|
988
1052
|
"""
|
|
@@ -1009,10 +1073,10 @@ class FileSpace(FileLocation):
|
|
|
1009
1073
|
Path to the file location
|
|
1010
1074
|
|
|
1011
1075
|
"""
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
)
|
|
1076
|
+
if not self.is_dir(path):
|
|
1077
|
+
raise NotADirectoryError('path is not a directory')
|
|
1078
|
+
|
|
1079
|
+
self._manager._delete(f'files/fs/{self._location}/{path}')
|
|
1016
1080
|
|
|
1017
1081
|
def rmdir(self, path: PathLike) -> None:
|
|
1018
1082
|
"""
|
|
@@ -43,10 +43,11 @@ class Manager(object):
|
|
|
43
43
|
"""SingleStoreDB manager base class."""
|
|
44
44
|
|
|
45
45
|
#: Management API version if none is specified.
|
|
46
|
-
default_version = config.get_option('management.version')
|
|
46
|
+
default_version = config.get_option('management.version') or 'v1'
|
|
47
47
|
|
|
48
48
|
#: Base URL if none is specified.
|
|
49
|
-
default_base_url = config.get_option('management.base_url')
|
|
49
|
+
default_base_url = config.get_option('management.base_url') \
|
|
50
|
+
or 'https://api.singlestore.com'
|
|
50
51
|
|
|
51
52
|
#: Object type
|
|
52
53
|
obj_type = ''
|
|
@@ -1481,10 +1481,11 @@ class WorkspaceManager(Manager):
|
|
|
1481
1481
|
"""
|
|
1482
1482
|
|
|
1483
1483
|
#: Workspace management API version if none is specified.
|
|
1484
|
-
default_version = config.get_option('management.version')
|
|
1484
|
+
default_version = config.get_option('management.version') or 'v1'
|
|
1485
1485
|
|
|
1486
1486
|
#: Base URL if none is specified.
|
|
1487
|
-
default_base_url = config.get_option('management.base_url')
|
|
1487
|
+
default_base_url = config.get_option('management.base_url') \
|
|
1488
|
+
or 'https://api.singlestore.com'
|
|
1488
1489
|
|
|
1489
1490
|
#: Object type
|
|
1490
1491
|
obj_type = 'workspace'
|
singlestoredb/utils/events.py
CHANGED
|
@@ -27,6 +27,22 @@ def subscribe(func: Callable[[Dict[str, Any]], None]) -> None:
|
|
|
27
27
|
_subscribers.add(func)
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
def unsubscribe(func: Callable[[Dict[str, Any]], None]) -> None:
|
|
31
|
+
"""
|
|
32
|
+
Unsubscribe from SingleStore portal events.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
func : Callable
|
|
37
|
+
The function to call when an event is received
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
try:
|
|
41
|
+
_subscribers.remove(func)
|
|
42
|
+
except KeyError:
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
30
46
|
def _event_handler(stream: Any, ident: Any, msg: Dict[str, Any]) -> None:
|
|
31
47
|
"""Handle request on the control stream."""
|
|
32
48
|
if not _subscribers or not isinstance(msg, dict):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
_singlestoredb_accel.pyd,sha256=
|
|
2
|
-
singlestoredb/__init__.py,sha256=
|
|
1
|
+
_singlestoredb_accel.pyd,sha256=YuyyOkJKfNWvP8UqILRk6CXXaqsNBUh9F8Q3b5OKZlc,59392
|
|
2
|
+
singlestoredb/__init__.py,sha256=Hn7bg_Mioi5UgJH2ZaXgIbOsFdb9Xa1wqDeJvmNEYCU,1712
|
|
3
3
|
singlestoredb/auth.py,sha256=RmYiH0Wlc2RXc4pTlRMysxtBI445ggCIwojWKC_eDLE,7844
|
|
4
4
|
singlestoredb/config.py,sha256=n6ludREIoiZDEzSGmv0xouv_zHFnznKNKxSvjzgQ3Lk,12876
|
|
5
5
|
singlestoredb/connection.py,sha256=I3A0VkA_E6pfUNCzIvj0KTb5zn6-htBAPsu6OVXO9-I,47150
|
|
@@ -32,33 +32,37 @@ singlestoredb/functions/ext/rowdat_1.py,sha256=KYj_y5JWm3_B2-QC47HK-CNOrzujBqGUw
|
|
|
32
32
|
singlestoredb/functions/ext/utils.py,sha256=OPMFD-tTCx2Kk9jguQkrTr7e4AgNkt15YsvaT1YSmN8,5480
|
|
33
33
|
singlestoredb/fusion/__init__.py,sha256=FHWtrg6OJFTf6Ye197V5sU6ssryr2h6FBcDIgXP7-H4,367
|
|
34
34
|
singlestoredb/fusion/graphql.py,sha256=SHqsPe4xgawdsTPHEtJGQlybYGWqPrGMmyK-v20RLac,5420
|
|
35
|
-
singlestoredb/fusion/handler.py,sha256=
|
|
35
|
+
singlestoredb/fusion/handler.py,sha256=ohnU0BIoJ9AHrVLlCHI-3E4Icqoocxqip8T-XyYxBWQ,28293
|
|
36
36
|
singlestoredb/fusion/registry.py,sha256=_eT1gd38VPlFKs5f9Pu6lqQyoDQ_ixW5O56QwYLQ89Y,6361
|
|
37
37
|
singlestoredb/fusion/result.py,sha256=EcFY5Qv43ySlQsfl_JB-I3ko7PzVdjuhhoKN96uHSAM,12171
|
|
38
38
|
singlestoredb/fusion/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
singlestoredb/fusion/handlers/export.py,sha256=
|
|
39
|
+
singlestoredb/fusion/handlers/export.py,sha256=Vf0idiFTluEhDpt7ozWSdYwQcOeXz2-J6-91ax8F834,7189
|
|
40
40
|
singlestoredb/fusion/handlers/files.py,sha256=sXO5OFS5QsmwNOnMY3G5xpMPqh4_WkssW3dOB6uI4VQ,19669
|
|
41
41
|
singlestoredb/fusion/handlers/job.py,sha256=3enfxHwERH7T4u0FEwOPN0IL0GtepaCYgEsisiy3Df4,21753
|
|
42
|
+
singlestoredb/fusion/handlers/models.py,sha256=XWaPJQc3GQIOAcjNcxBSGUBJ3xu2qkzQ4ILa40TFQmY,6486
|
|
42
43
|
singlestoredb/fusion/handlers/stage.py,sha256=PP-SSP204lwpmnycSXXSmFPzoN535JVuwglDCbaQ8Lw,14789
|
|
43
|
-
singlestoredb/fusion/handlers/utils.py,sha256=
|
|
44
|
+
singlestoredb/fusion/handlers/utils.py,sha256=qwKGKi7hVlxoROZnAdOgqN3Fw4EHxMynfCdUWKvjFvo,10374
|
|
44
45
|
singlestoredb/fusion/handlers/workspace.py,sha256=NxoEY5xd5lCQmXiim4nhAYCL0agHo1H_rGPpqa31hiw,28397
|
|
45
46
|
singlestoredb/http/__init__.py,sha256=4cEDvLloGc3LSpU-PnIwacyu0n5oIIIE6xk2SPyWD_w,939
|
|
46
47
|
singlestoredb/http/connection.py,sha256=LFUeWx7maS7xhQLqEX3pgvIGoosqyJTovtWwJ1DyDSA,40721
|
|
48
|
+
singlestoredb/magics/__init__.py,sha256=fqCBQ0s8o1CYE4Xo_XiSbkLDzLgMNDgpSkOx66-uDZw,1244
|
|
49
|
+
singlestoredb/magics/run_personal.py,sha256=M11xHi9lWquh_pLSpFI89LGE7PhOPQOGqlSPDl48itE,1900
|
|
50
|
+
singlestoredb/magics/run_shared.py,sha256=rnKpW4d8CJvD6ehK8jG8FlxuqZvjZl4KocPTsk-23O8,1805
|
|
47
51
|
singlestoredb/management/__init__.py,sha256=A66ZnFyX--PsAZ2tvtYUfIUBvVGDBFQsnVc6nGTlX60,277
|
|
48
52
|
singlestoredb/management/billing_usage.py,sha256=0UHFSPCrN0nyeGFFM-HXS3NP8pYmYo2BCCahDEPXvzg,3883
|
|
49
|
-
singlestoredb/management/cluster.py,sha256=
|
|
53
|
+
singlestoredb/management/cluster.py,sha256=auBzNYIXvnI6rq3DNpPgJhwWoT6JsyZRikjpON23Pxg,14867
|
|
50
54
|
singlestoredb/management/export.py,sha256=Ksrb8_sxeqva4NElaGxdPQUWQga2yOEkf0wnw5M-iGc,4302
|
|
51
|
-
singlestoredb/management/files.py,sha256=
|
|
55
|
+
singlestoredb/management/files.py,sha256=ly9Hwe0kVWqws8dvjuoIH0fURi8TadTTZPIFKTxnuWI,31677
|
|
52
56
|
singlestoredb/management/job.py,sha256=Npfe1JLYJlggGBrXLniPKwKUKF1i3alvSY1SFtvauSs,25498
|
|
53
|
-
singlestoredb/management/manager.py,sha256=
|
|
57
|
+
singlestoredb/management/manager.py,sha256=8zU0d7NG83PYMhoAs2JriTqbqh-R2tLX7VZoeZtcogY,9148
|
|
54
58
|
singlestoredb/management/organization.py,sha256=JBsNC4R3boUKdYvyCZyfGoVMC1mD6SPuMI1UssBVoOM,5611
|
|
55
59
|
singlestoredb/management/region.py,sha256=oGoLLS88dE1GmY7GCc0BV7X3f7bWwKQyeXOVBFmK9Pk,1678
|
|
56
60
|
singlestoredb/management/utils.py,sha256=BP-Wb8Sg16GbdLI_DeBz-3ttMklz6ZjYyMOz-sxElz8,13594
|
|
57
|
-
singlestoredb/management/workspace.py,sha256=
|
|
61
|
+
singlestoredb/management/workspace.py,sha256=erII_7SA4vdJkTPBKB6aa88mYujmXTYdNeQZu8KJKLM,58070
|
|
58
62
|
singlestoredb/mysql/__init__.py,sha256=CbpwzNUJPAmKPpIobC0-ugBta_RgHCMq7X7N75QLReY,4669
|
|
59
63
|
singlestoredb/mysql/_auth.py,sha256=YaqqyvAHmeraBv3BM207rNveUVPM-mPnW20ts_ynVWg,8341
|
|
60
64
|
singlestoredb/mysql/charset.py,sha256=mnCdMpvdub1S2mm2PSk2j5JddgsWRjsVLtGx-y9TskE,10724
|
|
61
|
-
singlestoredb/mysql/connection.py,sha256=
|
|
65
|
+
singlestoredb/mysql/connection.py,sha256=lzwf31pFioWCUaMBB_TahB9VsemKMS0l3DrUqO3ZCJE,74764
|
|
62
66
|
singlestoredb/mysql/converters.py,sha256=vebFFm6IrC0WgY-5Eh-esaPizY5cq3vDOUlEKGaYM-U,7771
|
|
63
67
|
singlestoredb/mysql/cursors.py,sha256=pkrP-1t8IhBJRnYpdM7Rdm-332nOq1RYTDJ_yg_q5HI,27682
|
|
64
68
|
singlestoredb/mysql/err.py,sha256=aDbmfq08gWVmfgIea735wSeiFdvYbB5wusgd3qTVq1s,2480
|
|
@@ -128,15 +132,15 @@ singlestoredb/utils/config.py,sha256=WVQ567ZzqzlTGueQH5fEpm5tPZuz8y7qvpEQUB-vPjk
|
|
|
128
132
|
singlestoredb/utils/convert_rows.py,sha256=gkZeZazeJvimCYEQ1FdAC-AmMDwmFGCuP6mi653bpns,1885
|
|
129
133
|
singlestoredb/utils/debug.py,sha256=y7dnJeJGt3U_BWXz9pLt1qNQREpPtumYX_sk1DiqG6Y,362
|
|
130
134
|
singlestoredb/utils/dtypes.py,sha256=_P2fTX2Fgv9Bcl-2L6KivhWgLzyu91sDamxVnmG92Mw,6103
|
|
131
|
-
singlestoredb/utils/events.py,sha256=
|
|
135
|
+
singlestoredb/utils/events.py,sha256=Wpp4Z5kw6f7axGAerMirEhgjcAArboQtMc4aqXzfKIc,1519
|
|
132
136
|
singlestoredb/utils/mogrify.py,sha256=gCcn99-vgsGVjTUV7RHJ6hH4vCNrsGB_Xo4z8kiSPDQ,4201
|
|
133
137
|
singlestoredb/utils/results.py,sha256=wR70LhCqlobniZf52r67zYLBOKjWHQm68NAskdRQND8,15862
|
|
134
138
|
singlestoredb/utils/xdict.py,sha256=-wi1lSPTnY99fhVMBhPKJ8cCsQhNG4GMUfkEBDKYgCw,13321
|
|
135
139
|
sqlx/__init__.py,sha256=4Sdn8HN-Hf8v0_wCt60DCckCg8BvgM3-9r4YVfZycRE,89
|
|
136
140
|
sqlx/magic.py,sha256=6VBlotgjautjev599tHaTYOfcfOA9m6gV_-P1_Qc4lI,3622
|
|
137
|
-
singlestoredb-1.
|
|
138
|
-
singlestoredb-1.
|
|
139
|
-
singlestoredb-1.
|
|
140
|
-
singlestoredb-1.
|
|
141
|
-
singlestoredb-1.
|
|
142
|
-
singlestoredb-1.
|
|
141
|
+
singlestoredb-1.11.0.dist-info/LICENSE,sha256=Bojenzui8aPNjlF3w4ojguDP7sTf8vFV_9Gc2UAG1sg,11542
|
|
142
|
+
singlestoredb-1.11.0.dist-info/METADATA,sha256=8tDiZ6TwCEXStAL2L0YaT2LGv5f3B2XrT-KU6K5XS4A,5711
|
|
143
|
+
singlestoredb-1.11.0.dist-info/WHEEL,sha256=UyMHzmWA0xVqVPKfTiLs2eN3OWWZUl-kQemNbpIqlKo,100
|
|
144
|
+
singlestoredb-1.11.0.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
|
|
145
|
+
singlestoredb-1.11.0.dist-info/top_level.txt,sha256=lA65Vf4qAMfg_s1oG3LEO90h4t1Z-SPDbRqkevI3bSY,40
|
|
146
|
+
singlestoredb-1.11.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|