kitedb 0.2.5__cp313-cp313-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.
- kitedb/__init__.py +273 -0
- kitedb/_kitedb.cp313-win_amd64.pyd +0 -0
- kitedb/_kitedb.pyi +677 -0
- kitedb/builders.py +901 -0
- kitedb/fluent.py +850 -0
- kitedb/schema.py +327 -0
- kitedb/traversal.py +1523 -0
- kitedb/vector_index.py +472 -0
- kitedb-0.2.5.dist-info/METADATA +217 -0
- kitedb-0.2.5.dist-info/RECORD +12 -0
- kitedb-0.2.5.dist-info/WHEEL +4 -0
- kitedb-0.2.5.dist-info/licenses/LICENSE +21 -0
kitedb/schema.py
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Schema Definition API for KiteDB
|
|
3
|
+
|
|
4
|
+
Provides type-safe schema builders for defining graph nodes and edges.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
>>> from kitedb import node, edge, prop, optional
|
|
8
|
+
>>>
|
|
9
|
+
>>> user = node("user",
|
|
10
|
+
... key=lambda id: f"user:{id}",
|
|
11
|
+
... props={
|
|
12
|
+
... "name": prop.string("name"),
|
|
13
|
+
... "email": prop.string("email"),
|
|
14
|
+
... "age": optional(prop.int("age")),
|
|
15
|
+
... }
|
|
16
|
+
... )
|
|
17
|
+
>>>
|
|
18
|
+
>>> knows = edge("knows", {
|
|
19
|
+
... "since": prop.int("since"),
|
|
20
|
+
... })
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from dataclasses import dataclass, field
|
|
26
|
+
from typing import (
|
|
27
|
+
Any,
|
|
28
|
+
Callable,
|
|
29
|
+
Dict,
|
|
30
|
+
Generic,
|
|
31
|
+
Literal,
|
|
32
|
+
Optional,
|
|
33
|
+
TypeVar,
|
|
34
|
+
Union,
|
|
35
|
+
overload,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# ============================================================================
|
|
39
|
+
# Property Type System
|
|
40
|
+
# ============================================================================
|
|
41
|
+
|
|
42
|
+
PropType = Literal["string", "int", "float", "bool", "vector"]
|
|
43
|
+
|
|
44
|
+
# Type variable for property values
|
|
45
|
+
T = TypeVar("T")
|
|
46
|
+
KeyArg = TypeVar("KeyArg", str, int)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True)
|
|
50
|
+
class PropDef(Generic[T]):
|
|
51
|
+
"""
|
|
52
|
+
A property definition with type information.
|
|
53
|
+
|
|
54
|
+
This holds metadata about a property (name, type, whether it's optional).
|
|
55
|
+
The generic parameter T represents the Python type this property maps to:
|
|
56
|
+
- "string" -> str
|
|
57
|
+
- "int" -> int
|
|
58
|
+
- "float" -> float
|
|
59
|
+
- "bool" -> bool
|
|
60
|
+
- "vector" -> list[float]
|
|
61
|
+
"""
|
|
62
|
+
name: str
|
|
63
|
+
type: PropType
|
|
64
|
+
optional: bool = False
|
|
65
|
+
|
|
66
|
+
def make_optional(self) -> PropDef[T]:
|
|
67
|
+
"""Convert this property to an optional property."""
|
|
68
|
+
return PropDef(name=self.name, type=self.type, optional=True)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class PropBuilder:
|
|
72
|
+
"""
|
|
73
|
+
Property type builders.
|
|
74
|
+
|
|
75
|
+
Use these to define typed properties on nodes and edges.
|
|
76
|
+
|
|
77
|
+
Example:
|
|
78
|
+
>>> name = prop.string("name")
|
|
79
|
+
>>> age = prop.int("age")
|
|
80
|
+
>>> score = optional(prop.float("score"))
|
|
81
|
+
>>> active = prop.bool("active")
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def string(name: str) -> PropDef[str]:
|
|
86
|
+
"""
|
|
87
|
+
String property.
|
|
88
|
+
Stored as UTF-8 strings.
|
|
89
|
+
"""
|
|
90
|
+
return PropDef(name=name, type="string")
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def int(name: str) -> PropDef[int]:
|
|
94
|
+
"""
|
|
95
|
+
Integer property.
|
|
96
|
+
Stored as 64-bit signed integers.
|
|
97
|
+
"""
|
|
98
|
+
return PropDef(name=name, type="int")
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def float(name: str) -> PropDef[float]:
|
|
102
|
+
"""
|
|
103
|
+
Float property.
|
|
104
|
+
Stored as 64-bit IEEE 754 floats.
|
|
105
|
+
"""
|
|
106
|
+
return PropDef(name=name, type="float")
|
|
107
|
+
|
|
108
|
+
@staticmethod
|
|
109
|
+
def bool(name: str) -> PropDef[bool]:
|
|
110
|
+
"""
|
|
111
|
+
Boolean property.
|
|
112
|
+
"""
|
|
113
|
+
return PropDef(name=name, type="bool")
|
|
114
|
+
|
|
115
|
+
@staticmethod
|
|
116
|
+
def vector(name: str) -> PropDef[list[float]]:
|
|
117
|
+
"""
|
|
118
|
+
Vector property for embeddings.
|
|
119
|
+
Stored as float32 arrays.
|
|
120
|
+
"""
|
|
121
|
+
return PropDef(name=name, type="vector")
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# Global prop builder instance
|
|
125
|
+
prop = PropBuilder()
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def optional(p: PropDef[T]) -> PropDef[T]:
|
|
129
|
+
"""
|
|
130
|
+
Helper to make a property optional.
|
|
131
|
+
|
|
132
|
+
Example:
|
|
133
|
+
>>> age = optional(prop.int("age"))
|
|
134
|
+
"""
|
|
135
|
+
return p.make_optional()
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# ============================================================================
|
|
139
|
+
# Node Definition
|
|
140
|
+
# ============================================================================
|
|
141
|
+
|
|
142
|
+
# Type for property schemas
|
|
143
|
+
PropsSchema = Dict[str, PropDef[Any]]
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@dataclass
|
|
147
|
+
class NodeDef(Generic[KeyArg]):
|
|
148
|
+
"""
|
|
149
|
+
A defined node type with metadata.
|
|
150
|
+
|
|
151
|
+
Created by `node()` and used throughout the API.
|
|
152
|
+
|
|
153
|
+
Attributes:
|
|
154
|
+
name: The node type name (must be unique per schema)
|
|
155
|
+
key_fn: Function to transform application IDs to full node keys
|
|
156
|
+
props: Property definitions for this node type
|
|
157
|
+
"""
|
|
158
|
+
name: str
|
|
159
|
+
key_fn: Callable[[KeyArg], str]
|
|
160
|
+
props: PropsSchema
|
|
161
|
+
# Internal: resolved prop key IDs (set during db initialization)
|
|
162
|
+
_prop_key_ids: Dict[str, int] = field(default_factory=dict, repr=False)
|
|
163
|
+
|
|
164
|
+
def __hash__(self) -> int:
|
|
165
|
+
return hash(self.name)
|
|
166
|
+
|
|
167
|
+
def __eq__(self, other: object) -> bool:
|
|
168
|
+
if isinstance(other, NodeDef):
|
|
169
|
+
return self.name == other.name
|
|
170
|
+
return False
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def node(
|
|
174
|
+
name: str,
|
|
175
|
+
*,
|
|
176
|
+
key: Callable[[KeyArg], str],
|
|
177
|
+
props: PropsSchema,
|
|
178
|
+
) -> NodeDef[KeyArg]:
|
|
179
|
+
"""
|
|
180
|
+
Define a node type with properties.
|
|
181
|
+
|
|
182
|
+
Creates a node definition that can be used for all node operations
|
|
183
|
+
(insert, update, delete, query). Provides full type inference for
|
|
184
|
+
insert values and return types.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
name: The node type name (must be unique)
|
|
188
|
+
key: Function to generate full keys from application IDs
|
|
189
|
+
props: Property definitions using `prop.*` builders
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
A NodeDef that can be used with the database API
|
|
193
|
+
|
|
194
|
+
Example:
|
|
195
|
+
>>> user = node("user",
|
|
196
|
+
... key=lambda id: f"user:{id}",
|
|
197
|
+
... props={
|
|
198
|
+
... "name": prop.string("name"),
|
|
199
|
+
... "email": prop.string("email"),
|
|
200
|
+
... "age": optional(prop.int("age")),
|
|
201
|
+
... }
|
|
202
|
+
... )
|
|
203
|
+
"""
|
|
204
|
+
return NodeDef(name=name, key_fn=key, props=props)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# Backwards compatibility alias
|
|
208
|
+
define_node = node
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
# ============================================================================
|
|
212
|
+
# Edge Definition
|
|
213
|
+
# ============================================================================
|
|
214
|
+
|
|
215
|
+
@dataclass
|
|
216
|
+
class EdgeDef:
|
|
217
|
+
"""
|
|
218
|
+
A defined edge type with metadata.
|
|
219
|
+
|
|
220
|
+
Created by `edge()` and used throughout the API.
|
|
221
|
+
|
|
222
|
+
Attributes:
|
|
223
|
+
name: The edge type name (must be unique per schema)
|
|
224
|
+
props: Property definitions for this edge type
|
|
225
|
+
"""
|
|
226
|
+
name: str
|
|
227
|
+
props: PropsSchema = field(default_factory=dict)
|
|
228
|
+
# Internal: resolved edge type ID (set during db initialization)
|
|
229
|
+
_etype_id: Optional[int] = field(default=None, repr=False)
|
|
230
|
+
# Internal: resolved prop key IDs (set during db initialization)
|
|
231
|
+
_prop_key_ids: Dict[str, int] = field(default_factory=dict, repr=False)
|
|
232
|
+
|
|
233
|
+
def __hash__(self) -> int:
|
|
234
|
+
return hash(self.name)
|
|
235
|
+
|
|
236
|
+
def __eq__(self, other: object) -> bool:
|
|
237
|
+
if isinstance(other, EdgeDef):
|
|
238
|
+
return self.name == other.name
|
|
239
|
+
return False
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@overload
|
|
243
|
+
def edge(name: str) -> EdgeDef: ...
|
|
244
|
+
|
|
245
|
+
@overload
|
|
246
|
+
def edge(name: str, props: PropsSchema) -> EdgeDef: ...
|
|
247
|
+
|
|
248
|
+
def edge(name: str, props: Optional[PropsSchema] = None) -> EdgeDef:
|
|
249
|
+
"""
|
|
250
|
+
Define an edge type with optional properties.
|
|
251
|
+
|
|
252
|
+
Creates an edge definition that can be used for all edge operations
|
|
253
|
+
(link, unlink, query). Edges are directional and can have properties.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
name: The edge type name (must be unique)
|
|
257
|
+
props: Optional property definitions using `prop.*` builders
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
An EdgeDef that can be used with the database API
|
|
261
|
+
|
|
262
|
+
Example:
|
|
263
|
+
>>> # Edge with properties
|
|
264
|
+
>>> knows = edge("knows", {
|
|
265
|
+
... "since": prop.int("since"),
|
|
266
|
+
... "weight": optional(prop.float("weight")),
|
|
267
|
+
... })
|
|
268
|
+
>>>
|
|
269
|
+
>>> # Edge without properties
|
|
270
|
+
>>> follows = edge("follows")
|
|
271
|
+
"""
|
|
272
|
+
return EdgeDef(name=name, props=props or {})
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
# Backwards compatibility alias
|
|
276
|
+
define_edge = edge
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# ============================================================================
|
|
280
|
+
# Type Inference Helpers (for documentation and type checkers)
|
|
281
|
+
# ============================================================================
|
|
282
|
+
|
|
283
|
+
# These TypedDict-style types help type checkers understand the shape
|
|
284
|
+
# of data passed to/from the API. In practice, we use runtime dicts
|
|
285
|
+
# but these provide IDE completion and type checking.
|
|
286
|
+
|
|
287
|
+
from typing import TypedDict
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
class NodeRefBase(TypedDict, total=False):
|
|
291
|
+
"""Base type for node references."""
|
|
292
|
+
pass
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class NodeRef(TypedDict):
|
|
296
|
+
"""
|
|
297
|
+
A node reference with its ID and key.
|
|
298
|
+
|
|
299
|
+
All returned nodes have these system fields plus their property fields.
|
|
300
|
+
"""
|
|
301
|
+
id: int # Internal node ID
|
|
302
|
+
key: str # Full node key (e.g., "user:alice")
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
# For dynamic property types, we can't use TypedDict directly
|
|
306
|
+
# but we provide runtime type checking and IDE support through
|
|
307
|
+
# the builder pattern.
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
__all__ = [
|
|
311
|
+
# Property builders
|
|
312
|
+
"prop",
|
|
313
|
+
"PropDef",
|
|
314
|
+
"PropBuilder",
|
|
315
|
+
"optional",
|
|
316
|
+
# Node definitions
|
|
317
|
+
"NodeDef",
|
|
318
|
+
"node",
|
|
319
|
+
"define_node", # backwards compat
|
|
320
|
+
# Edge definitions
|
|
321
|
+
"EdgeDef",
|
|
322
|
+
"edge",
|
|
323
|
+
"define_edge", # backwards compat
|
|
324
|
+
# Type helpers
|
|
325
|
+
"PropsSchema",
|
|
326
|
+
"NodeRef",
|
|
327
|
+
]
|