singlestoredb 1.15.4__cp38-abi3-win_amd64.whl → 1.15.6__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 CHANGED
Binary file
singlestoredb/__init__.py CHANGED
@@ -13,7 +13,7 @@ Examples
13
13
 
14
14
  """
15
15
 
16
- __version__ = '1.15.4'
16
+ __version__ = '1.15.6'
17
17
 
18
18
  from typing import Any
19
19
 
@@ -42,6 +42,7 @@ import tempfile
42
42
  import textwrap
43
43
  import threading
44
44
  import time
45
+ import traceback
45
46
  import typing
46
47
  import urllib
47
48
  import uuid
@@ -708,7 +709,21 @@ class Application(object):
708
709
  # Error response start
709
710
  error_response_dict: Dict[str, Any] = dict(
710
711
  type='http.response.start',
711
- status=401,
712
+ status=500,
713
+ headers=[(b'content-type', b'text/plain')],
714
+ )
715
+
716
+ # Timeout response start
717
+ timeout_response_dict: Dict[str, Any] = dict(
718
+ type='http.response.start',
719
+ status=504,
720
+ headers=[(b'content-type', b'text/plain')],
721
+ )
722
+
723
+ # Cancel response start
724
+ cancel_response_dict: Dict[str, Any] = dict(
725
+ type='http.response.start',
726
+ status=503,
712
727
  headers=[(b'content-type', b'text/plain')],
713
728
  )
714
729
 
@@ -1234,11 +1249,11 @@ class Application(object):
1234
1249
  },
1235
1250
  )
1236
1251
  body = (
1237
- '[TimeoutError] Function call timed out after ' +
1252
+ 'TimeoutError: Function call timed out after ' +
1238
1253
  str(func_info['timeout']) +
1239
1254
  ' seconds'
1240
1255
  ).encode('utf-8')
1241
- await send(self.error_response_dict)
1256
+ await send(self.timeout_response_dict)
1242
1257
 
1243
1258
  except asyncio.CancelledError:
1244
1259
  self.logger.exception(
@@ -1249,8 +1264,8 @@ class Application(object):
1249
1264
  'function_name': func_name.decode('utf-8'),
1250
1265
  },
1251
1266
  )
1252
- body = b'[CancelledError] Function call was cancelled'
1253
- await send(self.error_response_dict)
1267
+ body = b'CancelledError: Function call was cancelled'
1268
+ await send(self.cancel_response_dict)
1254
1269
 
1255
1270
  except Exception as e:
1256
1271
  self.logger.exception(
@@ -1262,7 +1277,12 @@ class Application(object):
1262
1277
  'exception_type': type(e).__name__,
1263
1278
  },
1264
1279
  )
1265
- body = f'[{type(e).__name__}] {str(e).strip()}'.encode('utf-8')
1280
+ msg = traceback.format_exc().strip().split(' File ')[-1]
1281
+ if msg.startswith('"/tmp/ipykernel_'):
1282
+ msg = 'Line ' + msg.split(', line ')[-1]
1283
+ else:
1284
+ msg = 'File ' + msg
1285
+ body = msg.encode('utf-8')
1266
1286
  await send(self.error_response_dict)
1267
1287
 
1268
1288
  finally:
@@ -15,7 +15,7 @@ from .utils import get_workspace_manager
15
15
 
16
16
  class UseWorkspaceHandler(SQLHandler):
17
17
  """
18
- USE WORKSPACE workspace [ with_database ];
18
+ USE WORKSPACE workspace [ in_group ] [ with_database ];
19
19
 
20
20
  # Workspace
21
21
  workspace = { workspace_id | workspace_name | current_workspace }
@@ -29,6 +29,15 @@ class UseWorkspaceHandler(SQLHandler):
29
29
  # Current workspace
30
30
  current_workspace = @@CURRENT
31
31
 
32
+ # Workspace group specification
33
+ in_group = IN GROUP { group_id | group_name }
34
+
35
+ # ID of workspace group
36
+ group_id = ID '<group-id>'
37
+
38
+ # Name of workspace group
39
+ group_name = '<group-name>'
40
+
32
41
  # Name of database
33
42
  with_database = WITH DATABASE 'database-name'
34
43
 
@@ -38,13 +47,18 @@ class UseWorkspaceHandler(SQLHandler):
38
47
 
39
48
  Arguments
40
49
  ---------
