Skip to content

Commit e7d45f2

Browse files
committed
[caliper] rename the caliper marker file into __caliper_test_metadata__.yaml
1 parent 4503449 commit e7d45f2

9 files changed

Lines changed: 139 additions & 58 deletions

File tree

projects/caliper/cli/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def parse_mlflow_url(url: str) -> dict[str, str | None]:
9999

100100
_ARTIFACTS_DIR_HELP = (
101101
"Root directory of the test artifact tree (directories containing "
102-
"__test_labels__.yaml). Optional manifest files (e.g. caliper.yaml) are searched here "
102+
"__caliper_test_metadata__.yaml). Optional manifest files (e.g. caliper.yaml) are searched here "
103103
"unless --postprocess-config is set."
104104
)
105105
_PLUGIN_MODULE_HELP = (
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""Caliper engine constants - central location for shared values."""
2+
3+
# Test metadata file markers
4+
METADATA_FILE = "__caliper_test_metadata__.yaml"
5+
LEGACY_METADATA_FILE = "__test_labels__.yaml"
6+
7+
# MatrixBenchmarking compatibility
8+
MATRIXBENCHMARKING_SETTINGS_FILE = "settings.yaml"
9+
10+
# MLflow artifact files
11+
METRICS_FILE = "metrics.json"
12+
PARAMETERS_FILE = "parameters.json"

projects/caliper/engine/file_export/artifacts_export_run.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import yaml
1515
from click.core import Context, ParameterSource
1616

17+
from projects.caliper.engine.constants import LEGACY_METADATA_FILE, METADATA_FILE
1718
from projects.caliper.engine.file_export.mlflow_config import (
1819
project_metadata_fields,
1920
validate_mlflow_config,
@@ -310,12 +311,20 @@ def run_artifacts_export(
310311

311312

312313
def discover_run_dirs(from_path: Path) -> list[Path]:
313-
"""Auto-detect test run directories via ``__test_labels__.yaml`` markers."""
314-
run_dirs: list[Path] = []
315-
for marker in sorted(from_path.rglob("__test_labels__.yaml")):
314+
"""Auto-detect test run directories via metadata markers (with backwards compatibility)."""
315+
# Collect directories with either metadata file (new format or legacy)
316+
metadata_dirs = set()
317+
318+
for marker in from_path.rglob(METADATA_FILE):
316319
if marker.is_file():
317-
run_dirs.append(marker.parent)
318-
return run_dirs
320+
metadata_dirs.add(marker.parent)
321+
322+
# Look for legacy format (for directories that don't have new format)
323+
for marker in from_path.rglob(LEGACY_METADATA_FILE):
324+
if marker.is_file() and marker.parent not in metadata_dirs:
325+
metadata_dirs.add(marker.parent)
326+
327+
return sorted(metadata_dirs)
319328

320329

321330
def run_multi_run_artifacts_export(

projects/caliper/engine/file_export/mlflow_backend.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from pathlib import Path
1010
from typing import Any
1111

12+
from projects.caliper.engine.constants import LEGACY_METADATA_FILE, METADATA_FILE
1213
from projects.caliper.engine.file_export.mlflow_secrets import (
1314
assert_tracking_uri_has_no_userinfo,
1415
mlflow_connection_env,
@@ -506,14 +507,22 @@ def _log_curve_metrics(metrics_curve: dict[str, Any]) -> None:
506507

507508

508509
def _log_metrics_and_params_from_tree(artifact_root: Path) -> None:
509-
"""Find metrics.json/parameters.json under __test_labels__.yaml-marked dirs and log them."""
510+
"""Find metrics.json/parameters.json under metadata-marked dirs and log them (with backwards compatibility)."""
510511
import mlflow
511512

512-
for marker in sorted(artifact_root.rglob("__test_labels__.yaml")):
513-
if not marker.is_file():
514-
continue
515-
run_dir = marker.parent
513+
# Collect directories with either metadata file (new format or legacy)
514+
metadata_dirs = set()
515+
516+
for marker in artifact_root.rglob(METADATA_FILE):
517+
if marker.is_file():
518+
metadata_dirs.add(marker.parent)
519+
520+
# Look for legacy format (for directories that don't have new format)
521+
for marker in artifact_root.rglob(LEGACY_METADATA_FILE):
522+
if marker.is_file() and marker.parent not in metadata_dirs:
523+
metadata_dirs.add(marker.parent)
516524

525+
for run_dir in sorted(metadata_dirs):
517526
mf = run_dir / "metrics.json"
518527
if mf.is_file():
519528
for k, v in _load_json_file(mf).items():

projects/caliper/engine/kpi/kpis_to_mlflow.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,46 @@
1717
from pathlib import Path
1818
from typing import Any
1919

20+
from projects.caliper.engine.constants import (
21+
LEGACY_METADATA_FILE,
22+
METADATA_FILE,
23+
METRICS_FILE,
24+
PARAMETERS_FILE,
25+
)
2026
from projects.caliper.engine.kpi.dataclasses import HierarchicalKpiFormat
2127

2228
logger = logging.getLogger(__name__)
2329

24-
METRICS_FILE = "metrics.json"
25-
PARAMETERS_FILE = "parameters.json"
26-
TEST_LABELS_MARKER = "__test_labels__.yaml"
30+
# Metadata file markers (new format preferred, legacy for backwards compatibility)
31+
METADATA_MARKER = METADATA_FILE
32+
LEGACY_METADATA_MARKER = LEGACY_METADATA_FILE
2733

2834

2935
def _build_run_dir_index(artifact_tree: Path) -> dict[str, Path]:
30-
"""Map run directory names to their paths using __test_labels__.yaml markers."""
36+
"""Map run directory names to their paths using metadata markers (with backwards compatibility)."""
3137
index: dict[str, Path] = {}
32-
for marker in sorted(artifact_tree.rglob(TEST_LABELS_MARKER)):
38+
39+
# Collect directories with either metadata file (new format or legacy)
40+
metadata_dirs = set()
41+
42+
for marker in artifact_tree.rglob(METADATA_MARKER):
3343
if marker.is_file():
34-
run_dir = marker.parent
35-
try:
36-
rel = run_dir.relative_to(artifact_tree)
37-
except ValueError:
38-
rel = Path(run_dir.name)
39-
index[str(rel)] = run_dir
40-
index[run_dir.name] = run_dir
44+
metadata_dirs.add(marker.parent)
45+
46+
# Look for legacy format (for directories that don't have new format)
47+
for marker in artifact_tree.rglob(LEGACY_METADATA_MARKER):
48+
if marker.is_file() and marker.parent not in metadata_dirs:
49+
metadata_dirs.add(marker.parent)
50+
51+
# Build index from collected directories
52+
for run_dir in sorted(metadata_dirs):
53+
try:
54+
rel = run_dir.relative_to(artifact_tree)
55+
except ValueError:
56+
rel = Path(run_dir.name)
57+
index[str(rel)] = run_dir
58+
index[run_dir.name] = run_dir
59+
4160
return index
4261

4362

projects/caliper/engine/model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
@dataclass
1212
class TestBaseNode:
13-
"""Directory containing __test_labels__.yaml or MatrixBenchmarking settings.yaml."""
13+
"""Directory containing __caliper_test_metadata__.yaml or MatrixBenchmarking settings.yaml."""
1414

1515
directory: Path
1616
test_labels: dict[str, Any]
@@ -173,7 +173,7 @@ def get_ai_data_artifact_files_for_test(self, test_dir: Path) -> list[str]:
173173
not across the entire base directory. This provides better security isolation.
174174
175175
Args:
176-
test_dir: The specific test directory to search within (where __test_labels__.yaml is located)
176+
test_dir: The specific test directory to search within (where test metadata file is located)
177177
178178
Returns:
179179
List of relative file paths from test_dir to copy for AI evaluation

projects/caliper/engine/traverse.py

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Discover test base directories via __test_labels__.yaml or MatrixBenchmarking settings.yaml."""
1+
"""Discover test base directories via __caliper_test_metadata__.yaml or MatrixBenchmarking settings.yaml."""
22

33
from __future__ import annotations
44

@@ -8,10 +8,18 @@
88

99
import yaml
1010

11+
from projects.caliper.engine.constants import (
12+
LEGACY_METADATA_FILE,
13+
MATRIXBENCHMARKING_SETTINGS_FILE,
14+
METADATA_FILE,
15+
)
1116
from projects.caliper.engine.model import TestBaseNode
1217

13-
MARKER = "__test_labels__.yaml"
14-
MATRIXBENCHMARKING_MARKER = "settings.yaml"
18+
# Primary marker
19+
MARKER = METADATA_FILE
20+
# Legacy marker for backwards compatibility
21+
LEGACY_MARKER = LEGACY_METADATA_FILE
22+
MATRIXBENCHMARKING_MARKER = MATRIXBENCHMARKING_SETTINGS_FILE
1523

1624

1725
def discover_test_bases(
@@ -40,6 +48,8 @@ def discover_test_bases(
4048
marker_found = None
4149
if MARKER in filenames:
4250
marker_found = MARKER
51+
elif LEGACY_MARKER in filenames:
52+
marker_found = LEGACY_MARKER # Backwards compatibility
4353
elif MATRIXBENCHMARKING_MARKER in filenames:
4454
marker_found = MATRIXBENCHMARKING_MARKER
4555

@@ -49,7 +59,7 @@ def discover_test_bases(
4959
path = Path(dirpath)
5060

5161
# Use hierarchical label loading for both marker types
52-
if marker_found == MARKER:
62+
if marker_found == MARKER or marker_found == LEGACY_MARKER:
5363
test_labels = _load_hierarchical_test_labels(path, base_dir)
5464
# For filtering, use the labels directly (hierarchical loading returns the labels dict)
5565
# Normalize missing "labels" entry to empty mapping to allow discovery of empty marker files
@@ -144,15 +154,16 @@ def _matches_any_local(labels_dict: dict, key: str, filter_values: list[str]) ->
144154

145155

146156
def _load_hierarchical_test_labels(test_dir: Path, base_dir: Path) -> dict[str, Any]:
147-
"""Load and merge __test_labels__.yaml files hierarchically from base_dir down to test_dir.
157+
"""Load and merge test metadata files hierarchically from base_dir down to test_dir.
148158
149-
Merges in order:
150-
1. base_dir/__test_labels__.*.yaml (all variants)
151-
2. parent_dir/__test_labels__.*.yaml (all variants)
152-
3. test_dir/__test_labels__.*.yaml (all variants)
153-
4. test_dir/__test_labels__.yaml (final, cannot be overridden)
159+
Merges in order (for each directory):
160+
1. __caliper_test_metadata__.*.yaml (all variants, new format)
161+
2. __test_labels__.*.yaml (all variants, legacy format)
162+
3. __caliper_test_metadata__.yaml (final, new format)
163+
4. __test_labels__.yaml (final, legacy fallback)
154164
155-
Later files override earlier ones, with the main __test_labels__.yaml having final priority.
165+
Later files override earlier ones, with the main metadata file having final priority.
166+
New format files are preferred over legacy format when both exist.
156167
"""
157168
import glob
158169

@@ -172,14 +183,19 @@ def _load_hierarchical_test_labels(test_dir: Path, base_dir: Path) -> dict[str,
172183
# test_dir is not under base_dir, just use test_dir
173184
path_parts = [test_dir_abs]
174185

175-
# For each directory in the hierarchy, merge __test_labels__.*.yaml files (excluding plain __test_labels__.yaml)
186+
# For each directory in the hierarchy, merge variant files (new format first, then legacy)
176187
for dir_path in path_parts:
177188
if not dir_path.is_dir():
178189
continue
179190

180-
# Find all __test_labels__.*.yaml files (but not __test_labels__.yaml itself)
181-
pattern = str(dir_path / "__test_labels__.*.yaml")
182-
variant_files = sorted(glob.glob(pattern))
191+
# Find all variant files - new format first
192+
new_pattern = str(dir_path / f"{METADATA_FILE.replace('.yaml', '.*.yaml')}")
193+
legacy_pattern = str(dir_path / f"{LEGACY_METADATA_FILE.replace('.yaml', '.*.yaml')}")
194+
195+
# Collect all variant files, prioritizing new format
196+
variant_files = []
197+
variant_files.extend(sorted(glob.glob(new_pattern)))
198+
variant_files.extend(sorted(glob.glob(legacy_pattern)))
183199

184200
for variant_file in variant_files:
185201
variant_path = Path(variant_file)
@@ -192,8 +208,12 @@ def _load_hierarchical_test_labels(test_dir: Path, base_dir: Path) -> dict[str,
192208
# Skip files that can't be loaded
193209
pass
194210

195-
# Finally, load the main __test_labels__.yaml from the test directory (final priority)
211+
# Finally, load the main metadata file from the test directory (final priority)
212+
# Prefer new format, fall back to legacy format
196213
main_labels_path = test_dir / MARKER
214+
if not main_labels_path.is_file():
215+
main_labels_path = test_dir / LEGACY_MARKER
216+
197217
if main_labels_path.is_file():
198218
try:
199219
main_labels = _load_labels(main_labels_path, is_matrixbenchmarking=False)

projects/caliper/orchestration/postprocess.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from pydantic import ValidationError
2020

21+
from projects.caliper.engine.constants import LEGACY_METADATA_FILE, METADATA_FILE
2122
from projects.caliper.orchestration.caliper_invocation import (
2223
_execute_caliper_command,
2324
_generate_automatic_status_file_path,
@@ -287,29 +288,40 @@ def _run_artifacts_to_ai_data(
287288

288289

289290
def _load_test_labels(test_dir: Path) -> dict[str, Any]:
290-
"""Load test labels from __test_labels__.yaml file if it exists.
291+
"""Load test labels from metadata file (new format preferred, legacy fallback).
291292
292293
Args:
293-
test_dir: Directory to search for __test_labels__.yaml
294+
test_dir: Directory to search for metadata files
294295
295296
Returns:
296-
Dictionary containing test labels, or empty dict if file doesn't exist
297+
Dictionary containing test labels, or empty dict if no file exists
297298
"""
298299
import yaml
299300

300-
test_labels_file = test_dir / "__test_labels__.yaml"
301-
if test_labels_file.exists():
301+
# Try new format first
302+
metadata_file = test_dir / METADATA_FILE
303+
if metadata_file.exists():
302304
try:
303-
with open(test_labels_file, encoding="utf-8") as f:
305+
with open(metadata_file, encoding="utf-8") as f:
304306
labels = yaml.safe_load(f)
305-
logger.debug(f"Loaded test labels from {test_labels_file}: {labels}")
307+
logger.debug(f"Loaded test metadata from {metadata_file}: {labels}")
306308
return labels or {}
307309
except Exception as e:
308-
logger.warning(f"Failed to load test labels from {test_labels_file}: {e}")
309-
return {}
310-
else:
311-
logger.debug(f"No test labels file found at {test_labels_file}")
312-
return {}
310+
logger.error(f"Failed to load test metadata from {metadata_file}: {e}")
311+
312+
# Fallback to legacy format
313+
legacy_file = test_dir / LEGACY_METADATA_FILE
314+
if legacy_file.exists():
315+
try:
316+
with open(legacy_file, encoding="utf-8") as f:
317+
labels = yaml.safe_load(f)
318+
logger.debug(f"Loaded test labels from legacy file {legacy_file}: {labels}")
319+
return labels or {}
320+
except Exception as e:
321+
logger.error(f"Failed to load test labels from {legacy_file}: {e}")
322+
323+
logger.debug(f"No metadata or test labels file found in {test_dir}")
324+
return {}
313325

314326

315327
def _run_kpis_to_csv(

projects/caliper/tests/test_multi_run_export.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Tests for the multi-run caliper export pipeline.
33
44
Covers:
5-
- Run directory auto-detection via __test_labels__.yaml markers
5+
- Run directory auto-detection via __caliper_test_metadata__.yaml markers
66
- Shared vs run-specific file partitioning
77
- metrics.json / parameters.json reading and MLflow logging
88
- Parent + nested child run creation
@@ -20,15 +20,15 @@
2020
import pytest
2121
import yaml
2222

23+
from projects.caliper.engine.constants import METADATA_FILE, METRICS_FILE, PARAMETERS_FILE
2324
from projects.caliper.engine.file_export.artifacts_export_run import discover_run_dirs
2425

25-
METRICS_FILE = "metrics.json"
26-
PARAMETERS_FILE = "parameters.json"
27-
TEST_LABELS_MARKER = "__test_labels__.yaml"
26+
# Use new format for tests
27+
TEST_LABELS_MARKER = METADATA_FILE
2828

2929

3030
def _write_test_labels(directory: Path, labels: dict) -> None:
31-
"""Helper to write a __test_labels__.yaml marker file."""
31+
"""Helper to write a test metadata marker file."""
3232
directory.mkdir(parents=True, exist_ok=True)
3333
(directory / TEST_LABELS_MARKER).write_text(
3434
yaml.safe_dump({"version": "1", "labels": labels}, sort_keys=False),

0 commit comments

Comments
 (0)