runic-migrate 0.1.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_migrate-0.1.0/.gitignore +114 -0
- runic_migrate-0.1.0/LICENSE.md +21 -0
- runic_migrate-0.1.0/PKG-INFO +120 -0
- runic_migrate-0.1.0/README.md +94 -0
- runic_migrate-0.1.0/pyproject.toml +256 -0
- runic_migrate-0.1.0/runic/__init__.py +33 -0
- runic_migrate-0.1.0/runic/adapters/__init__.py +68 -0
- runic_migrate-0.1.0/runic/adapters/falkordb.py +259 -0
- runic_migrate-0.1.0/runic/autogen.py +242 -0
- runic_migrate-0.1.0/runic/cli.py +531 -0
- runic_migrate-0.1.0/runic/config.py +8 -0
- runic_migrate-0.1.0/runic/context.py +258 -0
- runic_migrate-0.1.0/runic/exceptions.py +6 -0
- runic_migrate-0.1.0/runic/introspect.py +174 -0
- runic_migrate-0.1.0/runic/manifest.py +81 -0
- runic_migrate-0.1.0/runic/operations.py +298 -0
- runic_migrate-0.1.0/runic/script.py +394 -0
- runic_migrate-0.1.0/runic/service.py +121 -0
- runic_migrate-0.1.0/runic/templates/env.py.mako +11 -0
- runic_migrate-0.1.0/runic/templates/script.py.mako +25 -0
- runic_migrate-0.1.0/runic/testing.py +47 -0
- runic_migrate-0.1.0/runic/version.py +69 -0
|
@@ -0,0 +1,114 @@
|
|
|
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/
|
|
@@ -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.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: runic-migrate
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Graph schema migrations for FalkorDB.
|
|
5
|
+
Project-URL: Homepage, https://github.com/jenreh/python-kit
|
|
6
|
+
Project-URL: Repository, https://github.com/jenreh/python-kit
|
|
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: aiosqlite==0.22.1
|
|
17
|
+
Requires-Dist: falkordb>=1.6.1
|
|
18
|
+
Requires-Dist: falkordblite>=0.10.0
|
|
19
|
+
Requires-Dist: fastmcp==3.3.1
|
|
20
|
+
Requires-Dist: mako>=1.3.12
|
|
21
|
+
Requires-Dist: pydantic-settings==2.14.1
|
|
22
|
+
Requires-Dist: pydantic==2.13.4
|
|
23
|
+
Requires-Dist: rich==15.0.0
|
|
24
|
+
Requires-Dist: typer[all]==0.26.3
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
<div align="center">
|
|
28
|
+
<img src="docs/source/_static/runic.svg" width="240" alt="Runic logo">
|
|
29
|
+
|
|
30
|
+
# Runic
|
|
31
|
+
|
|
32
|
+
**Graph schema migrations for FalkorDB.**
|
|
33
|
+
|
|
34
|
+