41
- * ``<workspace-id>``: The ID of the workspace to delete.
42
- * ``<workspace-name>``: The name of the workspace to delete.
50
+ * ``<workspace-id>``: The ID of the workspace to use.
51
+ * ``<workspace-name>``: The name of the workspace to use.
52
+ * ``<group-id>``: The ID of the workspace group to search in.
53
+ * ``<group-name>``: The name of the workspace group to search in.
43
54
 
44
55
  Remarks
45
56
  -------
46
57
  * If you want to specify a database in the current workspace,
47
58
  the workspace name can be specified as ``@@CURRENT``.
59
+ * Use the ``IN GROUP`` clause to specify the ID or name of the workspace
60
+ group where the workspace should be found. If not specified, the current
61
+ workspace group will be used.
48
62
  * Specify the ``WITH DATABASE`` clause to select a default
49
63
  database for the session.
50
64
  * This command only works in a notebook session in the
@@ -57,23 +71,69 @@ class UseWorkspaceHandler(SQLHandler):
57
71
 
58
72
  USE WORKSPACE 'examplews' WITH DATABASE 'dbname';
59
73
 
74
+ The following command sets the workspace to ``examplews`` from a specific
75
+ workspace group::
76
+
77
+ USE WORKSPACE 'examplews' IN GROUP 'my-workspace-group';
78
+
60
79
  """
61
80
  def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
62
81
  from singlestoredb.notebook import portal
82
+
83
+ # Handle current workspace case
63
84
  if params['workspace'].get('current_workspace'):
64
85
  if params.get('with_database'):
65
86
  portal.default_database = params['with_database']
66
- elif params.get('with_database'):
67
- if params['workspace'].get('workspace_name'):
68
- portal.connection = params['workspace']['workspace_name'], \
69
- params['with_database']
87
+ return None
88
+
89
+ # Get workspace name or ID
90
+ workspace_name = params['workspace'].get('workspace_name')
91
+ workspace_id = params['workspace'].get('workspace_id')
92
+
93
+ # If IN GROUP is specified, look up workspace in that group
94
+ if params.get('in_group'):
95
+ workspace_group = get_workspace_group(params)
96
+
97
+ if workspace_name:
98
+ workspace = workspace_group.workspaces[workspace_name]
99
+ elif workspace_id:
100
+ # Find workspace by ID in the specified group
101
+ workspace = next(
102
+ (w for w in workspace_group.workspaces if w.id == workspace_id),
103
+ None,
104
+ )
105
+ if workspace is None:
106
+ raise KeyError(f'no workspace found with ID: {workspace_id}')
107
+
108
+ workspace_id = workspace.id
109
+
110
+ # Set workspace and database
111
+ if params.get('with_database'):
112
+ if params.get('in_group'):
113
+ # Use 3-element tuple: (workspace_group_id, workspace_name_or_id,
114
+ # database)
115
+ portal.connection = ( # type: ignore[assignment]
116
+ workspace_group.id,
117
+ workspace_name or workspace_id,
118
+ params['with_database'],
119
+ )
70
120
  else:
71
- portal.connection = params['workspace']['workspace_id'], \
72
- params['with_database']
73
- elif params['workspace'].get('workspace_name'):
74
- portal.workspace = params['workspace']['workspace_name']
121
+ # Use 2-element tuple: (workspace_name_or_id, database)
122
+ portal.connection = (
123
+ workspace_name or workspace_id,
124
+ params['with_database'],
125
+ )
75
126
  else:
76
- portal.workspace = params['workspace']['workspace_id']
127
+ if params.get('in_group'):
128
+ # Use 2-element tuple: (workspace_group_id, workspace_name_or_id)
129
+ portal.workspace = ( # type: ignore[assignment]
130
+ workspace_group.id,
131
+ workspace_name or workspace_id,
132
+ )
133
+ else:
134
+ # Use string: workspace_name_or_id
135
+ portal.workspace = workspace_name or workspace_id
136
+
77
137
  return None
78
138
 
79
139
 
@@ -460,7 +460,7 @@ class Stage(FileLocation):
460
460
 
461
461
  """
462
462
  res = self._manager._get(
463
- f'stage/{self._deployment_id}/fs/{stage_path}',
463
+ re.sub(r'/+$', r'/', f'stage/{self._deployment_id}/fs/{stage_path}'),
464
464
  ).json()
465
465
  if recursive:
466
466
  out = []
@@ -10,6 +10,7 @@ from typing import Dict
10
10
  from typing import List
11
11
  from typing import Optional
12
12
  from typing import Tuple
13
+ from typing import Union
13
14
 
14
15
  from . import _objects as obj
15
16
  from ..management import workspace as mgr
