runic-py 0.3.2__tar.gz → 0.3.4__tar.gz
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.
- {runic_py-0.3.2 → runic_py-0.3.4}/.gitignore +11 -11
- {runic_py-0.3.2 → runic_py-0.3.4}/PKG-INFO +14 -13
- {runic_py-0.3.2 → runic_py-0.3.4}/README.md +11 -11
- {runic_py-0.3.2 → runic_py-0.3.4}/pyproject.toml +7 -4
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/adapters/__init__.py +1 -1
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/adapters/_base.py +1 -1
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/adapters/age.py +5 -5
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/adapters/arcadedb.py +3 -3
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/adapters/falkordb.py +4 -4
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/adapters/memgraph.py +4 -4
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/adapters/neo4j.py +4 -4
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/operations.py +2 -2
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/schema.py +3 -3
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/__init__.py +24 -24
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/core/descriptors.py +6 -6
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/core/metadata.py +1 -1
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/core/models.py +4 -4
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/driver/__init__.py +3 -3
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/driver/age.py +5 -5
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/driver/arcadedb.py +3 -3
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/driver/bolt.py +3 -3
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/driver/factory.py +7 -7
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/driver/falkordb.py +1 -1
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/driver/memgraph.py +4 -4
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/driver/neo4j.py +4 -4
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/exceptions.py +1 -1
- runic_py-0.3.4/runic/ogm/mapper/__init__.py +5 -0
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/mapper/mapper.py +15 -15
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/mapper/relationship_loader.py +4 -4
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/mapper/relationship_writer.py +5 -5
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/operations.py +2 -2
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/query/__init__.py +13 -13
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/query/_compiler.py +5 -5
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/query/_decoder.py +6 -6
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/query/builder.py +28 -28
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/query/expressions.py +7 -7
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/query/specialised.py +8 -8
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/query/traversal.py +3 -3
- runic_py-0.3.4/runic/ogm/repository/__init__.py +9 -0
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/repository/async_repository.py +8 -8
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/repository/cypher.py +1 -1
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/repository/repository.py +7 -7
- runic_py-0.3.4/runic/ogm/schema/__init__.py +8 -0
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/session/_base.py +7 -7
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/session/async_session.py +25 -25
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/session/connection_pool.py +3 -3
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/session/session.py +31 -31
- runic_py-0.3.2/runic/orm/mapper/__init__.py +0 -5
- runic_py-0.3.2/runic/orm/repository/__init__.py +0 -9
- runic_py-0.3.2/runic/orm/schema/__init__.py +0 -8
- {runic_py-0.3.2 → runic_py-0.3.4}/LICENSE.md +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/__init__.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/__init__.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/autogen.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/checksum.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/cli.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/config.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/context.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/exceptions.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/introspect.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/manifest.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/script.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/service.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/templates/env.py.mako +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/templates/script.py.mako +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/testing.py +0 -0
- {runic_py-0.3.2 → runic_py-0.3.4}/runic/migrate/version.py +0 -0
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/core/__init__.py +0 -0
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/core/types.py +0 -0
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/repository/_base.py +0 -0
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/repository/protocol.py +0 -0
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/schema/index_manager.py +0 -0
- {runic_py-0.3.2/runic/orm → runic_py-0.3.4/runic/ogm}/session/__init__.py +0 -0
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
__pycache__/
|
|
2
2
|
__pypackages__/
|
|
3
3
|
.cache
|
|
4
|
+
.claude/ralph-loop.local.md
|
|
4
5
|
.coverage
|
|
5
6
|
.coverage.*
|
|
7
|
+
.deepeval_telemetry.txt
|
|
8
|
+
.deepeval-cache.json
|
|
9
|
+
.deepeval/
|
|
6
10
|
.dmypy.json
|
|
7
11
|
.DS_Store
|
|
8
12
|
.eggs/
|
|
@@ -13,6 +17,8 @@ __pypackages__/
|
|
|
13
17
|
.idea/
|
|
14
18
|
.installed.cfg
|
|
15
19
|
.ipynb_checkpoints
|
|
20
|
+
.latest_run_full.json
|
|
21
|
+
.latest_test_run.json
|
|
16
22
|
.mypy_cache/
|
|
17
23
|
.nox/
|
|
18
24
|
.pdm.toml
|
|
@@ -23,10 +29,12 @@ __pypackages__/
|
|
|
23
29
|
.python_packages
|
|
24
30
|
.pytype/
|
|
25
31
|
.ropeproject
|
|
32
|
+
.runic
|
|
26
33
|
.scrapy
|
|
27
34
|
.spyderproject
|
|
28
35
|
.spyproject
|
|
29
36
|
.states
|
|
37
|
+
.task/
|
|
30
38
|
.tox/
|
|
31
39
|
.venv
|
|
32
40
|
.venv.mac
|
|
@@ -57,11 +65,13 @@ __pypackages__/
|
|
|
57
65
|
*$py.class
|
|
58
66
|
/site
|
|
59
67
|
/vectorstore/
|
|
68
|
+
# DeepEval run caches (tests/evals suite runs from an isolated venv)
|
|
60
69
|
aila-storage/
|
|
61
70
|
assets/external/
|
|
62
71
|
build/
|
|
63
72
|
celerybeat-schedule
|
|
64
73
|
celerybeat.pid
|
|
74
|
+
CLAUDE.local.md
|
|
65
75
|
configuration/config.abaz009.yaml
|
|
66
76
|
configuration/config.bubb001.yaml
|
|
67
77
|
configuration/config.stie104.yaml
|
|
@@ -98,6 +108,7 @@ pip-delete-this-directory.txt
|
|
|
98
108
|
pip-log.txt
|
|
99
109
|
Pipfile
|
|
100
110
|
profile_default/
|
|
111
|
+
runic_test/
|
|
101
112
|
sdist/
|
|
102
113
|
share/python-wheels/
|
|
103
114
|
sketchpad/
|
|
@@ -112,14 +123,3 @@ var/
|
|
|
112
123
|
venv.bak/
|
|
113
124
|
venv/
|
|
114
125
|
wheels/
|
|
115
|
-
.task/
|
|
116
|
-
.runic
|
|
117
|
-
runic_test/
|
|
118
|
-
.claude/ralph-loop.local.md
|
|
119
|
-
|
|
120
|
-
# DeepEval run caches (tests/evals suite runs from an isolated venv)
|
|
121
|
-
.deepeval/
|
|
122
|
-
.deepeval-cache.json
|
|
123
|
-
.deepeval_telemetry.txt
|
|
124
|
-
.latest_run_full.json
|
|
125
|
-
.latest_test_run.json
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: runic-py
|
|
3
|
-
Version: 0.3.
|
|
4
|
-
Summary: Graph schema migrations and
|
|
3
|
+
Version: 0.3.4
|
|
4
|
+
Summary: Graph schema migrations and OGM for Cypher-based graph databases.
|
|
5
5
|
Project-URL: Homepage, https://runic-py.readthedocs.io/en/latest/
|
|
6
6
|
Project-URL: Repository, https://github.com/jenreh/runic
|
|
7
7
|
Author: Jens Rehpöhler
|
|
@@ -15,6 +15,7 @@ Classifier: Topic :: Database
|
|
|
15
15
|
Requires-Python: >=3.14
|
|
16
16
|
Requires-Dist: mako<2.0.0,>=1.3.0
|
|
17
17
|
Requires-Dist: rich<16.0.0,>=14.0.0
|
|
18
|
+
Requires-Dist: shellingham<2.0.0,>=1.5.0
|
|
18
19
|
Requires-Dist: typer<1.0.0,>=0.26.0
|
|
19
20
|
Provides-Extra: age
|
|
20
21
|
Requires-Dist: psycopg<4.0.0,>=3.3.4; extra == 'age'
|
|
@@ -39,9 +40,9 @@ Description-Content-Type: text/markdown
|
|
|
39
40
|
|
|
40
41
|
# Runic
|
|
41
42
|
|
|
42
|
-
**Graph schema migrations and
|
|
43
|
+
**Graph schema migrations and OGM for Cypher-based graph databases.**
|
|
43
44
|
|
|
44
|
-

