Newer
Older
TIASDataHub / .claude / rules / coding-style.md

paths: ["src/", "datasets/"]

コーディング規約 (Coding Standards)

Python コード(src/**)・マイグレーション(src/tiasdata/catalog/migrations/**)・データセットの定義(datasets/**)を編集するときは本ルールに従うこと.

基本方針 (Basic Policy)

  • ruff を唯一の lint / format ツールとして使用する.設定は pyproject.toml の [tool.ruff] に集約する
  • 標準(PEP 8)から逸脱しない範囲で ruff の自動修正に従う
  • 別ツール(black・isort・mypy 等)は導入しない(ruff で完結させる)
  • 使う側(TIASJudgeModel 等)と同じ規約にそろえる(サブモジュールとして同じ作業の中で編集されるため)

適用 ruff ルール (Ruff Rules)

pyproject.toml の [tool.ruff.lint] で select = ["E", "F", "W", "I", "B", "UP", "N"] を選択する.行長は 100 文字とする.実行コマンドは ENV_04 開発コマンドを参照する.

ルール内容
E・W (pycodestyle)PEP 8 形式
F (pyflakes)未使用変数・未定義シンボル等
I (isort)import 文の並び順
B (flake8-bugbear)バグになりやすいパターン
UP (pyupgrade)Python 3.12 の書き方への置き換え
N (pep8-naming)命名

臨床データを扱うコードの規則 (Clinical Data Rules)

本プロジェクトの最重要規則.PLAN_01 要件定義書の制約と SPEC_03「出力の規則」に対応する.

  • データの場所をコードに書かない.目録・ストア・取り込み元・計算サーバの場所は設定ファイル(config.py が読む)から受け取る.テスト用の既定値もコードに置かない
  • CLI の出力・ログ・例外メッセージに出すのは,件数・研究用 ID・SHA-256・種類名・所見の値・設定で付けた名前だけ.実際の患者 ID・対応表の中身・画像の中身は出さない.元のファイル名(source_name)は既定では出さない
  • 対応表(identity.sqlite)を開くのは取り込みの処理だけにする.他のモジュールから対応表を参照しない(例外: tiasdata backup が複製と点検のために開く.中身は表示しない)
  • 原本(取り込み元)に書き込まない.取り込み元は読み取り専用で開き,ストア・目録にだけ書く
  • ストアのファイルを書き換えない・消さない.ストアへの書き込みは「同じ名前が無ければコピーし,コピー後にハッシュを照合する」だけにする
  • print ではなく logging を使う.ただし CLI の結果表示(件数の表等)は標準出力に書いてよい

目録(SQLite)の規則 (Catalog Rules)

  • SQL は catalog/ の中にだけ書く.他のモジュールは catalog/ の関数を呼ぶ
  • 値は必ずプレースホルダ(?・:name)で渡す.f-string・%・+ で SQL に値を埋め込まない
  • 接続ごとに PRAGMA foreign_keys = ON を有効にする
  • 複数の表にまたがる登録・版の作成は 1 つのトランザクションで行う(with conn:).途中で失敗したら何も残さない
  • 凍結した版(dataset_versions・dataset_members・dataset_member_annotations)と所見(annotations)を UPDATE・DELETE しない.所見の訂正は新しい行の追加と superseded_by の設定だけで行う
  • 日時は UTC の ISO 8601(例: 2026-10-02T09:00:00Z)で保存する

マイグレーション (Migrations)

  • スキーマの変更は src/tiasdata/catalog/migrations/<系列>/NNNN_<内容>.sql(系列は catalog・identity.4 桁の連番)を追加して行う.ファイルの中に BEGIN・COMMIT・PRAGMA user_version を書かない(適用側が囲む).適用済みのマイグレーションファイルは編集しない
  • 1 つのファイルは 1 つのトランザクションで適用できる内容にする
  • 種類(kinds)の追加もマイグレーションで行い,同時に src/tiasdata/kinds/ に値の型を追加する
  • 表・列を変えたら SPEC_02 データモデルを先に更新する

型ヒント (Type Hints)

  • 公開関数・クラス(tiasdata から使う側に見えるもの): 引数と戻り値に型ヒント必須
  • 内部ヘルパ・テストコード: 任意.書ける所は書く
  • 目録の行・manifest の行・設定は pydantic のモデルで表す(辞書のまま受け渡さない)
  • 静的型チェック(mypy / pyright)は当面導入しない

公開 API の互換 (Public API Compatibility)

  • tiasdata の公開 API(load・open_bundle・Bundle 等)と manifest.csv の列は使う側が依存する.名前・意味を変える・消す場合は,PR に使う側への影響を書き,SPEC_03 を更新する
  • 列や引数の追加(既存の使い方を壊さないもの)は自由に行ってよい

docstring

  • 公開関数・クラス: docstring 必須.Google スタイル(Args: / Returns: / Raises:).日本語可
  • 例外を送出する公開関数は Raises: に書く
def load(name: str, version: int) -> Bundle:
    """データセットの版を指定してバンドルを開く.

    Args:
        name: データセット名(例: `tongue_color`).
        version: 版(1 以上).

    Returns:
        開いたバンドル.

    Raises:
        ValueError: バンドルが見つからない,または manifest の SHA-256 が一致しない.
    """

命名規則 (Naming)

対象スタイル例
モジュール・パッケージsnake_casebundle.py・tiasdata
関数・変数snake_casefreeze_version・manifest_sha256
クラスPascalCaseBundle・CatalogConfig
定数UPPER_SNAKE_CASESCHEMA_VERSION
プライベート接頭辞 __copy_to_store
種類名(kinds.kind)・データセット名snake_case の英小文字tongue_crop_masked・tongue_color

コメント (Comments)

  • WHY を書く: 何をしているかは識別子で表し,コメントは「なぜこの実装か」「制約」「出典」に限る
  • TODO は # TODO(rintoHasegawa): 内容 の形で書く

CLI 引数 (CLI Arguments)

  • argparse 標準を使う.ヘルプ文は日本語可
  • 短縮形より長い形を優先する(--version・--to)
  • データのパスを引数に取らない.取り込み元・受け渡し先は設定ファイルで付けた名前で指定する(SSH のコマンドにデータの場所が現れないようにするため)

参考 (References)