singlestoredb 0.10.0__cp38-abi3-win_amd64.whl → 0.10.2__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__ = '0.10.0'
16
+ __version__ = '0.10.2'
17
17
 
18
18
  from .alchemy import create_engine
19
19
  from .config import options, get_option, set_option, describe_option
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env python
2
2
  import datetime
3
+ import os
3
4
  from typing import Any
4
5
  from typing import Dict
5
6
  from typing import Optional
@@ -26,15 +27,17 @@ def get_workspace_group(params: Dict[str, Any]) -> WorkspaceGroup:
26
27
  """Find a workspace group matching group_id or group_name."""
27
28
  manager = get_workspace_manager()
28
29
 
29
- if params['group_name']:
30
+ group_name = params.get('group_name') or \
31
+ (params.get('in_group') or {}).get('group_name')
32
+ if group_name:
30
33
  workspace_groups = [
31
34
  x for x in manager.workspace_groups
32
- if x.name == params['group_name']
35
+ if x.name == group_name
33
36
  ]
34
37
 
35
38
  if not workspace_groups:
36
39
  raise KeyError(
37
- 'no workspace group found with name "{}"'.format(params['group_name']),
40
+ 'no workspace group found with name "{}"'.format(group_name),
38
41
  )
39
42
 
40
43
  if len(workspace_groups) > 1:
@@ -45,4 +48,17 @@ def get_workspace_group(params: Dict[str, Any]) -> WorkspaceGroup:
45
48
 
46
49
  return workspace_groups[0]
47
50
 
48
- return manager.get_workspace_group(params['group_id'])
51
+ group_id = params.get('group_id') or \
52
+ (params.get('in_group') or {}).get('group_id')
53
+ if group_id:
54
+ return manager.get_workspace_group(group_id)
55
+
56
+ if os.environ.get('SINGLESTOREDB_WORKSPACE_GROUP'):
57
+ return manager.get_workspace_group(
58
+ os.environ['SINGLESTOREDB_WORKSPACE_GROUP'],
59
+ )
60
+
61
+ if os.environ.get('SINGLESTOREDB_CLUSTER'):
62
+ raise ValueError('clusters and shared workspaces are not currently supported')
63
+
64
+ raise KeyError('no workspace group was specified')
@@ -80,8 +80,10 @@ ShowWorkspaceGroupsHandler.register()
80
80
 
81
81
  class ShowWorkspacesHandler(SQLHandler):
82
82
  """
83
- SHOW WORKSPACES IN GROUP { group_id | group_name }
84
- [ <like> ] [ <extended> ] [ <order-by> ] [ <limit> ];
83
+ SHOW WORKSPACES [ in_group ] [ <like> ] [ <extended> ] [ <order-by> ] [ <limit> ];
84
+
85
+ # Workspace group
86
+ in_group = IN GROUP { group_id | group_name }
85
87
 
86
88
  # ID of group
87
89
  group_id = ID '<group-id>'
@@ -198,10 +200,12 @@ CreateWorkspaceGroupHandler.register()
198
200
 
199
201
  class CreateWorkspaceHandler(SQLHandler):
200
202
  """
201
- CREATE WORKSPACE [ if_not_exists ] workspace_name
202
- IN GROUP { group_id | group_name }
203
+ CREATE WORKSPACE [ if_not_exists ] workspace_name [ in_group ]
203
204
  WITH SIZE size [ wait_on_active ];
204
205
 
206
+ # Create workspace in workspace group
207
+ in_group = IN GROUP { group_id | group_name }
208
+
205
209
  # Only run command if workspace doesn't already exist
206
210
  if_not_exists = IF NOT EXISTS
207
211
 