|
|
45
46
|
[](https://pypi.org/project/runic-py/)
|
|
46
47
|
[](https://www.python.org)
|
|
47
48
|
[](LICENSE.md)
|
|
@@ -55,7 +56,7 @@ Description-Content-Type: text/markdown
|
|
|
55
56
|
**Runic** is a Python toolkit for Cypher-based graph databases that covers two layers:
|
|
56
57
|
|
|
57
58
|
- **`runic.migrate`** — Alembic-style schema migrations with revision tracking, a CLI, and rollback snapshots.
|
|
58
|
-
- **`runic.
|
|
59
|
+
- **`runic.ogm`** — A lightweight graph OGM: declare `Node` and `Edge` models, manage sessions, traverse relationships, and sync indexes — all via a pluggable driver layer supporting FalkorDB, ArcadeDB, and any Bolt-compatible database.
|
|
59
60
|
|
|
60
61
|
## Features
|
|
61
62
|
|
|
@@ -183,12 +184,12 @@ print("current:", runic.migrate.current())
|
|
|
183
184
|
|
|
184
185
|
---
|
|
185
186
|
|
|
186
|
-
## runic.
|
|
187
|
+
## runic.ogm
|
|
187
188
|
|
|
188
189
|
### Defining models
|
|
189
190
|
|
|
190
191
|
```python
|
|
191
|
-
from runic.
|
|
192
|
+
from runic.ogm import Field, Node, Edge, Relation
|
|
192
193
|
|
|
193
194
|
|
|
194
195
|
class User(Node, labels=["User"]):
|
|
@@ -223,7 +224,7 @@ class Author(Node, labels=["Author"]):
|
|
|
223
224
|
`Session` accepts any `GraphDriver`. Use `create_driver()` to build one for your backend:
|
|
224
225
|
|
|
225
226
|
```python
|
|
226
|
-
from runic.
|
|
227
|
+
from runic.ogm import Session, Repository, create_driver
|
|
227
228
|
|
|
228
229
|
# Pick your backend — the rest of the code is identical
|
|
229
230
|
driver = create_driver("falkordb", host="localhost", port=6379, graph="myapp")
|
|
@@ -264,7 +265,7 @@ with Session(driver) as session:
|
|
|
264
265
|
### Pagination and custom queries
|
|
265
266
|
|
|
266
267
|
```python
|
|
267
|
-
from runic.
|
|
268
|
+
from runic.ogm import Repository
|
|
268
269
|
|
|
269
270
|
with Session(driver) as session:
|
|
270
271
|
repo = Repository(session, User)
|
|
@@ -290,7 +291,7 @@ class UserRepository(Repository[User]):
|
|
|
290
291
|
dynamic query composition (e.g. conditional UI filters) before execution:
|
|
291
292
|
|
|
292
293
|
```python
|
|
293
|
-
from runic.
|
|
294
|
+
from runic.ogm import select
|
|
294
295
|
|
|
295
296
|
stmt = select(User).where(User.active == True)
|
|
296
297
|
if min_age > 0:
|
|
@@ -311,7 +312,7 @@ still fully supported.
|
|
|
311
312
|
Declare indexes inline on `Field`, then let `SchemaManager` keep the live graph in sync:
|
|
312
313
|
|
|
313
314
|
```python
|
|
314
|
-
from runic.
|
|
315
|
+
from runic.ogm import Field, IndexManager, Node, SchemaManager
|
|
315
316
|
|
|
316
317
|
|
|
317
318
|
class Place(Node, labels=["Place"]):
|
|
@@ -336,7 +337,7 @@ print("valid:", result.is_valid)
|
|
|
336
337
|
```python
|
|
337
338
|
from datetime import UTC, datetime
|
|
338
339
|
from enum import StrEnum
|
|
339
|
-
from runic.
|
|
340
|
+
from runic.ogm import Field, GeoLocation, Node, Vector
|
|
340
341
|
|
|
341
342
|
|
|
342
343
|
class Status(StrEnum):
|
|
@@ -357,4 +358,4 @@ class Article(Node, labels=["Article"]):
|
|
|
357
358
|
|
|
358
359
|
## Documentation
|
|
359
360
|
|
|
360
|
-
Full conceptual overview, async usage, advanced CLI flags, and API reference at the complete [Runic Documentation](https://runic-py.readthedocs.io/latest
|
|
361
|
+
Full conceptual overview, async usage, advanced CLI flags, and API reference at the complete [Runic Documentation](https://runic-py.readthedocs.io/en/latest).
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
# Runic
|
|
5
5
|
|
|
6
|
-
**Graph schema migrations and
|
|
6
|
+
**Graph schema migrations and OGM for Cypher-based graph databases.**
|
|
7
7
|
|
|
8
|
-

|
|
9
9
|
[](https://pypi.org/project/runic-py/)
|
|
10
10
|
[](https://www.python.org)
|
|
11
11
|
[](LICENSE.md)
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
**Runic** is a Python toolkit for Cypher-based graph databases that covers two layers:
|
|
20
20
|
|
|
21
21
|
- **`runic.migrate`** — Alembic-style schema migrations with revision tracking, a CLI, and rollback snapshots.
|
|
22
|
-
- **`runic.
|
|
22
|
+
- **`runic.ogm`** — A lightweight graph OGM: declare `Node` and `Edge` models, manage sessions, traverse relationships, and sync indexes — all via a pluggable driver layer supporting FalkorDB, ArcadeDB, and any Bolt-compatible database.
|
|
23
23
|
|
|
24
24
|
## Features
|
|
25
25
|
|
|
@@ -147,12 +147,12 @@ print("current:", runic.migrate.current())
|
|
|
147
147
|
|
|
148
148
|
---
|
|
149
149
|
|
|
150
|
-
## runic.
|
|
150
|
+
## runic.ogm
|
|
151
151
|
|
|
152
152
|
### Defining models
|
|
153
153
|
|
|
154
154
|
```python
|
|
155
|
-
from runic.
|
|
155
|
+
from runic.ogm import Field, Node, Edge, Relation
|
|
156
156
|
|
|
157
157
|
|
|
158
158
|
class User(Node, labels=["User"]):
|
|
@@ -187,7 +187,7 @@ class Author(Node, labels=["Author"]):
|
|
|
187
187
|
`Session` accepts any `GraphDriver`. Use `create_driver()` to build one for your backend:
|
|
188
188
|
|
|
189
189
|
```python
|
|
190
|
-
from runic.
|
|
190
|
+
from runic.ogm import Session, Repository, create_driver
|
|
191
191
|
|
|
192
192
|
# Pick your backend — the rest of the code is identical
|
|
193
193
|
driver = create_driver("falkordb", host="localhost", port=6379, graph="myapp")
|
|
@@ -228,7 +228,7 @@ with Session(driver) as session:
|
|
|
228
228
|
### Pagination and custom queries
|
|
229
229
|
|
|
230
230
|
```python
|
|
231
|
-
from runic.
|
|
231
|
+
from runic.ogm import Repository
|
|
232
232
|
|
|
233
233
|
with Session(driver) as session:
|
|
234
234
|
repo = Repository(session, User)
|
|
@@ -254,7 +254,7 @@ class UserRepository(Repository[User]):
|
|
|
254
254
|
dynamic query composition (e.g. conditional UI filters) before execution:
|
|
255
255
|
|
|
256
256
|
```python
|
|
257
|
-
from runic.
|
|
257
|
+
from runic.ogm import select
|
|
258
258
|
|
|
259
259
|
stmt = select(User).where(User.active == True)
|
|
260
260
|
if min_age > 0:
|
|
@@ -275,7 +275,7 @@ still fully supported.
|
|
|
275
275
|
Declare indexes inline on `Field`, then let `SchemaManager` keep the live graph in sync:
|
|
276
276
|
|
|
277
277
|
```python
|
|
278
|
-
from runic.
|
|
278
|
+
from runic.ogm import Field, IndexManager, Node, SchemaManager
|
|
279
279
|
|
|
280
280
|
|
|
281
281
|
class Place(Node, labels=["Place"]):
|
|
@@ -300,7 +300,7 @@ print("valid:", result.is_valid)
|
|
|
300
300
|
```python
|
|
301
301
|
from datetime import UTC, datetime
|
|
302
302
|
from enum import StrEnum
|
|
303
|
-
from runic.
|
|
303
|
+
from runic.ogm import Field, GeoLocation, Node, Vector
|
|
304
304
|
|
|
305
305
|
|
|
306
306
|
class Status(StrEnum):
|
|
@@ -321,4 +321,4 @@ class Article(Node, labels=["Article"]):
|
|
|
321
321
|
|
|
322
322
|
## Documentation
|
|
323
323
|
|
|
324
|
-
Full conceptual overview, async usage, advanced CLI flags, and API reference at the complete [Runic Documentation](https://runic-py.readthedocs.io/latest
|
|
324
|
+
Full conceptual overview, async usage, advanced CLI flags, and API reference at the complete [Runic Documentation](https://runic-py.readthedocs.io/en/latest).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "runic-py"
|
|
3
|
-
version = "0.3.
|
|
4
|
-
description = "Graph schema migrations and
|
|
3
|
+
version = "0.3.4"
|
|
4
|
+
description = "Graph schema migrations and OGM for Cypher-based graph databases."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.14"
|
|
7
7
|
license = { text = "MIT" }
|
|
@@ -19,6 +19,7 @@ dependencies = [
|
|
|
19
19
|
"typer>=0.26.0,<1.0.0",
|
|
20
20
|
"rich>=14.0.0,<16.0.0",
|
|
21
21
|
"mako>=1.3.0,<2.0.0",
|
|
22
|
+
"shellingham>=1.5.0,<2.0.0",
|
|
22
23
|
]
|
|
23
24
|
|
|
24
25
|
[project.optional-dependencies]
|
|
@@ -92,7 +93,7 @@ exclude = [
|
|
|
92
93
|
|
|
93
94
|
[tool.bumpversion]
|
|
94
95
|
commit = false
|
|
95
|
-
current_version = "0.3.
|
|
96
|
+
current_version = "0.3.4"
|
|
96
97
|
tag = false
|
|
97
98
|
allow-dirty = false
|
|
98
99
|
|
|
@@ -271,6 +272,8 @@ exclude = [
|
|
|
271
272
|
"build",
|
|
272
273
|
"dist",
|
|
273
274
|
"examples",
|
|
275
|
+
"skill",
|
|
276
|
+
"tests/evals",
|
|
274
277
|
]
|
|
275
278
|
|
|
276
279
|
[tool.ty.rules]
|
|
@@ -282,7 +285,7 @@ cache_dir = ".cache/mypy"
|
|
|
282
285
|
|
|
283
286
|
[tool.coverage.run]
|
|
284
287
|
branch = true
|
|
285
|
-
source = ["
|
|
288
|
+
source = ["runic"]
|
|
286
289
|
omit = ["runic/adapters/*"]
|
|
287
290
|
|
|
288
291
|
[tool.coverage.report]
|
|
@@ -21,7 +21,7 @@ class GraphAdapter(Protocol):
|
|
|
21
21
|
@property
|
|
22
22
|
def name(self) -> str: ...
|
|
23
23
|
|
|
24
|
-
# Normalised query execution (satisfies runic.
|
|
24
|
+
# Normalised query execution (satisfies runic.ogm.operations._Executor)
|
|
25
25
|
def execute(self, cypher: str, params: dict[str, Any]) -> Any: ...
|
|
26
26
|
|
|
27
27
|
# Low-level query execution
|
|
@@ -12,7 +12,7 @@ from abc import ABC, abstractmethod
|
|
|
12
12
|
from typing import Any, Protocol, runtime_checkable
|
|
13
13
|
|
|
14
14
|
from runic.migrate.introspect import LiveSchema, SchemaSnapshot
|
|
15
|
-
from runic.
|
|
15
|
+
from runic.ogm.schema.index_manager import IndexSpec
|
|
16
16
|
|
|
17
17
|
log = logging.getLogger(__name__)
|
|
18
18
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Apache AGE stores graph data inside PostgreSQL, so migration version-tracking
|
|
4
4
|
nodes are created as AGE vertices (not PostgreSQL tables). The adapter
|
|
5
5
|
executes Cypher through the AGE ``cypher()`` SQL function and delegates
|
|
6
|
-
agtype decoding to the :mod:`runic.
|
|
6
|
+
agtype decoding to the :mod:`runic.ogm.driver.age` module.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
from __future__ import annotations
|
|
@@ -13,8 +13,8 @@ from typing import Any
|
|
|
13
13
|
|
|
14
14
|
from runic.migrate.adapters import GraphAdapter
|
|
15
15
|
from runic.migrate.adapters._base import GraphAdapterBase
|
|
16
|
-
from runic.
|
|
17
|
-
from runic.
|
|
16
|
+
from runic.ogm.driver.age import AGEDriver
|
|
17
|
+
from runic.ogm.schema.index_manager import IndexSpec
|
|
18
18
|
|
|
19
19
|
log = logging.getLogger(__name__)
|
|
20
20
|
|
|
@@ -40,7 +40,7 @@ class AGEAdapter(GraphAdapterBase, GraphAdapter):
|
|
|
40
40
|
username: str = "postgres",
|
|
41
41
|
password: str = "", # noqa: S107
|
|
42
42
|
) -> AGEAdapter:
|
|
43
|
-
from runic.
|
|
43
|
+
from runic.ogm.driver.age import create_age_driver
|
|
44
44
|
|
|
45
45
|
driver = create_age_driver(
|
|
46
46
|
host=host,
|
|
@@ -64,7 +64,7 @@ class AGEAdapter(GraphAdapterBase, GraphAdapter):
|
|
|
64
64
|
def run_query(self, query: str, params: dict | None = None) -> Any:
|
|
65
65
|
result = self._driver.execute(query, params or {})
|
|
66
66
|
# AGEDriver no longer auto-commits; the adapter owns the transaction
|
|
67
|
-
# lifecycle for write operations (not managed by an
|
|
67
|
+
# lifecycle for write operations (not managed by an OGM Session here).
|
|
68
68
|
self._driver.commit()
|
|
69
69
|
return result
|
|
70
70
|
|
|
@@ -7,9 +7,9 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
from runic.migrate.adapters import GraphAdapter
|
|
9
9
|
from runic.migrate.adapters._base import GraphAdapterBase
|
|
10
|
-
from runic.
|
|
11
|
-
from runic.
|
|
12
|
-
from runic.
|
|
10
|
+
from runic.ogm.driver.arcadedb import ArcadeDBDialect
|
|
11
|
+
from runic.ogm.driver.bolt import BoltDriver
|
|
12
|
+
from runic.ogm.schema.index_manager import IndexSpec
|
|
13
13
|
|
|
14
14
|
log = logging.getLogger(__name__)
|
|
15
15
|
|
|
@@ -10,8 +10,8 @@ from runic.migrate.adapters._base import _encode_kv_list, _parse_kv_list
|
|
|
10
10
|
from runic.migrate.exceptions import ConstraintFailedError, ConstraintTimeoutError
|
|
11
11
|
from runic.migrate.introspect import LiveSchema
|
|
12
12
|
from runic.migrate.manifest import UniqueConstraint
|
|
13
|
-
from runic.
|
|
14
|
-
from runic.
|
|
13
|
+
from runic.ogm.driver.falkordb import FalkorDBDriver, FalkorDBResult
|
|
14
|
+
from runic.ogm.schema.index_manager import IndexSpec
|
|
15
15
|
|
|
16
16
|
log = logging.getLogger(__name__)
|
|
17
17
|
|
|
@@ -34,7 +34,7 @@ _SET_TRACKING_QUERY = (
|
|
|
34
34
|
class FalkorDBAdapter(GraphAdapter):
|
|
35
35
|
"""GraphAdapter implementation for FalkorDB (standalone or embedded via falkordblite).
|
|
36
36
|
|
|
37
|
-
Query execution is routed through :class:`~runic.
|
|
37
|
+
Query execution is routed through :class:`~runic.ogm.driver.falkordb.FalkorDBDriver`
|
|
38
38
|
so results are normalised to ``GraphResult.rows`` — consistent with Bolt adapters.
|
|
39
39
|
The raw ``db`` and ``graph`` references are kept only for FalkorDB-specific migration
|
|
40
40
|
operations (constraint DDL via Redis commands, snapshot copy/delete).
|
|
@@ -97,7 +97,7 @@ class FalkorDBAdapter(GraphAdapter):
|
|
|
97
97
|
return self._graph.name # type: ignore[no-any-return]
|
|
98
98
|
|
|
99
99
|
def execute(self, cypher: str, params: dict[str, Any]) -> FalkorDBResult:
|
|
100
|
-
"""Normalised query execution via
|
|
100
|
+
"""Normalised query execution via OGM driver (result has .rows)."""
|
|
101
101
|
return self._driver.execute(cypher, params)
|
|
102
102
|
|
|
103
103
|
def run_query(self, query: str, params: dict | None = None) -> FalkorDBResult:
|
|
@@ -7,9 +7,9 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
from runic.migrate.adapters import GraphAdapter
|
|
9
9
|
from runic.migrate.adapters._base import GraphAdapterBase
|
|
10
|
-
from runic.
|
|
11
|
-
from runic.
|
|
12
|
-
from runic.
|
|
10
|
+
from runic.ogm.driver.bolt import BoltDriver
|
|
11
|
+
from runic.ogm.driver.memgraph import _MEMGRAPH_DIALECT, MemgraphDialect
|
|
12
|
+
from runic.ogm.schema.index_manager import IndexSpec
|
|
13
13
|
|
|
14
14
|
log = logging.getLogger(__name__)
|
|
15
15
|
|
|
@@ -17,7 +17,7 @@ log = logging.getLogger(__name__)
|
|
|
17
17
|
class MemgraphAdapter(GraphAdapterBase, GraphAdapter):
|
|
18
18
|
"""Migration adapter for Memgraph accessed via Bolt protocol.
|
|
19
19
|
|
|
20
|
-
Named index convention (must match :class:`~runic.
|
|
20
|
+
Named index convention (must match :class:`~runic.ogm.driver.memgraph.MemgraphDialect`):
|
|
21
21
|
|
|
22
22
|
- **Fulltext** (text search) index name = ``{label}`` (e.g. ``Post``)
|
|
23
23
|
- **Vector** index name = ``{label}_{prop}`` (e.g. ``Article_embedding``)
|
|
@@ -7,9 +7,9 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
from runic.migrate.adapters import GraphAdapter
|
|
9
9
|
from runic.migrate.adapters._base import GraphAdapterBase
|
|
10
|
-
from runic.
|
|
11
|
-
from runic.
|
|
12
|
-
from runic.
|
|
10
|
+
from runic.ogm.driver.bolt import BoltDriver
|
|
11
|
+
from runic.ogm.driver.neo4j import _NEO4J_DIALECT, Neo4jDialect
|
|
12
|
+
from runic.ogm.schema.index_manager import IndexSpec
|
|
13
13
|
|
|
14
14
|
log = logging.getLogger(__name__)
|
|
15
15
|
|
|
@@ -17,7 +17,7 @@ log = logging.getLogger(__name__)
|
|
|
17
17
|
class Neo4jAdapter(GraphAdapterBase, GraphAdapter):
|
|
18
18
|
"""Migration adapter for Neo4j 5.x accessed via Bolt protocol.
|
|
19
19
|
|
|
20
|
-
Named index convention (must match :class:`~runic.
|
|
20
|
+
Named index convention (must match :class:`~runic.ogm.driver.neo4j.Neo4jDialect`):
|
|
21
21
|
|
|
22
22
|
- **Fulltext** index name = ``{label}`` (e.g. ``Post``)
|
|
23
23
|
- **Vector** index name = ``{label}_{prop}`` (e.g. ``Article_embedding``)
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
|
-
from runic.
|
|
6
|
+
from runic.ogm.operations import DataOperations
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from runic.migrate.adapters import GraphAdapter
|
|
@@ -14,7 +14,7 @@ log = logging.getLogger(__name__)
|
|
|
14
14
|
class GraphOperations(DataOperations):
|
|
15
15
|
"""Migration-script API: data manipulation + DDL, both with preview mode.
|
|
16
16
|
|
|
17
|
-
Extends :class:`~runic.
|
|
17
|
+
Extends :class:`~runic.ogm.operations.DataOperations` with DDL operations
|
|
18
18
|
(indexes, constraints, snapshots) that delegate to the underlying adapter.
|
|
19
19
|
|
|
20
20
|
Migration scripts receive this object as their ``ops`` argument::
|
|
@@ -6,7 +6,7 @@ import logging
|
|
|
6
6
|
from dataclasses import dataclass, field
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
|
-
from runic.
|
|
9
|
+
from runic.ogm.schema.index_manager import IndexSpec, extract_declared_specs
|
|
10
10
|
|
|
11
11
|
log = logging.getLogger(__name__)
|
|
12
12
|
|
|
@@ -138,7 +138,7 @@ class IndexManager:
|
|
|
138
138
|
When *if_not_exists* is ``True`` (default), existing non-FULLTEXT specs are
|
|
139
139
|
skipped. FULLTEXT creation is always attempted — adapters must handle idempotency.
|
|
140
140
|
"""
|
|
141
|
-
from runic.
|
|
141
|
+
from runic.ogm.core.models import Edge, Node
|
|
142
142
|
|
|
143
143
|
if issubclass(entity_class, Node):
|
|
144
144
|
label: str = getattr(entity_class, "_primary_label", entity_class.__name__)
|
|
@@ -252,7 +252,7 @@ class SchemaManager:
|
|
|
252
252
|
No-op for schemaless backends. Issues ``CREATE VERTEX TYPE`` / ``CREATE EDGE TYPE``
|
|
253
253
|
DDL for ArcadeDB.
|
|
254
254
|
"""
|
|
255
|
-
from runic.
|
|
255
|
+
from runic.ogm.core.models import Edge, Node
|
|
256
256
|
|
|
257
257
|
for cls in entity_classes:
|
|
258
258
|
if issubclass(cls, Node):
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
"""runic.
|
|
1
|
+
"""runic.ogm — lightweight graph OGM for Cypher-based graph databases."""
|
|
2
2
|
|
|
3
|
-
from runic.
|
|
3
|
+
from runic.ogm.driver import (
|
|
4
4
|
AsyncGraphDriver,
|
|
5
5
|
GraphDialect,
|
|
6
6
|
GraphDriver,
|
|
7
7
|
GraphResult,
|
|
8
8
|
TransactionalGraphDriver,
|
|
9
9
|
)
|
|
10
|
-
from runic.
|
|
11
|
-
from runic.
|
|
12
|
-
from runic.
|
|
13
|
-
from runic.
|
|
14
|
-
from runic.
|
|
10
|
+
from runic.ogm.driver.age import AGEDialect, AGEDriver, create_age_driver
|
|
11
|
+
from runic.ogm.driver.arcadedb import ArcadeDBDialect, create_arcadedb_driver
|
|
12
|
+
from runic.ogm.driver.bolt import BoltDriver
|
|
13
|
+
from runic.ogm.driver.factory import create_driver
|
|
14
|
+
from runic.ogm.driver.falkordb import (
|
|
15
15
|
AsyncFalkorDBDriver,
|
|
16
16
|
FalkorDBDialect,
|
|
17
17
|
FalkorDBDriver,
|
|
18
18
|
create_falkordb_driver,
|
|
19
19
|
)
|
|
20
|
-
from runic.
|
|
21
|
-
from runic.
|
|
22
|
-
from runic.
|
|
20
|
+
from runic.ogm.driver.memgraph import MemgraphDialect, create_memgraph_driver
|
|
21
|
+
from runic.ogm.driver.neo4j import Neo4jDialect, create_neo4j_driver
|
|
22
|
+
from runic.ogm.core.descriptors import (
|
|
23
23
|
MISSING,
|
|
24
24
|
Field,
|
|
25
25
|
FieldDescriptor,
|
|
@@ -27,9 +27,9 @@ from runic.orm.core.descriptors import (
|
|
|
27
27
|
Relation,
|
|
28
28
|
_NOT_LOADED,
|
|
29
29
|
)
|
|
30
|
-
from runic.
|
|
31
|
-
from runic.
|
|
32
|
-
from runic.
|
|
30
|
+
from runic.ogm.core.metadata import EdgeMeta, MetaData, NodeMeta, get_metadata, metadata
|
|
31
|
+
from runic.ogm.core.models import Edge, Node
|
|
32
|
+
from runic.ogm.core.types import (
|
|
33
33
|
DatetimeConverter,
|
|
34
34
|
EnumConverter,
|
|
35
35
|
GeoLocation,
|
|
@@ -38,7 +38,7 @@ from runic.orm.core.types import (
|
|
|
38
38
|
Vector,
|
|
39
39
|
VectorConverter,
|
|
40
40
|
)
|
|
41
|
-
from runic.
|
|
41
|
+
from runic.ogm.exceptions import (
|
|
42
42
|
DetachedEntityError,
|
|
43
43
|
EntityNotFoundError,
|
|
44
44
|
FieldValidationError,
|
|
@@ -46,11 +46,11 @@ from runic.orm.exceptions import (
|
|
|
46
46
|
MetadataError,
|
|
47
47
|
OrmError,
|
|
48
48
|
)
|
|
49
|
-
from runic.
|
|
50
|
-
from runic.
|
|
51
|
-
from runic.
|
|
52
|
-
from runic.
|
|
53
|
-
from runic.
|
|
49
|
+
from runic.ogm.mapper.mapper import Mapper
|
|
50
|
+
from runic.ogm.mapper.relationship_loader import RelationshipLoader
|
|
51
|
+
from runic.ogm.repository.async_repository import AsyncRepository
|
|
52
|
+
from runic.ogm.repository.repository import Repository
|
|
53
|
+
from runic.ogm.query import (
|
|
54
54
|
AsyncQueryBuilder,
|
|
55
55
|
FulltextQueryBuilder,
|
|
56
56
|
QueryBuilder,
|
|
@@ -63,7 +63,7 @@ from runic.orm.query import (
|
|
|
63
63
|
select,
|
|
64
64
|
sum_,
|
|
65
65
|
)
|
|
66
|
-
from runic.
|
|
66
|
+
from runic.ogm.query.expressions import (
|
|
67
67
|
AggExpr,
|
|
68
68
|
CompoundExpr,
|
|
69
69
|
Expr,
|
|
@@ -71,10 +71,10 @@ from runic.orm.query.expressions import (
|
|
|
71
71
|
NegatedExpr,
|
|
72
72
|
OrderExpr,
|
|
73
73
|
)
|
|
74
|
-
from runic.
|
|
75
|
-
from runic.
|
|
76
|
-
from runic.
|
|
77
|
-
from runic.
|
|
74
|
+
from runic.ogm.schema.index_manager import IndexSpec
|
|
75
|
+
from runic.ogm.session.async_session import AsyncSession
|
|
76
|
+
from runic.ogm.session.connection_pool import AsyncConnectionManager, ConnectionManager
|
|
77
|
+
from runic.ogm.session.session import Session
|
|
78
78
|
|
|
79
79
|
__all__ = [ # noqa: RUF022
|
|
80
80
|
# Driver / dialect
|
|
@@ -7,7 +7,7 @@ from collections.abc import Callable
|
|
|
7
7
|
from typing import TYPE_CHECKING, Any, Literal, overload
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
-
from runic.
|
|
10
|
+
from runic.ogm.core.types import TypeConverter
|
|
11
11
|
|
|
12
12
|
log = logging.getLogger(__name__)
|
|
13
13
|
|
|
@@ -43,8 +43,8 @@ class FieldDescriptor:
|
|
|
43
43
|
--------------------------
|
|
44
44
|
When accessed at the **class level** (``User.name``, ``Rated.score``),
|
|
45
45
|
the descriptor returns itself. The comparison operators defined below
|
|
46
|
-
produce :class:`~runic.
|
|
47
|
-
with :meth:`~runic.
|
|
46
|
+
produce :class:`~runic.ogm.query.expressions.FilterExpr` objects for use
|
|
47
|
+
with :meth:`~runic.ogm.query.builder.QueryBuilder.where`:
|
|
48
48
|
|
|
49
49
|
.. code-block:: python
|
|
50
50
|
|
|
@@ -159,7 +159,7 @@ class FieldDescriptor:
|
|
|
159
159
|
|
|
160
160
|
session_ref = obj.__dict__.get("_session")
|
|
161
161
|
if session_ref is None:
|
|
162
|
-
from runic.
|
|
162
|
+
from runic.ogm.exceptions import DetachedEntityError
|
|
163
163
|
|
|
164
164
|
raise DetachedEntityError(
|
|
165
165
|
f"Entity {obj!r} has no active session. "
|
|
@@ -167,7 +167,7 @@ class FieldDescriptor:
|
|
|
167
167
|
)
|
|
168
168
|
session = session_ref() if isinstance(session_ref, weakref.ref) else session_ref
|
|
169
169
|
if session is None:
|
|
170
|
-
from runic.
|
|
170
|
+
from runic.ogm.exceptions import DetachedEntityError
|
|
171
171
|
|
|
172
172
|
raise DetachedEntityError(
|
|
173
173
|
f"Entity {obj!r}'s session was garbage-collected. "
|
|
@@ -228,7 +228,7 @@ class FieldDescriptor:
|
|
|
228
228
|
__hash__ = object.__hash__ # type: ignore[assignment]
|
|
229
229
|
|
|
230
230
|
def _make_filter(self, op: str, value: Any, negate: bool = False) -> Any:
|
|
231
|
-
from runic.
|
|
231
|
+
from runic.ogm.query.expressions import FilterExpr
|
|
232
232
|
|
|
233
233
|
return FilterExpr(
|
|
234
234
|
cls=self._owner or type(self),
|
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import logging
|
|
6
6
|
from dataclasses import dataclass, field
|
|
7
7
|
|
|
8
|
-
from runic.
|
|
8
|
+
from runic.ogm.core.descriptors import FieldDescriptor, FieldInfo
|
|
9
9
|
|
|
10
10
|
log = logging.getLogger(__name__)
|
|
11
11
|
|