Coverage for src / rasp_shutter / util.py: 84%
21 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-13 00:10 +0900
« prev ^ index » next coverage.py v7.13.1, created at 2026-02-13 00:10 +0900
1#!/usr/bin/env python3
2"""
3rasp-shutter アプリケーション用のユーティリティ関数
4"""
6import functools
7import os
8from collections.abc import Callable
9from typing import TypeVar
11F = TypeVar("F", bound=Callable)
14def is_dummy_mode() -> bool:
15 """DUMMY_MODEが有効かどうかを返す
17 テストやハードウェアなしでの動作確認時に使用される
18 環境変数 DUMMY_MODE が "true" の場合に True を返す
20 Returns
21 -------
22 bool: DUMMY_MODEが有効な場合 True
24 """
25 return os.environ.get("DUMMY_MODE", "false") == "true"
28def check_dummy_mode_for_api() -> tuple[dict[str, str], int] | None:
29 """テストAPIのDUMMY_MODEチェック
31 DUMMY_MODEが有効でない場合にエラーレスポンスを返す
32 テスト用APIで共通して使用するガード関数
34 Returns
35 -------
36 tuple[dict[str, str], int] | None:
37 DUMMY_MODEが無効の場合はエラーレスポンス (dict, 403)
38 DUMMY_MODEが有効の場合は None
40 Examples
41 --------
42 >>> error = check_dummy_mode_for_api()
43 >>> if error:
44 >>> return error
46 """
47 if not is_dummy_mode(): 47 ↛ 48line 47 didn't jump to line 48 because the condition on line 47 was never true
48 return {"error": "Test API is only available in DUMMY_MODE"}, 403
49 return None
52def is_pytest_running() -> bool:
53 """pytest実行中かどうかを返す
55 テスト環境でのみ特定の処理を行う場合に使用する。
56 環境変数 PYTEST_CURRENT_TEST が設定されている場合に True を返す。
58 Returns
59 -------
60 bool: pytest実行中の場合 True
62 """
63 return bool(os.environ.get("PYTEST_CURRENT_TEST"))
66def require_dummy_mode(f: F) -> F:
67 """DUMMY_MODE必須デコレータ
69 テスト用APIでDUMMY_MODEが有効でない場合に403エラーを返す。
70 各関数でのインラインチェックを不要にする。
72 Examples
73 --------
74 >>> @blueprint.route("/api/test/example", methods=["POST"])
75 >>> @require_dummy_mode
76 >>> def test_example():
77 >>> return {"success": True}
79 """
81 @functools.wraps(f)
82 def decorated_function(*args, **kwargs):
83 error = check_dummy_mode_for_api()
84 if error: 84 ↛ 85line 84 didn't jump to line 85 because the condition on line 84 was never true
85 return error
86 return f(*args, **kwargs)
88 # functools.wraps で型情報が保持されないため
89 return decorated_function # type: ignore[return-value]