@@ -264,15 +268,15 @@ class DropWorkspaceGroupHandler(SQLHandler):
264
268
  """
265
269
 
266
270
  def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
267
- manager = get_workspace_manager()
268
-
269
271
  try:
270
- name_or_id = params['group_name'] or params['group_id']
271
- wg = manager.workspace_groups[name_or_id]
272
- wg.terminate(wait_on_terminated=params['wait_on_terminated'])
272
+ workspace_group = get_workspace_group(params)
273
+ if workspace_group.terminated_at is not None:
274
+ raise KeyError
275
+ workspace_group.terminate(wait_on_terminated=params['wait_on_terminated'])
273
276
 
274
277
  except KeyError:
275
278
  if not params['if_exists']:
279
+ name_or_id = params['group_id'] or params['group_name']
276
280
  raise KeyError(f"could not find workspace group '{name_or_id}'")
277
281
 
278
282
  return None
@@ -284,7 +288,10 @@ DropWorkspaceGroupHandler.register()
284
288
  class DropWorkspaceHandler(SQLHandler):
285
289
  """
286
290
  DROP WORKSPACE [ if_exists ] { workspace_id | workspace_name }
287
- IN GROUP { group_id | group_name } [ wait_on_terminated ];
291
+ [ in_group ] [ wait_on_terminated ];
292
+
293
+ # Workspace group
294
+ in_group = IN GROUP { group_id | group_name }
288
295
 
289
296
  # Only drop workspace if it exists
290
297
  if_exists = IF EXISTS
