singlestoredb 1.6.2__py3-none-any.whl → 1.7.0__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 CHANGED
@@ -13,7 +13,7 @@ Examples
13
13
 
14
14
  """
15
15
 
16
- __version__ = '1.6.2'
16
+ __version__ = '1.7.0'
17
17
 
18
18
  from typing import Any
19
19
 
@@ -0,0 +1,2 @@
1
+ from ._cloud_functions import run_function_app # noqa: F401
2
+ from ._dashboards import run_dashboard_app # noqa: F401
@@ -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',
@@ -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,
@@ -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)
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: singlestoredb
3
- Version: 1.6.2
3
+ Version: 1.7.0
4
4
  Summary: Interface to the SingleStoreDB database and workspace management APIs
5
5
  Home-page: https://github.com/singlestore-labs/singlestoredb-python
6
6
  Author: SingleStore
@@ -1,7 +1,7 @@
1
- singlestoredb/__init__.py,sha256=k-LJN-GeJeTKCSDSlMPr4-mM2_k1vOO643_TA8IyyOs,1634
1
+ singlestoredb/__init__.py,sha256=dYAymV6mtmpkfZMMdLoAUjKcpN7Lh7jEOdNeFM3I7jM,1634
2
2
  singlestoredb/auth.py,sha256=u8D9tpKzrqa4ssaHjyZnGDX1q8XBpGtuoOkTkSv7B28,7599
3
- singlestoredb/config.py,sha256=0qU2lweqHIA5yuV0ZN_JS-cZCfLIxIHutgS2YKRuwXw,12067
4
- singlestoredb/connection.py,sha256=Gzq38vG8lXTx5v2WvHkdMg-abSTS6lguTsVMxbYHZmQ,45306
3
+ singlestoredb/config.py,sha256=NtONv4Etpraoy1nenHqRAS08xHJZmho00J95uDjLxQM,12290
4
+ singlestoredb/connection.py,sha256=x5lINBa9kB_GoEEeL2uUZi9G8pNwKuFtA1uqJirR6HI,45352
5
5
  singlestoredb/converters.py,sha256=t1hRMZfccWJs_WyOw-W-Kh87fxsOkpOnKXAeh_Nr-zU,20681
6
6
  singlestoredb/exceptions.py,sha256=HuoA6sMRL5qiCiee-_5ddTGmFbYC9Euk8TYUsh5GvTw,3234
7
7
  singlestoredb/pytest.py,sha256=OyF3BO9mgxenifYhOihnzGk8WzCJ_zN5_mxe8XyFPOc,9074
@@ -9,6 +9,12 @@ singlestoredb/types.py,sha256=FIqO1A7e0Gkk7ITmIysBy-P5S--ItbMSlYvblzqGS30,9969
9
9
  singlestoredb/ai/__init__.py,sha256=7Pubobzx5OlyepNo5DOOxWev1DUW9WFc9P6Qver2xpY,60
10
10
  singlestoredb/ai/embeddings.py,sha256=3jghE4WMf7vy8RobhrMOLvMLnDNGbkPCF48B3fGM38U,746
11
11
  singlestoredb/alchemy/__init__.py,sha256=dXRThusYrs_9GjrhPOw0-vw94in_T8yY9jE7SGCqiQk,2523
12
+ singlestoredb/apps/__init__.py,sha256=uuEH2WZ1ROpmkMBBdz1tSkQSdYR9blXXU2nn7E5P4qQ,118
13
+ singlestoredb/apps/_cloud_functions.py,sha256=qIykvR7TuTXvrNMOi25ejklQx79CpScC3tV49cejJR0,2036
14
+ singlestoredb/apps/_config.py,sha256=kCkuEnW8rXvGvG48o4QY35PSiIm4AyltqJn_bNoHmDI,1056
15
+ singlestoredb/apps/_dashboards.py,sha256=dSyc2NO8ocni6HC_ooruokiJgzEYUBLFg4ybS1FD9mM,1272
16
+ singlestoredb/apps/_process.py,sha256=G37fk6bzIxzhfEqp2aJBk3JCij-T2HFtTd078k5Xq9I,944
17
+ singlestoredb/apps/_uvicorn_util.py,sha256=rEK4nEmq5hbpRgsmK16UVlxe2DyQSq7C5w5WZSp0kX8,962
12
18
  singlestoredb/functions/__init__.py,sha256=WL1LqgMTdnGOse3tQqmD-HH8TdfCPS89GNO7hO0v_aw,41
13
19
  singlestoredb/functions/decorator.py,sha256=H12MUeBw8VOppx6esntaR43ukeIffbnAr716CBpYJ4g,5193
14
20
  singlestoredb/functions/dtypes.py,sha256=a2vevIug8NhiUCFiSOKwRPpdWU69Gn13ZoQ6Aovskhc,31408
@@ -22,16 +28,16 @@ singlestoredb/functions/ext/rowdat_1.py,sha256=JgKRsVSQYczFD6cmo2xLilbNPYpyLL2tP
22
28
  singlestoredb/functions/ext/utils.py,sha256=2-B8YU_Iekv8JcpI-ochs9TIeuyatLaLAH-AyYyUUIg,5311
23
29
  singlestoredb/fusion/__init__.py,sha256=Qo7SuqGw-l-vE8-EI2jhm6hXJkYfOLUKIws9c7LFNX0,356
24
30
  singlestoredb/fusion/graphql.py,sha256=ZA3HcDq5rER-dCEavwTqnF7KM0D2LCYIY7nLQk7lSso,5207
25
- singlestoredb/fusion/handler.py,sha256=6OmDzGUDl98bmQm1XjLIiK_6zi14qIz_XE-PmCBbX-Y,25155
31
+ singlestoredb/fusion/handler.py,sha256=A0fdo2pNtv5E5SPR9ufCIGeKwgiH3V2b4uqA4luYLKM,25384
26
32
  singlestoredb/fusion/registry.py,sha256=jjdRTYZ3ylhy6gAoW5xBj0tkxGFBT-2yLQ0tztTgDIY,6112
27
33
  singlestoredb/fusion/result.py,sha256=Bd3KbRpqWqQcWp_Chd4bzBy8Kfc8nXLS_Pn_GGbPO6o,11772
28
34
  singlestoredb/fusion/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- singlestoredb/fusion/handlers/job.py,sha256=EfAahiQkhrNUbO8jxCPMHtUhntAZOK2xsd1D0dSTMZY,21109
35
+ singlestoredb/fusion/handlers/job.py,sha256=KyAC7A28_7hd9eY1lICfQR7rQrDJ6S8G-Y0PeoLYey8,21285
30
36
  singlestoredb/fusion/handlers/stage.py,sha256=4BSwqcmA4PI3oksTdYaTmQ6bY-AzmL0mZfGnP3U0ldM,13643
31
37
  singlestoredb/fusion/handlers/utils.py,sha256=oYbf13Y3orEkJfHMNnO7B_W1anEdK-0S9vVVkF2pPFk,5109
32
38
  singlestoredb/fusion/handlers/workspace.py,sha256=4xN2TFO4yF7KZB2Fcht7IuvoDdAT6fDfDLjixiHZN8w,27506
33
39
  singlestoredb/http/__init__.py,sha256=A_2ZUCCpvRYIA6YDpPy57wL5R1eZ5SfP6I1To5nfJ2s,912
34
- singlestoredb/http/connection.py,sha256=T2NrL7XV30eQRdrcbP_IY8c3ZOV6Th4KQiuleW4tHUE,39450
40
+ singlestoredb/http/connection.py,sha256=dU0a72pMpyq9l9ADKs5jpB-GAJScBxgd83NOlGreIdc,39473
35
41
  singlestoredb/management/__init__.py,sha256=mhWXjLhp5-t8dhl0vl7SjayKrvJlDb5_hl1YWvDgiMA,237
36
42
  singlestoredb/management/billing_usage.py,sha256=9ighjIpcopgIyJOktBYQ6pahBZmWGHOPyyCW4gu9FGs,3735
37
43
  singlestoredb/management/cluster.py,sha256=i23Smr1PBrDZ8NO_VPd_-bEYkyHvVe9CCRGUjHn_1yQ,14362
@@ -44,7 +50,7 @@ singlestoredb/management/workspace.py,sha256=9oamNIaE5vLZNAlpl5SK-xu27qPqx2Ff3ZI
44
50
  singlestoredb/mysql/__init__.py,sha256=olUTAvkiERhDW41JXQMawkg-i0tvBEkoTkII1tt6lxU,4492
45
51
  singlestoredb/mysql/_auth.py,sha256=AugRitoUwgRIDFuJxuAH4MWIAmckY7Ji2pP6r_Ng9dY,8043
46
52
  singlestoredb/mysql/charset.py,sha256=-FlONDS_oAUF5B3mIgeHBPb_SCt4zHD33arUeBNctU0,10510
47
- singlestoredb/mysql/connection.py,sha256=NpehiK8NTPSc2KH4toLqik3e63XMZSov4s9gOVcBfko,72260
53
+ singlestoredb/mysql/connection.py,sha256=6N7ZG3rNMrpQhv4eixA686NdJ5GBe4HknSpy46qlZ9g,72367
48
54
  singlestoredb/mysql/converters.py,sha256=CVe8SDmjbIAhy1xpQ2N5OKWw6t5eWpw-EU3QTlA0Hh0,7500
49
55
  singlestoredb/mysql/cursors.py,sha256=Eqe7jITRvOo4P_TxIarTumg_2PG1DcCfZ4Uo9IFdDa8,26794
50
56
  singlestoredb/mysql/err.py,sha256=-m5rqXi8yhq6b8SCEJ2h0E5Rudh_15dlAU_WbJ1YrM8,2388
@@ -92,12 +98,12 @@ singlestoredb/tests/test.sql,sha256=dfMehVCQ9wObSVTQKyQi-fRFDZeqRxV4Cj8doBCPEFM,
92
98
  singlestoredb/tests/test2.sql,sha256=D4U2GSlOVeo39U8-RMM4YziJzYFfi4Ztm2YXJVJVAS8,37
93
99
  singlestoredb/tests/test_basics.py,sha256=1__lEF7FmQF4_pFi5R53TtJidtQznmQ592Ci6aDVgrc,46368
94
100
  singlestoredb/tests/test_config.py,sha256=63lyIQ2KrvGE6C9403B_4Mc90mX4tp42ys5Bih2sXrE,11184
95
- singlestoredb/tests/test_connection.py,sha256=ZmhnECusipQAuc6bfZOfMMZULrtxUhnxjxNNSSi6xH4,117697
101
+ singlestoredb/tests/test_connection.py,sha256=fvn-kPdeIMI9RGNz0dNk5ZmTCep1amwWQDHYfPdqO60,119699
96
102
  singlestoredb/tests/test_dbapi.py,sha256=IKq5Hcwx8WikASP8_AB5fo3TXv7ryWPCVGonoly00gI,652
97
103
  singlestoredb/tests/test_exceptions.py,sha256=tfr_8X2w1UmG4nkSBzWGB0C7ehrf1GAVgj6_ODaG-TM,1131
98
104
  singlestoredb/tests/test_ext_func.py,sha256=OWd-CJ1Owhx72nikSWWEF2EQFCJk7vEXZM2Oy9EbYQo,37357
99
105
  singlestoredb/tests/test_ext_func_data.py,sha256=yTADD93nPxX6_rZXXLZaOWEI_yPvYyir9psn5PK9ctU,47695
100
- singlestoredb/tests/test_fusion.py,sha256=W3aRfBeu8HBGm1CIQWFIeWUPBUlfHBCbJy8vejPHdRs,23828
106
+ singlestoredb/tests/test_fusion.py,sha256=W79zv1XcPiiYIYAGtUxLadAMwcJlo2QMmGgU_6-juDk,23965
101
107
  singlestoredb/tests/test_http.py,sha256=RXasTqBWRn__omj0eLFTJYIbZjd0PPdIV2d4Cqz0MC8,8580
102
108
  singlestoredb/tests/test_management.py,sha256=89hKu82qiH1YTbLzKl5FOPEapNB5qo8k06d3fkoYajc,34304
103
109
  singlestoredb/tests/test_plugin.py,sha256=qpO9wmWc62VaijN1sJ97YSYIX7I7Y5C6sY-WzwrutDQ,812
@@ -116,9 +122,9 @@ singlestoredb/utils/events.py,sha256=9IB84T3pKQjs7aaoSSJCw7soNngnhoTDWIC52M51R9Y
116
122
  singlestoredb/utils/mogrify.py,sha256=-a56IF70U6CkfadeaZgfjRSVsAD3PuqRrzPpjZlgbwY,4050
117
123
  singlestoredb/utils/results.py,sha256=bJtaUaDiFq26IsPAKZ2FHGB7csMn94EAxLKrP4HaEEA,15277
118
124
  singlestoredb/utils/xdict.py,sha256=S9HKgrPrnu_6b7iOwa2KrW8CmU1Uqx0BWdEyogFzWbE,12896
119
- singlestoredb-1.6.2.dist-info/LICENSE,sha256=Mlq78idURT-9G026aMYswwwnnrLcgzTLuXeAs5hjDLM,11341
120
- singlestoredb-1.6.2.dist-info/METADATA,sha256=K8wvPnmdbQcQV7pvRJARTF7L_7f9sdYct2SVUyAOoE4,5557
121
- singlestoredb-1.6.2.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
122
- singlestoredb-1.6.2.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
123
- singlestoredb-1.6.2.dist-info/top_level.txt,sha256=eet8bVPNRqiGeY0PrO5ERH2UpamwlrKHEQCffz4dOh8,14
124
- singlestoredb-1.6.2.dist-info/RECORD,,
125
+ singlestoredb-1.7.0.dist-info/LICENSE,sha256=Mlq78idURT-9G026aMYswwwnnrLcgzTLuXeAs5hjDLM,11341
126
+ singlestoredb-1.7.0.dist-info/METADATA,sha256=hut54uSeTSVJL5_3nTXZ5RaHNedRj7C1UU4YM0uOLG8,5557
127
+ singlestoredb-1.7.0.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
128
+ singlestoredb-1.7.0.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
129
+ singlestoredb-1.7.0.dist-info/top_level.txt,sha256=eet8bVPNRqiGeY0PrO5ERH2UpamwlrKHEQCffz4dOh8,14
130
+ singlestoredb-1.7.0.dist-info/RECORD,,