AQIT
0.1.0
Toggle main menu visibility
Loading...
Searching...
No Matches
store.py
Go to the documentation of this file.
1
# Copyright (c) 2025-present Aquin Labs Private Limited. All Rights Reserved.
2
# This file is part of the Aquin Engine. Unauthorized copying, modification,
3
# distribution, or use of this file, via any medium, is strictly prohibited.
4
# Proprietary and confidential. See LICENSE for terms.
5
6
"""On-disk layout under ./aquin_run/ — revisions, runs, checkpoints, gates."""
7
8
from
__future__
import
annotations
9
10
import
hashlib
11
import
json
12
import
shutil
13
from
pathlib
import
Path
14
from
typing
import
Any
15
16
from
aquin.recipe.schema
import
DataRevision, RecipeError, RunRecord
17
18
RUN_ROOT_NAME =
"aquin_run"
19
20
21
def
run_root
(cwd: Path |
None
=
None
) -> Path:
22
return
(cwd
or
Path.cwd()) / RUN_ROOT_NAME
23
24
25
def
revision_dir
(rev_id: str, *, cwd: Path |
None
=
None
) -> Path:
26
return
run_root
(cwd) /
"revisions"
/ rev_id
27
28
29
def
run_dir
(run_id: str, *, cwd: Path |
None
=
None
) -> Path:
30
return
run_root
(cwd) /
"runs"
/ run_id
31
32
33
def
hash_file
(path: Path) -> str:
34
digest = hashlib.sha256()
35
with
path.open(
"rb"
)
as
fh:
36
while
True
:
37
chunk = fh.read(1024 * 1024)
38
if
not
chunk:
39
break
40
digest.update(chunk)
41
return
digest.hexdigest()
42
43
44
def
_count_rows
(path: Path, fmt: str) -> int |
None
:
45
try
:
46
if
fmt ==
"csv"
:
47
with
path.open(encoding=
"utf-8"
, errors=
"replace"
)
as
fh:
48
n = sum(1
for
_
in
fh)
49
return
max(0, n - 1)
50
if
fmt ==
"jsonl"
:
51
with
path.open(encoding=
"utf-8"
, errors=
"replace"
)
as
fh:
52
return
sum(1
for
line
in
fh
if
line.strip())
53
except
OSError:
54
return
None
55
return
None
56
57
58
def
_csv_columns
(path: Path) -> list[str] |
None
:
59
try
:
60
with
path.open(encoding=
"utf-8"
, errors=
"replace"
)
as
fh:
61
header = fh.readline()
62
return
[c.strip()
for
c
in
header.strip().split(
","
)
if
c.strip()]
63
except
OSError:
64
return
None
65
66
67
def
capture_revision
(
68
path: str | Path,
69
*,
70
snapshot: bool =
False
,
71
cwd: Path |
None
=
None
,
72
) -> DataRevision:
73
src = Path(path).expanduser().resolve()
74
if
not
src.exists():
75
raise
RecipeError
(f
"Data path not found: {src}"
)
76
if
src.is_dir():
77
raise
RecipeError
(f
"Data path must be a file (csv/jsonl), got directory: {src}"
)
78
79
suffix = src.suffix.lower()
80
fmt = {
".csv"
:
"csv"
,
".jsonl"
:
"jsonl"
,
".json"
:
"json"
}.get(suffix, suffix.lstrip(
"."
)
or
"file"
)
81
sha =
hash_file
(src)
82
rev_id = sha[:12]
83
dest =
revision_dir
(rev_id, cwd=cwd)
84
dest.mkdir(parents=
True
, exist_ok=
True
)
85
86
snapshot_dir =
None
87
data_path = src
88
if
snapshot:
89
copied = dest / src.name
90
shutil.copy2(src, copied)
91
snapshot_dir = str(copied)
92
data_path = copied
93
94
rev =
DataRevision
(
95
id=rev_id,
96
path=str(data_path),
97
sha256=sha,
98
format=fmt,
99
n_rows=
_count_rows
(src, fmt),
100
columns=
_csv_columns
(src)
if
fmt ==
"csv"
else
None
,
101
snapshot_dir=snapshot_dir,
102
)
103
(dest /
"manifest.json"
).write_text(json.dumps(rev.to_dict(), indent=2), encoding=
"utf-8"
)
104
return
rev
105
106
107
def
write_json
(path: Path, payload: Any) ->
None
:
108
path.parent.mkdir(parents=
True
, exist_ok=
True
)
109
path.write_text(json.dumps(payload, indent=2, default=str), encoding=
"utf-8"
)
110
111
112
def
save_run
(record: RunRecord) -> Path:
113
d = Path(record.run_dir)
114
d.mkdir(parents=
True
, exist_ok=
True
)
115
write_json
(d /
"run.json"
, record.to_dict())
116
if
record.checkpoint:
117
write_json
(d /
"checkpoint.json"
, record.checkpoint)
118
if
record.gate:
119
write_json
(d /
"gate.json"
, record.gate)
120
if
record.metrics:
121
write_json
(d /
"metrics.json"
, record.metrics)
122
if
record.inspect:
123
write_json
(d /
"inspect.json"
, record.inspect)
124
return
d /
"run.json"
125
126
127
def
load_run
(run_id: str, *, cwd: Path |
None
=
None
) -> RunRecord:
128
path =
run_dir
(run_id, cwd=cwd) /
"run.json"
129
if
not
path.is_file():
130
raise
RecipeError
(f
"No run {run_id!r} under {run_root(cwd) / 'runs'}"
)
131
data = json.loads(path.read_text(encoding=
"utf-8"
))
132
return
RunRecord
(
133
run_id=data[
"run_id"
],
134
name=data.get(
"name"
)
or
""
,
135
family=data.get(
"family"
)
or
""
,
136
status=data.get(
"status"
)
or
"unknown"
,
137
run_dir=data.get(
"run_dir"
)
or
str(path.parent),
138
recipe=dict(data.get(
"recipe"
)
or
{}),
139
revision=dict(data.get(
"revision"
)
or
{}),
140
checkpoint=data.get(
"checkpoint"
),
141
gate=data.get(
"gate"
),
142
metrics=dict(data.get(
"metrics"
)
or
{}),
143
inspect=dict(data.get(
"inspect"
)
or
{}),
144
error=data.get(
"error"
),
145
)
aquin.recipe.schema.DataRevision
Definition
schema.py:29
aquin.recipe.schema.RecipeError
Definition
schema.py:24
aquin.recipe.schema.RunRecord
Definition
schema.py:163
aquin.recipe.schema
Definition
schema.py:1
aquin.recipe.store.revision_dir
Path revision_dir(str rev_id, *, Path|None cwd=None)
Definition
store.py:29
aquin.recipe.store.write_json
None write_json(Path path, Any payload)
Definition
store.py:111
aquin.recipe.store.load_run
RunRecord load_run(str run_id, *, Path|None cwd=None)
Definition
store.py:131
aquin.recipe.store.run_dir
Path run_dir(str run_id, *, Path|None cwd=None)
Definition
store.py:33
aquin.recipe.store.run_root
Path run_root(Path|None cwd=None)
Definition
store.py:25
aquin.recipe.store.save_run
Path save_run(RunRecord record)
Definition
store.py:116
aquin.recipe.store._csv_columns
list[str]|None _csv_columns(Path path)
Definition
store.py:62
aquin.recipe.store._count_rows
int|None _count_rows(Path path, str fmt)
Definition
store.py:48
aquin.recipe.store.hash_file
str hash_file(Path path)
Definition
store.py:37
aquin.recipe.store.capture_revision
DataRevision capture_revision(str|Path path, *, bool snapshot=False, Path|None cwd=None)
Definition
store.py:76
aquin
recipe
store.py
AQIT · Aquin Labs Private Limited · Apache 2.0 · Generated by
1.18.0