@@ -307,16 +314,15 @@ class DropWorkspaceHandler(SQLHandler):
307
314
  """
308
315
 
309
316
  def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
310
- manager = get_workspace_manager()
311
-
312
317
  try:
318
+ workspace_group = get_workspace_group(params)
313
319
  workspace_name_or_id = params['workspace_name'] or params['workspace_id']
314
- group_name_or_id = params['group_name'] or params['group_id']
315
- wg = manager.workspace_groups[group_name_or_id]
316
- ws = wg.workspaces[workspace_name_or_id]
320
+ ws = workspace_group.workspaces[workspace_name_or_id]
317
321
  ws.terminate(wait_on_terminated=params['wait_on_terminated'])
318
322
 
319
323
  except KeyError:
324
+ group_name_or_id = params['in_group'].get('group_id', None) or \
325
+ params['in_group'].get('group_name', None)
320
326
  if not params['if_exists']:
321
327
  raise KeyError(
322
328
  f"could not find workspace '{workspace_name_or_id}' "
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env python
2
2
  """SingleStoreDB Cluster Management."""
3
3
  import datetime
4
+ import functools
4
5
  import os
5
6
  import re
6
7
  import sys
7
8
  from typing import Any
9
+ from typing import Callable
8
10
  from typing import Dict
9
11
  from typing import List
10
12
  from typing import Optional
@@ -31,37 +33,44 @@ else:
31
33
  PathLikeABC = os.PathLike[str]
32
34
 
33
35
 
34
- def get_token() -> Optional[str]:
35
- """Return the token for the Management API."""
36
- # See if an API key is configured
37
- tok = get_option('management.token')
38
- if tok:
39
- return tok
36
+ class TTLProperty(object):
37
+ """Property with time limit."""
40
38
 
41
- # See if the connection URL contains a JWT
42
- url = get_option('host')
43
- if not url:
44
- return None
39
+ def __init__(self, fget: Callable[[Any], Any], ttl: datetime.timedelta):
40
+ self.fget = fget
41
+ self.ttl = ttl
42
+ self._last_executed = datetime.datetime(2000, 1, 1)
43
+ self._last_result = None
44
+ self.__doc__ = fget.__doc__
45
+ self._name = ''
45
46
 
46
- urlp = urlparse(url, scheme='singlestoredb', allow_fragments=True)
47
- if urlp.password:
48
- try:
49
- jwt.decode(urlp.password, options={'verify_signature': False})
50
- return urlp.password
51
- except jwt.DecodeError:
52
- pass
47
+ def reset(self) -> None:
48
+ self._last_executed = datetime.datetime(2000, 1, 1)
49
+ self._last_result = None
53
50
 
54
- # Didn't find a key anywhere
55
- return None
51
+ def __set_name__(self, owner: Any, name: str) -> None:
52
+ self._name = name
56
53
 
54
+ def __get__(self, obj: Any, objtype: Any = None) -> Any:
55
+ if obj is None:
56
+ return self
57
57
 
58
- def get_organization() -> Optional[str]:
59
- """Return the organization for the current token or environment."""
60
- org = os.environ.get('SINGLESTOREDB_ORGANIZATION')
61
- if org:
62
- return org
58
+ if self._last_result is not None \
59
+ and (datetime.datetime.now() - self._last_executed) < self.ttl:
60
+ return self._last_result
63
61
 
64
- return None
62
+ self._last_result = self.fget(obj)
63
+ self._last_executed = datetime.datetime.now()
64
+
65
+ return self._last_result
66
+
67
+
68
+ def ttl_property(ttl: datetime.timedelta) -> Callable[[Any], Any]:
69
+ """Property with a time-to-live."""
70
+ def wrapper(func: Callable[[Any], Any]) -> Any:
71
+ out = TTLProperty(func, ttl=ttl)
72
+ return functools.wraps(func)(out)
73
+ return wrapper
65
74
 
66
75
 
67
76
  class NamedList(List[T]):
@@ -107,6 +116,39 @@ class NamedList(List[T]):
107
116
  raise
108
117
 
109
118
 
119
+ def get_token() -> Optional[str]:
120
+ """Return the token for the Management API."""
121
+ # See if an API key is configured
122
+ tok = get_option('management.token')
123
+ if tok:
124
+ return tok
125
+
126
+ # See if the connection URL contains a JWT
127
+ url = get_option('host')
128
+ if not url:
129
+ return None
130
+
131
+ urlp = urlparse(url, scheme='singlestoredb', allow_fragments=True)
132
+ if urlp.password:
133
+ try:
134
+ jwt.decode(urlp.password, options={'verify_signature': False})
135
+ return urlp.password
136
+ except jwt.DecodeError:
137
+ pass
138
+
139
+ # Didn't find a key anywhere
140
+ return None
141
+
142
+
143
+ def get_organization() -> Optional[str]:
144
+ """Return the organization for the current token or environment."""
145
+ org = os.environ.get('SINGLESTOREDB_ORGANIZATION')
146
+ if org:
147
+ return org
148
+
149
+ return None
150
+
151
+
110
152
  def enable_http_tracing() -> None:
111
153
  """Enable tracing of HTTP requests."""
112
154
  import logging
@@ -28,6 +28,7 @@ from .utils import NamedList
28
28
  from .utils import PathLike
29
29
  from .utils import snake_to_camel
30
30
  from .utils import to_datetime
31
+ from .utils import ttl_property
31
32
  from .utils import vars_to_str
32
33
 
33
34
 
@@ -1119,7 +1120,7 @@ class WorkspaceGroup(object):
1119
1120
  try:
1120
1121
  region = [x for x in manager.regions if x.id == obj['regionID']][0]
1121
1122
  except IndexError:
1122
- region = None
1123
+ region = Region(obj.get('regionID', '<unknown>'), '<unknown>', '<unknown>')
1123
1124
  out = cls(
1124
1125
  name=obj['name'],
1125
1126
  id=obj['workspaceGroupID'],
@@ -1377,23 +1378,23 @@ class WorkspaceManager(Manager):
1377
1378
  #: Object type
1378
1379
  obj_type = 'workspace'
1379
1380
 
1380
- @ property
1381
+ @property
1381
1382
  def workspace_groups(self) -> NamedList[WorkspaceGroup]:
1382
1383
  """Return a list of available workspace groups."""
1383
1384
  res = self._get('workspaceGroups')
1384
1385
  return NamedList([WorkspaceGroup.from_dict(item, self) for item in res.json()])
1385
1386
 
1386
- @ property
1387
+ @property
1387
1388
  def organizations(self) -> Organizations:
1388
1389
  """Return the organizations."""
1389
1390
  return Organizations(self)
1390
1391
 
1391
- @ property
1392
+ @property
1392
1393
  def billing(self) -> Billing:
1393
1394
  """Return the current billing information."""
1394
1395
  return Billing(self)
1395
1396
 
1396
- @ property
1397
+ @ttl_property(datetime.timedelta(hours=1))
1397
1398
  def regions(self) -> NamedList[Region]:
1398
1399
  """Return a list of available regions."""
1399
1400
  res = self._get('regions')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: singlestoredb
3
- Version: 0.10.0
3
+ Version: 0.10.2
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=Jjd6MaIvCYkXOOEpmyp59vl9GbG1nNhNX0Aw-sIU45Q,45568
2
- singlestoredb/__init__.py,sha256=0NRPHoBellCGLI_aEk1_axilX9YBo7VNdm40gMq7pzY,910
1
+ _singlestoredb_accel.pyd,sha256=8PqjY5PQXqifYCe96103HTZ-dhDT7H-1FTJ5gx84_B8,45568
2
+ singlestoredb/__init__.py,sha256=HVmH2GEx2_Vmnv0hvAFuRaB2yiP3MMmGY6cfiqJ2AFo,910
3
3
  singlestoredb/auth.py,sha256=RmYiH0Wlc2RXc4pTlRMysxtBI445ggCIwojWKC_eDLE,7844
4
4
  singlestoredb/config.py,sha256=Uq7LWKlIwMAJC3_G3j5dUIQVJf2JzbDVtRK6votjuDw,7746
5
5
  singlestoredb/connection.py,sha256=gSKmMN1d_ZSXVTmzfuHK3BXcLyNGiaSi2Vy6z7nymjg,45657
@@ -22,8 +22,8 @@ singlestoredb/fusion/registry.py,sha256=7wELKu09I6N4Oif4lpqAHCy8p_C4COn85hhtoCN5
22
22
  singlestoredb/fusion/result.py,sha256=EcFY5Qv43ySlQsfl_JB-I3ko7PzVdjuhhoKN96uHSAM,12171
23
23
  singlestoredb/fusion/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  singlestoredb/fusion/handlers/stage.py,sha256=VEoHU3q5BX3lCl6pG9jVf-eviqkTZhyzTbO3sRKrMPs,5426
25
- singlestoredb/fusion/handlers/utils.py,sha256=GPDlvm-hU2zwTYczyITHcWwmBc4BwhiVN5JF3SeX2Nw,1476
26
- singlestoredb/fusion/handlers/workspace.py,sha256=Q6rEa0I74V3ujn_JHzUAROz8GxgLMjLWSaeiVpC5ZSs,9770
25
+ singlestoredb/fusion/handlers/utils.py,sha256=H79iVSp0EZKyL3vI8OX8m8cBuFfU-7X9u5CjqnFBmRs,2045
26
+ singlestoredb/fusion/handlers/workspace.py,sha256=b21Vi6zZPi8TyWaI7BcAF4L7KGU6xFNV3EAN7wF1fN4,10045
27
27
  singlestoredb/http/__init__.py,sha256=4cEDvLloGc3LSpU-PnIwacyu0n5oIIIE6xk2SPyWD_w,939
28
28
  singlestoredb/http/connection.py,sha256=vYP10ZsqrhK8RrLS17OVuMkpTsO0VZQu3bxx1FQzUwU,37839
29
29
  singlestoredb/management/__init__.py,sha256=kdKM-wErALWaEHYBLx_raHkJ8xUvUPflhOk8OBJyn58,173
@@ -32,8 +32,8 @@ singlestoredb/management/cluster.py,sha256=0GhpuSt_rcFz5f1hzcRHK911KWFewljlV4GFt
32
32
  singlestoredb/management/manager.py,sha256=-fcuqyM3amze72kNF8JXjQOkWzZrdp9LVDd1ySNWHzI,8813
33
33
  singlestoredb/management/organization.py,sha256=iz5Mde0lat3EYLpwNDbnS0ytI33O6tG6-wYDL4-TGdM,2200
34
34
  singlestoredb/management/region.py,sha256=oGoLLS88dE1GmY7GCc0BV7X3f7bWwKQyeXOVBFmK9Pk,1678
35
- singlestoredb/management/utils.py,sha256=7Lz2JvudiA4uHJ2uM50zeaPtzHUo8hfcCSbEipkhLpo,7227
36
- singlestoredb/management/workspace.py,sha256=HfxnlGPu6Lt0eG_ZPevqjf68IwI0KlS2_8e5qrO-NJo,49129
35
+ singlestoredb/management/utils.py,sha256=-XXP7FnCRWlDcPMo6oOG-_UYI00QQqUpXM4TlILu5Kw,8533
36
+ singlestoredb/management/workspace.py,sha256=Bzkzp2_UymVfyOJDg4SjtPa2MsWAC0UinofR-xMxYN0,49253
37
37
  singlestoredb/mysql/__init__.py,sha256=CbpwzNUJPAmKPpIobC0-ugBta_RgHCMq7X7N75QLReY,4669
38
38
  singlestoredb/mysql/_auth.py,sha256=YaqqyvAHmeraBv3BM207rNveUVPM-mPnW20ts_ynVWg,8341
39
39
  singlestoredb/mysql/charset.py,sha256=mnCdMpvdub1S2mm2PSk2j5JddgsWRjsVLtGx-y9TskE,10724
@@ -98,8 +98,8 @@ singlestoredb/utils/debug.py,sha256=y7dnJeJGt3U_BWXz9pLt1qNQREpPtumYX_sk1DiqG6Y,
98
98
  singlestoredb/utils/mogrify.py,sha256=gCcn99-vgsGVjTUV7RHJ6hH4vCNrsGB_Xo4z8kiSPDQ,4201
99
99
  singlestoredb/utils/results.py,sha256=ely2XVAHHejObjLibS3UcrPOuCO2g5aRtA3PxAMtE-g,5432
100
100
  singlestoredb/utils/xdict.py,sha256=-wi1lSPTnY99fhVMBhPKJ8cCsQhNG4GMUfkEBDKYgCw,13321
101
- singlestoredb-0.10.0.dist-info/LICENSE,sha256=Bojenzui8aPNjlF3w4ojguDP7sTf8vFV_9Gc2UAG1sg,11542
102
- singlestoredb-0.10.0.dist-info/METADATA,sha256=qGhIMkL82Uz22yjAtqT-l5T2eiKqf-bcZt7YnxuWiKo,7794
103
- singlestoredb-0.10.0.dist-info/WHEEL,sha256=NWRSyYmhZPn8_0pCTTzBY74ihO0hpYMm3KvprjPFRJU,100
104
- singlestoredb-0.10.0.dist-info/top_level.txt,sha256=SDtemIXf-Kp-_F2f_S6x0db33cHGOILdAEsIQZe2LZc,35
105
- singlestoredb-0.10.0.dist-info/RECORD,,
101
+ singlestoredb-0.10.2.dist-info/LICENSE,sha256=Bojenzui8aPNjlF3w4ojguDP7sTf8vFV_9Gc2UAG1sg,11542
102
+ singlestoredb-0.10.2.dist-info/METADATA,sha256=WJLPuZGqhIr4yEui0bNp7_4jhJkryaQ4-ZdHRkhkXus,7794
103
+ singlestoredb-0.10.2.dist-info/WHEEL,sha256=NWRSyYmhZPn8_0pCTTzBY74ihO0hpYMm3KvprjPFRJU,100
104
+ singlestoredb-0.10.2.dist-info/top_level.txt,sha256=SDtemIXf-Kp-_F2f_S6x0db33cHGOILdAEsIQZe2LZc,35
105
+ singlestoredb-0.10.2.dist-info/RECORD,,