lorebase-core 0.2.3__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.
- lorebase_core/__init__.py +1 -0
- lorebase_core/canonical/__init__.py +35 -0
- lorebase_core/canonical/hashing.py +128 -0
- lorebase_core/canonical/jcs.py +162 -0
- lorebase_core/expr/__init__.py +118 -0
- lorebase_core/expr/ast.py +443 -0
- lorebase_core/expr/checker.py +428 -0
- lorebase_core/expr/compiler.py +87 -0
- lorebase_core/expr/context.py +82 -0
- lorebase_core/expr/derivations.py +306 -0
- lorebase_core/expr/environment.py +176 -0
- lorebase_core/expr/errors.py +98 -0
- lorebase_core/expr/evaluator.py +414 -0
- lorebase_core/expr/functions.py +898 -0
- lorebase_core/expr/limits.py +52 -0
- lorebase_core/expr/operations.py +479 -0
- lorebase_core/expr/ops.py +243 -0
- lorebase_core/expr/resolver.py +96 -0
- lorebase_core/expr/rows.py +148 -0
- lorebase_core/expr/sensitivity.py +337 -0
- lorebase_core/expr/types.py +227 -0
- lorebase_core/expr/validation.py +51 -0
- lorebase_core/expr/values.py +169 -0
- lorebase_core/expr/visibility.py +363 -0
- lorebase_core/infer/__init__.py +36 -0
- lorebase_core/infer/columns.py +621 -0
- lorebase_core/infer/engine.py +546 -0
- lorebase_core/infer/keys.py +164 -0
- lorebase_core/infer/names.py +145 -0
- lorebase_core/infer/options.py +290 -0
- lorebase_core/infer/profile.py +54 -0
- lorebase_core/infer/proposal.py +122 -0
- lorebase_core/infer/references.py +314 -0
- lorebase_core/infer/suggestions.py +731 -0
- lorebase_core/infer/tables.py +81 -0
- lorebase_core/merge/__init__.py +89 -0
- lorebase_core/merge/conflicts.py +262 -0
- lorebase_core/merge/consistency.py +440 -0
- lorebase_core/merge/data_merge.py +522 -0
- lorebase_core/merge/engine.py +476 -0
- lorebase_core/merge/index.py +100 -0
- lorebase_core/merge/objects.py +204 -0
- lorebase_core/merge/policies.py +322 -0
- lorebase_core/merge/resolve.py +321 -0
- lorebase_core/merge/schema_merge.py +429 -0
- lorebase_core/merge/state.py +443 -0
- lorebase_core/model/__init__.py +245 -0
- lorebase_core/model/attribute.py +72 -0
- lorebase_core/model/base.py +61 -0
- lorebase_core/model/derivation.py +95 -0
- lorebase_core/model/domain.py +71 -0
- lorebase_core/model/embedding.py +193 -0
- lorebase_core/model/ids.py +78 -0
- lorebase_core/model/kind.py +85 -0
- lorebase_core/model/lineage.py +114 -0
- lorebase_core/model/operation.py +161 -0
- lorebase_core/model/paths.py +141 -0
- lorebase_core/model/record.py +127 -0
- lorebase_core/model/relation.py +83 -0
- lorebase_core/model/schema.py +219 -0
- lorebase_core/model/source.py +204 -0
- lorebase_core/model/trait.py +37 -0
- lorebase_core/model/vault.py +43 -0
- lorebase_core/model/yaml_schema.py +1058 -0
- lorebase_core/query/__init__.py +97 -0
- lorebase_core/query/dsl.py +227 -0
- lorebase_core/query/resolve.py +794 -0
- lorebase_core/revision/__init__.py +59 -0
- lorebase_core/revision/ancestry.py +272 -0
- lorebase_core/revision/changeset.py +62 -0
- lorebase_core/revision/revision.py +121 -0
- lorebase_core/tree/__init__.py +76 -0
- lorebase_core/tree/diff.py +119 -0
- lorebase_core/tree/hamt.py +333 -0
- lorebase_core/tree/node.py +280 -0
- lorebase_core/tree/params.py +33 -0
- lorebase_core/tree/root.py +70 -0
- lorebase_core/tree/store.py +98 -0
- lorebase_core/types/__init__.py +71 -0
- lorebase_core/types/casts.py +271 -0
- lorebase_core/types/constraints.py +299 -0
- lorebase_core/types/encoding.py +538 -0
- lorebase_core/types/errors.py +41 -0
- lorebase_core/types/matching.py +40 -0
- lorebase_core/types/types.py +187 -0
- lorebase_core/validate/__init__.py +49 -0
- lorebase_core/validate/changes.py +70 -0
- lorebase_core/validate/changeset.py +551 -0
- lorebase_core/validate/data_rules.py +291 -0
- lorebase_core/validate/issues.py +123 -0
- lorebase_core/validate/schema_rules.py +1304 -0
- lorebase_core-0.2.3.dist-info/METADATA +9 -0
- lorebase_core-0.2.3.dist-info/RECORD +94 -0
- lorebase_core-0.2.3.dist-info/WHEEL +4 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.3"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Canonical JSON (RFC 8785 with Lorebase rules) and content hashing."""
|
|
2
|
+
|
|
3
|
+
from lorebase_core.canonical.hashing import (
|
|
4
|
+
HASH_SCHEME,
|
|
5
|
+
HASH_SIZE,
|
|
6
|
+
NODE_HASH_TYPE,
|
|
7
|
+
REVISION_HASH_TYPE,
|
|
8
|
+
ObjectType,
|
|
9
|
+
canonical_bytes,
|
|
10
|
+
from_hex,
|
|
11
|
+
hex,
|
|
12
|
+
node_hash,
|
|
13
|
+
normalize,
|
|
14
|
+
object_hash,
|
|
15
|
+
revision_hash,
|
|
16
|
+
)
|
|
17
|
+
from lorebase_core.canonical.jcs import CanonicalError, format_number, jcs_bytes
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"HASH_SCHEME",
|
|
21
|
+
"HASH_SIZE",
|
|
22
|
+
"NODE_HASH_TYPE",
|
|
23
|
+
"REVISION_HASH_TYPE",
|
|
24
|
+
"CanonicalError",
|
|
25
|
+
"ObjectType",
|
|
26
|
+
"canonical_bytes",
|
|
27
|
+
"format_number",
|
|
28
|
+
"from_hex",
|
|
29
|
+
"hex",
|
|
30
|
+
"jcs_bytes",
|
|
31
|
+
"node_hash",
|
|
32
|
+
"normalize",
|
|
33
|
+
"object_hash",
|
|
34
|
+
"revision_hash",
|
|
35
|
+
]
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""Lorebase canonical form and content hashing (design 6.1, AC-09)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import unicodedata
|
|
7
|
+
from collections.abc import Mapping, Sequence
|
|
8
|
+
from enum import StrEnum
|
|
9
|
+
|
|
10
|
+
from lorebase_core.canonical.jcs import CanonicalError, jcs_bytes
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"HASH_SCHEME",
|
|
14
|
+
"HASH_SIZE",
|
|
15
|
+
"NODE_HASH_TYPE",
|
|
16
|
+
"REVISION_HASH_TYPE",
|
|
17
|
+
"ObjectType",
|
|
18
|
+
"canonical_bytes",
|
|
19
|
+
"from_hex",
|
|
20
|
+
"hex",
|
|
21
|
+
"node_hash",
|
|
22
|
+
"normalize",
|
|
23
|
+
"object_hash",
|
|
24
|
+
"revision_hash",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
HASH_SCHEME = "lb1"
|
|
28
|
+
"""Version tag of the hashing scheme. Changing any hashing rule requires a new tag."""
|
|
29
|
+
|
|
30
|
+
HASH_SIZE = hashlib.sha256().digest_size
|
|
31
|
+
"""Size in bytes of every Lorebase hash."""
|
|
32
|
+
|
|
33
|
+
NODE_HASH_TYPE = "node"
|
|
34
|
+
REVISION_HASH_TYPE = "revision"
|
|
35
|
+
|
|
36
|
+
_SEPARATOR = b"\x00"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ObjectType(StrEnum):
|
|
40
|
+
"""Types of content-addressed objects (design 6.1)."""
|
|
41
|
+
|
|
42
|
+
SCHEMA_KIND = "schema.kind"
|
|
43
|
+
SCHEMA_RELATION = "schema.relation"
|
|
44
|
+
SCHEMA_TRAIT = "schema.trait"
|
|
45
|
+
SCHEMA_OPERATION = "schema.operation"
|
|
46
|
+
SCHEMA_DERIVATION = "schema.derivation"
|
|
47
|
+
SCHEMA_SOURCE = "schema.source"
|
|
48
|
+
SCHEMA_DOMAIN = "schema.domain"
|
|
49
|
+
RECORD = "record"
|
|
50
|
+
LINK = "link"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
_HASHED_TYPES = frozenset({*(t.value for t in ObjectType), REVISION_HASH_TYPE})
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def normalize(value: object) -> object:
|
|
57
|
+
"""Apply the Lorebase value rules before RFC 8785 serialization.
|
|
58
|
+
|
|
59
|
+
Strings (including object keys) are NFC-normalized and object members whose
|
|
60
|
+
value is ``None`` are omitted, since null and absent are the same. ``None``
|
|
61
|
+
inside arrays is kept, because array positions are significant.
|
|
62
|
+
Integers and decimals of Attribute values are expected to arrive already
|
|
63
|
+
encoded as canonical strings; timestamps are taken as given.
|
|
64
|
+
"""
|
|
65
|
+
if isinstance(value, str):
|
|
66
|
+
return unicodedata.normalize("NFC", value)
|
|
67
|
+
if isinstance(value, Mapping):
|
|
68
|
+
result: dict[str, object] = {}
|
|
69
|
+
for key, item in value.items():
|
|
70
|
+
if not isinstance(key, str):
|
|
71
|
+
raise CanonicalError(f"object keys must be strings, got {type(key).__name__}")
|
|
72
|
+
if item is None:
|
|
73
|
+
continue
|
|
74
|
+
nfc_key = unicodedata.normalize("NFC", key)
|
|
75
|
+
if nfc_key in result:
|
|
76
|
+
raise CanonicalError(f"duplicate object key after NFC normalization: {nfc_key!r}")
|
|
77
|
+
result[nfc_key] = normalize(item)
|
|
78
|
+
return result
|
|
79
|
+
if isinstance(value, Sequence) and not isinstance(value, bytes | bytearray):
|
|
80
|
+
return [normalize(item) for item in value]
|
|
81
|
+
return value
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def canonical_bytes(value: object) -> bytes:
|
|
85
|
+
"""Return the Lorebase canonical JSON bytes of ``value`` (RFC 8785 plus Lorebase rules)."""
|
|
86
|
+
return jcs_bytes(normalize(value))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def object_hash(object_type: str, value: object) -> bytes:
|
|
90
|
+
"""Return ``sha256("lb1\\x00" + object_type + "\\x00" + canonical_bytes(value))``.
|
|
91
|
+
|
|
92
|
+
``object_type`` is an :class:`ObjectType` or ``"revision"``.
|
|
93
|
+
"""
|
|
94
|
+
if object_type not in _HASHED_TYPES:
|
|
95
|
+
raise ValueError(f"unknown object type: {object_type!r}")
|
|
96
|
+
return _scoped_hash(str(object_type), canonical_bytes(value))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def revision_hash(value: object) -> bytes:
|
|
100
|
+
"""Hash a canonical Revision payload (design 6.4)."""
|
|
101
|
+
return _scoped_hash(REVISION_HASH_TYPE, canonical_bytes(value))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def node_hash(body: bytes) -> bytes:
|
|
105
|
+
"""Hash an encoded tree node: ``sha256("lb1\\x00node\\x00" + body)`` (design 6.2)."""
|
|
106
|
+
return _scoped_hash(NODE_HASH_TYPE, body)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def hex(h: bytes) -> str:
|
|
110
|
+
"""Render a hash as lowercase hex, the API representation."""
|
|
111
|
+
return h.hex()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def from_hex(text: str) -> bytes:
|
|
115
|
+
"""Parse a lowercase hex hash produced by :func:`hex`."""
|
|
116
|
+
if len(text) != 2 * HASH_SIZE or text != text.lower():
|
|
117
|
+
raise ValueError(f"expected {2 * HASH_SIZE} lowercase hex characters")
|
|
118
|
+
return bytes.fromhex(text)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _scoped_hash(scope: str, body: bytes) -> bytes:
|
|
122
|
+
digest = hashlib.sha256()
|
|
123
|
+
digest.update(HASH_SCHEME.encode("ascii"))
|
|
124
|
+
digest.update(_SEPARATOR)
|
|
125
|
+
digest.update(scope.encode("ascii"))
|
|
126
|
+
digest.update(_SEPARATOR)
|
|
127
|
+
digest.update(body)
|
|
128
|
+
return digest.digest()
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"""RFC 8785 JSON Canonicalization Scheme (JCS) serializer.
|
|
2
|
+
|
|
3
|
+
This module implements the plain RFC 8785 rules. The Lorebase value rules
|
|
4
|
+
(NFC strings, omitted nulls) are applied on top of it by
|
|
5
|
+
:func:`lorebase_core.canonical.canonical_bytes`.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import math
|
|
11
|
+
import re
|
|
12
|
+
from collections.abc import Mapping, Sequence
|
|
13
|
+
from decimal import Decimal
|
|
14
|
+
|
|
15
|
+
__all__ = ["CanonicalError", "format_number", "jcs_bytes"]
|
|
16
|
+
|
|
17
|
+
# ECMAScript Number::toString switches to exponential notation outside
|
|
18
|
+
# 1e-7 < |x| < 1e21 (RFC 8785, section 3.2.2.3).
|
|
19
|
+
_MAX_PLAIN_EXPONENT = 21
|
|
20
|
+
_MIN_PLAIN_EXPONENT = -6
|
|
21
|
+
|
|
22
|
+
_ESCAPES = {
|
|
23
|
+
0x08: "\\b",
|
|
24
|
+
0x09: "\\t",
|
|
25
|
+
0x0A: "\\n",
|
|
26
|
+
0x0C: "\\f",
|
|
27
|
+
0x0D: "\\r",
|
|
28
|
+
0x22: '\\"',
|
|
29
|
+
0x5C: "\\\\",
|
|
30
|
+
}
|
|
31
|
+
_FIRST_PRINTABLE = 0x20
|
|
32
|
+
#: Characters `_write_string` escapes; a string without any is written as it is.
|
|
33
|
+
_NEEDS_ESCAPE = re.compile(r'[\x00-\x1f"\\]')
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class CanonicalError(ValueError):
|
|
37
|
+
"""Raised when a value cannot be represented in canonical JSON."""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def jcs_bytes(value: object) -> bytes:
|
|
41
|
+
"""Serialize a JSON-compatible value to RFC 8785 canonical UTF-8 bytes.
|
|
42
|
+
|
|
43
|
+
Accepted types: ``None``, ``bool``, ``int`` (only if its decimal text is
|
|
44
|
+
the canonical text of an IEEE 754 double), ``float`` (finite), ``str``, mappings with ``str``
|
|
45
|
+
keys, lists and tuples.
|
|
46
|
+
"""
|
|
47
|
+
parts: list[str] = []
|
|
48
|
+
_write(value, parts)
|
|
49
|
+
try:
|
|
50
|
+
return "".join(parts).encode("utf-8")
|
|
51
|
+
except UnicodeEncodeError as exc:
|
|
52
|
+
raise CanonicalError("string contains a lone surrogate") from exc
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def format_number(value: float) -> str:
|
|
56
|
+
"""Format a number with the ECMAScript Number::toString rules (RFC 8785 3.2.2.3)."""
|
|
57
|
+
if isinstance(value, bool):
|
|
58
|
+
raise CanonicalError("booleans are not numbers")
|
|
59
|
+
if isinstance(value, int):
|
|
60
|
+
# RFC 8785 numbers are IEEE 754 doubles. An integer is accepted only when
|
|
61
|
+
# its decimal text is already the canonical text of its double, so no
|
|
62
|
+
# digit is silently changed; other integers must be passed as strings.
|
|
63
|
+
try:
|
|
64
|
+
text = format_number(float(value))
|
|
65
|
+
except OverflowError:
|
|
66
|
+
text = ""
|
|
67
|
+
if text != str(value):
|
|
68
|
+
raise CanonicalError(
|
|
69
|
+
f"integer {value} is not exactly representable; pass it as a string"
|
|
70
|
+
)
|
|
71
|
+
return text
|
|
72
|
+
if not math.isfinite(value):
|
|
73
|
+
raise CanonicalError("NaN and Infinity are not valid JSON numbers")
|
|
74
|
+
if value == 0:
|
|
75
|
+
return "0"
|
|
76
|
+
sign = "-" if value < 0 else ""
|
|
77
|
+
# repr() yields the shortest digit string that round-trips, which is the
|
|
78
|
+
# digit selection ECMAScript requires.
|
|
79
|
+
_, digit_tuple, exponent = Decimal(repr(abs(value))).as_tuple()
|
|
80
|
+
assert isinstance(exponent, int)
|
|
81
|
+
digits = "".join(str(d) for d in digit_tuple).rstrip("0")
|
|
82
|
+
exponent += len(digit_tuple) - len(digits)
|
|
83
|
+
k = len(digits)
|
|
84
|
+
n = exponent + k # value = 0.digits * 10**n
|
|
85
|
+
if k <= n <= _MAX_PLAIN_EXPONENT:
|
|
86
|
+
body = digits + "0" * (n - k)
|
|
87
|
+
elif 0 < n <= _MAX_PLAIN_EXPONENT:
|
|
88
|
+
body = digits[:n] + "." + digits[n:]
|
|
89
|
+
elif _MIN_PLAIN_EXPONENT < n <= 0:
|
|
90
|
+
body = "0." + "0" * (-n) + digits
|
|
91
|
+
else:
|
|
92
|
+
e = n - 1
|
|
93
|
+
e_text = f"+{e}" if e >= 0 else str(e)
|
|
94
|
+
mantissa = digits if k == 1 else digits[0] + "." + digits[1:]
|
|
95
|
+
body = f"{mantissa}e{e_text}"
|
|
96
|
+
return sign + body
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _write(value: object, out: list[str]) -> None:
|
|
100
|
+
if value is None:
|
|
101
|
+
out.append("null")
|
|
102
|
+
elif value is True:
|
|
103
|
+
out.append("true")
|
|
104
|
+
elif value is False:
|
|
105
|
+
out.append("false")
|
|
106
|
+
elif isinstance(value, int | float):
|
|
107
|
+
out.append(format_number(value))
|
|
108
|
+
elif isinstance(value, str):
|
|
109
|
+
_write_string(value, out)
|
|
110
|
+
elif isinstance(value, Mapping):
|
|
111
|
+
_write_object(value, out)
|
|
112
|
+
elif isinstance(value, Sequence) and not isinstance(value, bytes | bytearray):
|
|
113
|
+
out.append("[")
|
|
114
|
+
for index, item in enumerate(value):
|
|
115
|
+
if index:
|
|
116
|
+
out.append(",")
|
|
117
|
+
_write(item, out)
|
|
118
|
+
out.append("]")
|
|
119
|
+
else:
|
|
120
|
+
raise CanonicalError(f"unsupported type for canonical JSON: {type(value).__name__}")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _write_object(value: Mapping[object, object], out: list[str]) -> None:
|
|
124
|
+
keys: list[str] = []
|
|
125
|
+
for key in value:
|
|
126
|
+
if not isinstance(key, str):
|
|
127
|
+
raise CanonicalError(f"object keys must be strings, got {type(key).__name__}")
|
|
128
|
+
keys.append(key)
|
|
129
|
+
keys.sort(key=_utf16_sort_key)
|
|
130
|
+
out.append("{")
|
|
131
|
+
for index, key in enumerate(keys):
|
|
132
|
+
if index:
|
|
133
|
+
out.append(",")
|
|
134
|
+
_write_string(key, out)
|
|
135
|
+
out.append(":")
|
|
136
|
+
_write(value[key], out)
|
|
137
|
+
out.append("}")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _utf16_sort_key(key: str) -> bytes:
|
|
141
|
+
# Big-endian UTF-16 bytes compare exactly like sequences of UTF-16 code units.
|
|
142
|
+
try:
|
|
143
|
+
return key.encode("utf-16-be")
|
|
144
|
+
except UnicodeEncodeError as exc:
|
|
145
|
+
raise CanonicalError("object key contains a lone surrogate") from exc
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _write_string(value: str, out: list[str]) -> None:
|
|
149
|
+
if _NEEDS_ESCAPE.search(value) is None:
|
|
150
|
+
out.append(f'"{value}"')
|
|
151
|
+
return
|
|
152
|
+
out.append('"')
|
|
153
|
+
for char in value:
|
|
154
|
+
code = ord(char)
|
|
155
|
+
escaped = _ESCAPES.get(code)
|
|
156
|
+
if escaped is not None:
|
|
157
|
+
out.append(escaped)
|
|
158
|
+
elif code < _FIRST_PRINTABLE:
|
|
159
|
+
out.append(f"\\u{code:04x}")
|
|
160
|
+
else:
|
|
161
|
+
out.append(char)
|
|
162
|
+
out.append('"')
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Expression engine (design 5.7, 5.8, AC-06): CEL parsed by cel-python, type checked against
|
|
2
|
+
the Schema and evaluated in a bounded, deterministic sandbox without I/O.
|
|
3
|
+
|
|
4
|
+
- ``compile(expression, environment)`` parses and type checks; environments come from
|
|
5
|
+
``operation_environment`` and ``record_environment``.
|
|
6
|
+
- ``compile_operation`` / ``compile_derivation`` compile every expression of an element;
|
|
7
|
+
``derivation_inputs`` and ``links_read`` tell what a Derivation reads.
|
|
8
|
+
- ``evaluate_precondition``, ``check_preconditions``, ``evaluate_review_policy`` and
|
|
9
|
+
``plan_steps`` evaluate Operations; ``evaluate_derivation`` and ``matches_filter``
|
|
10
|
+
evaluate Derivations. Records come from a caller-supplied ``RecordResolver``.
|
|
11
|
+
- ``compile_row_expression`` and ``evaluate_row_expression`` handle the ``expression`` of a
|
|
12
|
+
Source's Attribute mapping, over one row of the Source; ``RowExpressions`` compiles them
|
|
13
|
+
once over the Source's columns.
|
|
14
|
+
- ``ExprLimits`` bounds compiling and evaluation; ``ExprError`` reports problems with a
|
|
15
|
+
stable code, the position in the expression and the path in the schema element.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from lorebase_core.expr.compiler import CompiledExpression, compile, run
|
|
19
|
+
from lorebase_core.expr.context import EvaluationContext, Principal, activation
|
|
20
|
+
from lorebase_core.expr.derivations import (
|
|
21
|
+
CompiledDerivation,
|
|
22
|
+
compile_derivation,
|
|
23
|
+
derivation_expression_errors,
|
|
24
|
+
derivation_inputs,
|
|
25
|
+
derivation_reads,
|
|
26
|
+
evaluate_derivation,
|
|
27
|
+
links_read,
|
|
28
|
+
matches_filter,
|
|
29
|
+
)
|
|
30
|
+
from lorebase_core.expr.environment import (
|
|
31
|
+
Environment,
|
|
32
|
+
LinkField,
|
|
33
|
+
operation_environment,
|
|
34
|
+
record_environment,
|
|
35
|
+
)
|
|
36
|
+
from lorebase_core.expr.errors import ExprError, ExprErrorCode, Position
|
|
37
|
+
from lorebase_core.expr.limits import ExprLimits
|
|
38
|
+
from lorebase_core.expr.operations import (
|
|
39
|
+
RESERVED_PARAMETER_NAMES,
|
|
40
|
+
CompiledOperation,
|
|
41
|
+
CompiledStep,
|
|
42
|
+
PreconditionFailure,
|
|
43
|
+
StepPlan,
|
|
44
|
+
check_preconditions,
|
|
45
|
+
compile_operation,
|
|
46
|
+
evaluate_precondition,
|
|
47
|
+
evaluate_review_policy,
|
|
48
|
+
operation_expression_errors,
|
|
49
|
+
plan_steps,
|
|
50
|
+
)
|
|
51
|
+
from lorebase_core.expr.resolver import (
|
|
52
|
+
LinkedRecord,
|
|
53
|
+
LinksRequest,
|
|
54
|
+
MemoryResolver,
|
|
55
|
+
RecordNotLoaded,
|
|
56
|
+
RecordRequest,
|
|
57
|
+
RecordResolver,
|
|
58
|
+
)
|
|
59
|
+
from lorebase_core.expr.rows import (
|
|
60
|
+
RowExpressions,
|
|
61
|
+
compile_row_expression,
|
|
62
|
+
evaluate_row_expression,
|
|
63
|
+
row_environment,
|
|
64
|
+
row_value,
|
|
65
|
+
row_variables,
|
|
66
|
+
)
|
|
67
|
+
from lorebase_core.expr.types import ExprType, TypeKind, from_type_spec
|
|
68
|
+
|
|
69
|
+
__all__ = [
|
|
70
|
+
"RESERVED_PARAMETER_NAMES",
|
|
71
|
+
"CompiledDerivation",
|
|
72
|
+
"CompiledExpression",
|
|
73
|
+
"CompiledOperation",
|
|
74
|
+
"CompiledStep",
|
|
75
|
+
"Environment",
|
|
76
|
+
"EvaluationContext",
|
|
77
|
+
"ExprError",
|
|
78
|
+
"ExprErrorCode",
|
|
79
|
+
"ExprLimits",
|
|
80
|
+
"ExprType",
|
|
81
|
+
"LinkField",
|
|
82
|
+
"LinkedRecord",
|
|
83
|
+
"LinksRequest",
|
|
84
|
+
"MemoryResolver",
|
|
85
|
+
"Position",
|
|
86
|
+
"PreconditionFailure",
|
|
87
|
+
"Principal",
|
|
88
|
+
"RecordNotLoaded",
|
|
89
|
+
"RecordRequest",
|
|
90
|
+
"RecordResolver",
|
|
91
|
+
"RowExpressions",
|
|
92
|
+
"StepPlan",
|
|
93
|
+
"TypeKind",
|
|
94
|
+
"activation",
|
|
95
|
+
"check_preconditions",
|
|
96
|
+
"compile",
|
|
97
|
+
"compile_derivation",
|
|
98
|
+
"compile_operation",
|
|
99
|
+
"compile_row_expression",
|
|
100
|
+
"derivation_expression_errors",
|
|
101
|
+
"derivation_inputs",
|
|
102
|
+
"derivation_reads",
|
|
103
|
+
"evaluate_derivation",
|
|
104
|
+
"evaluate_precondition",
|
|
105
|
+
"evaluate_review_policy",
|
|
106
|
+
"evaluate_row_expression",
|
|
107
|
+
"from_type_spec",
|
|
108
|
+
"links_read",
|
|
109
|
+
"matches_filter",
|
|
110
|
+
"operation_environment",
|
|
111
|
+
"operation_expression_errors",
|
|
112
|
+
"plan_steps",
|
|
113
|
+
"record_environment",
|
|
114
|
+
"row_environment",
|
|
115
|
+
"row_value",
|
|
116
|
+
"row_variables",
|
|
117
|
+
"run",
|
|
118
|
+
]
|