Coverage for flask/src/app.py: 100%
42 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-28 13:33 +0900
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-28 13:33 +0900
1#!/usr/bin/env python3
2"""
3電動シャッターの開閉を自動化するアプリのサーバーです
5Usage:
6 app.py [-c CONFIG] [-p PORT] [-d] [-D]
8Options:
9 -c CONFIG : CONFIG を設定ファイルとして読み込んで実行します。[default: config.yaml]
10 -p PORT : WEB サーバのポートを指定します。[default: 5000]
11 -d : ダミーモードで実行します。CI テストで利用することを想定しています。
12 -D : デバッグモードで動作します。
13"""
15import atexit
16import logging
17import os
19import flask_cors
21import flask
23SCHEMA_CONFIG = "config.schema"
26def create_app(config, dummy_mode=False):
27 # NOTE: オプションでダミーモードが指定された場合、環境変数もそれに揃えておく
28 if dummy_mode:
29 os.environ["DUMMY_MODE"] = "true"
30 else: # pragma: no cover
31 os.environ["DUMMY_MODE"] = "false"
33 # NOTE: テストのため、環境変数 DUMMY_MODE をセットしてからロードしたいのでこの位置
34 import my_lib.webapp.config
36 my_lib.webapp.config.URL_PREFIX = "/rasp-shutter"
37 my_lib.webapp.config.init(config)
39 import my_lib.webapp.base
40 import my_lib.webapp.event
41 import my_lib.webapp.log
42 import my_lib.webapp.util
43 import rasp_shutter.webapp_control
44 import rasp_shutter.webapp_schedule
45 import rasp_shutter.webapp_sensor
47 app = flask.Flask("rasp-shutter")
49 # NOTE: アクセスログは無効にする
50 logging.getLogger("werkzeug").setLevel(logging.ERROR)
52 if os.environ.get("WERKZEUG_RUN_MAIN") == "true":
53 if dummy_mode:
54 logging.warning("Set dummy mode")
55 else: # pragma: no cover
56 pass
58 rasp_shutter.webapp_control.init()
59 rasp_shutter.webapp_schedule.init(config)
60 my_lib.webapp.log.init(config)
62 def notify_terminate(): # pragma: no cover
63 my_lib.webapp.log.info("🏃 アプリを再起動します。")
64 my_lib.webapp.log.term()
66 atexit.register(notify_terminate)
67 else: # pragma: no cover
68 pass
70 flask_cors.CORS(app)
72 app.config["CONFIG"] = config
73 app.config["DUMMY_MODE"] = dummy_mode
75 app.json.compat = True
77 app.register_blueprint(rasp_shutter.webapp_control.blueprint)
78 app.register_blueprint(rasp_shutter.webapp_schedule.blueprint)
79 app.register_blueprint(rasp_shutter.webapp_sensor.blueprint)
81 app.register_blueprint(my_lib.webapp.base.blueprint_default)
82 app.register_blueprint(my_lib.webapp.base.blueprint)
83 app.register_blueprint(my_lib.webapp.event.blueprint)
84 app.register_blueprint(my_lib.webapp.log.blueprint)
85 app.register_blueprint(my_lib.webapp.util.blueprint)
87 my_lib.webapp.config.show_handler_list(app)
89 return app
92if __name__ == "__main__":
93 import pathlib
95 import docopt
96 import my_lib.config
97 import my_lib.logger
99 args = docopt.docopt(__doc__)
101 config_file = args["-c"]
102 port = args["-p"]
103 dummy_mode = args["-d"]
104 debug_mode = args["-D"]
106 my_lib.logger.init("hems.rasp-shutter", level=logging.DEBUG if debug_mode else logging.INFO)
108 config = my_lib.config.load(config_file, pathlib.Path(SCHEMA_CONFIG))
110 app = create_app(config, dummy_mode)
112 # NOTE: スクリプトの自動リロード停止したい場合は use_reloader=False にする
113 app.run(host="0.0.0.0", port=port, threaded=True, use_reloader=True) # noqa: S104