refactor: use Path convenience methods for file operations

Simplified file reading patterns by using Path.read_text() instead of
with path.open() as f: f.read(). This makes the code more concise and
Pythonic while maintaining the same functionality.

Changes:
- Replace path.open().read() with path.read_text()
- Replace yaml.safe_load(f) with yaml.safe_load(path.read_text())
- Eliminate redundant file reads in configurator.py (read file once)
- Reduce code by 10 lines overall

All changes preserve existing behavior and encoding specifications.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Tsvika Shapira 2025-12-25 19:07:57 +02:00
parent b1925368f9
commit 52661e5b5c
9 changed files with 18 additions and 27 deletions

View File

@ -37,7 +37,7 @@ from pathlib import Path
from nanochat.common import get_base_dir
api_key = Path("openroutertoken.txt").open("r", encoding="utf-8").read().strip()
api_key = Path("openroutertoken.txt").read_text(encoding="utf-8").strip()
url = "https://openrouter.ai/api/v1/chat/completions"
headers = {
@ -45,7 +45,7 @@ headers = {
"Content-Type": "application/json"
}
readme = Path("README.md").open("r", encoding="utf-8").read().strip()
readme = Path("README.md").read_text(encoding="utf-8").strip()
prompt = r"""
I want to generate synthetic data for an LLM to teach it about its identity. Here is the identity I want:

View File

@ -30,10 +30,9 @@ for arg in sys.argv[1:]:
assert not arg.startswith('--')
config_file = Path(arg)
print0(f"Overriding config with {config_file}:")
with config_file.open() as f:
print0(f.read())
with config_file.open() as f:
exec(f.read())
config_content = config_file.read_text()
print0(config_content)
exec(config_content)
else:
# assume it's a --key=value argument
assert arg.startswith('--')

View File

@ -278,13 +278,12 @@ class Report:
# write the header first
header_file = report_dir / "header.md"
if header_file.exists():
with header_file.open("r", encoding="utf-8") as f:
header_content = f.read()
out_file.write(header_content)
start_time = extract_timestamp(header_content, "Run started:")
# capture bloat data for summary later (the stuff after Bloat header and until \n\n)
bloat_data = re.search(r"### Bloat\n(.*?)\n\n", header_content, re.DOTALL)
bloat_data = bloat_data.group(1) if bloat_data else ""
header_content = header_file.read_text(encoding="utf-8")
out_file.write(header_content)
start_time = extract_timestamp(header_content, "Run started:")
# capture bloat data for summary later (the stuff after Bloat header and until \n\n)
bloat_data = re.search(r"### Bloat\n(.*?)\n\n", header_content, re.DOTALL)
bloat_data = bloat_data.group(1) if bloat_data else ""
else:
start_time = None # will cause us to not write the total wall clock time
bloat_data = "[bloat data missing]"
@ -295,8 +294,7 @@ class Report:
if not section_file.exists():
print(f"Warning: {section_file} does not exist, skipping")
continue
with section_file.open("r", encoding="utf-8") as in_file:
section = in_file.read()
section = section_file.read_text(encoding="utf-8")
# Extract timestamp from this section (the last section's timestamp will "stick" as end_time)
if "rl" not in file_name:
# Skip RL sections for end_time calculation because RL is experimental

View File

@ -22,8 +22,7 @@ split_tokens = 20*524288 # number of tokens to evaluate per split
model_tag = None # optional model tag for the output directory name
model_step = None # optional model step for the output directory name
device_type = "" # cuda|cpu|mps (empty => autodetect)
with (Path('nanochat') / 'configurator.py').open() as f:
exec(f.read()) # overrides from command line or config file
exec((Path('nanochat') / 'configurator.py').read_text()) # overrides from command line or config file
# Load the base model and the tokenizer
device_type = autodetect_device_type() if device_type == "" else device_type

View File

@ -66,8 +66,7 @@ model_tag = "" # optionally override the model tag for the output checkpoint dir
# now allow CLI to override the settings via the configurator lol
config_keys = [k for k,v in globals().items() if not k.startswith('_') and isinstance(v, (int, float, bool, str))]
configurator_path = Path('nanochat') / 'configurator.py'
with configurator_path.open() as f:
exec(f.read()) # overrides from command line or config file
exec(configurator_path.read_text()) # overrides from command line or config file
user_config = {k: globals()[k] for k in config_keys} # will be useful for logging
# -----------------------------------------------------------------------------

View File

@ -49,8 +49,7 @@ eval_examples = 400 # number of examples used for evaluating pass@k
# now allow CLI to override the settings via the configurator lol
config_keys = [k for k,v in globals().items() if not k.startswith('_') and isinstance(v, (int, float, bool, str))]
configurator_path = Path('nanochat') / 'configurator.py'
with configurator_path.open() as f:
exec(f.read()) # overrides from command line or config file
exec(configurator_path.read_text()) # overrides from command line or config file
user_config = {k: globals()[k] for k in config_keys} # will be useful for logging
# -----------------------------------------------------------------------------

View File

@ -59,8 +59,7 @@ eval_metrics_max_problems = 1024
# now allow CLI to override the settings via the configurator lol
config_keys = [k for k,v in globals().items() if not k.startswith('_') and isinstance(v, (int, float, bool, str))]
configurator_path = Path('nanochat') / 'configurator.py'
with configurator_path.open() as f:
exec(f.read()) # overrides from command line or config file
exec(configurator_path.read_text()) # overrides from command line or config file
user_config = {k: globals()[k] for k in config_keys} # possibly useful for logging
# -----------------------------------------------------------------------------

View File

@ -243,8 +243,7 @@ app.add_middleware(
async def root():
"""Serve the chat UI."""
ui_html_path = Path("nanochat") / "ui.html"
with ui_html_path.open("r", encoding="utf-8") as f:
html_content = f.read()
html_content = ui_html_path.read_text(encoding="utf-8")
# Replace the API_URL to use the same origin
html_content = html_content.replace(
"const API_URL = `http://${window.location.hostname}:8000`;",

View File

@ -51,8 +51,7 @@ total_batch_size = 524288
dry_run = 0 # dry_run=1 is for experiments: we will log to wandb but we won't write checkpoints or report
config_keys = [k for k,v in globals().items() if not k.startswith('_') and isinstance(v, (int, float, bool, str))]
configurator_path = Path('nanochat') / 'configurator.py'
with configurator_path.open() as f:
exec(f.read()) # overrides from command line or config file
exec(configurator_path.read_text()) # overrides from command line or config file
user_config = {k: globals()[k] for k in config_keys} # possibly useful for logging
# -----------------------------------------------------------------------------