Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
0d4c655
feat(01-01): extend MD5 exclusion constants with test/, tests/, .code…
FileSystemGuy Jun 16, 2026
b586693
feat(01-02): add code_image module — capture, load, and verify primit…
FileSystemGuy Jun 16, 2026
b25578b
test(01-03): add unit-test suite for code_image module
FileSystemGuy Jun 16, 2026
325f01e
chore: include ancillary worktree edits alongside phase 1
FileSystemGuy Jun 16, 2026
53308f4
test(02-01): add failing tests for EXIT_CODE.CODE_IMAGE_ERROR
FileSystemGuy Jun 17, 2026
3f2d9b0
feat(02-01): add EXIT_CODE.CODE_IMAGE_ERROR enum member
FileSystemGuy Jun 17, 2026
88b0c67
test(02-01): add failing tests for generate_output_location prefix
FileSystemGuy Jun 17, 2026
915ab7f
feat(02-01): thread orgname/systemname kwargs into generate_output_lo…
FileSystemGuy Jun 17, 2026
d4e94a8
test(02-03): add failing tests for STRUCT-06 refactor and mode-aware …
FileSystemGuy Jun 17, 2026
b781f03
feat(02-03): refactor STRUCT-06 for CLOSED+OPEN layered self-check; m…
FileSystemGuy Jun 17, 2026
d3f2e3f
docs(02-04): align Rules.md with runtime capture + layered validator
FileSystemGuy Jun 17, 2026
015ef82
test(02-02): add failing tests for capture_or_verify_code_image helper
FileSystemGuy Jun 17, 2026
f4a93c7
feat(02-02): add capture_or_verify_code_image CLI dispatch helper
FileSystemGuy Jun 17, 2026
87bef2f
test(02-02): add failing tests for main.py code-image wiring
FileSystemGuy Jun 17, 2026
d0f3dca
feat(02-02): wire capture_or_verify_code_image into main.py CLI dispatch
FileSystemGuy Jun 17, 2026
ee2ec98
test(02-05): add CAP/VALR contract + path-traversal tests for CLI helper
FileSystemGuy Jun 17, 2026
9a3fc5e
test(02-05): update TestStruct06 fixture; add TestStruct06_OpenCodeDi…
FileSystemGuy Jun 17, 2026
4b3216c
test(02-05): add TestStruct05_OpenSubmitter; update legacy STRUCT-05 …
FileSystemGuy Jun 17, 2026
13bd98e
test(01-02): add failing tests for nested-excluded-dir walker divergence
FileSystemGuy Jun 17, 2026
0a8aac8
fix(01-02): align compute_code_tree_md5 with capture walker for neste…
FileSystemGuy Jun 17, 2026
f8151fc
test(02-02): add failing tests for vectordb/kvcache canonical type-na…
FileSystemGuy Jun 17, 2026
866ff5a
fix(02-02): canonicalize vectordb/kvcache type segment + align Rules.…
FileSystemGuy Jun 17, 2026
eb46498
test(02-02,02-03): add failing tests for per-type OPEN code path-shape
FileSystemGuy Jun 18, 2026
390eb20
fix(02-02,02-03): per-type OPEN code path-shape — drop model segment …
FileSystemGuy Jun 18, 2026
8fba4c4
docs(02-04): Rules.md — vector_database OPEN code/ is per-type, not p…
FileSystemGuy Jun 18, 2026
b97c466
test(02-01,02-02,02-03): RED — vector_database paths must include <in…
FileSystemGuy Jun 18, 2026
96f0ed0
fix(02-01,02-02,02-03): restore per-<index_type> shape for vector_dat…
FileSystemGuy Jun 18, 2026
db70f6e
docs(02-04): Rules.md — restore per-<index_type> shape for vector_dat…
FileSystemGuy Jun 18, 2026
3ce47be
docs(02-03): refresh _iter_open_code_dirs docstring after per-index_t…
FileSystemGuy Jun 18, 2026
ed17367
chore(03-01): release artifacts — bump to 3.0.14, regen uv.lock, clea…
FileSystemGuy Jun 18, 2026
e883b6e
Merge remote-tracking branch 'origin/main' into FileSystemGuy-capture…
FileSystemGuy Jun 18, 2026
7511394
fix(capture): reject mlpstorage_version="unknown" sentinel at capture…
FileSystemGuy Jun 18, 2026
b873e4b
test(accumulation): update vectordb path tests for per-index_type con…
FileSystemGuy Jun 18, 2026
34b3619
feat(04-01): add INDEX_TYPE_TOKEN_TO_DIR mapping and rewrite vdb path…
FileSystemGuy Jun 18, 2026
de345c1
docs(04-01): refresh _iter_open_code_dirs walker comments for vdb_bench
FileSystemGuy Jun 18, 2026
42fa5a4
test(04-01): pin new vdb_bench/<DisplayIndex>/ shape in fixtures
FileSystemGuy Jun 18, 2026
23bc041
refactor(04-02): extract layered code-image helper and rewire 3.6.1
FileSystemGuy Jun 18, 2026
f552103
feat(04-02): implement Rules.md §5 VdbCheck with all 16 rule methods
FileSystemGuy Jun 18, 2026
d05ad05
chore(04-02): drop STUB_COVERAGE['VdbCheck'] entry (D-01)
FileSystemGuy Jun 18, 2026
f457d52
docs(04-03): refresh §2.1.5.b leaf description for vdb_bench + displa…
FileSystemGuy Jun 18, 2026
b9d480b
docs(04-03): rewrite §2.1.27 vdb_bench subtrees with <command>/<datet…
FileSystemGuy Jun 18, 2026
1474d6f
docs(04-03): rewrite §5.3.1 (D-04) and §5.6.1 (D-06) prose
FileSystemGuy Jun 18, 2026
de99a55
test(04-04): add per-rule TestClass sweep for VdbCheck §5.1.1-5.6.5
FileSystemGuy Jun 18, 2026
d036f00
test(04-04): add end-to-end tests for TrainingCheck §3.6.1 layered check
FileSystemGuy Jun 18, 2026
625a11c
fix(04): WR-01 skip dot-prefixed entries in _iter_open_code_dirs
FileSystemGuy Jun 19, 2026
e35e83d
fix(04): WR-02 collapse null YAML nodes with `or {}` in chained .get …
FileSystemGuy Jun 19, 2026
ecac710
fix(04): WR-03 wrap capture post-copy steps in rollback try/except
FileSystemGuy Jun 19, 2026
b306303
fix(04): WR-04 raise CodeImageError for missing args.benchmark / leaf…
FileSystemGuy Jun 19, 2026
9515078
fix(04): WR-05 tighten 5.5.1 S3 backend match to exact names + 's3-' …
FileSystemGuy Jun 19, 2026
1206165
fix(04): WR-06 warn when df-mount match is indeterminate
FileSystemGuy Jun 19, 2026
5c58aa0
fix(04): WR-07 skip upstream-identity walk on MissingHashFile
FileSystemGuy Jun 19, 2026
054eb7f
fix(04): WR-07 (STRUCT-06) apply same MissingHashFile short-circuit
FileSystemGuy Jun 19, 2026
a7f5d20
chore: ignore .gsd-tmp/ for gsd-code-fixer worktree
FileSystemGuy Jun 19, 2026
709c0ac
fix(04): IN-01 use CodeTreeUnreadable for unreadable-tree branch
FileSystemGuy Jun 19, 2026
cc05dc2
fix(04): IN-02 use CodeTreeUnreadable for source-walk failure
FileSystemGuy Jun 19, 2026
f9af70e
fix(04): IN-03 enforce results_dir-must-exist contract
FileSystemGuy Jun 19, 2026
2bdc7eb
fix(04): IN-04 drop redundant target_dir.mkdir before copytree
FileSystemGuy Jun 19, 2026
cd55ea4
fix(04): IN-05 gate 'not configured' warning on actual closed/ submit…
FileSystemGuy Jun 19, 2026
4e34ddd
fix(04): IN-06 add TODO-001 marker at df parse site
FileSystemGuy Jun 19, 2026
8edc84f
fix(04): extend rules-coverage regex to enumerate §5 + §6 IDs
FileSystemGuy Jun 19, 2026
b98472f
fix: guard num_client_hosts derivation when --hosts is None
FileSystemGuy Jun 19, 2026
8a3dabd
fix: emit traceback when --debug CLI flag is set, not just MLPS_DEBUG…
FileSystemGuy Jun 19, 2026
dc29798
fix: thread orgname/systemname into generate_output_location
FileSystemGuy Jun 19, 2026
beb9bbb
fix: rewrite generate_output_location suggestion strings
FileSystemGuy Jun 19, 2026
17204da
fix: exclude dot-prefixed local-artifact dirs from code-image MD5
FileSystemGuy Jun 19, 2026
cc2b660
chore: untrack summary.csv submission-checker output
FileSystemGuy Jun 19, 2026
e15fe7a
chore: revert whitespace-only CLAUDE.md changes
FileSystemGuy Jun 19, 2026
da6752f
Merge branch 'main' into FileSystemGuy-code-image-capture-v1
FileSystemGuy Jun 19, 2026
6e80bc8
test: update generate_output_location mock assertion for new kwargs
FileSystemGuy Jun 19, 2026
6de8ef2
Merge branch 'main' into FileSystemGuy-code-image-capture-v1
dslik Jun 19, 2026
325c2f0
Merge remote-tracking branch 'origin/main' into FileSystemGuy-code-im…
FileSystemGuy Jun 20, 2026
10124ba
refactor: rename on-disk type segment vdb_bench -> vector_database
FileSystemGuy Jun 20, 2026
3320af3
refactor: use UPPERCASE index name on disk; drop display/token vocab …
FileSystemGuy Jun 20, 2026
a8a141e
security: validate every path-component arg in generate_output_location
FileSystemGuy Jun 20, 2026
6699b62
chore: bump version 3.0.15 -> 3.0.16; regenerate uv.lock
FileSystemGuy Jun 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ CLAUDE.md
.roomodes
LOCAL_BRANCH_NOTES.md
.planning/
.gsd-tmp/