@@ -167,15 +168,32 @@ class Portal(object):
167
168
  return obj.workspace
168
169
 
169
170
  @workspace.setter
170
- def workspace(self, name_or_id: str) -> None:
171
+ def workspace(self, workspace_spec: Union[str, Tuple[str, str]]) -> None:
171
172
  """Set workspace."""
172
- if re.match(
173
- r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}',
174
- name_or_id, flags=re.I,
175
- ):
176
- w = mgr.get_workspace(name_or_id)
173
+ if isinstance(workspace_spec, tuple):
174
+ # 2-element tuple: (workspace_group_id, workspace_name_or_id)
175
+ workspace_group_id, name_or_id = workspace_spec
176
+ uuid_pattern = (
177
+ r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}'
178
+ )
179
+ if re.match(uuid_pattern, name_or_id, flags=re.I):
180
+ w = mgr.get_workspace(name_or_id)
181
+ else:
182
+ w = mgr.get_workspace_group(workspace_group_id).workspaces[
183
+ name_or_id
184
+ ]
177
185
  else:
178
- w = mgr.get_workspace_group(self.workspace_group_id).workspaces[name_or_id]
186
+ # String: workspace_name_or_id (existing behavior)
187
+ name_or_id = workspace_spec
188
+ uuid_pattern = (
189
+ r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}'
190
+ )
191
+ if re.match(uuid_pattern, name_or_id, flags=re.I):
192
+ w = mgr.get_workspace(name_or_id)
193
+ else:
194
+ w = mgr.get_workspace_group(
195
+ self.workspace_group_id,
196
+ ).workspaces[name_or_id]
179
197
 
180
198
  if w.state and w.state.lower() not in ['active', 'resumed']:
181
199
  raise RuntimeError('workspace is not active')
@@ -196,16 +214,37 @@ class Portal(object):
196
214
  return self.workspace, self.default_database
197
215
 
198
216
  @connection.setter
199
- def connection(self, workspace_and_default_database: Tuple[str, str]) -> None:
217
+ def connection(
218
+ self,
219
+ connection_spec: Union[Tuple[str, str], Tuple[str, str, str]],
220
+ ) -> None:
200
221
  """Set workspace and default database name."""
201
- name_or_id, default_database = workspace_and_default_database
202
- if re.match(
203
- r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}',
204
- name_or_id, flags=re.I,
205
- ):
206
- w = mgr.get_workspace(name_or_id)
222
+ if len(connection_spec) == 3:
223
+ # 3-element tuple: (workspace_group_id, workspace_name_or_id,
224
+ # default_database)
225
+ workspace_group_id, name_or_id, default_database = connection_spec
226
+ uuid_pattern = (
227
+ r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}'
228
+ )
229
+ if re.match(uuid_pattern, name_or_id, flags=re.I):
230
+ w = mgr.get_workspace(name_or_id)
231
+ else:
232
+ w = mgr.get_workspace_group(workspace_group_id).workspaces[
233
+ name_or_id
234
+ ]
207
235
  else:
208
- w = mgr.get_workspace_group(self.workspace_group_id).workspaces[name_or_id]
236
+ # 2-element tuple: (workspace_name_or_id, default_database)
237
+ # existing behavior
238
+ name_or_id, default_database = connection_spec
239
+ uuid_pattern = (
240
+ r'[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}'
241
+ )
242
+ if re.match(uuid_pattern, name_or_id, flags=re.I):
243
+ w = mgr.get_workspace(name_or_id)
244
+ else:
245
+ w = mgr.get_workspace_group(
246
+ self.workspace_group_id,
247
+ ).workspaces[name_or_id]
209
248
 
210
249
  if w.state and w.state.lower() not in ['active', 'resumed']:
211
250
  raise RuntimeError('workspace is not active')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: singlestoredb
3
- Version: 1.15.4
3
+ Version: 1.15.6
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,5 +1,5 @@
1
- _singlestoredb_accel.pyd,sha256=pnSk2OzR1AeUi3XIarCYaeYx3xUGJXV6DRb_3slPiGw,63488
2
- singlestoredb/__init__.py,sha256=EwLbr4GH-i_26n8ywl_sKtFmpNcMQLg6c0prNGYc6hI,2347
1
+ _singlestoredb_accel.pyd,sha256=e736ankVmiZDRPiM5iv1GxqfBbOVri5D1d0FWpZT1xg,63488
2
+ singlestoredb/__init__.py,sha256=A_4RNaBLNmhnDGqQqUsibM95HmI7okgsntzd8CIRiNI,2347
3
3
  singlestoredb/auth.py,sha256=RmYiH0Wlc2RXc4pTlRMysxtBI445ggCIwojWKC_eDLE,7844
