singlestoredb 1.4.1__cp38-abi3-macosx_10_9_universal2.whl → 1.4.3__cp38-abi3-macosx_10_9_universal2.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.

Binary file
singlestoredb/__init__.py CHANGED
@@ -13,7 +13,7 @@ Examples
13
13
 
14
14
  """
15
15
 
16
- __version__ = '1.4.1'
16
+ __version__ = '1.4.3'
17
17
 
18
18
  from typing import Any
19
19
 
@@ -28,8 +28,23 @@ CORE_GRAMMAR = r'''
28
28
  eq = ws* "=" ws*
29
29
  open_paren = ws* "(" ws*
30
30
  close_paren = ws* ")" ws*
31
+ open_repeats = ws* ~r"[\(\[\{]" ws*
32
+ close_repeats = ws* ~r"[\)\]\}]" ws*
31
33
  select = ~r"SELECT"i ws+ ~r".+" ws*
32
- '''
34
+
35
+ json = ws* json_object ws*
36
+ json_object = ~r"{\s*" json_members? ~r"\s*}"
37
+ json_members = json_mapping (~r"\s*,\s*" json_mapping)*
38
+ json_mapping = json_string ~r"\s*:\s*" json_value
39
+ json_array = ~r"\[\s*" json_items? ~r"\s*\]"
40
+ json_items = json_value (~r"\s*,\s*" json_value)*
41
+ json_value = json_object / json_array / json_string / json_true_val / json_false_val / json_null_val / json_number
42
+ json_true_val = "true"
43
+ json_false_val = "false"
44
+ json_null_val = "null"
45
+ json_string = ~r"\"[ !#-\[\]-\U0010ffff]*(?:\\(?:[\"\\/bfnrt]|u[0-9A-Fa-f]{4})[ !#-\[\]-\U0010ffff]*)*\""
46
+ json_number = ~r"-?(0|[1-9][0-9]*)(\.\d*)?([eE][-+]?\d+)?"
47
+ ''' # noqa: E501
33
48
 
34
49
  BUILTINS = {
35
50
  '<order-by>': r'''
@@ -47,6 +62,7 @@ BUILTINS = {
47
62
  ''',
48
63
  '<integer>': '',
49
64
  '<number>': '',
65
+ '<json>': '',
50
66
  }
51
67
 
52
68
  BUILTIN_DEFAULTS = { # type: ignore
@@ -54,9 +70,36 @@ BUILTIN_DEFAULTS = { # type: ignore
54
70
  'like': None,
55
71
  'extended': False,
56
72
  'limit': None,
73
+ 'json': {},
74
+ }
75
+
76
+ _json_unesc_re = re.compile(r'\\(["/\\bfnrt]|u[0-9A-Fa-f])')
77
+ _json_unesc_map = {
78
+ '"': '"',
79
+ '/': '/',
80
+ '\\': '\\',
81
+ 'b': '\b',
82
+ 'f': '\f',
83
+ 'n': '\n',
84
+ 'r': '\r',
85
+ 't': '\t',
57
86
  }
58
87
 
59
88
 
89
+ def _json_unescape(m: Any) -> str:
90
+ c = m.group(1)
91
+ if c[0] == 'u':
92
+ return chr(int(c[1:], 16))
93
+ c2 = _json_unesc_map.get(c)
94
+ if not c2:
95
+ raise ValueError(f'invalid escape sequence: {m.group(0)}')
96
+ return c2
97
+
98
+
99
+ def json_unescape(s: str) -> str:
100
+ return _json_unesc_re.sub(_json_unescape, s[1:-1])
101
+
102
+
60
103
  def get_keywords(grammar: str) -> Tuple[str, ...]:
61
104
  """Return all all-caps words from the beginning of the line."""
62
105
  m = re.match(r'^\s*((?:[A-Z0-9_]+)(\s+|$|;))+', grammar)
@@ -89,7 +132,7 @@ def process_alternates(m: Any) -> str:
89
132
  def process_repeats(m: Any) -> str:
90
133
  """Add repeated patterns."""
91
134
  sql = m.group(1).strip()
92
- return f'open_paren? {sql} ws* ( comma {sql} ws* )* close_paren?'
135
+ return f'open_repeats? {sql} ws* ( comma {sql} ws* )* close_repeats?'
93
136
 
94
137
 
95
138
  def lower_and_regex(m: Any) -> str:
@@ -639,6 +682,14 @@ class SQLHandler(NodeVisitor):
639
682
  """Close parenthesis."""
640
683
  return
641
684
 
685
+ def visit_open_repeats(self, node: Node, visited_children: Iterable[Any]) -> Any:
686
+ """Open repeat grouping."""
687
+ return
688
+
689
+ def visit_close_repeats(self, node: Node, visited_children: Iterable[Any]) -> Any:
690
+ """Close repeat grouping."""
691
+ return
692
+
642
693
  def visit_init(self, node: Node, visited_children: Iterable[Any]) -> Any:
643
694
  """Entry point of the grammar."""
644
695
  _, out, *_ = visited_children
@@ -662,6 +713,57 @@ class SQLHandler(NodeVisitor):
662
713
  ascending.append(value[1].upper().startswith('A'))
663
714
  return {'order_by': {'by': by, 'ascending': ascending}}
664
715
 
716
+ def _delimited(self, node: Node, children: Iterable[Any]) -> Any:
717
+ children = list(children)
718
+ items = [children[0]]
719
+ items.extend(item for _, item in children[1])
720
+ return items
721
+
722
+ def _atomic(self, node: Node, children: Iterable[Any]) -> Any:
723
+ return list(children)[0]
724
+
725
+ # visitors
726
+ visit_json_value = _atomic
727
+ visit_json_members = visit_json_items = _delimited
728
+
729
+ def visit_json_object(self, node: Node, children: Iterable[Any]) -> Any:
730
+ _, members, _ = children
731
+ if isinstance(members, list):
732
+ members = members[0]
733
+ else:
734
+ members = []
735
+ members = [x for x in members if x != '']
736
+ return dict(members)
737
+
738
+ def visit_json_array(self, node: Node, children: Iterable[Any]) -> Any:
739
+ _, values, _ = children
740
+ if isinstance(values, list):
741
+ values = values[0]
742
+ else:
743
+ values = []
744
+ return values
745
+
746
+ def visit_json_mapping(self, node: Node, children: Iterable[Any]) -> Any:
747
+ key, _, value = children
748
+ return key, value
749
+
750
+ def visit_json_string(self, node: Node, children: Iterable[Any]) -> Any:
751
+ return json_unescape(node.text)
752
+
753
+ def visit_json_number(self, node: Node, children: Iterable[Any]) -> Any:
754
+ if '.' in node.text:
755
+ return float(node.text)
756
+ return int(node.text)
757
+
758
+ def visit_json_true_val(self, node: Node, children: Iterable[Any]) -> Any:
759
+ return True
760
+
761
+ def visit_json_false_val(self, node: Node, children: Iterable[Any]) -> Any:
762
+ return False
763
+
764
+ def visit_json_null_val(self, node: Node, children: Iterable[Any]) -> Any:
765
+ return None
766
+
665
767
  def generic_visit(self, node: Node, visited_children: Iterable[Any]) -> Any:
666
768
  """
