From 38268b52a54993e9f1964daf171289e97bfd26c2 Mon Sep 17 00:00:00 2001 From: tkgstrator <29420801+tkgstrator@users.noreply.github.com> Date: Mon, 13 Jul 2026 03:46:36 +0000 Subject: [PATCH] build(train): add python-dotenv for .env credential loading Load environment variables from .env into os.environ at the start of each training entrypoint (train_board_ocr, train_piece, train_detector) so HuggingFace (HF_TOKEN) and Weights & Biases (WANDB_API_KEY, CF_ACCESS_CLIENT_*) can resolve credentials without exporting them by hand. load_dotenv() is a no-op when .env is missing and does not override existing os.environ entries, so devcontainer-exported values still win. Bump version to 0.3.1. Co-Authored-By: Claude Opus 4.8 (1M context) --- mito_train/training/train_board_ocr.py | 5 +++++ mito_train/training/train_detector.py | 5 +++++ mito_train/training/train_piece.py | 5 +++++ pyproject.toml | 3 ++- uv.lock | 13 ++++++++++++- 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/mito_train/training/train_board_ocr.py b/mito_train/training/train_board_ocr.py index fab556a..07b8385 100644 --- a/mito_train/training/train_board_ocr.py +++ b/mito_train/training/train_board_ocr.py @@ -20,6 +20,8 @@ from importlib.metadata import version as _pkg_version from pathlib import Path +from dotenv import load_dotenv + import torch import torch.nn as nn import torch.nn.functional as F @@ -506,6 +508,9 @@ def log_main(msg: str) -> None: def main() -> None: + # Pull HF_TOKEN / WANDB_API_KEY / CF_* out of .env into os.environ before + # any HF or wandb call resolves credentials. No-op if .env is missing. + load_dotenv() p = argparse.ArgumentParser() p.add_argument("--mode", choices=["smoke", "full"], default="smoke") p.add_argument("--backbone", default="mobilenet_v3_small", diff --git a/mito_train/training/train_detector.py b/mito_train/training/train_detector.py index d95fcb4..cd0d953 100644 --- a/mito_train/training/train_detector.py +++ b/mito_train/training/train_detector.py @@ -20,6 +20,8 @@ import argparse from pathlib import Path +from dotenv import load_dotenv + import torch import torch.nn as nn import torch.nn.functional as F @@ -74,6 +76,9 @@ def evaluate(model: nn.Module, loader: DataLoader, device: str) -> dict[str, flo def main() -> None: + # Pull HF_TOKEN / WANDB_API_KEY / CF_* out of .env into os.environ before + # any wandb or HF call resolves credentials. No-op if .env is missing. + load_dotenv() p = argparse.ArgumentParser() p.add_argument("--train-manifest", type=Path, default=Path("data/detector/train.jsonl")) p.add_argument("--val-manifest", type=Path, default=Path("data/detector/val.jsonl")) diff --git a/mito_train/training/train_piece.py b/mito_train/training/train_piece.py index 911b997..dd6a5b7 100644 --- a/mito_train/training/train_piece.py +++ b/mito_train/training/train_piece.py @@ -18,6 +18,8 @@ import os from pathlib import Path +from dotenv import load_dotenv + import torch import torch.nn as nn from torch.utils.data import DataLoader @@ -219,6 +221,9 @@ def run_manifest(args: argparse.Namespace) -> None: def main() -> None: + # Pull WANDB_API_KEY / CF_* / HF_TOKEN out of .env into os.environ before + # any wandb or HF call resolves credentials. No-op if .env is missing. + load_dotenv() p = argparse.ArgumentParser() p.add_argument("--mode", choices=["smoke", "manifest"], default="smoke") # smoke-mode args diff --git a/pyproject.toml b/pyproject.toml index 65b9dfb..054dfcf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mito-train" -version = "0.3.0" +version = "0.3.1" description = "ぴよ将棋OCR 3モデル (board-detector / piece-classifier / hand-classifier) の学習・ONNX出力" requires-python = ">=3.11" dependencies = [ @@ -15,6 +15,7 @@ dependencies = [ "onnxscript>=0.7.1", "opencv-python-headless>=5.0.0.93", "pillow>=12.3.0", + "python-dotenv>=1.1.1", "python-shogi>=1.1.1", "pyyaml>=6.0.3", "timm>=1.0.28", diff --git a/uv.lock b/uv.lock index 348ec64..ac793db 100644 --- a/uv.lock +++ b/uv.lock @@ -1119,7 +1119,7 @@ wheels = [ [[package]] name = "mito-train" -version = "0.3.0" +version = "0.3.1" source = { editable = "." } dependencies = [ { name = "albumentations" }, @@ -1134,6 +1134,7 @@ dependencies = [ { name = "onnxscript" }, { name = "opencv-python-headless" }, { name = "pillow" }, + { name = "python-dotenv" }, { name = "python-shogi" }, { name = "pyyaml" }, { name = "timm" }, @@ -1160,6 +1161,7 @@ requires-dist = [ { name = "onnxscript", specifier = ">=0.7.1" }, { name = "opencv-python-headless", specifier = ">=5.0.0.93" }, { name = "pillow", specifier = ">=12.3.0" }, + { name = "python-dotenv", specifier = ">=1.1.1" }, { name = "python-shogi", specifier = ">=1.1.1" }, { name = "pyyaml", specifier = ">=6.0.3" }, { name = "timm", specifier = ">=1.0.28" }, @@ -2269,6 +2271,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] +[[package]] +name = "python-dotenv" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, +] + [[package]] name = "python-shogi" version = "1.1.1"