4
4
  singlestoredb/config.py,sha256=rS8OmWMaHfMJQTkmSw_qwXR2R0HP80eP4gjzVmXkL2E,14419
5
5
  singlestoredb/connection.py,sha256=I2AP_0l7hNARfXiSuVW953CsGYn_rKbTg_NyWEiGHbY,47542
@@ -48,7 +48,7 @@ singlestoredb/functions/signature.py,sha256=1aSFezUgWSRsGcrBjOVVZyZgw0q356y7IWgM
48
48
  singlestoredb/functions/utils.py,sha256=lZPxdYfHxrSfxGWCoF0YZyakVy2iYlozJ1lPSaPKRlo,11190
49
49
  singlestoredb/functions/ext/__init__.py,sha256=5ppI8IZN_zOwoJFdu_Oq9ipxtyHw9n6OMVAa_s9T_yY,24
50
50
  singlestoredb/functions/ext/arrow.py,sha256=mQhwaMpvCH_dP92WIhP_j-stu272n4UAHsFUOBTgnq0,9436
51
- singlestoredb/functions/ext/asgi.py,sha256=trGgDFrOr3p3GeU12Nehoma5zVlGwMnncHzbaqXI2Q0,73763
51
+ singlestoredb/functions/ext/asgi.py,sha256=JzhuCMHLPTT8ILPt7hmwUndrtvrbPrVNVSSHrj0qg9k,74401
52
52
  singlestoredb/functions/ext/json.py,sha256=j9133xOpyuSqb8smBmi_bPvv6OYCbNfpbLbEicyGqmQ,10522
53
53
  singlestoredb/functions/ext/mmap.py,sha256=0BN9OyEONZ174qdZWe2m3Xykt3-QcxyLYBt2iCG772Q,14123
54
54
  singlestoredb/functions/ext/rowdat_1.py,sha256=UNMMUA8mb6iIRfJV2FsdA20Sw6s-LEdHQ_tC4K4g70Q,21836
@@ -71,7 +71,7 @@ singlestoredb/fusion/handlers/job.py,sha256=3enfxHwERH7T4u0FEwOPN0IL0GtepaCYgEsi
71
71
  singlestoredb/fusion/handlers/models.py,sha256=MglLrl57l7sG2K0MDnmnO1wnocdcbEIWvAJS6W74VgE,6481
72
72
  singlestoredb/fusion/handlers/stage.py,sha256=oNl11GYUUQHmIrWsqaA1X8lokvFxFgN0Cez7h3o8XK8,14774
73
73
  singlestoredb/fusion/handlers/utils.py,sha256=nV2lSzKhv7CzM7I_uIh5kmDV0Ec6VeeKoHczx5pVNcw,11009
74
- singlestoredb/fusion/handlers/workspace.py,sha256=NxoEY5xd5lCQmXiim4nhAYCL0agHo1H_rGPpqa31hiw,28397
74
+ singlestoredb/fusion/handlers/workspace.py,sha256=2m8tBM6XY4nUk64uY7puqecFc7fBNQo2G9nDaO2nlS0,30623
75
75
  singlestoredb/http/__init__.py,sha256=4cEDvLloGc3LSpU-PnIwacyu0n5oIIIE6xk2SPyWD_w,939
76
76
  singlestoredb/http/connection.py,sha256=dDoSUOlKlKYkGUpcLkSV76V72HWQeUM9NohcoLtFop8,40994
77
77
  singlestoredb/magics/__init__.py,sha256=fqCBQ0s8o1CYE4Xo_XiSbkLDzLgMNDgpSkOx66-uDZw,1244
@@ -88,7 +88,7 @@ singlestoredb/management/manager.py,sha256=SR4FvzxYXrn5WruiHG99upZn-8TPgRUSLW8zB
88
88
  singlestoredb/management/organization.py,sha256=viFG8eLVOs-NeoL6zm8nypFRQ-oiRDD2Sk-bL2b6hvw,6095
89
89
  singlestoredb/management/region.py,sha256=4c4z6ETYrSIK3wm2UA4Wr2Td1UgoechN0l1-mqy5bvQ,4283
90
90
  singlestoredb/management/utils.py,sha256=RtFhdIIliQ6aulYs99fgAQ0FxL2LfV-5oPRd9s_bBok,13626