# DLIO test artifacts — created in cwd when running dlio_benchmark tests
output/
Expand All @@ -70,6 +71,12 @@ env-fast
sim_*.tsv
sim_*.tsv.zst

# Submission checker default CSV output (utility_args.py default --csv path,
# README.md §submission-checker). Runtime artifact, not source — keep
# untracked so contributors don't see a dirty working tree after running
# `mlpstorage validate ...` without an explicit --csv path.
summary.csv

# Sweep run logs and results (local benchmark output)
sweep_logs/
sweep_flux_master.log
Expand Down
154 changes: 105 additions & 49 deletions Rules.md

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion mlpstorage_py/benchmarks/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,18 @@ def generate_output_location(self) -> str:
"""
if not self.BENCHMARK_TYPE:
raise ValueError('No benchmark specified. Unable to generate output location')
return generate_output_location(self, self.run_datetime)
# Thread the validated orgname/systemname stashed by
# capture_or_verify_code_image (code_image.py: args._validated_orgname /
# args._validated_systemname) so generate_output_location's
# OPEN/CLOSED ConfigurationError path doesn't fire. For legacy /
# whatif modes these attrs are absent (getattr default None) and the
# function's mode check skips the orgname/systemname requirement.
return generate_output_location(
self,
self.run_datetime,
orgname=getattr(self.args, "_validated_orgname", None),
systemname=getattr(self.args, "_validated_systemname", None),
)

_COLLISION_BUMP_BUDGET = DEFAULT_COLLISION_BUMP_BUDGET

Expand Down
3 changes: 3 additions & 0 deletions mlpstorage_py/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ def get_datetime_string():
# VDB Benchmark Configuration
VDB_INDEX_TYPES = ["DISKANN", "HNSW", "AISAQ", "IVF_FLAT", "IVF_SQ8", "FLAT"]
VDB_INDEX_TYPES_CLOSED = ["DISKANN", "HNSW", "AISAQ"]

VDB_ORCHESTRATION_MODES = ["ssh", "mpi"]
VDB_BENCHMARK_MODES = ["timed", "query_count", "sweep"]
# Vector-database engines. Only milvus is wired up today; the slot exists so
Expand Down Expand Up @@ -154,6 +155,8 @@ class EXIT_CODE(enum.IntEnum):
SUCCESS = 0
GENERAL_ERROR = 1
INVALID_ARGUMENTS = 2
# CAP/VALR failure exit code (per 02-CONTEXT.md D-22). Aliased with INVALID_ARGUMENTS=2 for ergonomic naming at the typed-exception → exit mapping in main.py.
CODE_IMAGE_ERROR = 2
FILE_NOT_FOUND = 3
PERMISSION_DENIED = 4
CONFIGURATION_ERROR = 5
Expand Down
7 changes: 7 additions & 0 deletions mlpstorage_py/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ def __init__(self, message: str, parameter: str = None,
expected=expected,
actual=actual
)
# Expose the missing/invalid parameter name as a direct attribute so
# the CLI dispatch layer (and tests) can inspect it without poking at
# the structured-error context dict. Documented use case: the Phase 2
# generate_output_location trust-contract raises ConfigurationError
# with parameter="orgname" or "systemname" so the dispatch helper
# can map it back to the MLPSTORAGE_* env-var the user must set.
self.parameter = parameter

@staticmethod
def _default_suggestion(code: ErrorCode) -> str:
Expand Down
30 changes: 28 additions & 2 deletions mlpstorage_py/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
)
from mlpstorage_py.validation_helpers import validate_benchmark_environment
from mlpstorage_py.progress import progress_context
from mlpstorage_py.submission_checker.tools.code_image import capture_or_verify_code_image, CodeImageError

logger = setup_logging("MLPerfStorage")
signal_received = False
Expand Down Expand Up @@ -202,6 +203,18 @@ def run_benchmark(args, run_datetime):
else:
logger.warning("Skipping environment validation (--skip-validation flag)")

# Capture/verify code image BEFORE benchmark instantiation (Phase 2 D-07).
# Helper internally gates on (args.mode, args.command) per D-10, so it is
# safe to call unconditionally — non-result-generating commands no-op.
# Helper also owns ALL env-var reading and validation (POSIX regex + inline
# `.`/`..` path-traversal guard) — see Plan 02 REVIEWS.md consensus finding.
with progress_context(
"Capturing or verifying code image...",
total=None,
logger=logger
) as (update, set_desc):
capture_or_verify_code_image(args, os.environ, logger)

program_switch_dict = dict(
training=TrainingBenchmark,
checkpointing=CheckpointingBenchmark,
Expand Down Expand Up @@ -404,6 +417,15 @@ def main():
logger.info(f"Suggestion: {e.suggestion}")
return EXIT_CODE.FAILURE

except CodeImageError as e:
# Phase 2 D-22: code-image capture/verify failures (incl. MissingHashFile,
# MalformedHashFile, hash-mismatch CodeImageError) map to a dedicated
# exit code distinct from generic FAILURE so CI/scripts can detect them.
# CodeImageError is NOT a MLPStorageException subclass, so it requires
# an explicit handler ordered BEFORE the MLPStorageException catch-all.
logger.error(str(e))
return EXIT_CODE.CODE_IMAGE_ERROR

except MLPStorageException as e:
# Catch-all for any other custom exceptions
logger.error(str(e))
Expand All @@ -424,8 +446,12 @@ def main():
logger.error(f"Unexpected error: {str(e)}")
logger.error(format_error('INTERNAL_ERROR', error=str(e)))

# Show traceback if in debug mode
if MLPS_DEBUG:
# Show traceback if in debug mode. MLPS_DEBUG is the env-var path
# (read at import time); also check `--debug` directly via sys.argv
# so the CLI flag emits a trace even though `args` is not in scope
# here. `--debug` is store_true so a bare-token check suffices.
debug_cli = '--debug' in sys.argv
if MLPS_DEBUG or debug_cli:
logger.debug("Stack trace:")
traceback.print_exc()
else:
Expand Down
144 changes: 134 additions & 10 deletions mlpstorage_py/rules/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,44 @@
"""