667
769
  Handle all undefined rules.
@@ -675,6 +777,9 @@ class SQLHandler(NodeVisitor):
675
777
  rule can have repeated values, a list of values is returned.
676
778
 
677
779
  """
780
+ if node.expr_name.startswith('json'):
781
+ return visited_children or node.text
782
+
678
783
  # Call a grammar rule
679
784
  if node.expr_name in type(self).rule_info:
680
785
  n_keywords = type(self).rule_info[node.expr_name]['n_keywords']
@@ -123,14 +123,14 @@ class NamedList(List[T]):
123
123
  def _setup_authentication_info_handler() -> Callable[..., Dict[str, Any]]:
124
124
  """Setup authentication info event handler."""
125
125
 
126
- authentication_info: List[Tuple[str, Any]] = []
126
+ authentication_info: Dict[str, Any] = {}
127
127
 
128
128
  def handle_authentication_info(msg: Dict[str, Any]) -> None:
129
129
  """Handle authentication info events."""
130
130
  nonlocal authentication_info
131
131
  if msg.get('name', '') != 'singlestore.portal.authentication_updated':
132
132
  return
133
- authentication_info = list(msg.get('data', {}).items())
133
+ authentication_info = dict(msg.get('data', {}))
134
134
 
135
135
  events.subscribe(handle_authentication_info)
136
136
 
@@ -145,11 +145,27 @@ def _setup_authentication_info_handler() -> Callable[..., Dict[str, Any]]:
145
145
  out['user'] = data['user']
146
146
  if 'password' in data:
147
147
  out['password'] = data['password']
148
- authentication_info = list(out.items())
148
+ authentication_info = out
149
149
 
150
150
  events.subscribe(handle_authentication_info)
151
151
 
152
+ def retrieve_current_authentication_info() -> List[Tuple[str, Any]]:
153
+ """Retrieve JWT if not expired."""
154
+ nonlocal authentication_info
155
+ password = authentication_info.get('password')
156
+ if password:
157
+ expires = datetime.datetime.fromtimestamp(
158
+ jwt.decode(
159
+ password,
160
+ options={'verify_signature': False},
161
+ )['exp'],
162
+ )
163
+ if datetime.datetime.now() > expires:
164
+ authentication_info = {}
165
+ return list(authentication_info.items())
166
+
152
167
  def get_env() -> List[Tuple[str, Any]]:
168
+ """Retrieve JWT from environment."""
153
169
  conn = {}
154
170
  url = os.environ.get('SINGLESTOREDB_URL') or get_option('host')
155
171
  if url:
@@ -170,7 +186,7 @@ def _setup_authentication_info_handler() -> Callable[..., Dict[str, Any]]:
170
186
  return dict(
171
187
  itertools.chain(
172
188
  (get_env() if include_env else []),
173
- authentication_info,
189
+ retrieve_current_authentication_info(),
174
190
  ),
175
191
  )
176
192
 
@@ -182,7 +182,7 @@ class Portal(object):
182
182
  id = w.id
183
183
 
184
184
  self._call_javascript(
185
- 'changeWorkspace', [id],
185
+ 'changeDeployment', [id],
186
186
  wait_on_condition=lambda: self.workspace_id == id, # type: ignore
187
187
  timeout_message='timeout waiting for workspace update',
188
188
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: singlestoredb
3
- Version: 1.4.1
3
+ Version: 1.4.3
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,20 +1,20 @@
1
- _singlestoredb_accel.abi3.so,sha256=Wf5qOAlVEZh3MLHzLkanuIeaN_sdTJ_H6iqy1V8a_fc,206633
2
- singlestoredb-1.4.1.dist-info/RECORD,,
3
- singlestoredb-1.4.1.dist-info/LICENSE,sha256=Mlq78idURT-9G026aMYswwwnnrLcgzTLuXeAs5hjDLM,11341
4
- singlestoredb-1.4.1.dist-info/WHEEL,sha256=_VEguvlLpUd-c8RbFMA4yMIVNMBv2LhpxYLCEQ-Bogk,113
5
- singlestoredb-1.4.1.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
6
- singlestoredb-1.4.1.dist-info/top_level.txt,sha256=SDtemIXf-Kp-_F2f_S6x0db33cHGOILdAEsIQZe2LZc,35
7
- singlestoredb-1.4.1.dist-info/METADATA,sha256=e3LgU-lYTxOTjgFy24CcG69A9Vvq6Ke5YV0bV0oT2XA,5570
1
+ _singlestoredb_accel.abi3.so,sha256=LdeetXG6sTUuEEgSgzZmI1BV4plUvKyNq-ewAJcP16Y,206633
2
+ singlestoredb-1.4.3.dist-info/RECORD,,
3
+ singlestoredb-1.4.3.dist-info/LICENSE,sha256=Mlq78idURT-9G026aMYswwwnnrLcgzTLuXeAs5hjDLM,11341
4
+ singlestoredb-1.4.3.dist-info/WHEEL,sha256=_VEguvlLpUd-c8RbFMA4yMIVNMBv2LhpxYLCEQ-Bogk,113
5
+ singlestoredb-1.4.3.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
6
+ singlestoredb-1.4.3.dist-info/top_level.txt,sha256=SDtemIXf-Kp-_F2f_S6x0db33cHGOILdAEsIQZe2LZc,35
7
+ singlestoredb-1.4.3.dist-info/METADATA,sha256=sNKDftR6stTzMfX0NjKgcevlLjU9SQKhU6861nPiXQE,5570
8
8
  singlestoredb/auth.py,sha256=u8D9tpKzrqa4ssaHjyZnGDX1q8XBpGtuoOkTkSv7B28,7599
9
9
  singlestoredb/config.py,sha256=H4pQxqBEGGCmVHg40VEnAdqGXHun8ougZzj-Ed6ZLH4,11822
10
- singlestoredb/__init__.py,sha256=P2EmifYW3g7dPP3gIrZyeec6uJpf9rZUbYwUeW_YGTE,1634
10
+ singlestoredb/__init__.py,sha256=NTrIpxhbm7oMxrNbbjVKdK-4ShuyvUChQlP3z-kL9Ko,1634
11
11
  singlestoredb/types.py,sha256=FIqO1A7e0Gkk7ITmIysBy-P5S--ItbMSlYvblzqGS30,9969
12
12
  singlestoredb/connection.py,sha256=WL_TSSHhhjLV0pnJOtaeMAf0o1DI-PJv9xnLFf_cM08,45173
13
13
  singlestoredb/pytest.py,sha256=OyF3BO9mgxenifYhOihnzGk8WzCJ_zN5_mxe8XyFPOc,9074
14
14
  singlestoredb/exceptions.py,sha256=HuoA6sMRL5qiCiee-_5ddTGmFbYC9Euk8TYUsh5GvTw,3234
15
15
  singlestoredb/converters.py,sha256=t1hRMZfccWJs_WyOw-W-Kh87fxsOkpOnKXAeh_Nr-zU,20681
16
16
  singlestoredb/fusion/graphql.py,sha256=ZA3HcDq5rER-dCEavwTqnF7KM0D2LCYIY7nLQk7lSso,5207
17
- singlestoredb/fusion/handler.py,sha256=hXvJoauKnixfU67IgobmuZF4WKchSzzhUwsPQf_FWT4,21581
17
+ singlestoredb/fusion/handler.py,sha256=wuNq-nzzBngSha_kZ_Da7V7VzQzmhgXgUfh2V0HXLVI,24976
18
18
  singlestoredb/fusion/registry.py,sha256=jjdRTYZ3ylhy6gAoW5xBj0tkxGFBT-2yLQ0tztTgDIY,6112
19
19
  singlestoredb/fusion/__init__.py,sha256=Qo7SuqGw-l-vE8-EI2jhm6hXJkYfOLUKIws9c7LFNX0,356
20
20
  singlestoredb/fusion/result.py,sha256=Bd3KbRpqWqQcWp_Chd4bzBy8Kfc8nXLS_Pn_GGbPO6o,11772
@@ -47,7 +47,7 @@ singlestoredb/tests/ext_funcs/__init__.py,sha256=qZLnDI_Ck0tguVi-K-BKXDHAcC0jui3
47
47
  singlestoredb/management/organization.py,sha256=Y0JFSxYF_UOjip53gcbBXWPCe_t92zo3d99jZNrhkx4,4995
48
48
  singlestoredb/management/region.py,sha256=HnLcWUh7r_aLECliplCDHak4a_F3B7LOSXEYMW66qD0,1611
49
49
  singlestoredb/management/__init__.py,sha256=mhWXjLhp5-t8dhl0vl7SjayKrvJlDb5_hl1YWvDgiMA,237
50
- singlestoredb/management/utils.py,sha256=nTsGTDgl8lmjwcfl2nMS6feRn5P-jUjHlkVGzG5qrXM,10783
50
+ singlestoredb/management/utils.py,sha256=t-O6NRb4Wad1qJJ1afxtFR1IX-0bezEqplKllnm8tto,11398
51
51
  singlestoredb/management/cluster.py,sha256=i23Smr1PBrDZ8NO_VPd_-bEYkyHvVe9CCRGUjHn_1yQ,14362
52
52
  singlestoredb/management/workspace.py,sha256=9oamNIaE5vLZNAlpl5SK-xu27qPqx2Ff3ZIdKckNfmc,61673
53
53
  singlestoredb/management/manager.py,sha256=sFP1vZGS8WpN8E0XLu1N7Mxtq6Sixalln44HlTQEyXI,8800
@@ -119,5 +119,5 @@ singlestoredb/functions/ext/json.py,sha256=XkI8jirxi1T9F-M0p9NpLezph0MRAhYmDiPuU
119
119
  singlestoredb/functions/ext/rowdat_1.py,sha256=JgKRsVSQYczFD6cmo2xLilbNPYpyLL2tPOWO1Gh25ow,22306
120
120
  singlestoredb/notebook/__init__.py,sha256=v0j1E3MFAtaC8wTrR-F7XY0nytUvQ4XpYhVXddv2xA0,533
121
121
  singlestoredb/notebook/_objects.py,sha256=MkB1eowEq5SQXFHY00xAKAyyeLqHu_uaZiA20BCJPaE,8043
122
- singlestoredb/notebook/_portal.py,sha256=a0UeRwXQl-tBEfV_IOOL_UK2Zzrs-RgGswvjJiZk8Wc,8485
122
+ singlestoredb/notebook/_portal.py,sha256=08_8hFFuD9Ybq3K8ruHOgMhDqzdhjj7o0Sq368zH714,8486
123
123
  singlestoredb/alchemy/__init__.py,sha256=dXRThusYrs_9GjrhPOw0-vw94in_T8yY9jE7SGCqiQk,2523