Skip to content

Commit 737387f

Browse files
satraclaude
andcommitted
fix(040): update all tests for Parquet-only pipeline
- test_staging.py: uses write_staged_batch + iter_staged (no write_staged_entity) - test_embeddings.py: relaxed assertions for comprehensive embedding text - test_pipeline_e2e.py: counts from ParquetStore (not YAML glob) T007, T009, T014, T019 marked done. 26/33 tasks complete. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ee24e08 commit 737387f

4 files changed

Lines changed: 60 additions & 39 deletions

File tree

library/tests/test_embeddings.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ def test_build_element_text_full():
2323
{"class": "Subject", "name": "age", "description": "Age of the subject in years"}
2424
]
2525
}
26-
assert _build_element_text(data) == "Subject age: Age of the subject in years"
26+
text = _build_element_text(data)
27+
assert "Subject age: Age of the subject in years" in text
2728

2829

2930
def test_build_element_text_no_description():
@@ -177,4 +178,5 @@ def test_build_element_embeddings_from_files(tmp_path):
177178

178179
# We can test the text construction without needing the model
179180
data = yaml.safe_load((elements_dir / "age_abc123.yaml").read_text())
180-
assert _build_element_text(data) == "Subject age: Age"
181+
text = _build_element_text(data)
182+
assert "Subject age: Age" in text

library/tests/test_pipeline_e2e.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,15 @@ def _run_pipeline(source: str, output_dir: Path, skip_enrich: bool = True) -> di
2424
if not skip_enrich:
2525
enrich_elements(staging_dir=staging)
2626
commit_stats = commit_staged(staging, output_dir)
27+
from undata_library.storage.parquet_store import ParquetStore
28+
29+
store = ParquetStore(output_dir)
2730
return {
2831
"ingest": stats,
2932
"commit": commit_stats,
30-
"elements": len(list((output_dir / "elements").glob("*.yaml"))),
31-
"schemas": len(list((output_dir / "schemas").glob("*.yaml")))
32-
if (output_dir / "schemas").exists()
33-
else 0,
34-
"values": len(list((output_dir / "values").glob("*.yaml")))
35-
if (output_dir / "values").exists()
36-
else 0,
33+
"elements": store.count("elements"),
34+
"schemas": store.count("schemas"),
35+
"values": store.count("values"),
3736
}
3837

3938

@@ -67,7 +66,7 @@ class TestNewEntityFlow:
6766
def test_synthetic_element_committed(self, tmp_path):
6867
# First run: normal BIDS extraction
6968
_run_pipeline("bids", tmp_path)
70-
initial_count = len(list((tmp_path / "elements").glob("*.yaml")))
69+
initial_count = ParquetStore(tmp_path).count("elements")
7170

7271
# Add a synthetic element to a new staging run
7372
run_id = generate_run_id()
@@ -81,7 +80,7 @@ def test_synthetic_element_committed(self, tmp_path):
8180
)
8281
commit_staged(staging, tmp_path)
8382

84-
final_count = len(list((tmp_path / "elements").glob("*.yaml")))
83+
final_count = ParquetStore(tmp_path).count("elements")
8584
assert final_count == initial_count + 1
8685

8786

@@ -100,7 +99,7 @@ def test_double_ingest_merges_not_duplicates(self, tmp_path):
10099
def test_entity_level_dedup(self, tmp_path):
101100
"""T038e: Ingesting a duplicate entity merges provenance, not duplicates."""
102101
_run_pipeline("bids", tmp_path)
103-
initial = len(list((tmp_path / "elements").glob("*.yaml")))
102+
initial = ParquetStore(tmp_path).count("elements")
104103

105104
# Create a second staging with same content + different provenance
106105
from undata_library.staging import create_staging_dir, generate_run_id
@@ -115,7 +114,7 @@ def test_entity_level_dedup(self, tmp_path):
115114
)
116115
commit_staged(staging, tmp_path)
117116

118-
final = len(list((tmp_path / "elements").glob("*.yaml")))
117+
final = ParquetStore(tmp_path).count("elements")
119118
# Should have merged into existing, not created a new one
120119
# (or created exactly 1 if TaskName didn't exist before)
121120
assert final <= initial + 1

library/tests/test_staging.py

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
"""Tests for staging directory management."""
1+
"""Tests for staging directory management (Parquet-only)."""
22

33
import time
44

55
from undata_library.staging import (
66
cleanup_stale_staging,
7+
count_staged,
78
create_staging_dir,
89
generate_run_id,
9-
write_staged_entity,
10+
iter_staged,
11+
write_staged_batch,
1012
)
1113

1214

@@ -21,35 +23,53 @@ def test_create_staging_dir(tmp_path):
2123
staging = create_staging_dir(tmp_path, rid)
2224
assert staging.exists()
2325
assert (staging / "elements").exists()
24-
assert (staging / "schemas").exists()
25-
assert (staging / "values").exists()
26-
assert (staging / "valuesets").exists()
2726

2827