import os
import re
import sys
from typing import Tuple, List, Optional

from mlpstorage_py.config import BENCHMARK_TYPES, DATETIME_STR
from mlpstorage_py.errors import ConfigurationError, ErrorCode

# Env-var names used by the Phase 2 CLI dispatch layer to source orgname/systemname (D-01, D-02).
# generate_output_location itself does NOT read these; the helper in
# mlpstorage_py/submission_checker/tools/code_image.py reads + validates them and threads
# the values through as keyword arguments. The names are exported here so the helper has a
# single source of truth for the env-var spelling.
MLPSTORAGE_ORGNAME_ENVVAR = "MLPSTORAGE_ORGNAME"
MLPSTORAGE_SYSTEMNAME_ENVVAR = "MLPSTORAGE_SYSTEMNAME"

# Each path segment appended to results_dir by generate_output_location must
# match this — POSIX-safe alphanumeric plus '.', '_', '-' — and must not be
# '.' or '..'. Blocks path-traversal ('../') and absolute-path resets ('/')
# at the trust boundary between args/env-var input and os.path.join, even
# for callers that bypass the CLI's argparse choices= validation.
_SAFE_PATH_COMPONENT_RE = re.compile(r"^[A-Za-z0-9._-]+$")


def _check_safe_path_component(name: str, value: str) -> None:
"""Raise ValueError if value is not safe as a single path segment.

Caller handles None/empty upstream as a separate "missing required arg"
failure mode; this helper assumes value is a non-empty string.
"""
if value in (".", ".."):
raise ValueError(
f"{name}={value!r} is not a safe path component (reserved name)"
)
if not _SAFE_PATH_COMPONENT_RE.match(value):
raise ValueError(
f"{name}={value!r} is not a safe path component "
f"(must match {_SAFE_PATH_COMPONENT_RE.pattern})"
)


