runic-py 0.2.0__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.2.0/.gitignore +117 -0
- runic_py-0.2.0/LICENSE.md +21 -0
- runic_py-0.2.0/PKG-INFO +192 -0
- runic_py-0.2.0/README.md +171 -0
- runic_py-0.2.0/pyproject.toml +267 -0
- runic_py-0.2.0/runic/__init__.py +13 -0
- runic_py-0.2.0/runic/migrate/__init__.py +27 -0
- runic_py-0.2.0/runic/migrate/adapters/__init__.py +129 -0
- runic_py-0.2.0/runic/migrate/adapters/falkordb.py +353 -0
- runic_py-0.2.0/runic/migrate/autogen.py +242 -0
- runic_py-0.2.0/runic/migrate/checksum.py +14 -0
- runic_py-0.2.0/runic/migrate/cli.py +880 -0
- runic_py-0.2.0/runic/migrate/config.py +8 -0
- runic_py-0.2.0/runic/migrate/context.py +526 -0
- runic_py-0.2.0/runic/migrate/exceptions.py +18 -0
- runic_py-0.2.0/runic/migrate/introspect.py +556 -0
- runic_py-0.2.0/runic/migrate/manifest.py +81 -0
- runic_py-0.2.0/runic/migrate/operations.py +173 -0
- runic_py-0.2.0/runic/migrate/script.py +452 -0
- runic_py-0.2.0/runic/migrate/service.py +27 -0
- runic_py-0.2.0/runic/migrate/templates/env.py.mako +86 -0
- runic_py-0.2.0/runic/migrate/templates/script.py.mako +27 -0
- runic_py-0.2.0/runic/migrate/testing.py +48 -0
- runic_py-0.2.0/runic/migrate/version.py +38 -0
- runic_py-0.2.0/runic/orm/__init__.py +82 -0
- runic_py-0.2.0/runic/orm/core/__init__.py +0 -0
- runic_py-0.2.0/runic/orm/core/descriptors.py +305 -0
- runic_py-0.2.0/runic/orm/core/metadata.py +216 -0
- runic_py-0.2.0/runic/orm/core/models.py +312 -0
- runic_py-0.2.0/runic/orm/core/types.py +158 -0
- runic_py-0.2.0/runic/orm/exceptions.py +30 -0
- runic_py-0.2.0/runic/orm/mapper/__init__.py +0 -0
- runic_py-0.2.0/runic/orm/mapper/mapper.py +361 -0
- runic_py-0.2.0/runic/orm/mapper/relationship_loader.py +251 -0
- runic_py-0.2.0/runic/orm/repository/__init__.py +12 -0
- runic_py-0.2.0/runic/orm/repository/async_repository.py +180 -0
- runic_py-0.2.0/runic/orm/repository/cypher.py +67 -0
- runic_py-0.2.0/runic/orm/repository/pagination.py +105 -0
- runic_py-0.2.0/runic/orm/repository/protocol.py +91 -0
- runic_py-0.2.0/runic/orm/repository/repository.py +190 -0
- runic_py-0.2.0/runic/orm/schema/__init__.py +11 -0
- runic_py-0.2.0/runic/orm/schema/index_manager.py +195 -0
- runic_py-0.2.0/runic/orm/schema/schema_manager.py +173 -0
- runic_py-0.2.0/runic/orm/session/__init__.py +0 -0
- runic_py-0.2.0/runic/orm/session/async_session.py +340 -0
- runic_py-0.2.0/runic/orm/session/connection_pool.py +56 -0
- runic_py-0.2.0/runic/orm/session/session.py +385 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
__pypackages__/
|
|
3
|
+
.cache
|
|
4
|
+
.coverage
|
|
5
|
+
.coverage.*
|
|
6
|
+
.dmypy.json
|
|
7
|
+
.DS_Store
|
|
8
|
+
.eggs/
|
|
9
|
+
.env
|
|
10
|
+
.env.backup
|
|
11
|
+
.env.docker
|
|
12
|
+
.hypothesis/
|
|
13
|
+
.idea/
|
|
14
|
+
.installed.cfg
|
|
15
|
+
.ipynb_checkpoints
|
|
16
|
+
.mypy_cache/
|
|
17
|
+
.nox/
|
|
18
|
+
.pdm.toml
|
|
19
|
+
.pybuilder/
|
|
20
|
+
.pyre/
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.Python
|
|
23
|
+
.python_packages
|
|
24
|
+
.pytype/
|
|
25
|
+
.ropeproject
|
|
26
|
+
.scrapy
|
|
27
|
+
.spyderproject
|
|
28
|
+
.spyproject
|
|
29
|
+
.states
|
|
30
|
+
.tox/
|
|
31
|
+
.venv
|
|
32
|
+
.venv.mac
|
|
33
|
+
.web
|
|
34
|
+
.webassets-cache
|
|
35
|
+
*.bak
|
|
36
|
+
*.cover
|
|
37
|
+
*.db
|
|
38
|
+
*.egg
|
|
39
|
+
*.egg-info/
|
|
40
|
+
*.kv-env.*
|
|
41
|
+
*.log
|
|
42
|
+
*.manifest
|
|
43
|
+
*.mo
|
|
44
|
+
*.pot
|
|
45
|
+
*.py,cover
|
|
46
|
+
*.py[cod]
|
|
47
|
+
*.sage.py
|
|
48
|
+
*.so
|
|
49
|
+
*.spec
|
|
50
|
+
*.terraform.lock.hcl
|
|
51
|
+
*.tfplan
|
|
52
|
+
*.tfstate
|
|
53
|
+
*.tfstate.*.backup
|
|
54
|
+
*.tfstate.backup
|
|
55
|
+
*.tfvars
|
|
56
|
+
**/.terraform/*
|
|
57
|
+
*$py.class
|
|
58
|
+
/site
|
|
59
|
+
/vectorstore/
|
|
60
|
+
aila-storage/
|
|
61
|
+
assets/external/
|
|
62
|
+
build/
|
|
63
|
+
celerybeat-schedule
|
|
64
|
+
celerybeat.pid
|
|
65
|
+
configuration/config.abaz009.yaml
|
|
66
|
+
configuration/config.bubb001.yaml
|
|
67
|
+
configuration/config.stie104.yaml
|
|
68
|
+
configuration/config.voro047.yaml
|
|
69
|
+
connector examples/sharepoint.json
|
|
70
|
+
cover/
|
|
71
|
+
coverage.xml
|
|
72
|
+
cython_debug/
|
|
73
|
+
db.sqlite3
|
|
74
|
+
db.sqlite3-journal
|
|
75
|
+
develop-eggs/
|
|
76
|
+
dist/
|
|
77
|
+
dmypy.json
|
|
78
|
+
docs/_build/
|
|
79
|
+
Documents/
|
|
80
|
+
downloads/
|
|
81
|
+
eggs/
|
|
82
|
+
env.bak/
|
|
83
|
+
env/
|
|
84
|
+
ENV/
|
|
85
|
+
htmlcov/
|
|
86
|
+
instance/
|
|
87
|
+
ipython_config.py
|
|
88
|
+
knowledge/migrate.py
|
|
89
|
+
lib/
|
|
90
|
+
lib64/
|
|
91
|
+
local_settings.py
|
|
92
|
+
local.settings.json
|
|
93
|
+
MANIFEST
|
|
94
|
+
nosetests.xml
|
|
95
|
+
out
|
|
96
|
+
parts/
|
|
97
|
+
pip-delete-this-directory.txt
|
|
98
|
+
pip-log.txt
|
|
99
|
+
Pipfile
|
|
100
|
+
profile_default/
|
|
101
|
+
sdist/
|
|
102
|
+
share/python-wheels/
|
|
103
|
+
sketchpad/
|
|
104
|
+
sketchpad/
|
|
105
|
+
stores/
|
|
106
|
+
target/
|
|
107
|
+
tests/mcp_test.py
|
|
108
|
+
tmp.txt
|
|
109
|
+
uploaded_files/
|
|
110
|
+
uploads/
|
|
111
|
+
var/
|
|
112
|
+
venv.bak/
|
|
113
|
+
venv/
|
|
114
|
+
wheels/
|
|
115
|
+
.task/
|
|
116
|
+
.runic
|
|
117
|
+
runic_test/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Jens Rehpöhler
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
runic_py-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: runic-py
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Graph schema migrations for FalkorDB.
|
|
5
|
+
Project-URL: Homepage, https://runic-py.readthedocs.io/latest/
|
|
6
|
+
Project-URL: Repository, https://github.com/jenreh/runic
|
|
7
|
+
Author: Jens Rehpöhler
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE.md
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Topic :: Home Automation
|
|
15
|
+
Requires-Python: >=3.14
|
|
16
|
+
Requires-Dist: falkordb<2.0.0,>=1.6.0
|
|
17
|
+
Requires-Dist: mako<2.0.0,>=1.3.0
|
|
18
|
+
Requires-Dist: rich<16.0.0,>=15.0.0
|
|
19
|
+
Requires-Dist: typer<1.0.0,>=0.26.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
<div align="center">
|
|
23
|
+
<img src="docs/source/_static/runic.svg" width="240" alt="Runic logo">
|
|
24
|
+
|
|
25
|
+
# Runic
|
|
26
|
+
|
|
27
|
+
**Graph schema migrations for FalkorDB.**
|
|
28
|
+
|
|
29
|
+

|
|
30
|
+
[](https://www.python.org)
|
|
31
|
+
[](LICENSE.md)
|
|
32
|
+
|
|
33
|
+
[Features](#features) • [Installation](#installation) • [A Simple Example](#a-simple-example) • [Documentation](#documentation)
|
|
34
|
+
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
**Runic** is a lightweight, Alembic-style migration framework built specifically for [FalkorDB](https://falkordb.com/).
|
|
40
|
+
It brings robust revision tracking, linear graph migrations, and a powerful CLI to graph database environments, managing schema versioning through Cypher scripts and native FalkorDB syntax.
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- **Alembic-Style Workflow** — Familiar CLI verbs like `init`, `revision`, `upgrade`, `downgrade`, and `current`.
|
|
45
|
+
- **Graph-Native** — Treats your database as a graph. Stores migration states intelligently inside dedicated nodes (e.g., `:_FalkorMigrateVersion`).
|
|
46
|
+
- **Idempotent Cypher** — Encourages explicit, heavily-guarded migration steps, supporting robust backward capability even without transactional DDLs.
|
|
47
|
+
- **Offline & Dry Run** — Review generated Cypher scripts thoroughly before executing them in production.
|
|
48
|
+
- **Rollback Snapshots** — Advanced capabilities utilizing `GRAPH.COPY` for high-risk, non-reversible data migrations.
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
Install via `pip` or `uv`:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
uv pip install runic
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or add it to an existing project:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv add runic
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
> [!NOTE]
|
|
65
|
+
> Runic requires Python 3.14+ and is optimized for the latest FalkorDB clients.
|
|
66
|
+
|
|
67
|
+
## A Simple Example
|
|
68
|
+
|
|
69
|
+
Initialize your project and generate a new revision:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Set up a new runic environment
|
|
73
|
+
runic init
|
|
74
|
+
|
|
75
|
+
# Create your first revision script
|
|
76
|
+
runic revision -m "create user index"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
This generates a revision file in `runic/versions`. Open it and define your upgrades and downgrades:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
"""create user index
|
|
83
|
+
|
|
84
|
+
Revision ID: 1975ea83b712
|
|
85
|
+
Revises: None
|
|
86
|
+
Create Date: 2026-05-30 14:00:00.000000
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
from datetime import UTC, datetime
|
|
90
|
+
|
|
91
|
+
revision = "1975ea83b712"
|
|
92
|
+
down_revision = None
|
|
93
|
+
message = "create user index"
|
|
94
|
+
create_date = datetime.fromisoformat("2026-05-30T14:00:00+00:00")
|
|
95
|
+
branch_labels = []
|
|
96
|
+
depends_on = []
|
|
97
|
+
irreversible = False
|
|
98
|
+
snapshot = False
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def upgrade(op) -> None:
|
|
102
|
+
op.create_range_index("User", "email")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def downgrade(op) -> None:
|
|
106
|
+
op.drop_range_index("User", "email")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Then apply your changes:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
runic upgrade # apply all pending revisions
|
|
113
|
+
runic downgrade # roll back one step (default target: -1)
|
|
114
|
+
runic downgrade 1975e # roll back to a revision — prefix is enough
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Baselining an existing graph
|
|
118
|
+
|
|
119
|
+
If you have a FalkorDB graph that was built without Runic, use `baseline` to bring it under management without re-running anything on the source:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# Introspect the live graph, generate a root revision, and stamp it as applied
|
|
123
|
+
runic baseline -m "baseline"
|
|
124
|
+
# Generated: runic/versions/<hex>_baseline.py
|
|
125
|
+
# Stamped: <hex>
|
|
126
|
+
|
|
127
|
+
# Verify the graph is now tracked
|
|
128
|
+
runic current
|
|
129
|
+
# <hex> baseline
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The generated revision recreates all indexes and constraints from scratch — safe to replay on a fresh empty graph (CI, cloning, new tenants):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
runic upgrade head # rebuilds the full schema on an empty graph
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Re-running `baseline` on an already-managed graph is refused:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
runic baseline -m "again"
|
|
142
|
+
# Error: Graph already managed by runic.migrate. Use `runic upgrade` instead.
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
To mark an existing graph as baselined without generating a file (useful when you manage the revision file yourself):
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
runic baseline --stamp-only
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Baseline → autogenerate workflow
|
|
152
|
+
|
|
153
|
+
Once you have a baseline revision, use the standard autogenerate workflow to evolve the schema:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# After changing your SchemaManifest in env.py:
|
|
157
|
+
runic revision --autogenerate -m "add embedding index"
|
|
158
|
+
runic upgrade head
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The baseline revision is the root of the chain (`down_revision = None`). Future revisions chain off it normally.
|
|
162
|
+
|
|
163
|
+
## Programmatic SDK
|
|
164
|
+
|
|
165
|
+
Use runic directly in Python — no CLI, no `env.py` needed:
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from pathlib import Path
|
|
169
|
+
from runic import Runic, init
|
|
170
|
+
from runic.migrate.adapters import create_adapter
|
|
171
|
+
|
|
172
|
+
# One-time setup: scaffold the migration directory
|
|
173
|
+
init(Path("runic/"))
|
|
174
|
+
|
|
175
|
+
# Connect and run
|
|
176
|
+
adapter = create_adapter(
|
|
177
|
+
"falkordb",
|
|
178
|
+
url="falkor://localhost:6379",
|
|
179
|
+
graph_name="my_graph",
|
|
180
|
+
)
|
|
181
|
+
runic = Runic(adapter, script_location=Path("runic/"))
|
|
182
|
+
runic.migrate.upgrade("head")
|
|
183
|
+
|
|
184
|
+
print("current:", runic.migrate.current())
|
|
185
|
+
print("history:", runic.migrate.get_history())
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`Runic` is the single class you need. It handles upgrades, downgrades, stamping, history queries, and revision creation in one coherent API.
|
|
189
|
+
|
|
190
|
+
## Documentation
|
|
191
|
+
|
|
192
|
+
For a full conceptual overview, advanced CLI usage, and deep dives into branching or multi-head resolution, visit the complete [Runic Documentation](https://runic-py.readthedocs.io/latest/).
|
runic_py-0.2.0/README.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="docs/source/_static/runic.svg" width="240" alt="Runic logo">
|
|
3
|
+
|
|
4
|
+
# Runic
|
|
5
|
+
|
|
6
|
+
**Graph schema migrations for FalkorDB.**
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
[](https://www.python.org)
|
|
10
|
+
[](LICENSE.md)
|
|
11
|
+
|
|
12
|
+
[Features](#features) • [Installation](#installation) • [A Simple Example](#a-simple-example) • [Documentation](#documentation)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
**Runic** is a lightweight, Alembic-style migration framework built specifically for [FalkorDB](https://falkordb.com/).
|
|
19
|
+
It brings robust revision tracking, linear graph migrations, and a powerful CLI to graph database environments, managing schema versioning through Cypher scripts and native FalkorDB syntax.
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **Alembic-Style Workflow** — Familiar CLI verbs like `init`, `revision`, `upgrade`, `downgrade`, and `current`.
|
|
24
|
+
- **Graph-Native** — Treats your database as a graph. Stores migration states intelligently inside dedicated nodes (e.g., `:_FalkorMigrateVersion`).
|
|
25
|
+
- **Idempotent Cypher** — Encourages explicit, heavily-guarded migration steps, supporting robust backward capability even without transactional DDLs.
|
|
26
|
+
- **Offline & Dry Run** — Review generated Cypher scripts thoroughly before executing them in production.
|
|
27
|
+
- **Rollback Snapshots** — Advanced capabilities utilizing `GRAPH.COPY` for high-risk, non-reversible data migrations.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
Install via `pip` or `uv`:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv pip install runic
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or add it to an existing project:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uv add runic
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> [!NOTE]
|
|
44
|
+
> Runic requires Python 3.14+ and is optimized for the latest FalkorDB clients.
|
|
45
|
+
|
|
46
|
+
## A Simple Example
|
|
47
|
+
|
|
48
|
+
Initialize your project and generate a new revision:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Set up a new runic environment
|
|
52
|
+
runic init
|
|
53
|
+
|
|
54
|
+
# Create your first revision script
|
|
55
|
+
runic revision -m "create user index"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This generates a revision file in `runic/versions`. Open it and define your upgrades and downgrades:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
"""create user index
|
|
62
|
+
|
|
63
|
+
Revision ID: 1975ea83b712
|
|
64
|
+
Revises: None
|
|
65
|
+
Create Date: 2026-05-30 14:00:00.000000
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
from datetime import UTC, datetime
|
|
69
|
+
|
|
70
|
+
revision = "1975ea83b712"
|
|
71
|
+
down_revision = None
|
|
72
|
+
message = "create user index"
|
|
73
|
+
create_date = datetime.fromisoformat("2026-05-30T14:00:00+00:00")
|
|
74
|
+
branch_labels = []
|
|
75
|
+
depends_on = []
|
|
76
|
+
irreversible = False
|
|
77
|
+
snapshot = False
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def upgrade(op) -> None:
|
|
81
|
+
op.create_range_index("User", "email")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def downgrade(op) -> None:
|
|
85
|
+
op.drop_range_index("User", "email")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Then apply your changes:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
runic upgrade # apply all pending revisions
|
|
92
|
+
runic downgrade # roll back one step (default target: -1)
|
|
93
|
+
runic downgrade 1975e # roll back to a revision — prefix is enough
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Baselining an existing graph
|
|
97
|
+
|
|
98
|
+
If you have a FalkorDB graph that was built without Runic, use `baseline` to bring it under management without re-running anything on the source:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Introspect the live graph, generate a root revision, and stamp it as applied
|
|
102
|
+
runic baseline -m "baseline"
|
|
103
|
+
# Generated: runic/versions/<hex>_baseline.py
|
|
104
|
+
# Stamped: <hex>
|
|
105
|
+
|
|
106
|
+
# Verify the graph is now tracked
|
|
107
|
+
runic current
|
|
108
|
+
# <hex> baseline
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The generated revision recreates all indexes and constraints from scratch — safe to replay on a fresh empty graph (CI, cloning, new tenants):
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
runic upgrade head # rebuilds the full schema on an empty graph
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Re-running `baseline` on an already-managed graph is refused:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
runic baseline -m "again"
|
|
121
|
+
# Error: Graph already managed by runic.migrate. Use `runic upgrade` instead.
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
To mark an existing graph as baselined without generating a file (useful when you manage the revision file yourself):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
runic baseline --stamp-only
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Baseline → autogenerate workflow
|
|
131
|
+
|
|
132
|
+
Once you have a baseline revision, use the standard autogenerate workflow to evolve the schema:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# After changing your SchemaManifest in env.py:
|
|
136
|
+
runic revision --autogenerate -m "add embedding index"
|
|
137
|
+
runic upgrade head
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The baseline revision is the root of the chain (`down_revision = None`). Future revisions chain off it normally.
|
|
141
|
+
|
|
142
|
+
## Programmatic SDK
|
|
143
|
+
|
|
144
|
+
Use runic directly in Python — no CLI, no `env.py` needed:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from pathlib import Path
|
|
148
|
+
from runic import Runic, init
|
|
149
|
+
from runic.migrate.adapters import create_adapter
|
|
150
|
+
|
|
151
|
+
# One-time setup: scaffold the migration directory
|
|
152
|
+
init(Path("runic/"))
|
|
153
|
+
|
|
154
|
+
# Connect and run
|
|
155
|
+
adapter = create_adapter(
|
|
156
|
+
"falkordb",
|
|
157
|
+
url="falkor://localhost:6379",
|
|
158
|
+
graph_name="my_graph",
|
|
159
|
+
)
|
|
160
|
+
runic = Runic(adapter, script_location=Path("runic/"))
|
|
161
|
+
runic.migrate.upgrade("head")
|
|
162
|
+
|
|
163
|
+
print("current:", runic.migrate.current())
|
|
164
|
+
print("history:", runic.migrate.get_history())
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`Runic` is the single class you need. It handles upgrades, downgrades, stamping, history queries, and revision creation in one coherent API.
|
|
168
|
+
|
|
169
|
+
## Documentation
|
|
170
|
+
|
|
171
|
+
For a full conceptual overview, advanced CLI usage, and deep dives into branching or multi-head resolution, visit the complete [Runic Documentation](https://runic-py.readthedocs.io/latest/).
|