singlestoredb 1.6.2__cp38-abi3-win32.whl → 1.7.0__cp38-abi3-win32.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/apps/__init__.py +2 -0
- singlestoredb/apps/_cloud_functions.py +70 -0
- singlestoredb/apps/_config.py +33 -0
- singlestoredb/apps/_dashboards.py +51 -0
- singlestoredb/apps/_process.py +32 -0
- singlestoredb/apps/_uvicorn_util.py +32 -0
- singlestoredb/config.py +7 -0
- singlestoredb/connection.py +1 -0
- singlestoredb/fusion/handler.py +7 -0
- singlestoredb/fusion/handlers/job.py +16 -0
- singlestoredb/http/connection.py +2 -3
- singlestoredb/mysql/connection.py +3 -0
- singlestoredb/tests/test_connection.py +33 -0
- singlestoredb/tests/test_fusion.py +4 -0
- {singlestoredb-1.6.2.dist-info → singlestoredb-1.7.0.dist-info}/METADATA +1 -1
- {singlestoredb-1.6.2.dist-info → singlestoredb-1.7.0.dist-info}/RECORD +22 -16
- {singlestoredb-1.6.2.dist-info → singlestoredb-1.7.0.dist-info}/LICENSE +0 -0
- {singlestoredb-1.6.2.dist-info → singlestoredb-1.7.0.dist-info}/WHEEL +0 -0
- {singlestoredb-1.6.2.dist-info → singlestoredb-1.7.0.dist-info}/entry_points.txt +0 -0
- {singlestoredb-1.6.2.dist-info → singlestoredb-1.7.0.dist-info}/top_level.txt +0 -0
_singlestoredb_accel.pyd
CHANGED
|
Binary file
|
singlestoredb/__init__.py
CHANGED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import typing
|
|
3
|
+
import urllib.parse
|
|
4
|
+
|
|
5
|
+
from ._config import AppConfig
|
|
6
|
+
from ._process import kill_process_by_port
|
|
7
|
+
|
|
8
|
+
if typing.TYPE_CHECKING:
|
|
9
|
+
from fastapi import FastAPI
|
|
10
|
+
from ._uvicorn_util import AwaitableUvicornServer
|
|
11
|
+
|
|
12
|
+
# Keep track of currently running server
|
|
13
|
+
_running_server: 'typing.Optional[AwaitableUvicornServer]' = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def run_function_app(
|
|
17
|
+
app: 'FastAPI',
|
|
18
|
+
log_level: str = 'error',
|
|
19
|
+
kill_existing_app_server: bool = True,
|
|
20
|
+
) -> None:
|
|
21
|
+
|
|
22
|
+
global _running_server
|
|
23
|
+
from ._uvicorn_util import AwaitableUvicornServer
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
import uvicorn
|
|
27
|
+
except ImportError:
|
|
28
|
+
raise ImportError('package uvicorn is required to run cloud functions')
|
|
29
|
+
try:
|
|
30
|
+
import fastapi
|
|
31
|
+
except ImportError:
|
|
32
|
+
raise ImportError('package fastapi is required to run cloud functions')
|
|
33
|
+
|
|
34
|
+
if not isinstance(app, fastapi.FastAPI):
|
|
35
|
+
raise TypeError('app is not an instance of FastAPI')
|
|
36
|
+
|
|
37
|
+
app_config = AppConfig.from_env()
|
|
38
|
+
|
|
39
|
+
if kill_existing_app_server:
|
|
40
|
+
# Shutdown the server gracefully if it was started by us.
|
|
41
|
+
# Since the uvicorn server doesn't start a new subprocess
|
|
42
|
+
# killing the process would result in kernel dying.
|
|
43
|
+
if _running_server is not None:
|
|
44
|
+
await _running_server.shutdown()
|
|
45
|
+
_running_server = None
|
|
46
|
+
|
|
47
|
+
# Kill if any other process is occupying the port
|
|
48
|
+
kill_process_by_port(app_config.listen_port)
|
|
49
|
+
|
|
50
|
+
# Add `GET /` route, used for liveness check
|
|
51
|
+
@app.get('/')
|
|
52
|
+
def ping() -> str:
|
|
53
|
+
return 'Success!'
|
|
54
|
+
|
|
55
|
+
base_path = urllib.parse.urlparse(app_config.url).path
|
|
56
|
+
app.root_path = base_path
|
|
57
|
+
|
|
58
|
+
config = uvicorn.Config(
|
|
59
|
+
app,
|
|
60
|
+
host='0.0.0.0',
|
|
61
|
+
port=app_config.listen_port,
|
|
62
|
+
log_level=log_level,
|
|
63
|
+
)
|
|
64
|
+
_running_server = AwaitableUvicornServer(config)
|
|
65
|
+
|
|
66
|
+
asyncio.create_task(_running_server.serve())
|
|
67
|
+
await _running_server.wait_for_startup()
|
|
68
|
+
|
|
69
|
+
if app_config.running_interactively:
|
|
70
|
+
print(f'Cloud function available at {app_config.url}')
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class AppConfig:
|
|
7
|
+
listen_port: int
|
|
8
|
+
url: str
|
|
9
|
+
running_interactively: bool
|
|
10
|
+
|
|
11
|
+
@classmethod
|
|
12
|
+
def from_env(cls) -> 'AppConfig':
|
|
13
|
+
port = os.environ.get('SINGLESTOREDB_APP_LISTEN_PORT')
|
|
14
|
+
if port is None:
|
|
15
|
+
raise RuntimeError(
|
|
16
|
+
'Missing SINGLESTOREDB_APP_LISTEN_PORT environment variable. '
|
|
17
|
+
'Is the code running outside SingleStoreDB notebook environment?',
|
|
18
|
+
)
|
|
19
|
+
url = os.environ.get('SINGLESTOREDB_APP_URL')
|
|
20
|
+
if url is None:
|
|
21
|
+
raise RuntimeError(
|
|
22
|
+
'Missing SINGLESTOREDB_APP_URL environment variable. '
|
|
23
|
+
'Is the code running outside SingleStoreDB notebook environment?',
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
workload_type = os.environ.get('SINGLESTOREDB_WORKLOAD_TYPE')
|
|
27
|
+
running_interactively = workload_type == 'InteractiveNotebook'
|
|
28
|
+
|
|
29
|
+
return cls(
|
|
30
|
+
listen_port=int(port),
|
|
31
|
+
url=url,
|
|
32
|
+
running_interactively=running_interactively,
|
|
33
|
+
)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
import urllib.parse
|
|
3
|
+
|
|
4
|
+
from ._config import AppConfig
|
|
5
|
+
from ._process import kill_process_by_port
|
|
6
|
+
|
|
7
|
+
if typing.TYPE_CHECKING:
|
|
8
|
+
from plotly.graph_objs import Figure
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run_dashboard_app(
|
|
12
|
+
figure: 'Figure',
|
|
13
|
+
debug: bool = False,
|
|
14
|
+
kill_existing_app_server: bool = True,
|
|
15
|
+
) -> None:
|
|
16
|
+
try:
|
|
17
|
+
import dash
|
|
18
|
+
except ImportError:
|
|
19
|
+
raise ImportError('package dash is required to run dashboards')
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
from plotly.graph_objs import Figure
|
|
23
|
+
except ImportError:
|
|
24
|
+
raise ImportError('package dash is required to run dashboards')
|
|
25
|
+
|
|
26
|
+
if not isinstance(figure, Figure):
|
|
27
|
+
raise TypeError('figure is not an instance of plotly Figure')
|
|
28
|
+
|
|
29
|
+
app_config = AppConfig.from_env()
|
|
30
|
+
|
|
31
|
+
if kill_existing_app_server:
|
|
32
|
+
kill_process_by_port(app_config.listen_port)
|
|
33
|
+
|
|
34
|
+
base_path = urllib.parse.urlparse(app_config.url).path
|
|
35
|
+
|
|
36
|
+
app = dash.Dash(requests_pathname_prefix=base_path)
|
|
37
|
+
app.layout = dash.html.Div(
|
|
38
|
+
[
|
|
39
|
+
dash.dcc.Graph(figure=figure),
|
|
40
|
+
],
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
app.run(
|
|
44
|
+
host='0.0.0.0',
|
|
45
|
+
debug=debug,
|
|
46
|
+
port=str(app_config.listen_port),
|
|
47
|
+
jupyter_mode='external',
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if app_config.running_interactively:
|
|
51
|
+
print(f'Dash app available at {app_config.url}')
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import signal
|
|
3
|
+
import typing
|
|
4
|
+
if typing.TYPE_CHECKING:
|
|
5
|
+
from psutil import Process
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def kill_process_by_port(port: int) -> None:
|
|
9
|
+
existing_process = _find_process_by_port(port)
|
|
10
|
+
kernel_pid = os.getpid()
|
|
11
|
+
# Make sure we are not killing current kernel
|
|
12
|
+
if existing_process is not None and kernel_pid != existing_process.pid:
|
|
13
|
+
print(f'Killing process {existing_process.pid} which is using port {port}')
|
|
14
|
+
os.kill(existing_process.pid, signal.SIGKILL)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _find_process_by_port(port: int) -> 'Process | None':
|
|
18
|
+
try:
|
|
19
|
+
import psutil
|
|
20
|
+
except ImportError:
|
|
21
|
+
raise ImportError('package psutil is required')
|
|
22
|
+
|
|
23
|
+
for proc in psutil.process_iter(['pid']):
|
|
24
|
+
try:
|
|
25
|
+
connections = proc.connections()
|
|
26
|
+
for conn in connections:
|
|
27
|
+
if conn.laddr.port == port:
|
|
28
|
+
return proc
|
|
29
|
+
except psutil.AccessDenied:
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
return None
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import socket
|
|
3
|
+
from typing import List
|
|
4
|
+
from typing import Optional
|
|
5
|
+
try:
|
|
6
|
+
import uvicorn
|
|
7
|
+
except ImportError:
|
|
8
|
+
raise ImportError('package uvicorn is required')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AwaitableUvicornServer(uvicorn.Server):
|
|
12
|
+
"""
|
|
13
|
+
Adds `wait_for_startup` method.
|
|
14
|
+
The function (asynchronously) blocks until the server
|
|
15
|
+
starts listening or throws an error.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, config: 'uvicorn.Config') -> None:
|
|
19
|
+
super().__init__(config)
|
|
20
|
+
self._startup_future = asyncio.get_event_loop().create_future()
|
|
21
|
+
|
|
22
|
+
async def startup(self, sockets: Optional[List[socket.socket]] = None) -> None:
|
|
23
|
+
try:
|
|
24
|
+
result = await super().startup(sockets)
|
|
25
|
+
self._startup_future.set_result(True)
|
|
26
|
+
return result
|
|
27
|
+
except Exception as error:
|
|
28
|
+
self._startup_future.set_exception(error)
|
|
29
|
+
raise error
|
|
30
|
+
|
|
31
|
+
async def wait_for_startup(self) -> None:
|
|
32
|
+
await self._startup_future
|
singlestoredb/config.py
CHANGED
|
@@ -103,6 +103,13 @@ register_option(
|
|
|
103
103
|
environ='SINGLESTOREDB_MULTI_STATEMENTS',
|
|
104
104
|
)
|
|
105
105
|
|
|
106
|
+
register_option(
|
|
107
|
+
'client_found_rows', 'bool', check_bool, False,
|
|
108
|
+
'Should affected_rows in OK_PACKET indicate the '
|
|
109
|
+
'number of matched rows instead of changed?',
|
|
110
|
+
environ='SINGLESTOREDB_CLIENT_FOUND_ROWS',
|
|
111
|
+
)
|
|
112
|
+
|
|
106
113
|
register_option(
|
|
107
114
|
'ssl_key', 'str', check_str, None,
|
|
108
115
|
'File containing SSL key',
|
singlestoredb/connection.py
CHANGED
|
@@ -1298,6 +1298,7 @@ def connect(
|
|
|
1298
1298
|
program_name: Optional[str] = None,
|
|
1299
1299
|
conn_attrs: Optional[Dict[str, str]] = None,
|
|
1300
1300
|
multi_statements: Optional[bool] = None,
|
|
1301
|
+
client_found_rows: Optional[bool] = None,
|
|
1301
1302
|
connect_timeout: Optional[int] = None,
|
|
1302
1303
|
nan_as_null: Optional[bool] = None,
|
|
1303
1304
|
inf_as_null: Optional[bool] = None,
|
singlestoredb/fusion/handler.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
import abc
|
|
3
3
|
import functools
|
|
4
|
+
import os
|
|
4
5
|
import re
|
|
5
6
|
import sys
|
|
6
7
|
import textwrap
|
|
@@ -543,6 +544,7 @@ class SQLHandler(NodeVisitor):
|
|
|
543
544
|
|
|
544
545
|
_grammar: str = CORE_GRAMMAR
|
|
545
546
|
_is_compiled: bool = False
|
|
547
|
+
_enabled: bool = True
|
|
546
548
|
|
|
547
549
|
def __init__(self, connection: Connection):
|
|
548
550
|
self.connection = connection
|
|
@@ -581,6 +583,11 @@ class SQLHandler(NodeVisitor):
|
|
|
581
583
|
Overwrite an existing command with the same name?
|
|
582
584
|
|
|
583
585
|
"""
|
|
586
|
+
if not cls._enabled and \
|
|
587
|
+
os.environ.get('SINGLESTOREDB_FUSION_ENABLE_HIDDEN', '0').lower() not in \
|
|
588
|
+
['1', 't', 'true', 'y', 'yes']:
|
|
589
|
+
return
|
|
590
|
+
|
|
584
591
|
from . import registry
|
|
585
592
|
cls.compile()
|
|
586
593
|
registry.register_handler(cls, overwrite=overwrite)
|
|
@@ -122,6 +122,8 @@ class ScheduleJobHandler(SQLHandler):
|
|
|
122
122
|
;
|
|
123
123
|
"""
|
|
124
124
|
|
|
125
|
+
_enabled = False
|
|
126
|
+
|
|
125
127
|
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
126
128
|
res = FusionSQLResult()
|
|
127
129
|
res.add_field('JobID', result.STRING)
|
|
@@ -222,6 +224,8 @@ class RunJobHandler(SQLHandler):
|
|
|
222
224
|
|
|
223
225
|
"""
|
|
224
226
|
|
|
227
|
+
_enabled = False
|
|
228
|
+
|
|
225
229
|
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
226
230
|
res = FusionSQLResult()
|
|
227
231
|
res.add_field('JobID', result.STRING)
|
|
@@ -284,6 +288,8 @@ class WaitOnJobsHandler(SQLHandler):
|
|
|
284
288
|
|
|
285
289
|
"""
|
|
286
290
|
|
|
291
|
+
_enabled = False
|
|
292
|
+
|
|
287
293
|
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
288
294
|
res = FusionSQLResult()
|
|
289
295
|
res.add_field('Success', result.BOOL)
|
|
@@ -353,6 +359,8 @@ class ShowJobsHandler(SQLHandler):
|
|
|
353
359
|
|
|
354
360
|
"""
|
|
355
361
|
|
|
362
|
+
_enabled = False
|
|
363
|
+
|
|
356
364
|
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
357
365
|
res = FusionSQLResult()
|
|
358
366
|
res.add_field('JobID', result.STRING)
|
|
@@ -484,6 +492,8 @@ class ShowJobExecutionsHandler(SQLHandler):
|
|
|
484
492
|
EXTENDED;
|
|
485
493
|
"""
|
|
486
494
|
|
|
495
|
+
_enabled = False
|
|
496
|
+
|
|
487
497
|
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
488
498
|
res = FusionSQLResult()
|
|
489
499
|
res.add_field('ExecutionID', result.STRING)
|
|
@@ -554,6 +564,8 @@ class ShowJobParametersHandler(SQLHandler):
|
|
|
554
564
|
SHOW JOB PARAMETERS FOR 'job1';
|
|
555
565
|
"""
|
|
556
566
|
|
|
567
|
+
_enabled = False
|
|
568
|
+
|
|
557
569
|
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
558
570
|
res = FusionSQLResult()
|
|
559
571
|
res.add_field('Name', result.STRING)
|
|
@@ -594,6 +606,8 @@ class ShowJobRuntimesHandler(SQLHandler):
|
|
|
594
606
|
SHOW JOB RUNTIMES;
|
|
595
607
|
"""
|
|
596
608
|
|
|
609
|
+
_enabled = False
|
|
610
|
+
|
|
597
611
|
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
598
612
|
res = FusionSQLResult()
|
|
599
613
|
res.add_field('Name', result.STRING)
|
|
@@ -639,6 +653,8 @@ class DropJobHandler(SQLHandler):
|
|
|
639
653
|
DROP JOBS 'job1', 'job2';
|
|
640
654
|
"""
|
|
641
655
|
|
|
656
|
+
_enabled = False
|
|
657
|
+
|
|
642
658
|
def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
|
|
643
659
|
res = FusionSQLResult()
|
|
644
660
|
res.add_field('JobID', result.STRING)
|
singlestoredb/http/connection.py
CHANGED
|
@@ -386,6 +386,8 @@ class Cursor(connection.Cursor):
|
|
|
386
386
|
"""
|
|
387
387
|
if self._connection is None:
|
|
388
388
|
raise ProgrammingError(errno=2048, msg='Connection is closed.')
|
|
389
|
+
if 'timeout' not in kwargs:
|
|
390
|
+
kwargs['timeout'] = self._connection.connection_params['connect_timeout']
|
|
389
391
|
return self._connection._post(path, *args, **kwargs)
|
|
390
392
|
|
|
391
393
|
def callproc(
|
|
@@ -1126,9 +1128,6 @@ class Connection(connection.Connection):
|
|
|
1126
1128
|
|
|
1127
1129
|
self._sync_connection(kwargs)
|
|
1128
1130
|
|
|
1129
|
-
if 'timeout' not in kwargs:
|
|
1130
|
-
kwargs['timeout'] = get_option('connect_timeout')
|
|
1131
|
-
|
|
1132
1131
|
return self._sess.post(urljoin(self._url, path), *args, **kwargs)
|
|
1133
1132
|
|
|
1134
1133
|
def close(self) -> None:
|
|
@@ -347,6 +347,7 @@ class Connection(BaseConnection):
|
|
|
347
347
|
driver=None, # internal use
|
|
348
348
|
conn_attrs=None,
|
|
349
349
|
multi_statements=None,
|
|
350
|
+
client_found_rows=None,
|
|
350
351
|
nan_as_null=None,
|
|
351
352
|
inf_as_null=None,
|
|
352
353
|
encoding_errors='strict',
|
|
@@ -380,6 +381,8 @@ class Connection(BaseConnection):
|
|
|
380
381
|
client_flag |= CLIENT.LOCAL_FILES
|
|
381
382
|
if multi_statements:
|
|
382
383
|
client_flag |= CLIENT.MULTI_STATEMENTS
|
|
384
|
+
if client_found_rows:
|
|
385
|
+
client_flag |= CLIENT.FOUND_ROWS
|
|
383
386
|
|
|
384
387
|
if read_default_group and not read_default_file:
|
|
385
388
|
if sys.platform.startswith('win'):
|
|
@@ -2776,6 +2776,39 @@ class TestConnection(unittest.TestCase):
|
|
|
2776
2776
|
self.assertEqual([(2,)], list(cur))
|
|
2777
2777
|
self.assertIsNone(cur.nextset())
|
|
2778
2778
|
|
|
2779
|
+
def test_client_found_rows(self):
|
|
2780
|
+
if self.conn.driver not in ['http', 'https']:
|
|
2781
|
+
with s2.connect(database=type(self).dbname, client_found_rows=False) as conn:
|
|
2782
|
+
with conn.cursor() as cur:
|
|
2783
|
+
tag = str(uuid.uuid4()).replace('-', '_')
|
|
2784
|
+
table_name = f'test_client_found_rows_{tag}'
|
|
2785
|
+
cur.execute(f"CREATE TABLE {table_name} (id BIGINT \
|
|
2786
|
+
PRIMARY KEY, s TEXT DEFAULT 'def');")
|
|
2787
|
+
cur.execute(f'INSERT INTO {table_name} (id) \
|
|
2788
|
+
VALUES (1), (2), (3);')
|
|
2789
|
+
cur.execute(f"UPDATE {table_name} SET s = 'def' \
|
|
2790
|
+
WHERE id = 1;")
|
|
2791
|
+
# UPDATE statement above is not changing any rows,
|
|
2792
|
+
# so affected_rows is 0 if client_found_rows is False (default)
|
|
2793
|
+
self.assertEqual(0, conn.affected_rows())
|
|
2794
|
+
cur.execute(f'DROP TABLE {table_name};')
|
|
2795
|
+
|
|
2796
|
+
with s2.connect(database=type(self).dbname, client_found_rows=True) as conn:
|
|
2797
|
+
with conn.cursor() as cur:
|
|
2798
|
+
tag = str(uuid.uuid4()).replace('-', '_')
|
|
2799
|
+
table_name = f'test_client_found_rows_{tag}'
|
|
2800
|
+
cur.execute(f"CREATE TABLE {table_name} (id BIGINT \
|
|
2801
|
+
PRIMARY KEY, s TEXT DEFAULT 'def');")
|
|
2802
|
+
cur.execute(f'INSERT INTO {table_name} (id) \
|
|
2803
|
+
VALUES (1), (2), (3);')
|
|
2804
|
+
cur.execute(f"UPDATE {table_name} SET s = 'def' \
|
|
2805
|
+
WHERE id = 1;")
|
|
2806
|
+
# UPDATE statement above is not changing any rows,
|
|
2807
|
+
# but affected_rows is 1 as 1 row is subject to update, and
|
|
2808
|
+
# this is what affected_rows return when client_found_rows is True
|
|
2809
|
+
self.assertEqual(1, conn.affected_rows())
|
|
2810
|
+
cur.execute(f'DROP TABLE {table_name};')
|
|
2811
|
+
|
|
2779
2812
|
def test_connect_timeout(self):
|
|
2780
2813
|
with s2.connect(database=type(self).dbname, connect_timeout=8) as conn:
|
|
2781
2814
|
with conn.cursor() as cur:
|
|
@@ -465,6 +465,10 @@ class TestWorkspaceFusion(unittest.TestCase):
|
|
|
465
465
|
pass
|
|
466
466
|
|
|
467
467
|
|
|
468
|
+
@unittest.skipIf(
|
|
469
|
+
os.environ.get('SINGLESTOREDB_FUSION_ENABLE_HIDDEN', '0') == '0',
|
|
470
|
+
'Hidden Fusion commands are not enabled.',
|
|
471
|
+
)
|
|
468
472
|
@pytest.mark.management
|
|
469
473
|
class TestJobsFusion(unittest.TestCase):
|
|
470
474
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
_singlestoredb_accel.pyd,sha256=
|
|
2
|
-
singlestoredb/__init__.py,sha256=
|
|
1
|
+
_singlestoredb_accel.pyd,sha256=RynkDNV_UXfCdGo5PfvktuRnMaaGyfgMd5y4O_kj97U,59904
|
|
2
|
+
singlestoredb/__init__.py,sha256=QfF5_hgd3Qij5ssWBZesWxdych7o-gKPfWx4G1uR-XM,1697
|
|
3
3
|
singlestoredb/auth.py,sha256=RmYiH0Wlc2RXc4pTlRMysxtBI445ggCIwojWKC_eDLE,7844
|
|
4
|
-
singlestoredb/config.py,sha256=
|
|
5
|
-
singlestoredb/connection.py,sha256=
|
|
4
|
+
singlestoredb/config.py,sha256=LlrwKor_23uA9u7jWBYb-IaOKs30CjWIM7o9xCXEPcc,12721
|
|
5
|
+
singlestoredb/connection.py,sha256=QC5YQemwJOhdW_-ZBFpNLE15xFxwI1fB2LuvE1hNi9k,46812
|
|
6
6
|
singlestoredb/converters.py,sha256=7_Of1f3Ow-JUoY1pHFlMPYxvt8llzdk-7X8qk5z2xJM,21631
|
|
7
7
|
singlestoredb/exceptions.py,sha256=WCCJrNSsU-hD-621Jpd6bwmvGftQ7byXkk-XKXlaxpg,3354
|
|
8
8
|
singlestoredb/pytest.py,sha256=TH364xRCN7_QaN0oRQDHixrEcDx_ZBgu3bmY0tvKrYU,9357
|
|
@@ -10,6 +10,12 @@ singlestoredb/types.py,sha256=Lv0BEQl6aSZBiAe0OSI07FEJhcHZ9HX45iT9NU_mxHQ,10334
|
|
|
10
10
|
singlestoredb/ai/__init__.py,sha256=nT048t90xqjaNhz7KJ10KfSVW4RcZRoujyC6po6Nmb8,61
|
|
11
11
|
singlestoredb/ai/embeddings.py,sha256=KVvQY3viyYWXDBobFpj0xqiGRijt36zcHHlPNAfFAxA,770
|
|
12
12
|
singlestoredb/alchemy/__init__.py,sha256=bUmCl1xUn2v36RMbXLIrvgKzZSqx71mp1ReUw9JeVA8,2613
|
|
13
|
+
singlestoredb/apps/__init__.py,sha256=IKQrPKb1d_LQvmr7jXQvgPRrB5Ja_1kGAXwYvdjp6ok,120
|
|
14
|
+
singlestoredb/apps/_cloud_functions.py,sha256=v8PEBz8MXryarE0nfqjwwnZiAO1S659WeITXGjJRcC4,2106
|
|
15
|
+
singlestoredb/apps/_config.py,sha256=DzWlFdW0_wANnE5XddLQeUv8y_zRUvw8KNz7B4l9KnU,1089
|
|
16
|
+
singlestoredb/apps/_dashboards.py,sha256=FOEPjxpiQL9vBaMQBlTfpmA0b4a-cadSdTFrfjdIcY4,1323
|
|
17
|
+
singlestoredb/apps/_process.py,sha256=eMiBO4piaRX1S6zdnMx0X0E4J7E1XrXndnVW0GRYq1Y,976
|
|
18
|
+
singlestoredb/apps/_uvicorn_util.py,sha256=Petkmq5keBPfXZsHBrnZfY3O2rUHvb3Cw6o-BRz5MP0,994
|
|
13
19
|
singlestoredb/functions/__init__.py,sha256=EVxqWOCcXiIX4Yj7rljAYBBoVbTvm2KSuKSkMBDnEeU,42
|
|
14
20
|
singlestoredb/functions/decorator.py,sha256=M103c1JAZfyGFQAU4uJ_J8XGGH3InhcfrNUCoEORNFQ,5335
|
|
15
21
|
singlestoredb/functions/dtypes.py,sha256=5IwMSaSzxtSowxXrm5hZXW1lpNm6QILxiU4mAUEkBO0,32854
|
|
@@ -23,16 +29,16 @@ singlestoredb/functions/ext/rowdat_1.py,sha256=KYj_y5JWm3_B2-QC47HK-CNOrzujBqGUw
|
|
|
23
29
|
singlestoredb/functions/ext/utils.py,sha256=OPMFD-tTCx2Kk9jguQkrTr7e4AgNkt15YsvaT1YSmN8,5480
|
|
24
30
|
singlestoredb/fusion/__init__.py,sha256=FHWtrg6OJFTf6Ye197V5sU6ssryr2h6FBcDIgXP7-H4,367
|
|
25
31
|
singlestoredb/fusion/graphql.py,sha256=SHqsPe4xgawdsTPHEtJGQlybYGWqPrGMmyK-v20RLac,5420
|
|
26
|
-
singlestoredb/fusion/handler.py,sha256=
|
|
32
|
+
singlestoredb/fusion/handler.py,sha256=iILH6aeVWOPbqbkJ8m8CVYV61uJnw8ohYIv8U7bXklM,26231
|
|
27
33
|
singlestoredb/fusion/registry.py,sha256=_eT1gd38VPlFKs5f9Pu6lqQyoDQ_ixW5O56QwYLQ89Y,6361
|
|
28
34
|
singlestoredb/fusion/result.py,sha256=EcFY5Qv43ySlQsfl_JB-I3ko7PzVdjuhhoKN96uHSAM,12171
|
|
29
35
|
singlestoredb/fusion/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
-
singlestoredb/fusion/handlers/job.py,sha256=
|
|
36
|
+
singlestoredb/fusion/handlers/job.py,sha256=TE57c3IDsKb6C5QH4AKAZBMMeZCIaQ4NrZPzXIq0KaI,21959
|
|
31
37
|
singlestoredb/fusion/handlers/stage.py,sha256=uPqawMvchnpyrPYLhB0joTremCURNYKOvYntFc3zTRU,14133
|
|
32
38
|
singlestoredb/fusion/handlers/utils.py,sha256=7xWb_1mJzxW0po9iHVY2ZVnRvHIQgOlKZQZ1zllJBjk,5271
|
|
33
39
|
singlestoredb/fusion/handlers/workspace.py,sha256=NxoEY5xd5lCQmXiim4nhAYCL0agHo1H_rGPpqa31hiw,28397
|
|
34
40
|
singlestoredb/http/__init__.py,sha256=4cEDvLloGc3LSpU-PnIwacyu0n5oIIIE6xk2SPyWD_w,939
|
|
35
|
-
singlestoredb/http/connection.py,sha256=
|
|
41
|
+
singlestoredb/http/connection.py,sha256=LFUeWx7maS7xhQLqEX3pgvIGoosqyJTovtWwJ1DyDSA,40721
|
|
36
42
|
singlestoredb/management/__init__.py,sha256=pQbsOffl-i6zIzR63MCxSjxPY6TNmy7Kg0BCTExt3mk,244
|
|
37
43
|
singlestoredb/management/billing_usage.py,sha256=0UHFSPCrN0nyeGFFM-HXS3NP8pYmYo2BCCahDEPXvzg,3883
|
|
38
44
|
singlestoredb/management/cluster.py,sha256=XfdBuTlrAG-mnW1BFKeoAr4YSE5IVgxLjbuBSpqIySo,14823
|
|
@@ -45,7 +51,7 @@ singlestoredb/management/workspace.py,sha256=BBNa3Af5IaUAwtzHWrNTJXoc8anXJ7FiWH9
|
|
|
45
51
|
singlestoredb/mysql/__init__.py,sha256=CbpwzNUJPAmKPpIobC0-ugBta_RgHCMq7X7N75QLReY,4669
|
|
46
52
|
singlestoredb/mysql/_auth.py,sha256=YaqqyvAHmeraBv3BM207rNveUVPM-mPnW20ts_ynVWg,8341
|
|
47
53
|
singlestoredb/mysql/charset.py,sha256=mnCdMpvdub1S2mm2PSk2j5JddgsWRjsVLtGx-y9TskE,10724
|
|
48
|
-
singlestoredb/mysql/connection.py,sha256=
|
|
54
|
+
singlestoredb/mysql/connection.py,sha256=M7SH2QJbD6IG-E6UOzLuneGtXKmKbvjhvYn18EMnA_A,74379
|
|
49
55
|
singlestoredb/mysql/converters.py,sha256=vebFFm6IrC0WgY-5Eh-esaPizY5cq3vDOUlEKGaYM-U,7771
|
|
50
56
|
singlestoredb/mysql/cursors.py,sha256=pkrP-1t8IhBJRnYpdM7Rdm-332nOq1RYTDJ_yg_q5HI,27682
|
|
51
57
|
singlestoredb/mysql/err.py,sha256=aDbmfq08gWVmfgIea735wSeiFdvYbB5wusgd3qTVq1s,2480
|
|
@@ -93,12 +99,12 @@ singlestoredb/tests/test.sql,sha256=winJzhZ2W52PcQ1j8X_NNIDRBmEa-xMAYrS_hoUtAP8,
|
|
|
93
99
|
singlestoredb/tests/test2.sql,sha256=CEM8_lX189iQU65G3Pod7lig6osfrveQyoDz6HC35YQ,38
|
|
94
100
|
singlestoredb/tests/test_basics.py,sha256=tLiR46qUy8-OHHRSHsQTBp5q9NAwNPR9HvfutI6YgnM,47629
|
|
95
101
|
singlestoredb/tests/test_config.py,sha256=Ad0PDmCnJMOyy9f7WTKiRasSR_3mYRByUlSb7k5ZySg,11502
|
|
96
|
-
singlestoredb/tests/test_connection.py,sha256=
|
|
102
|
+
singlestoredb/tests/test_connection.py,sha256=UmoNo8erkcifEMbHZl83yAaRsyh6HANRdEtY3aViOK8,122792
|
|
97
103
|
singlestoredb/tests/test_dbapi.py,sha256=cNJoTEZvYG7ckcwT7xqlkJX-2TDEYGTDDU1Igucp48k,679
|
|
98
104
|
singlestoredb/tests/test_exceptions.py,sha256=vscMYmdOJr0JmkTAJrNI2w0Q96Nfugjkrt5_lYnw8i0,1176
|
|
99
105
|
singlestoredb/tests/test_ext_func.py,sha256=gQErR-wAN8BqLNG5U4pNbg4qkQEo6Re8Hd9_Ztqo1RM,38550
|
|
100
106
|
singlestoredb/tests/test_ext_func_data.py,sha256=9kn8BWmCjkbnP6hSbFhmhcdW4OmVT-GSvBTIzFBLEys,48796
|
|
101
|
-
singlestoredb/tests/test_fusion.py,sha256=
|
|
107
|
+
singlestoredb/tests/test_fusion.py,sha256=Qab2TTVwUPo7NPso6nIQgDkR6hHtDLp5j1gO7X4bDsk,24685
|
|
102
108
|
singlestoredb/tests/test_http.py,sha256=7hwXe61hlUes3nji0MTTZweo94tJAlJ-vA5ct9geXFQ,8868
|
|
103
109
|
singlestoredb/tests/test_management.py,sha256=B4NkK7J0luuS7T-7OR5qzu-v8gkViIiXie-58bHQIDQ,35334
|
|
104
110
|
singlestoredb/tests/test_plugin.py,sha256=P1nXLnTafaHkHN-6bVbGryxTu7OWJPU9SYFZ_WQUwq8,845
|
|
@@ -117,9 +123,9 @@ singlestoredb/utils/events.py,sha256=rC9cHAetua_E1f-EiFkFM-gJzQSQIH5Uk-4sspC3KjI
|
|
|
117
123
|
singlestoredb/utils/mogrify.py,sha256=gCcn99-vgsGVjTUV7RHJ6hH4vCNrsGB_Xo4z8kiSPDQ,4201
|
|
118
124
|
singlestoredb/utils/results.py,sha256=wR70LhCqlobniZf52r67zYLBOKjWHQm68NAskdRQND8,15862
|
|
119
125
|
singlestoredb/utils/xdict.py,sha256=-wi1lSPTnY99fhVMBhPKJ8cCsQhNG4GMUfkEBDKYgCw,13321
|
|
120
|
-
singlestoredb-1.
|
|
121
|
-
singlestoredb-1.
|
|
122
|
-
singlestoredb-1.
|
|
123
|
-
singlestoredb-1.
|
|
124
|
-
singlestoredb-1.
|
|
125
|
-
singlestoredb-1.
|
|
126
|
+
singlestoredb-1.7.0.dist-info/LICENSE,sha256=Bojenzui8aPNjlF3w4ojguDP7sTf8vFV_9Gc2UAG1sg,11542
|
|
127
|
+
singlestoredb-1.7.0.dist-info/METADATA,sha256=dx6R3uQafE_V3NoNKsT5mJCqTo1jrF6NdTdBqZ0rgY4,5710
|
|
128
|
+
singlestoredb-1.7.0.dist-info/WHEEL,sha256=c4k7z5HB0t-y0nBCv6KyJ6KCjn8SEGPddD0lhaPtU3E,96
|
|
129
|
+
singlestoredb-1.7.0.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
|
|
130
|
+
singlestoredb-1.7.0.dist-info/top_level.txt,sha256=SDtemIXf-Kp-_F2f_S6x0db33cHGOILdAEsIQZe2LZc,35
|
|
131
|
+
singlestoredb-1.7.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|