Coverage for flask/src/app.py: 87%
45 statements
« prev ^ index » next coverage.py v7.6.8, created at 2024-11-24 13:56 +0900
« prev ^ index » next coverage.py v7.6.8, created at 2024-11-24 13:56 +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
18import signal
20import flask_cors
22import flask
24SCHEMA_CONFIG = "config.schema"
27def sig_handler(num, frame): # noqa: ARG001
28 global should_terminate
30 logging.warning("receive signal %d", num)
32 if num == signal.SIGTERM:
33 import rasp_water.valve
35 rasp_water.valve.term()
38def create_app(config, dummy_mode=False):
39 # NOTE: オプションでダミーモードが指定された場合,環境変数もそれに揃えておく
40 if dummy_mode:
41 os.environ["DUMMY_MODE"] = "true"
42 else: # pragma: no cover
43 os.environ["DUMMY_MODE"] = "false"
45 # NOTE: テストのため,環境変数 DUMMY_MODE をセットしてからロードしたいのでこの位置
46 import my_lib.webapp.config
48 my_lib.webapp.config.URL_PREFIX = "/rasp-water"
49 my_lib.webapp.config.init(config)
51 import my_lib.webapp.base
52 import my_lib.webapp.event
53 import my_lib.webapp.log
54 import my_lib.webapp.util
55 import rasp_water.webapp_schedule
56 import rasp_water.webapp_valve
58 app = flask.Flask("rasp-water")
60 # NOTE: アクセスログは無効にする
61 logging.getLogger("werkzeug").setLevel(logging.ERROR)
63 if os.environ.get("WERKZEUG_RUN_MAIN") == "true":
64 if dummy_mode:
65 logging.warning("Set dummy mode")
66 else: # pragma: no cover
67 pass
69 rasp_water.webapp_schedule.init(config)
70 rasp_water.webapp_valve.init(config)
71 my_lib.webapp.log.init(config)
73 def notify_terminate(): # pragma: no cover
74 rasp_water.valve.set_state(rasp_water.valve.VALVE_STATE.CLOSE)
75 my_lib.webapp.log.info("🏃 アプリを再起動します.")
76 my_lib.webapp.log.term()
78 atexit.register(notify_terminate)
79 else: # pragma: no cover
80 pass
82 flask_cors.CORS(app)
84 app.config["CONFIG"] = config
85 app.config["DUMMY_MODE"] = dummy_mode
87 app.config["JSONIFY_PRETTYPRINT_REGULAR"] = True
89 app.register_blueprint(rasp_water.webapp_valve.blueprint)
90 app.register_blueprint(rasp_water.webapp_schedule.blueprint)
92 app.register_blueprint(my_lib.webapp.base.blueprint_default)
93 app.register_blueprint(my_lib.webapp.base.blueprint)
94 app.register_blueprint(my_lib.webapp.event.blueprint)
95 app.register_blueprint(my_lib.webapp.log.blueprint)
96 app.register_blueprint(my_lib.webapp.util.blueprint)
98 # app.debug = True
100 return app
103if __name__ == "__main__":
104 import pathlib
106 import docopt
107 import my_lib.config
108 import my_lib.logger
110 args = docopt.docopt(__doc__)
112 config_file = args["-c"]
113 port = args["-p"]
114 dummy_mode = args["-D"]
115 debug_mode = args["-d"]
117 my_lib.logger.init("hems.rasp-water", level=logging.DEBUG if debug_mode else logging.INFO)
119 config = my_lib.config.load(config_file, pathlib.Path(SCHEMA_CONFIG))
121 app = create_app(config, dummy_mode)
123 # NOTE: スクリプトの自動リロード停止したい場合は use_reloader=False にする
124 app.run(host="0.0.0.0", port=port, threaded=True, use_reloader=True) # noqa: S104
126 signal.signal(signal.SIGTERM, sig_handler)