29-
def test_write_staged_entity(tmp_path):
28+
def test_write_staged_batch(tmp_path):
3029
staging = create_staging_dir(tmp_path, "test-run")
31-
data = {
32-
"semantic": {"data_type": "string"},
33-
"provenance": [{"source": "test", "class": "X", "name": "field"}],
34-
}
35-
path = write_staged_entity(staging, "elements", data)
36-
assert path.exists()
37-
assert path.parent.name == "elements"
38-
assert path.suffix == ".yaml"
39-
# UUID filename (not content-addressed)
40-
assert len(path.stem) == 36 # UUID length
30+
entities = [
31+
{
32+
"semantic": {"data_type": "string"},
33+
"provenance": [{"source": "test", "class": "X", "name": "field1"}],
34+
},
35+
{
36+
"semantic": {"data_type": "integer"},
37+
"provenance": [{"source": "test", "class": "X", "name": "field2"}],
38+
},
39+
]
40+
written = write_staged_batch(staging, "elements", entities, source="test")
41+
assert written == 2
42+
43+
44+
def test_count_staged(tmp_path):
45+
staging = create_staging_dir(tmp_path, "test-run")
46+
write_staged_batch(
47+
staging,
48+
"elements",
49+
[{"semantic": {"data_type": "string"}, "provenance": [{"source": "t", "class": "X", "name": "a"}]}],
50+
source="test",
51+
)
52+
assert count_staged(staging, "elements") == 1
53+
54+
55+
def test_iter_staged(tmp_path):
56+
staging = create_staging_dir(tmp_path, "test-run")
57+
write_staged_batch(
58+
staging,
59+
"elements",
60+
[{"semantic": {"data_type": "string"}, "provenance": [{"source": "t", "class": "X", "name": "a"}]}],
61+
source="test",
62+
)
63+
entities = list(iter_staged(staging, "elements"))
64+
assert len(entities) == 1
4165

4266

4367
def test_cleanup_stale_staging(tmp_path):
44-
# Create an "old" staging dir
45-
old = create_staging_dir(tmp_path, "old-run")
46-
# Backdate its mtime
4768
import os
4869

49-
old_time = time.time() - (25 * 3600) # 25 hours ago
70+
old = create_staging_dir(tmp_path, "old-run")
71+
old_time = time.time() - (25 * 3600)
5072
os.utime(old, (old_time, old_time))
51-
52-
# Create a "new" staging dir
5373
create_staging_dir(tmp_path, "new-run")
5474

5575
removed = cleanup_stale_staging(tmp_path, max_age_hours=24)

specs/040-unified-embedding-storage/tasks.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
- [X] T004 [US5] Rewrite FileBackend to delegate all entity operations to ParquetStore (remove YAML read/write) in library/src/undata_library/storage/file_backend.py
2727
- [X] T005 [US5] Remove FileEntityStore class (YAML-backed entity store) from library/src/undata_library/storage/file_backend.py
2828
- [X] T006 [US5] Update StorageBackend protocol — remove write_batch/read_batch (ParquetStore handles natively) in library/src/undata_library/storage/protocol.py
29-
- [ ] T007 [US5] Update all pipeline callers to use ParquetStore directly: enrich.py, align.py, alias_detection.py, transform.py in library/src/undata_library/
29+
- [X] T007 [US5] Update all pipeline callers to use ParquetStore directly: enrich.py, align.py, alias_detection.py, transform.py in library/src/undata_library/
3030
- [X] T008 [US5] Remove iter_staged YAML path and write_staged_entity from library/src/undata_library/staging.py
31-
- [ ] T009 [US5] Run full test suite — verify no tests depend on YAML entity files in library/tests/
31+
- [X] T009 [US5] Run full test suite — verify no tests depend on YAML entity files in library/tests/
3232

3333
**Checkpoint**: All entity access goes through ParquetStore; no YAML entity I/O remains
3434

@@ -44,7 +44,7 @@
4444
- [X] T011 [US1] Rewrite commit_staged to read from ParquetStore, compute sha256, write committed entities to ParquetStore (no YAML output) in library/src/undata_library/commit.py
4545
- [X] T012 [US1] Rewrite cross-reference resolution (_resolve_cross_references) to operate on DataFrames from ParquetStore in library/src/undata_library/commit.py
4646
- [X] T013 [US1] Remove yaml.dump calls from commit path and yaml_to_parquet conversion step in library/src/undata_library/commit.py and library/src/undata_library/staging.py
47-
- [ ] T014 [US1] Update batch_ingest to use ParquetStore throughout (no YAML intermediaries) in library/src/undata_library/ingest.py
47+
- [X] T014 [US1] Update batch_ingest to use ParquetStore throughout (no YAML intermediaries) in library/src/undata_library/ingest.py
4848
- [ ] T015 [US1] Add test: pipeline run produces zero YAML entity files in library/tests/test_parquet_pipeline.py
4949

5050
**Checkpoint**: `find output -name "*.yaml" -not -path "*/runs/*"` returns 0
@@ -60,7 +60,7 @@
6060
- [X] T016 [US2] Create build_comprehensive_embedding_text() that uses name + description + type + unit + annotations + provenance in library/src/undata_library/embeddings.py
6161
- [X] T017 [US2] Add embedding computation step to commit_staged — after sha256 computation, compute embeddings for all entities in batch in library/src/undata_library/commit.py
6262
- [X] T018 [US2] Ensure all entity types (elements, schemas, values, valuesets) get embeddings at commit in library/src/undata_library/commit.py
63-
- [ ] T019 [US2] Update backend import to skip embedding model loading when all entities have pre-computed embeddings in backend/src/storage/database_backend.py
63+
- [X] T019 [US2] Update backend import to skip embedding model loading when all entities have pre-computed embeddings in backend/src/storage/database_backend.py
6464
- [ ] T020 [US2] Update backend import_service to read Parquet-only (remove YAML import path) in backend/src/services/import_service.py
6565
- [ ] T021 [US2] Add test: committed entity has embedding field with 384 floats in library/tests/test_parquet_pipeline.py
6666
- [ ] T022 [US2] Add test: backend import of 100 entities with embeddings completes without loading sentence-transformers model in backend/tests/test_import.py

0 commit comments

Comments
 (0)