|
|
35
|
+
[](https://pypi.python.org/pypi/runic)
|
|
36
|
+
[](https://www.python.org)
|
|
37
|
+
[](LICENSE.md)
|
|
38
|
+
|
|
39
|
+
[Features](#features) • [Installation](#installation) • [A Simple Example](#a-simple-example) • [Documentation](#documentation)
|
|
40
|
+
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
**Runic** is a lightweight, Alembic-style migration framework built specifically for [FalkorDB](https://falkordb.com/).
|
|
46
|
+
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.
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- **Alembic-Style Workflow** — Familiar CLI verbs like `init`, `revision`, `upgrade`, `downgrade`, and `current`.
|
|
51
|
+
- **Graph-Native** — Treats your database as a graph. Stores migration states intelligently inside dedicated nodes (e.g., `:_FalkorMigrateVersion`).
|
|
52
|
+
- **Idempotent Cypher** — Encourages explicit, heavily-guarded migration steps, supporting robust backward capability even without transactional DDLs.
|
|
53
|
+
- **Offline & Dry Run** — Review generated Cypher scripts thoroughly before executing them in production.
|
|
54
|
+
- **Rollback Snapshots** — Advanced capabilities utilizing `GRAPH.COPY` for high-risk, non-reversible data migrations.
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
Install via `pip` or `uv`:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv pip install runic
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Or add it to an existing project:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
uv add runic
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
> [!NOTE]
|
|
71
|
+
> Runic requires Python 3.14+ and is optimized for the latest FalkorDB clients.
|
|
72
|
+
|
|
73
|
+
## A Simple Example
|
|
74
|
+
|
|
75
|
+
Initialize your project and generate a new revision:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Set up a new runic environment
|
|
79
|
+
runic init
|
|
80
|
+
|
|
81
|
+
# Create your first revision script
|
|
82
|
+
runic revision -m "create user index"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This generates a revision file in `runic/versions`. Open it and define your upgrades and downgrades:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
"""create user index
|
|
89
|
+
|
|
90
|
+
Revision ID: 1975ea83b712
|
|
91
|
+
Revises: None
|
|
92
|
+
Create Date: 2026-05-30 14:00:00.000000
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
from runic import op
|
|
96
|
+
|
|
97
|
+
# revision identifiers, used by Runic.
|
|
98
|
+
revision = "1975ea83b712"
|
|
99
|
+
down_revision = None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def upgrade() -> None:
|
|
103
|
+
# Use Cypher to create an index
|
|
104
|
+
op.run_cypher("CREATE INDEX ON :User(email)")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def downgrade() -> None:
|
|
108
|
+
# Safely revert the operation
|
|
109
|
+
op.run_cypher("DROP INDEX ON :User(email)")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Then apply your changes:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
runic upgrade head
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Documentation
|
|
119
|
+
|
|
120
|
+
For a full conceptual overview, advanced CLI usage, and deep dives into branching or multi-head resolution, visit the complete [Runic Documentation](https://jenreh.github.io/runic/).
|
|
@@ -0,0 +1,94 @@
|
|
|
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://pypi.python.org/pypi/runic)
|
|
10
|
+
[](https://www.python.org)
|
|
11
|
+
[](LICENSE.md)
|
|
12
|
+
|
|
13
|
+
[Features](#features) • [Installation](#installation) • [A Simple Example](#a-simple-example) • [Documentation](#documentation)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
**Runic** is a lightweight, Alembic-style migration framework built specifically for [FalkorDB](https://falkordb.com/).
|
|
20
|
+
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.
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
- **Alembic-Style Workflow** — Familiar CLI verbs like `init`, `revision`, `upgrade`, `downgrade`, and `current`.
|
|
25
|
+
- **Graph-Native** — Treats your database as a graph. Stores migration states intelligently inside dedicated nodes (e.g., `:_FalkorMigrateVersion`).
|
|
26
|
+
- **Idempotent Cypher** — Encourages explicit, heavily-guarded migration steps, supporting robust backward capability even without transactional DDLs.
|
|
27
|
+
- **Offline & Dry Run** — Review generated Cypher scripts thoroughly before executing them in production.
|
|
28
|
+
- **Rollback Snapshots** — Advanced capabilities utilizing `GRAPH.COPY` for high-risk, non-reversible data migrations.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
Install via `pip` or `uv`:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
uv pip install runic
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or add it to an existing project:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv add runic
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
> [!NOTE]
|
|
45
|
+
> Runic requires Python 3.14+ and is optimized for the latest FalkorDB clients.
|
|
46
|
+
|
|
47
|
+
## A Simple Example
|
|
48
|
+
|
|
49
|
+
Initialize your project and generate a new revision:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Set up a new runic environment
|
|
53
|
+
runic init
|
|
54
|
+
|
|
55
|
+
# Create your first revision script
|
|
56
|
+
runic revision -m "create user index"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This generates a revision file in `runic/versions`. Open it and define your upgrades and downgrades:
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
"""create user index
|
|
63
|
+
|
|
64
|
+
Revision ID: 1975ea83b712
|
|
65
|
+
Revises: None
|
|
66
|
+
Create Date: 2026-05-30 14:00:00.000000
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
from runic import op
|
|
70
|
+
|
|
71
|
+
# revision identifiers, used by Runic.
|
|
72
|
+
revision = "1975ea83b712"
|
|
73
|
+
down_revision = None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def upgrade() -> None:
|
|
77
|
+
# Use Cypher to create an index
|
|
78
|
+
op.run_cypher("CREATE INDEX ON :User(email)")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def downgrade() -> None:
|
|
82
|
+
# Safely revert the operation
|
|
83
|
+
op.run_cypher("DROP INDEX ON :User(email)")
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Then apply your changes:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
runic upgrade head
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Documentation
|
|
93
|
+
|
|
94
|
+
For a full conceptual overview, advanced CLI usage, and deep dives into branching or multi-head resolution, visit the complete [Runic Documentation](https://jenreh.github.io/runic/).
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "runic-migrate"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Graph schema migrations for FalkorDB."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.14"
|
|
7
|
+
license = { text = "MIT" }
|
|
8
|
+
authors = [{ name = "Jens Rehpöhler" }]
|
|
9
|
+
keywords = []
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Intended Audience :: Developers",
|
|
12
|
+
"License :: OSI Approved :: MIT License",
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
15
|
+
"Topic :: Home Automation",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
dependencies = [
|
|
19
|
+
"fastmcp==3.3.1",
|
|
20
|
+
"typer[all]==0.26.3",
|
|
21
|
+
"rich==15.0.0",
|
|
22
|
+
"pydantic==2.13.4",
|
|
23
|
+
"pydantic-settings==2.14.1",
|
|
24
|
+
"aiosqlite==0.22.1",
|
|
25
|
+
"falkordb>=1.6.1",
|
|
26
|
+
"mako>=1.3.12",
|
|
27
|
+
"falkordblite>=0.10.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[dependency-groups]
|
|
31
|
+
dev = [
|
|
32
|
+
"bump-my-version==1.3.0",
|
|
33
|
+
"detect-secrets==1.5.0",
|
|
34
|
+
"pre-commit==4.6.0",
|
|
35
|
+
"pytest==9.0.3",
|
|
36
|
+
"pytest-asyncio==1.4.0",
|
|
37
|
+
"pytest-cov==7.1.0",
|
|
38
|
+
"pytest-httpserver==1.1.5",
|
|
39
|
+
"ruff==0.15.15",
|
|
40
|
+
"mypy==2.1.0",
|
|
41
|
+
"types-PyYAML==6.0.12.20260510",
|
|
42
|
+
"falkordblite>=0.10.0",
|
|
43
|
+
"sphinx>=9.1.0",
|
|
44
|
+
"furo>=2025.12.19",
|
|
45
|
+
"sphinx-copybutton>=0.5.2",
|
|
46
|
+
"sphinx-design>=0.7.0",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[project.scripts]
|
|
50
|
+
runic = "runic.cli:app"
|
|
51
|
+
|
|
52
|
+
[project.urls]
|
|
53
|
+
Homepage = "https://github.com/jenreh/python-kit"
|
|
54
|
+
Repository = "https://github.com/jenreh/python-kit"
|
|
55
|
+
|
|
56
|
+
[tool.hatch.build.targets.wheel]
|
|
57
|
+
packages = ["runic"]
|
|
58
|
+
|
|
59
|
+
[tool.hatch.build.targets.sdist]
|
|
60
|
+
include = [
|
|
61
|
+
"/runic",
|
|
62
|
+
"README.md",
|
|
63
|
+
"pyproject.toml",
|
|
64
|
+
]
|
|
65
|
+
exclude = [
|
|
66
|
+
".agents/",
|
|
67
|
+
".cache/",
|
|
68
|
+
".claude/",
|
|
69
|
+
".devcontainer/",
|
|
70
|
+
".github/",
|
|
71
|
+
".vscode/",
|
|
72
|
+
"skill/",
|
|
73
|
+
"spec/",
|
|
74
|
+
"tests/",
|
|
75
|
+
".env",
|
|
76
|
+
".gitignore",
|
|
77
|
+
".pre-commit-config.yaml",
|
|
78
|
+
"AGENTS.md",
|
|
79
|
+
"coverage.xml",
|
|
80
|
+
"Taskfile.yaml",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[tool.bumpversion]
|
|
84
|
+
commit = false
|
|
85
|
+
current_version = "0.1.0"
|
|
86
|
+
tag = false
|
|
87
|
+
allow-dirty = false
|
|
88
|
+
|
|
89
|
+
[[tool.bumpversion.files]]
|
|
90
|
+
filename = "pyproject.toml"
|
|
91
|
+
search = 'version = "{current_version}"'
|
|
92
|
+
replace = 'version = "{new_version}"'
|
|
93
|
+
|
|
94
|
+
[[tool.bumpversion.files]]
|
|
95
|
+
filename = "README.md"
|
|
96
|
+
search = ''
|
|
97
|
+
replace = ''
|
|
98
|
+
|
|
99
|
+
[tool.ruff]
|
|
100
|
+
cache-dir = ".cache/ruff"
|
|
101
|
+
indent-width = 4
|
|
102
|
+
line-length = 88
|
|
103
|
+
target-version = "py314"
|
|
104
|
+
extend-exclude = [
|
|
105
|
+
".agents",
|
|
106
|
+
".cache",
|
|
107
|
+
".claude",
|
|
108
|
+
".devcontainer",
|
|
109
|
+
".github",
|
|
110
|
+
".vscode",
|
|
111
|
+
"build",
|
|
112
|
+
"dist",
|
|
113
|
+
"docs",
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
[tool.ruff.lint]
|
|
117
|
+
extend-select = ["I"]
|
|
118
|
+
ignore = [
|
|
119
|
+
"EM101",
|
|
120
|
+
"EM102",
|
|
121
|
+
"ISC001",
|
|
122
|
+
"N811",
|
|
123
|
+
"N818",
|
|
124
|
+
"PLR0913",
|
|
125
|
+
"PT011",
|
|
126
|
+
"PT012",
|
|
127
|
+
"RUF012",
|
|
128
|
+
"RUF100",
|
|
129
|
+
"SIM300",
|
|
130
|
+
"E501",
|
|
131
|
+
"B008",
|
|
132
|
+
"ASYNC240",
|
|
133
|
+
"PYI034",
|
|
134
|
+
"S101",
|
|
135
|
+
"PLR0912",
|
|
136
|
+
"PLR0915",
|
|
137
|
+
"ASYNC109",
|
|
138
|
+
"ARG001",
|
|
139
|
+
"PLR2004",
|
|
140
|
+
"PLW0603",
|
|
141
|
+
"PLC0415",
|
|
142
|
+
"SIM105",
|
|
143
|
+
"PLW2901",
|
|
144
|
+
"PLR0911",
|
|
145
|
+
"B017",
|
|
146
|
+
"RUF001",
|
|
147
|
+
"RUF002",
|
|
148
|
+
"RUF003",
|
|
149
|
+
]
|
|
150
|
+
select = [
|
|
151
|
+
"A",
|
|
152
|
+
"ANN001",
|
|
153
|
+
"ANN201",
|
|
154
|
+
"ARG",
|
|
155
|
+
"ASYNC",
|
|
156
|
+
"B",
|
|
157
|
+
"C4",
|
|
158
|
+
"DTZ",
|
|
159
|
+
"E",
|
|
160
|
+
"EM",
|
|
161
|
+
"EXE",
|
|
162
|
+
"F",
|
|
163
|
+
"FIX",
|
|
164
|
+
"G",
|
|
165
|
+
"ICN",
|
|
166
|
+
"LOG",
|
|
167
|
+
"N",
|
|
168
|
+
"PERF",
|
|
169
|
+
"PIE",
|
|
170
|
+
"PL",
|
|
171
|
+
"PT",
|
|
172
|
+
"PTH",
|
|
173
|
+
"PYI",
|
|
174
|
+
"Q",
|
|
175
|
+
"RET",
|
|
176
|
+
"RUF",
|
|
177
|
+
"S",
|
|
178
|
+
"SIM",
|
|
179
|
+
"SLF",
|
|
180
|
+
"SLF001",
|
|
181
|
+
"T20",
|
|
182
|
+
"TID",
|
|
183
|
+
"UP",
|
|
184
|
+
"W",
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
[tool.ruff.lint.per-file-ignores]
|
|
188
|
+
"__init__.py" = ["F401", "I001"]
|
|
189
|
+
"test_**.py" = [
|
|
190
|
+
"S101",
|
|
191
|
+
"PLR2004",
|
|
192
|
+
"ANN001",
|
|
193
|
+
"S106",
|
|
194
|
+
"SLF001",
|
|
195
|
+
"RET504",
|
|
196
|
+
"PERF401",
|
|
197
|
+
"E402",
|
|
198
|
+
"S501",
|
|
199
|
+
"S110",
|
|
200
|
+
"ARG002",
|
|
201
|
+
"ARG005",
|
|
202
|
+
"E741",
|
|
203
|
+
"RUF059",
|
|
204
|
+
]
|
|
205
|
+
|
|
206
|
+
[tool.ruff.format]
|
|
207
|
+
quote-style = "double"
|
|
208
|
+
indent-style = "space"
|
|
209
|
+
skip-magic-trailing-comma = false
|
|
210
|
+
line-ending = "auto"
|
|
211
|
+
docstring-code-format = true
|
|
212
|
+
docstring-code-line-length = "dynamic"
|
|
213
|
+
exclude = ["*.pyi"]
|
|
214
|
+
|
|
215
|
+
[tool.ruff.lint.isort]
|
|
216
|
+
known-local-folder = ["sonos"]
|
|
217
|
+
|
|
218
|
+
[tool.pytest.ini_options]
|
|
219
|
+
cache_dir = ".cache/pytest"
|
|
220
|
+
testpaths = ["tests"]
|
|
221
|
+
asyncio_mode = "auto"
|
|
222
|
+
markers = [
|
|
223
|
+
"sonos_live: requires real Sonos hardware on the network",
|
|
224
|
+
"integration: requires falkordblite (embedded FalkorDB, no external server)",
|
|
225
|
+
]
|
|
226
|
+
|
|
227
|
+
[tool.mypy]
|
|
228
|
+
cache_dir = ".cache/mypy"
|
|
229
|
+
disallow_untyped_defs = true
|
|
230
|
+
incremental = true
|
|
231
|
+
python_version = "3.14"
|
|
232
|
+
warn_return_any = true
|
|
233
|
+
warn_unused_configs = true
|
|
234
|
+
ignore_missing_imports = true
|
|
235
|
+
exclude = [
|
|
236
|
+
".cache",
|
|
237
|
+
".claude",
|
|
238
|
+
".venv",
|
|
239
|
+
"build",
|
|
240
|
+
"dist",
|
|
241
|
+
]
|
|
242
|
+
|
|
243
|
+
[tool.coverage.run]
|
|
244
|
+
branch = true
|
|
245
|
+
source = ["app", "runic"]
|
|
246
|
+
omit = []
|
|
247
|
+
|
|
248
|
+
[tool.coverage.report]
|
|
249
|
+
exclude_lines = ["if TYPE_CHECKING:", "if __name__ == .__main__.:", "pragma: no cover"]
|
|
250
|
+
fail_under = 80
|
|
251
|
+
show_missing = true
|
|
252
|
+
skip_covered = true
|
|
253
|
+
|
|
254
|
+
[build-system]
|
|
255
|
+
requires = ["hatchling"]
|
|
256
|
+
build-backend = "hatchling.build"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from runic import context
|
|
2
|
+
from runic.context import IrreversibleMigrationError
|
|
3
|
+
from runic.exceptions import MultipleBasesError, MultipleHeadsError
|
|
4
|
+
from runic.manifest import (
|
|
5
|
+
FulltextIndex,
|
|
6
|
+
MandatoryConstraint,
|
|
7
|
+
RangeIndex,
|
|
8
|
+
SchemaManifest,
|
|
9
|
+
UniqueConstraint,
|
|
10
|
+
VectorIndex,
|
|
11
|
+
)
|
|
12
|
+
from runic.operations import ConstraintFailedError, ConstraintTimeoutError, op
|
|
13
|
+
from runic.script import AmbiguousRevision, RevisionNotFound
|
|
14
|
+
from runic.service import RunicService
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"AmbiguousRevision",
|
|
18
|
+
"ConstraintFailedError",
|
|
19
|
+
"ConstraintTimeoutError",
|
|
20
|
+
"FulltextIndex",
|
|
21
|
+
"IrreversibleMigrationError",
|
|
22
|
+
"MandatoryConstraint",
|
|
23
|
+
"MultipleBasesError",
|
|
24
|
+
"MultipleHeadsError",
|
|
25
|
+
"RangeIndex",
|
|
26
|
+
"RevisionNotFound",
|
|
27
|
+
"RunicService",
|
|
28
|
+
"SchemaManifest",
|
|
29
|
+
"UniqueConstraint",
|
|
30
|
+
"VectorIndex",
|
|
31
|
+
"context",
|
|
32
|
+
"op",
|
|
33
|
+
]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Protocol, runtime_checkable
|
|
4
|
+
|
|
5
|
+
from runic.introspect import LiveSchema
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@runtime_checkable
|
|
9
|
+
class GraphAdapter(Protocol):
|
|
10
|
+
"""Protocol all graph-database adapters must satisfy.
|
|
11
|
+
|
|
12
|
+
The runic core depends only on this interface — no FalkorDB or any other
|
|
13
|
+
concrete database client leaks into shared code.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def name(self) -> str: ...
|
|
18
|
+
|
|
19
|
+
# Low-level query execution
|
|
20
|
+
def run_query(self, query: str, params: dict | None = None) -> Any: ...
|
|
21
|
+
def run_ro_query(self, query: str) -> Any: ...
|
|
22
|
+
|
|
23
|
+
# Version tracking
|
|
24
|
+
def get_version(self) -> list[str]: ...
|
|
25
|
+
def set_version(self, revisions: list[str]) -> None: ...
|
|
26
|
+
|
|
27
|
+
# Schema introspection
|
|
28
|
+
def read_live_schema(self) -> LiveSchema: ...
|
|
29
|
+
|
|
30
|
+
# Schema DDL
|
|
31
|
+
def create_range_index(
|
|
32
|
+
self, label: str, prop: str, *, rel: bool = False
|
|
33
|
+
) -> None: ...
|
|
34
|
+
def drop_range_index(self, label: str, prop: str, *, rel: bool = False) -> None: ...
|
|
35
|
+
def create_fulltext_index(
|
|
36
|
+
self,
|
|
37
|
+
label: str,
|
|
38
|
+
*props: str,
|
|
39
|
+
language: str | None = None,
|
|
40
|
+
stopwords: list[str] | None = None,
|
|
41
|
+
) -> None: ...
|
|
42
|
+
def drop_fulltext_index(self, label: str, *props: str) -> None: ...
|
|
43
|
+
def create_vector_index(
|
|
44
|
+
self,
|
|
45
|
+
label: str,
|
|
46
|
+
prop: str,
|
|
47
|
+
dimension: int,
|
|
48
|
+
similarity: str,
|
|
49
|
+
*,
|
|
50
|
+
m: int = 16,
|
|
51
|
+
ef_construction: int = 200,
|
|
52
|
+
ef_runtime: int = 10,
|
|
53
|
+
) -> None: ...
|
|
54
|
+
def drop_vector_index(self, label: str, prop: str) -> None: ...
|
|
55
|
+
def create_constraint(
|
|
56
|
+
self, kind: str, entity: str, label: str, props: list[str]
|
|
57
|
+
) -> None: ...
|
|
58
|
+
def drop_constraint(
|
|
59
|
+
self, kind: str, entity: str, label: str, props: list[str]
|
|
60
|
+
) -> None: ...
|
|
61
|
+
|
|
62
|
+
# Snapshots
|
|
63
|
+
def snapshot(self, snap_name: str) -> None: ...
|
|
64
|
+
def restore_snapshot(self, snap_name: str) -> None: ...
|
|
65
|
+
def snapshot_exists(self, snap_name: str) -> bool: ...
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
__all__ = ["GraphAdapter"]
|