========================================================================
Python コーディング規則 (Python Coding Style Guide)
========================================================================

1. 基本方針 (Basic Policy)
------------------------------------------------------------------------
PEP 8 を基本とし，チーム内での一貫性を最優先とする．
本規則に明記されていない事項は PEP 8 に従う．
※ 書式・記述スタイルの基準は `GUIDE_01_ドキュメント作成ガイド.txt` を参照する．


2. フォーマット (Formatting)
------------------------------------------------------------------------

2-1. インデント
    ・半角スペース4つを使用する．タブ文字は使用しない．
    ・継続行は，開き括弧に揃えるか，ハンギングインデント（スペース4つ追加）とする．
    ・例:

        # 開き括弧に揃える
        result = some_function(arg_one, arg_two,
                               arg_three, arg_four)

        # ハンギングインデント
        result = some_function(
            arg_one, arg_two,
            arg_three, arg_four,
        )

2-2. 1行の最大文字数
    ・79文字を上限とする（PEP 8 準拠）．
    ・文字列やコメントが長くなる場合は，括弧による暗黙の行継続を優先する．
    ・バックスラッシュ `\` による行継続は極力避ける．

2-3. 空行
    ・トップレベルの関数・クラス定義の間: 2行空ける．
    ・クラス内のメソッド定義の間: 1行空ける．
    ・関数内の論理的なまとまりの区切り: 1行空ける（使いすぎに注意）．

2-4. 文字コード
    ・UTF-8 を使用する．
    ・エンコーディング宣言（`# -*- coding: utf-8 -*-`）は Python 3 では不要．


3. 命名規則 (Naming Conventions)
------------------------------------------------------------------------

3-1. 一覧

    ■ 変数・関数・メソッド・引数
    ・スタイル: snake_case
    ・例: `motor_speed`，`calc_distance`，`handle_input`

    ■ 定数
    ・スタイル: UPPER_SNAKE_CASE
    ・例: `MAX_SPEED`，`DEFAULT_PORT`，`PIN_MOTOR_LEFT`

    ■ クラス
    ・スタイル: PascalCase
    ・例: `MotorController`，`SensorReader`，`UltrasonicSensor`

    ■ モジュール（ファイル名）
    ・スタイル: snake_case
    ・例: `motor_controller.py`，`sensor_reader.py`

    ■ パッケージ（ディレクトリ名）
    ・スタイル: 全て小文字，アンダースコアなし（短い名前を推奨）
    ・例: `drivers`，`utils`，`config`

    ■ プライベート
    ・先頭にアンダースコア1つを付与する．
    ・例: `_internal_value`，`_calc_raw_data`

3-2. 命名の原則
    ・意味のある名前を付け，略語は最小限にする．
        - NG: `d`，`tmp`，`val`，`calc`（単体で使用）
        - OK: `distance`，`temperature`，`motor_value`
    ・ループカウンタ等，スコープが極めて狭い場合のみ `i`，`j`，`x`，`y` を許容する．
    ・bool 型の変数は `is_`，`has_`，`can_` 等の接頭辞を付ける．
        - 例: `is_connected`，`has_obstacle`，`can_move`


4. import の規則 (Import Rules)
------------------------------------------------------------------------

4-1. 順序
    以下の順序で記述し，グループ間に1行空ける．

    1. 標準ライブラリ（`os`，`sys`，`time` 等）
    2. サードパーティライブラリ（`RPi.GPIO`，`numpy` 等）
    3. プロジェクト内モジュール

    ・例:

        import os
        import sys
        import time

        import RPi.GPIO as GPIO

        from drivers.motor import MotorController
        from sensors.ultrasonic import UltrasonicSensor

4-2. スタイル
    ・1行に1モジュールを記述する．
        - NG: `import os, sys`
        - OK: `import os` と `import sys` を別行に記述
    ・`from ... import *` は禁止する（名前空間の汚染を防ぐ）．
    ・`from ... import` で複数の名前を取り込む場合は括弧でまとめる．

        from sensors.ultrasonic import (
            UltrasonicSensor,
            TRIGGER_PIN,
            ECHO_PIN,
        )


5. 型ヒント (Type Hints)
------------------------------------------------------------------------

5-1. 方針
    ・関数の引数と返り値には型ヒントを付与する．
    ・ローカル変数への型ヒントは，型が自明でない場合のみ付与する．

5-2. 書式
    ・Python 3.10 以降の記法（`X | None`，`list[int]`）を使用する．
    ・例:

        def calc_distance(speed: float, duration: float) -> float:
            return speed * duration

        def find_obstacle(sensors: list[UltrasonicSensor]) -> int | None:
            ...


6. コーディングルール (Coding Rules)
------------------------------------------------------------------------

6-1. 比較
    ・`None` との比較は `is` / `is not` を使用する．
        - NG: `if value == None:`
        - OK: `if value is None:`
    ・bool 値との比較は暗黙的に行う．
        - NG: `if is_active == True:`
        - OK: `if is_active:`

6-2. 文字列
    ・引用符はダブルクォート `"` で統一する．
    ・文字列の組み立てには f-string を使用する．
        - NG: `"Speed: " + str(speed)`
        - OK: `f"Speed: {speed}"`

6-3. 例外処理
    ・裸の `except:` は禁止する．必ず例外クラスを指定する．
        - NG: `except:`
        - OK: `except ValueError:`
    ・`except Exception` も極力避け，具体的な例外を捕捉する．

6-4. with 文
    ・ファイル操作や GPIO のクリーンアップなど，リソース管理には `with` 文を使用する．
    ・例:

        with open("config.json", "r") as f:
            config = json.load(f)

6-5. マジックナンバーの禁止
    ・意味のある数値は定数として定義する．
        - NG: `time.sleep(0.5)`
        - OK:
            SENSOR_INTERVAL_SEC = 0.5
            time.sleep(SENSOR_INTERVAL_SEC)


7. ファイル構成 (File Structure)
------------------------------------------------------------------------
1つの Python ファイル内は，以下の順序で記述する．

    1. ファイルドキュメント（docstring）
    2. import 文
    3. 定数定義
    4. クラス定義 / 関数定義
    5. `if __name__ == "__main__":` ブロック（必要な場合のみ）

・例:

    """
    motor_controller
    モーターの制御を担当するモジュール
    """

    import time

    import RPi.GPIO as GPIO

    from config.pins import PIN_MOTOR_LEFT, PIN_MOTOR_RIGHT

    MAX_SPEED = 100
    DEFAULT_SPEED = 50


    class MotorController:
        """左右のモーターを制御するクラス"""

        def __init__(self, left_pin: int, right_pin: int) -> None:
            ...

        def forward(self, speed: int = DEFAULT_SPEED) -> None:
            ...


    if __name__ == "__main__":
        controller = MotorController(PIN_MOTOR_LEFT, PIN_MOTOR_RIGHT)
        controller.forward()


8. ツール設定 (Tooling)
------------------------------------------------------------------------
コードの品質を自動で維持するため，以下のツールの導入を推奨する．

■ フォーマッター
・black: コードの自動整形に使用する．
    - 1行の最大文字数は 79 に設定する．

■ リンター
・flake8 または ruff: スタイル違反や潜在的なバグを検出する．

■ 型チェッカー
・mypy: 型ヒントの整合性を静的に検証する．

※ ツールの具体的な設定や導入手順は `ENV_` カテゴリのドキュメントに記載する．