def calculate_training_data_size(args, cluster_information, dataset_params, reader_params, logger,
Expand Down Expand Up @@ -118,28 +152,61 @@ def calculate_training_data_size(args, cluster_information, dataset_params, read
return int(required_file_count), int(required_subfolders_count), int(total_disk_bytes)


def generate_output_location(benchmark, datetime_str=None, **kwargs) -> str:
def generate_output_location(
benchmark,
datetime_str=None,
*,
orgname: Optional[str] = None,
systemname: Optional[str] = None,
**kwargs,
) -> str:
"""
Generate a standardized output location for benchmark results.

Output structure follows this pattern:
RESULTS_DIR:
<benchmark_name>:
<model>:
<command>:
<datetime>:
run_<run_number> (Optional)

CLOSED (args.mode == "closed"):
<results_dir>/closed/<orgname>/<benchmark_name>/<model>/<command>/<datetime>/

OPEN (args.mode == "open"):
<results_dir>/open/<orgname>/results/<systemname>/<benchmark_name>/<model>/<command>/<datetime>/

Legacy (args.mode not in {"closed", "open"}, or attribute missing —
e.g. whatif, programmatic callers from tests):
<results_dir>/<benchmark_name>/<model>/<command>/<datetime>/

The per-``BENCHMARK_TYPES`` tail (training/checkpointing/vector_database/
kv_cache) is unchanged below the new prefix.

Args:
benchmark: Benchmark instance.
datetime_str: Optional datetime string for the run.
**kwargs: Additional benchmark-specific parameters.
orgname: Keyword-only. Submitter organization name; required when
``benchmark.args.mode`` is "closed" or "open". The CLI dispatch
layer (Plan 02-02) reads ``MLPSTORAGE_ORGNAME`` from the
environment, validates it per Rules.md §2.1.1, and threads the
validated value through as this keyword argument. This function
does NOT read ``os.environ`` — passing the value explicitly is a
trust-contract requirement so programmatic callers (tests,
future tooling) receive a typed ``ConfigurationError`` if they
forget to thread it through, rather than a hidden ``KeyError``.
systemname: Keyword-only. System name; required when
``benchmark.args.mode`` is "open". Same trust-contract semantics
as ``orgname``; sourced from ``MLPSTORAGE_SYSTEMNAME`` by the
dispatch layer.
**kwargs: Additional benchmark-specific parameters (reserved).

Returns:
Full path to the output location.

Raises:
ValueError: If required parameters are missing.
ValueError: If required parameters are missing (e.g. ``args.model``
for training/checkpointing benchmarks).
ConfigurationError: If ``benchmark.args.mode`` is "closed" or "open"
but ``orgname`` (and, for "open", ``systemname``) was not threaded
through by the caller. The ``parameter`` attribute identifies the
missing kwarg; the ``suggestion`` field references the
``MLPSTORAGE_*`` env-var the dispatch layer must read.
"""
if datetime_str is None:
datetime_str = DATETIME_STR
Expand All @@ -151,17 +218,68 @@ def generate_output_location(benchmark, datetime_str=None, **kwargs) -> str:
else:
run_number = 0

# New D-03 prefix: insert {closed|open}/<orgname>[/results/<systemname>]/
# before the legacy per-type chain. The values are explicit kwargs threaded
# by the CLI dispatch layer (Plan 02-02); env-var reading is owned by that
# helper, not this function (see module-level constants above for the
# env-var-name source of truth).
mode = getattr(benchmark.args, "mode", None)
if mode in ("closed", "open"):
if not orgname:
raise ConfigurationError(
"orgname is required when args.mode in {closed, open} but was "
"not provided to generate_output_location",
parameter="orgname",
suggestion=(
f"The CLI dispatch layer should read the "
f"{MLPSTORAGE_ORGNAME_ENVVAR} environment variable and "
"thread the validated value through as the orgname "
"keyword. Programmatic callers must pass orgname= "
"explicitly."
),
code=ErrorCode.CONFIG_MISSING_REQUIRED,
)
_check_safe_path_component("orgname", orgname)
output_location = os.path.join(output_location, mode, orgname)

if mode == "open":
if not systemname:
raise ConfigurationError(
"systemname is required when args.mode == 'open' but was "
"not provided to generate_output_location",
parameter="systemname",
suggestion=(
f"The CLI dispatch layer should read the "
f"{MLPSTORAGE_SYSTEMNAME_ENVVAR} environment "
"variable and thread the validated value through "
"as the systemname keyword. Programmatic callers "
"must pass systemname= explicitly."
),
code=ErrorCode.CONFIG_MISSING_REQUIRED,
)
_check_safe_path_component("systemname", systemname)
output_location = os.path.join(output_location, "results", systemname)

# datetime_str is built into every per-type path below; validate once here.
_check_safe_path_component("datetime_str", datetime_str)

# Handle different benchmark types
if benchmark.BENCHMARK_TYPE == BENCHMARK_TYPES.training:
if not hasattr(benchmark.args, "model"):
raise ValueError("Model name is required for training benchmark output location")

_check_safe_path_component("model", benchmark.args.model)
_check_safe_path_component("command", benchmark.args.command)
output_location = os.path.join(output_location, benchmark.BENCHMARK_TYPE.name)
output_location = os.path.join(output_location, benchmark.args.model)
output_location = os.path.join(output_location, benchmark.args.command)
output_location = os.path.join(output_location, datetime_str)

elif benchmark.BENCHMARK_TYPE == BENCHMARK_TYPES.vector_database:
# Results split by index_type because AISAQ is not comparable to
# DISKANN/HNSW — they must live in separate on-disk trees so
# submission validation and downstream tooling never collate them
# (per Rules.md §2.1.27).
engine = getattr(benchmark.args, "vdb_engine", None)
if not engine:
raise ValueError(
Expand All @@ -177,7 +295,10 @@ def generate_output_location(benchmark, datetime_str=None, **kwargs) -> str:
"VectorDB index is required for output location "
"(set --vdb-index on the CLI)."
)


_check_safe_path_component("vdb_engine", engine)
_check_safe_path_component("vdb_index", vdb_index)
_check_safe_path_component("command", benchmark.args.command)
output_location = os.path.join(output_location, benchmark.BENCHMARK_TYPE.name)
output_location = os.path.join(output_location, engine)
output_location = os.path.join(output_location, vdb_index)
Expand All @@ -192,6 +313,8 @@ def generate_output_location(benchmark, datetime_str=None, **kwargs) -> str:
"args.model before calling generate_output_location "
"(KVCacheBenchmark.__init__ defaults this from KVCACHE_MODEL_DEFAULT)."
)
_check_safe_path_component("model", model)
_check_safe_path_component("command", benchmark.args.command)
output_location = os.path.join(output_location, benchmark.BENCHMARK_TYPE.name)
output_location = os.path.join(output_location, model)
output_location = os.path.join(output_location, benchmark.args.command)
Expand All @@ -201,6 +324,7 @@ def generate_output_location(benchmark, datetime_str=None, **kwargs) -> str:
if not hasattr(benchmark.args, "model"):
raise ValueError("Model name is required for checkpointing benchmark output location")

_check_safe_path_component("model", benchmark.args.model)
output_location = os.path.join(output_location, benchmark.BENCHMARK_TYPE.name)
output_location = os.path.join(output_location, benchmark.args.model)
output_location = os.path.join(output_location, datetime_str)
Expand Down
Loading
Loading