91
- singlestoredb/management/workspace.py,sha256=UYepKm0D4CKsSQ-sPWwPysPT_YcZw2RjJSOZe5Ri_SA,63852
91
+ singlestoredb/management/workspace.py,sha256=nEQDkMkIiwhh_sPlbQ-m0XDYx8bk44X7p5COCN5ja2M,63874
92
92
  singlestoredb/mysql/__init__.py,sha256=CbpwzNUJPAmKPpIobC0-ugBta_RgHCMq7X7N75QLReY,4669
93
93
  singlestoredb/mysql/_auth.py,sha256=YaqqyvAHmeraBv3BM207rNveUVPM-mPnW20ts_ynVWg,8341
94
94
  singlestoredb/mysql/charset.py,sha256=mnCdMpvdub1S2mm2PSk2j5JddgsWRjsVLtGx-y9TskE,10724
@@ -132,7 +132,7 @@ singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py,sha256
132
132
  singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py,sha256=K4EnQCWI_4ShmCv6xHSBDo0B2HVbJvGGYHWygp2bBBk,2920
133
133
  singlestoredb/notebook/__init__.py,sha256=XGvAnkjV_6MjaNv6aqxqDL3ovPApKmNX-2UYH1t0cec,549
134
134
  singlestoredb/notebook/_objects.py,sha256=rDfHGLLwrnuhVMOyNojzrGamykyfOQxZfH2EnFd8vEw,8256
135
- singlestoredb/notebook/_portal.py,sha256=ip3MkJ51syxppUVGRjgqLfR0He4KCZVklFwWT_X270s,10011
135
+ singlestoredb/notebook/_portal.py,sha256=tC8OAw7iose2Ok4dI-bNLVKL2HH3yrijxq5oov6MIdM,11709
136
136
  singlestoredb/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
137
  singlestoredb/server/docker.py,sha256=gdGLEaUkPQJQ8u_1C1OQYr4iXPx1s6CmQmXKOrJFn3g,15095
138
138
  singlestoredb/server/free_tier.py,sha256=rugYt_5jIC6AsE2UhR5hiLQKExyOqSXFyBoIaqG2pIc,8653
@@ -175,9 +175,9 @@ singlestoredb/utils/results.py,sha256=wR70LhCqlobniZf52r67zYLBOKjWHQm68NAskdRQND
175
175
  singlestoredb/utils/xdict.py,sha256=-wi1lSPTnY99fhVMBhPKJ8cCsQhNG4GMUfkEBDKYgCw,13321
176
176
  sqlx/__init__.py,sha256=4Sdn8HN-Hf8v0_wCt60DCckCg8BvgM3-9r4YVfZycRE,89
177
177
  sqlx/magic.py,sha256=6VBlotgjautjev599tHaTYOfcfOA9m6gV_-P1_Qc4lI,3622
178
- singlestoredb-1.15.4.dist-info/LICENSE,sha256=Bojenzui8aPNjlF3w4ojguDP7sTf8vFV_9Gc2UAG1sg,11542
179
- singlestoredb-1.15.4.dist-info/METADATA,sha256=HG1N3v3BlVsk-KFd88OlM_HZGfquzioaWdmkrGXpt-c,5949
180
- singlestoredb-1.15.4.dist-info/WHEEL,sha256=UyMHzmWA0xVqVPKfTiLs2eN3OWWZUl-kQemNbpIqlKo,100
181
- singlestoredb-1.15.4.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
182
- singlestoredb-1.15.4.dist-info/top_level.txt,sha256=lA65Vf4qAMfg_s1oG3LEO90h4t1Z-SPDbRqkevI3bSY,40
183
- singlestoredb-1.15.4.dist-info/RECORD,,
178
+ singlestoredb-1.15.6.dist-info/LICENSE,sha256=Bojenzui8aPNjlF3w4ojguDP7sTf8vFV_9Gc2UAG1sg,11542
179
+ singlestoredb-1.15.6.dist-info/METADATA,sha256=ICEo4jJSocU5Nr1RHn2NF2XGosmGHHPJhFPwX8BUKwQ,5949
180
+ singlestoredb-1.15.6.dist-info/WHEEL,sha256=UyMHzmWA0xVqVPKfTiLs2eN3OWWZUl-kQemNbpIqlKo,100
181
+ singlestoredb-1.15.6.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
182
+ singlestoredb-1.15.6.dist-info/top_level.txt,sha256=lA65Vf4qAMfg_s1oG3LEO90h4t1Z-SPDbRqkevI3bSY,40
183
+ singlestoredb-1.15.6.dist-info/RECORD,,