surrealdb-orm 0.1.3__py3-none-any.whl → 0.5.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.
- surreal_orm/__init__.py +78 -3
- surreal_orm/aggregations.py +164 -0
- surreal_orm/auth/__init__.py +15 -0
- surreal_orm/auth/access.py +167 -0
- surreal_orm/auth/mixins.py +302 -0
- surreal_orm/cli/__init__.py +15 -0
- surreal_orm/cli/commands.py +369 -0
- surreal_orm/connection_manager.py +58 -18
- surreal_orm/fields/__init__.py +36 -0
- surreal_orm/fields/encrypted.py +166 -0
- surreal_orm/fields/relation.py +465 -0
- surreal_orm/migrations/__init__.py +51 -0
- surreal_orm/migrations/executor.py +380 -0
- surreal_orm/migrations/generator.py +272 -0
- surreal_orm/migrations/introspector.py +305 -0
- surreal_orm/migrations/migration.py +188 -0
- surreal_orm/migrations/operations.py +531 -0
- surreal_orm/migrations/state.py +406 -0
- surreal_orm/model_base.py +594 -135
- surreal_orm/py.typed +0 -0
- surreal_orm/query_set.py +609 -34
- surreal_orm/relations.py +645 -0
- surreal_orm/surreal_function.py +95 -0
- surreal_orm/surreal_ql.py +113 -0
- surreal_orm/types.py +86 -0
- surreal_sdk/README.md +79 -0
- surreal_sdk/__init__.py +151 -0
- surreal_sdk/connection/__init__.py +17 -0
- surreal_sdk/connection/base.py +516 -0
- surreal_sdk/connection/http.py +421 -0
- surreal_sdk/connection/pool.py +244 -0
- surreal_sdk/connection/websocket.py +519 -0
- surreal_sdk/exceptions.py +71 -0
- surreal_sdk/functions.py +607 -0
- surreal_sdk/protocol/__init__.py +13 -0
- surreal_sdk/protocol/rpc.py +218 -0
- surreal_sdk/py.typed +0 -0
- surreal_sdk/pyproject.toml +49 -0
- surreal_sdk/streaming/__init__.py +31 -0
- surreal_sdk/streaming/change_feed.py +278 -0
- surreal_sdk/streaming/live_query.py +265 -0
- surreal_sdk/streaming/live_select.py +369 -0
- surreal_sdk/transaction.py +386 -0
- surreal_sdk/types.py +346 -0
- surrealdb_orm-0.5.0.dist-info/METADATA +465 -0
- surrealdb_orm-0.5.0.dist-info/RECORD +52 -0
- {surrealdb_orm-0.1.3.dist-info → surrealdb_orm-0.5.0.dist-info}/WHEEL +1 -1
- surrealdb_orm-0.5.0.dist-info/entry_points.txt +2 -0
- {surrealdb_orm-0.1.3.dist-info → surrealdb_orm-0.5.0.dist-info}/licenses/LICENSE +1 -1
- surrealdb_orm-0.1.3.dist-info/METADATA +0 -184
- surrealdb_orm-0.1.3.dist-info/RECORD +0 -11
surreal_sdk/functions.py
ADDED
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Function call API for SurrealDB SDK.
|
|
3
|
+
|
|
4
|
+
Provides a fluent interface for calling SurrealDB built-in and custom functions.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Generator
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from .connection.base import BaseSurrealConnection
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Built-in SurrealDB function namespaces
|
|
14
|
+
BUILTIN_NAMESPACES = frozenset(
|
|
15
|
+
{
|
|
16
|
+
"array",
|
|
17
|
+
"bytes",
|
|
18
|
+
"count",
|
|
19
|
+
"crypto",
|
|
20
|
+
"duration",
|
|
21
|
+
"encoding",
|
|
22
|
+
"geo",
|
|
23
|
+
"http",
|
|
24
|
+
"math",
|
|
25
|
+
"meta",
|
|
26
|
+
"object",
|
|
27
|
+
"parse",
|
|
28
|
+
"rand",
|
|
29
|
+
"record",
|
|
30
|
+
"search",
|
|
31
|
+
"session",
|
|
32
|
+
"sleep",
|
|
33
|
+
"string",
|
|
34
|
+
"time",
|
|
35
|
+
"type",
|
|
36
|
+
"value",
|
|
37
|
+
"vector",
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class FunctionCall:
|
|
43
|
+
"""
|
|
44
|
+
Represents a SurrealDB function call ready for execution.
|
|
45
|
+
|
|
46
|
+
Can be awaited directly to execute the function.
|
|
47
|
+
|
|
48
|
+
Usage:
|
|
49
|
+
result = await conn.fn.math.sqrt(16)
|
|
50
|
+
# Equivalent to: SELECT * FROM math::sqrt(16)
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
connection: "BaseSurrealConnection",
|
|
56
|
+
function_path: str,
|
|
57
|
+
args: tuple[Any, ...],
|
|
58
|
+
):
|
|
59
|
+
"""
|
|
60
|
+
Initialize a function call.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
connection: The database connection
|
|
64
|
+
function_path: Full function path (e.g., "math::sqrt" or "fn::my_func")
|
|
65
|
+
args: Function arguments
|
|
66
|
+
"""
|
|
67
|
+
self._connection = connection
|
|
68
|
+
self._function_path = function_path
|
|
69
|
+
self._args = args
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def function_path(self) -> str:
|
|
73
|
+
"""Get the function path."""
|
|
74
|
+
return self._function_path
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def args(self) -> tuple[Any, ...]:
|
|
78
|
+
"""Get the function arguments."""
|
|
79
|
+
return self._args
|
|
80
|
+
|
|
81
|
+
def to_sql(self) -> tuple[str, dict[str, Any]]:
|
|
82
|
+
"""
|
|
83
|
+
Convert to SurrealQL with parameterized variables.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Tuple of (sql_string, variables_dict)
|
|
87
|
+
"""
|
|
88
|
+
params: dict[str, Any] = {}
|
|
89
|
+
placeholders: list[str] = []
|
|
90
|
+
|
|
91
|
+
for i, arg in enumerate(self._args):
|
|
92
|
+
param_name = f"fn_arg_{i}"
|
|
93
|
+
params[param_name] = arg
|
|
94
|
+
placeholders.append(f"${param_name}")
|
|
95
|
+
|
|
96
|
+
args_str = ", ".join(placeholders)
|
|
97
|
+
sql = f"RETURN {self._function_path}({args_str});"
|
|
98
|
+
|
|
99
|
+
return sql, params
|
|
100
|
+
|
|
101
|
+
async def execute(self) -> Any:
|
|
102
|
+
"""
|
|
103
|
+
Execute the function call and return result.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
The function result
|
|
107
|
+
"""
|
|
108
|
+
sql, params = self.to_sql()
|
|
109
|
+
result = await self._connection.query(sql, params)
|
|
110
|
+
|
|
111
|
+
# Extract scalar result from QueryResponse
|
|
112
|
+
if result.first_result and result.first_result.result is not None:
|
|
113
|
+
return result.first_result.result
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
def __await__(self) -> Generator[Any, None, Any]:
|
|
117
|
+
"""Allow direct await: result = await conn.fn.math.sqrt(16)"""
|
|
118
|
+
return self.execute().__await__()
|
|
119
|
+
|
|
120
|
+
def __repr__(self) -> str:
|
|
121
|
+
args_repr = ", ".join(repr(a) for a in self._args)
|
|
122
|
+
return f"FunctionCall({self._function_path}({args_repr}))"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class FunctionNamespace:
|
|
126
|
+
"""
|
|
127
|
+
Namespace for building function calls.
|
|
128
|
+
|
|
129
|
+
Supports dot notation for nested namespaces:
|
|
130
|
+
conn.fn.math.sqrt(16) -> math::sqrt($fn_arg_0)
|
|
131
|
+
conn.fn.time.now() -> time::now()
|
|
132
|
+
conn.fn.cast_vote(...) -> fn::cast_vote(...)
|
|
133
|
+
|
|
134
|
+
Built-in namespaces (math, time, array, etc.) use namespace::function format.
|
|
135
|
+
Unknown namespaces are treated as custom functions with fn:: prefix.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
def __init__(
|
|
139
|
+
self,
|
|
140
|
+
connection: "BaseSurrealConnection",
|
|
141
|
+
path: list[str] | None = None,
|
|
142
|
+
):
|
|
143
|
+
"""
|
|
144
|
+
Initialize a function namespace.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
connection: The database connection
|
|
148
|
+
path: Current namespace path (e.g., ["math", "sqrt"])
|
|
149
|
+
"""
|
|
150
|
+
self._connection = connection
|
|
151
|
+
self._path = path or []
|
|
152
|
+
|
|
153
|
+
def __getattr__(self, name: str) -> "FunctionNamespace":
|
|
154
|
+
"""
|
|
155
|
+
Access a sub-namespace or prepare a function call.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
name: Namespace or function name
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
New FunctionNamespace with extended path
|
|
162
|
+
|
|
163
|
+
Examples:
|
|
164
|
+
conn.fn.math -> FunctionNamespace(path=["math"])
|
|
165
|
+
conn.fn.math.sqrt -> FunctionNamespace(path=["math", "sqrt"])
|
|
166
|
+
"""
|
|
167
|
+
# Prevent recursion on special attributes
|
|
168
|
+
if name.startswith("_"):
|
|
169
|
+
raise AttributeError(f"'{type(self).__name__}' has no attribute '{name}'")
|
|
170
|
+
return FunctionNamespace(self._connection, self._path + [name])
|
|
171
|
+
|
|
172
|
+
def __call__(self, *args: Any) -> FunctionCall:
|
|
173
|
+
"""
|
|
174
|
+
Call the function with arguments.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
*args: Function arguments
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
FunctionCall ready to execute
|
|
181
|
+
|
|
182
|
+
Raises:
|
|
183
|
+
ValueError: If called on root namespace
|
|
184
|
+
|
|
185
|
+
Examples:
|
|
186
|
+
conn.fn.math.sqrt(16) -> FunctionCall for "math::sqrt"
|
|
187
|
+
conn.fn.cast_vote(a, b, c) -> FunctionCall for "fn::cast_vote"
|
|
188
|
+
"""
|
|
189
|
+
if not self._path:
|
|
190
|
+
raise ValueError("Cannot call root function namespace directly")
|
|
191
|
+
|
|
192
|
+
# Build function path based on namespace type
|
|
193
|
+
if self._path[0] in BUILTIN_NAMESPACES:
|
|
194
|
+
# Built-in function: math::sqrt, time::now, etc.
|
|
195
|
+
function_path = "::".join(self._path)
|
|
196
|
+
else:
|
|
197
|
+
# Custom function: fn::my_function, fn::nested::func
|
|
198
|
+
function_path = "fn::" + "::".join(self._path)
|
|
199
|
+
|
|
200
|
+
return FunctionCall(self._connection, function_path, args)
|
|
201
|
+
|
|
202
|
+
def __repr__(self) -> str:
|
|
203
|
+
path_str = "::".join(self._path) if self._path else "<root>"
|
|
204
|
+
return f"FunctionNamespace({path_str})"
|
|
205
|
+
|
|
206
|
+
# Typed helper properties for common namespaces
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def math(self) -> "MathFunctions":
|
|
210
|
+
"""Access math functions with type hints."""
|
|
211
|
+
return MathFunctions(self._connection)
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def time(self) -> "TimeFunctions":
|
|
215
|
+
"""Access time functions with type hints."""
|
|
216
|
+
return TimeFunctions(self._connection)
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def array(self) -> "ArrayFunctions":
|
|
220
|
+
"""Access array functions with type hints."""
|
|
221
|
+
return ArrayFunctions(self._connection)
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def string(self) -> "StringFunctions":
|
|
225
|
+
"""Access string functions with type hints."""
|
|
226
|
+
return StringFunctions(self._connection)
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def crypto(self) -> "CryptoFunctions":
|
|
230
|
+
"""Access crypto functions with type hints."""
|
|
231
|
+
return CryptoFunctions(self._connection)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class MathFunctions:
|
|
235
|
+
"""
|
|
236
|
+
Typed math function namespace with IDE hints.
|
|
237
|
+
|
|
238
|
+
All SurrealDB math:: functions with type annotations.
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
def __init__(self, connection: "BaseSurrealConnection"):
|
|
242
|
+
self._connection = connection
|
|
243
|
+
self._ns = FunctionNamespace(connection, ["math"])
|
|
244
|
+
|
|
245
|
+
def abs(self, value: float | int) -> FunctionCall:
|
|
246
|
+
"""Return absolute value. math::abs(number)"""
|
|
247
|
+
return self._ns.abs(value)
|
|
248
|
+
|
|
249
|
+
def ceil(self, value: float | int) -> FunctionCall:
|
|
250
|
+
"""Return ceiling value. math::ceil(number)"""
|
|
251
|
+
return self._ns.ceil(value)
|
|
252
|
+
|
|
253
|
+
def floor(self, value: float | int) -> FunctionCall:
|
|
254
|
+
"""Return floor value. math::floor(number)"""
|
|
255
|
+
return self._ns.floor(value)
|
|
256
|
+
|
|
257
|
+
def round(self, value: float | int) -> FunctionCall:
|
|
258
|
+
"""Return rounded value. math::round(number)"""
|
|
259
|
+
return self._ns.round(value)
|
|
260
|
+
|
|
261
|
+
def sqrt(self, value: float | int) -> FunctionCall:
|
|
262
|
+
"""Return square root. math::sqrt(number)"""
|
|
263
|
+
return self._ns.sqrt(value)
|
|
264
|
+
|
|
265
|
+
def pow(self, base: float | int, exponent: float | int) -> FunctionCall:
|
|
266
|
+
"""Return power. math::pow(base, exponent)"""
|
|
267
|
+
return self._ns.pow(base, exponent)
|
|
268
|
+
|
|
269
|
+
def log(self, value: float | int) -> FunctionCall:
|
|
270
|
+
"""Return natural logarithm. math::log(number)"""
|
|
271
|
+
return self._ns.log(value)
|
|
272
|
+
|
|
273
|
+
def log2(self, value: float | int) -> FunctionCall:
|
|
274
|
+
"""Return base-2 logarithm. math::log2(number)"""
|
|
275
|
+
return self._ns.log2(value)
|
|
276
|
+
|
|
277
|
+
def log10(self, value: float | int) -> FunctionCall:
|
|
278
|
+
"""Return base-10 logarithm. math::log10(number)"""
|
|
279
|
+
return self._ns.log10(value)
|
|
280
|
+
|
|
281
|
+
def sin(self, value: float | int) -> FunctionCall:
|
|
282
|
+
"""Return sine. math::sin(number)"""
|
|
283
|
+
return self._ns.sin(value)
|
|
284
|
+
|
|
285
|
+
def cos(self, value: float | int) -> FunctionCall:
|
|
286
|
+
"""Return cosine. math::cos(number)"""
|
|
287
|
+
return self._ns.cos(value)
|
|
288
|
+
|
|
289
|
+
def tan(self, value: float | int) -> FunctionCall:
|
|
290
|
+
"""Return tangent. math::tan(number)"""
|
|
291
|
+
return self._ns.tan(value)
|
|
292
|
+
|
|
293
|
+
def max(self, *values: float | int) -> FunctionCall:
|
|
294
|
+
"""Return maximum value. math::max(numbers...)"""
|
|
295
|
+
return self._ns.max(*values)
|
|
296
|
+
|
|
297
|
+
def min(self, *values: float | int) -> FunctionCall:
|
|
298
|
+
"""Return minimum value. math::min(numbers...)"""
|
|
299
|
+
return self._ns.min(*values)
|
|
300
|
+
|
|
301
|
+
def sum(self, values: list[float | int]) -> FunctionCall:
|
|
302
|
+
"""Return sum of values. math::sum(array)"""
|
|
303
|
+
return self._ns.sum(values)
|
|
304
|
+
|
|
305
|
+
def mean(self, values: list[float | int]) -> FunctionCall:
|
|
306
|
+
"""Return mean of values. math::mean(array)"""
|
|
307
|
+
return self._ns.mean(values)
|
|
308
|
+
|
|
309
|
+
def median(self, values: list[float | int]) -> FunctionCall:
|
|
310
|
+
"""Return median of values. math::median(array)"""
|
|
311
|
+
return self._ns.median(values)
|
|
312
|
+
|
|
313
|
+
def __getattr__(self, name: str) -> "FunctionNamespace":
|
|
314
|
+
"""Fall back to dynamic namespace for unlisted functions."""
|
|
315
|
+
result: FunctionNamespace = getattr(self._ns, name)
|
|
316
|
+
return result
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
class TimeFunctions:
|
|
320
|
+
"""
|
|
321
|
+
Typed time function namespace with IDE hints.
|
|
322
|
+
|
|
323
|
+
All SurrealDB time:: functions with type annotations.
|
|
324
|
+
"""
|
|
325
|
+
|
|
326
|
+
def __init__(self, connection: "BaseSurrealConnection"):
|
|
327
|
+
self._connection = connection
|
|
328
|
+
self._ns = FunctionNamespace(connection, ["time"])
|
|
329
|
+
|
|
330
|
+
def now(self) -> FunctionCall:
|
|
331
|
+
"""Return current datetime. time::now()"""
|
|
332
|
+
return self._ns.now()
|
|
333
|
+
|
|
334
|
+
def day(self, datetime: Any) -> FunctionCall:
|
|
335
|
+
"""Return day of month. time::day(datetime)"""
|
|
336
|
+
return self._ns.day(datetime)
|
|
337
|
+
|
|
338
|
+
def month(self, datetime: Any) -> FunctionCall:
|
|
339
|
+
"""Return month. time::month(datetime)"""
|
|
340
|
+
return self._ns.month(datetime)
|
|
341
|
+
|
|
342
|
+
def year(self, datetime: Any) -> FunctionCall:
|
|
343
|
+
"""Return year. time::year(datetime)"""
|
|
344
|
+
return self._ns.year(datetime)
|
|
345
|
+
|
|
346
|
+
def hour(self, datetime: Any) -> FunctionCall:
|
|
347
|
+
"""Return hour. time::hour(datetime)"""
|
|
348
|
+
return self._ns.hour(datetime)
|
|
349
|
+
|
|
350
|
+
def minute(self, datetime: Any) -> FunctionCall:
|
|
351
|
+
"""Return minute. time::minute(datetime)"""
|
|
352
|
+
return self._ns.minute(datetime)
|
|
353
|
+
|
|
354
|
+
def second(self, datetime: Any) -> FunctionCall:
|
|
355
|
+
"""Return second. time::second(datetime)"""
|
|
356
|
+
return self._ns.second(datetime)
|
|
357
|
+
|
|
358
|
+
def floor(self, datetime: Any, duration: str) -> FunctionCall:
|
|
359
|
+
"""Floor datetime to duration. time::floor(datetime, duration)"""
|
|
360
|
+
return self._ns.floor(datetime, duration)
|
|
361
|
+
|
|
362
|
+
def ceil(self, datetime: Any, duration: str) -> FunctionCall:
|
|
363
|
+
"""Ceil datetime to duration. time::ceil(datetime, duration)"""
|
|
364
|
+
return self._ns.ceil(datetime, duration)
|
|
365
|
+
|
|
366
|
+
def round(self, datetime: Any, duration: str) -> FunctionCall:
|
|
367
|
+
"""Round datetime to duration. time::round(datetime, duration)"""
|
|
368
|
+
return self._ns.round(datetime, duration)
|
|
369
|
+
|
|
370
|
+
def unix(self, datetime: Any) -> FunctionCall:
|
|
371
|
+
"""Return Unix timestamp. time::unix(datetime)"""
|
|
372
|
+
return self._ns.unix(datetime)
|
|
373
|
+
|
|
374
|
+
def format(self, datetime: Any, format_str: str) -> FunctionCall:
|
|
375
|
+
"""Format datetime. time::format(datetime, format)"""
|
|
376
|
+
return self._ns.format(datetime, format_str)
|
|
377
|
+
|
|
378
|
+
def __getattr__(self, name: str) -> "FunctionNamespace":
|
|
379
|
+
"""Fall back to dynamic namespace for unlisted functions."""
|
|
380
|
+
result: FunctionNamespace = getattr(self._ns, name)
|
|
381
|
+
return result
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
class ArrayFunctions:
|
|
385
|
+
"""
|
|
386
|
+
Typed array function namespace with IDE hints.
|
|
387
|
+
|
|
388
|
+
All SurrealDB array:: functions with type annotations.
|
|
389
|
+
"""
|
|
390
|
+
|
|
391
|
+
def __init__(self, connection: "BaseSurrealConnection"):
|
|
392
|
+
self._connection = connection
|
|
393
|
+
self._ns = FunctionNamespace(connection, ["array"])
|
|
394
|
+
|
|
395
|
+
def len(self, array: list[Any]) -> FunctionCall:
|
|
396
|
+
"""Return array length. array::len(array)"""
|
|
397
|
+
return self._ns.len(array)
|
|
398
|
+
|
|
399
|
+
def append(self, array: list[Any], value: Any) -> FunctionCall:
|
|
400
|
+
"""Append value to array. array::append(array, value)"""
|
|
401
|
+
return self._ns.append(array, value)
|
|
402
|
+
|
|
403
|
+
def prepend(self, array: list[Any], value: Any) -> FunctionCall:
|
|
404
|
+
"""Prepend value to array. array::prepend(array, value)"""
|
|
405
|
+
return self._ns.prepend(array, value)
|
|
406
|
+
|
|
407
|
+
def concat(self, *arrays: list[Any]) -> FunctionCall:
|
|
408
|
+
"""Concatenate arrays. array::concat(arrays...)"""
|
|
409
|
+
return self._ns.concat(*arrays)
|
|
410
|
+
|
|
411
|
+
def distinct(self, array: list[Any]) -> FunctionCall:
|
|
412
|
+
"""Return distinct values. array::distinct(array)"""
|
|
413
|
+
return self._ns.distinct(array)
|
|
414
|
+
|
|
415
|
+
def flatten(self, array: list[Any]) -> FunctionCall:
|
|
416
|
+
"""Flatten nested arrays. array::flatten(array)"""
|
|
417
|
+
return self._ns.flatten(array)
|
|
418
|
+
|
|
419
|
+
def reverse(self, array: list[Any]) -> FunctionCall:
|
|
420
|
+
"""Reverse array. array::reverse(array)"""
|
|
421
|
+
return self._ns.reverse(array)
|
|
422
|
+
|
|
423
|
+
def sort(self, array: list[Any]) -> FunctionCall:
|
|
424
|
+
"""Sort array. array::sort(array)"""
|
|
425
|
+
return self._ns.sort(array)
|
|
426
|
+
|
|
427
|
+
def slice(self, array: list[Any], start: int, end: int | None = None) -> FunctionCall:
|
|
428
|
+
"""Slice array. array::slice(array, start, end)"""
|
|
429
|
+
if end is not None:
|
|
430
|
+
return self._ns.slice(array, start, end)
|
|
431
|
+
return self._ns.slice(array, start)
|
|
432
|
+
|
|
433
|
+
def first(self, array: list[Any]) -> FunctionCall:
|
|
434
|
+
"""Return first element. array::first(array)"""
|
|
435
|
+
return self._ns.first(array)
|
|
436
|
+
|
|
437
|
+
def last(self, array: list[Any]) -> FunctionCall:
|
|
438
|
+
"""Return last element. array::last(array)"""
|
|
439
|
+
return self._ns.last(array)
|
|
440
|
+
|
|
441
|
+
def __getattr__(self, name: str) -> "FunctionNamespace":
|
|
442
|
+
"""Fall back to dynamic namespace for unlisted functions."""
|
|
443
|
+
result: FunctionNamespace = getattr(self._ns, name)
|
|
444
|
+
return result
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
class StringFunctions:
|
|
448
|
+
"""
|
|
449
|
+
Typed string function namespace with IDE hints.
|
|
450
|
+
|
|
451
|
+
All SurrealDB string:: functions with type annotations.
|
|
452
|
+
"""
|
|
453
|
+
|
|
454
|
+
def __init__(self, connection: "BaseSurrealConnection"):
|
|
455
|
+
self._connection = connection
|
|
456
|
+
self._ns = FunctionNamespace(connection, ["string"])
|
|
457
|
+
|
|
458
|
+
def len(self, string: str) -> FunctionCall:
|
|
459
|
+
"""Return string length. string::len(string)"""
|
|
460
|
+
return self._ns.len(string)
|
|
461
|
+
|
|
462
|
+
def lowercase(self, string: str) -> FunctionCall:
|
|
463
|
+
"""Convert to lowercase. string::lowercase(string)"""
|
|
464
|
+
return self._ns.lowercase(string)
|
|
465
|
+
|
|
466
|
+
def uppercase(self, string: str) -> FunctionCall:
|
|
467
|
+
"""Convert to uppercase. string::uppercase(string)"""
|
|
468
|
+
return self._ns.uppercase(string)
|
|
469
|
+
|
|
470
|
+
def trim(self, string: str) -> FunctionCall:
|
|
471
|
+
"""Trim whitespace. string::trim(string)"""
|
|
472
|
+
return self._ns.trim(string)
|
|
473
|
+
|
|
474
|
+
def concat(self, *strings: str) -> FunctionCall:
|
|
475
|
+
"""Concatenate strings. string::concat(strings...)"""
|
|
476
|
+
return self._ns.concat(*strings)
|
|
477
|
+
|
|
478
|
+
def split(self, string: str, delimiter: str) -> FunctionCall:
|
|
479
|
+
"""Split string. string::split(string, delimiter)"""
|
|
480
|
+
return self._ns.split(string, delimiter)
|
|
481
|
+
|
|
482
|
+
def join(self, array: list[str], delimiter: str) -> FunctionCall:
|
|
483
|
+
"""Join array. string::join(array, delimiter)"""
|
|
484
|
+
return self._ns.join(array, delimiter)
|
|
485
|
+
|
|
486
|
+
def replace(self, string: str, search: str, replace: str) -> FunctionCall:
|
|
487
|
+
"""Replace in string. string::replace(string, search, replace)"""
|
|
488
|
+
return self._ns.replace(string, search, replace)
|
|
489
|
+
|
|
490
|
+
def slice(self, string: str, start: int, end: int | None = None) -> FunctionCall:
|
|
491
|
+
"""Slice string. string::slice(string, start, end)"""
|
|
492
|
+
if end is not None:
|
|
493
|
+
return self._ns.slice(string, start, end)
|
|
494
|
+
return self._ns.slice(string, start)
|
|
495
|
+
|
|
496
|
+
def contains(self, string: str, search: str) -> FunctionCall:
|
|
497
|
+
"""Check if string contains substring. string::contains(string, search)"""
|
|
498
|
+
return self._ns.contains(string, search)
|
|
499
|
+
|
|
500
|
+
def starts_with(self, string: str, prefix: str) -> FunctionCall:
|
|
501
|
+
"""Check if string starts with prefix. string::startsWith(string, prefix)"""
|
|
502
|
+
return self._ns.startsWith(string, prefix)
|
|
503
|
+
|
|
504
|
+
def ends_with(self, string: str, suffix: str) -> FunctionCall:
|
|
505
|
+
"""Check if string ends with suffix. string::endsWith(string, suffix)"""
|
|
506
|
+
return self._ns.endsWith(string, suffix)
|
|
507
|
+
|
|
508
|
+
def __getattr__(self, name: str) -> "FunctionNamespace":
|
|
509
|
+
"""Fall back to dynamic namespace for unlisted functions."""
|
|
510
|
+
result: FunctionNamespace = getattr(self._ns, name)
|
|
511
|
+
return result
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
class CryptoFunctions:
|
|
515
|
+
"""
|
|
516
|
+
Typed crypto function namespace with IDE hints.
|
|
517
|
+
|
|
518
|
+
All SurrealDB crypto:: functions with type annotations.
|
|
519
|
+
"""
|
|
520
|
+
|
|
521
|
+
def __init__(self, connection: "BaseSurrealConnection"):
|
|
522
|
+
self._connection = connection
|
|
523
|
+
self._ns = FunctionNamespace(connection, ["crypto"])
|
|
524
|
+
|
|
525
|
+
def md5(self, value: str) -> FunctionCall:
|
|
526
|
+
"""Return MD5 hash. crypto::md5(string)"""
|
|
527
|
+
return self._ns.md5(value)
|
|
528
|
+
|
|
529
|
+
def sha1(self, value: str) -> FunctionCall:
|
|
530
|
+
"""Return SHA-1 hash. crypto::sha1(string)"""
|
|
531
|
+
return self._ns.sha1(value)
|
|
532
|
+
|
|
533
|
+
def sha256(self, value: str) -> FunctionCall:
|
|
534
|
+
"""Return SHA-256 hash. crypto::sha256(string)"""
|
|
535
|
+
return self._ns.sha256(value)
|
|
536
|
+
|
|
537
|
+
def sha512(self, value: str) -> FunctionCall:
|
|
538
|
+
"""Return SHA-512 hash. crypto::sha512(string)"""
|
|
539
|
+
return self._ns.sha512(value)
|
|
540
|
+
|
|
541
|
+
def __getattr__(self, name: str) -> "FunctionNamespace":
|
|
542
|
+
"""Fall back to dynamic namespace for unlisted functions."""
|
|
543
|
+
result: FunctionNamespace = getattr(self._ns, name)
|
|
544
|
+
return result
|
|
545
|
+
|
|
546
|
+
@property
|
|
547
|
+
def argon2(self) -> "Argon2Functions":
|
|
548
|
+
"""Access crypto::argon2 functions."""
|
|
549
|
+
return Argon2Functions(self._connection)
|
|
550
|
+
|
|
551
|
+
@property
|
|
552
|
+
def bcrypt(self) -> "BcryptFunctions":
|
|
553
|
+
"""Access crypto::bcrypt functions."""
|
|
554
|
+
return BcryptFunctions(self._connection)
|
|
555
|
+
|
|
556
|
+
@property
|
|
557
|
+
def scrypt(self) -> "ScryptFunctions":
|
|
558
|
+
"""Access crypto::scrypt functions."""
|
|
559
|
+
return ScryptFunctions(self._connection)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
class Argon2Functions:
|
|
563
|
+
"""Crypto argon2 sub-namespace."""
|
|
564
|
+
|
|
565
|
+
def __init__(self, connection: "BaseSurrealConnection"):
|
|
566
|
+
self._connection = connection
|
|
567
|
+
self._ns = FunctionNamespace(connection, ["crypto", "argon2"])
|
|
568
|
+
|
|
569
|
+
def compare(self, hash: str, password: str) -> FunctionCall:
|
|
570
|
+
"""Compare password with argon2 hash. crypto::argon2::compare(hash, password)"""
|
|
571
|
+
return self._ns.compare(hash, password)
|
|
572
|
+
|
|
573
|
+
def generate(self, password: str) -> FunctionCall:
|
|
574
|
+
"""Generate argon2 hash. crypto::argon2::generate(password)"""
|
|
575
|
+
return self._ns.generate(password)
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
class BcryptFunctions:
|
|
579
|
+
"""Crypto bcrypt sub-namespace."""
|
|
580
|
+
|
|
581
|
+
def __init__(self, connection: "BaseSurrealConnection"):
|
|
582
|
+
self._connection = connection
|
|
583
|
+
self._ns = FunctionNamespace(connection, ["crypto", "bcrypt"])
|
|
584
|
+
|
|
585
|
+
def compare(self, hash: str, password: str) -> FunctionCall:
|
|
586
|
+
"""Compare password with bcrypt hash. crypto::bcrypt::compare(hash, password)"""
|
|
587
|
+
return self._ns.compare(hash, password)
|
|
588
|
+
|
|
589
|
+
def generate(self, password: str) -> FunctionCall:
|
|
590
|
+
"""Generate bcrypt hash. crypto::bcrypt::generate(password)"""
|
|
591
|
+
return self._ns.generate(password)
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
class ScryptFunctions:
|
|
595
|
+
"""Crypto scrypt sub-namespace."""
|
|
596
|
+
|
|
597
|
+
def __init__(self, connection: "BaseSurrealConnection"):
|
|
598
|
+
self._connection = connection
|
|
599
|
+
self._ns = FunctionNamespace(connection, ["crypto", "scrypt"])
|
|
600
|
+
|
|
601
|
+
def compare(self, hash: str, password: str) -> FunctionCall:
|
|
602
|
+
"""Compare password with scrypt hash. crypto::scrypt::compare(hash, password)"""
|
|
603
|
+
return self._ns.compare(hash, password)
|
|
604
|
+
|
|
605
|
+
def generate(self, password: str) -> FunctionCall:
|
|
606
|
+
"""Generate scrypt hash. crypto::scrypt::generate(password)"""
|
|
607
|
+
return self._ns.generate(password)
|