Coverage for app.py : 81%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import importlib
2import os
3import sys
5import click
6import jinja2
7from flask import Flask
8from flask import send_from_directory
9from flask_admin import Admin
10from flask_admin.menu import MenuLink
11from flask_login import current_user
13from shopyo.api.file import trycopy
16base_path = os.path.dirname(os.path.abspath(__file__))
17sys.path.insert(0, base_path)
18from config import app_config
19from init import csrf
20from init import db
21from init import login_manager
22from init import ma
23from init import mail
24from init import migrate
25from init import modules_path
28from shopyo_admin import DefaultModelView
29from shopyo_admin import MyAdminIndexView
32def create_app(config_name="development"):
34 global_template_variables = {}
35 global_configs = {}
36 app = Flask(
37 __name__,
38 instance_path=os.path.join(base_path, "instance"),
39 instance_relative_config=True,
40 )
41 load_config_from_obj(app, config_name)
42 load_config_from_instance(app, config_name)
43 create_config_json()
44 load_extensions(app)
45 setup_flask_admin(app)
46 register_devstatic(app)
47 load_blueprints(app, config_name, global_template_variables, global_configs)
48 setup_theme_paths(app)
49 inject_global_vars(app, global_template_variables)
50 return app
53def load_config_from_obj(app, config_name):
55 try:
56 configuration = app_config[config_name]
57 except KeyError as e:
58 print(
59 f"[ ] Invalid config name {e}. Available configurations are: "
60 f"{list(app_config.keys())}\n"
61 )
62 sys.exit(1)
64 app.config.from_object(configuration)
67def load_config_from_instance(app, config_name):
69 if config_name != "testing": 69 ↛ 71line 69 didn't jump to line 71, because the condition on line 69 was never true
70 # load the instance config, if it exists, when not testing
71 app.config.from_pyfile("config.py", silent=True)
73 # create empty instance folder and empty config if not present
74 try:
75 os.makedirs(app.instance_path)
76 with open(os.path.join(app.instance_path, "config.py"), "a"):
77 pass
78 except OSError:
79 pass
82def create_config_json():
83 if not os.path.exists("config.json"): 83 ↛ 84line 83 didn't jump to line 84, because the condition on line 83 was never true
84 trycopy("config_demo.json", "config.json")
87def load_extensions(app):
88 migrate.init_app(app, db)
89 db.init_app(app)
90 ma.init_app(app)
91 mail.init_app(app)
92 login_manager.init_app(app)
93 csrf.init_app(app)
96def setup_flask_admin(app):
97 admin = Admin(
98 app,
99 name="My App",
100 template_mode="bootstrap4",
101 index_view=MyAdminIndexView(),
102 )
103 # admin.add_view(DefaultModelView(Settings, db.session))
104 admin.add_link(MenuLink(name="Logout", category="", url="/auth/logout?next=/admin"))
107def register_devstatic(app):
108 @app.route("/devstatic/<path:boxormodule>/f/<path:filename>")
109 def devstatic(boxormodule, filename):
110 if app.config["DEBUG"]:
111 module_static = os.path.join(modules_path, boxormodule, "static")
112 return send_from_directory(module_static, filename=filename)
115def load_blueprints(app, config_name, global_template_variables, global_configs):
116 """
117 - Registers blueprints
118 - Adds global template objects from modules
119 - Adds global configs from modules
120 """
122 for folder in os.listdir(os.path.join(base_path, "modules")):
123 if folder.startswith("__"): # ignore __pycache__
124 continue
126 if folder.startswith("box__"):
127 # boxes
128 for sub_folder in os.listdir(os.path.join(base_path, "modules", folder)):
129 if sub_folder.startswith("__"): # ignore __pycache__ 129 ↛ 130line 129 didn't jump to line 130, because the condition on line 129 was never true
130 continue
131 elif sub_folder.endswith(".json"): # box_info.json
132 continue
133 try:
134 sys_mod = importlib.import_module(
135 f"modules.{folder}.{sub_folder}.view"
136 )
137 app.register_blueprint(getattr(sys_mod, f"{sub_folder}_blueprint"))
138 except AttributeError:
139 pass
140 try:
141 mod_global = importlib.import_module(
142 f"modules.{folder}.{sub_folder}.global"
143 )
144 global_template_variables.update(mod_global.available_everywhere)
145 except ImportError: 145 ↛ 148line 145 didn't jump to line 148
146 pass
148 except AttributeError:
149 pass
151 # load configs
152 try:
153 mod_global = importlib.import_module(
154 f"modules.{folder}.{sub_folder}.global"
155 )
156 if config_name in mod_global.configs: 156 ↛ 128, 156 ↛ 1572 missed branches: 1) line 156 didn't jump to line 128, because the condition on line 156 was never false, 2) line 156 didn't jump to line 157, because the condition on line 156 was never true
157 global_configs.update(mod_global.configs.get(config_name))
158 except ImportError:
159 pass
161 except AttributeError:
162 # click.echo('info: config not found in global')
163 pass
164 else:
165 # apps
166 try:
167 mod = importlib.import_module(f"modules.{folder}.view")
168 app.register_blueprint(getattr(mod, f"{folder}_blueprint"))
169 except AttributeError:
170 # print("[ ] Blueprint skipped:", e)
171 pass
173 # global's available everywhere template vars
174 try:
175 mod_global = importlib.import_module(f"modules.{folder}.global")
176 global_template_variables.update(mod_global.available_everywhere)
177 except ImportError:
178 # print(f"[ ] {e}")
179 pass
181 except AttributeError:
182 pass
184 # load configs
185 try:
186 mod_global = importlib.import_module(f"modules.{folder}.global")
187 if config_name in mod_global.configs: 187 ↛ 122line 187 didn't jump to line 122, because the condition on line 187 was never false
188 global_configs.update(mod_global.configs.get(config_name))
189 except ImportError: 189 ↛ 192line 189 didn't jump to line 192
190 # print(f"[ ] {e}")
191 pass
192 except AttributeError:
193 # click.echo('info: config not found in global')
194 pass
196 app.config.update(**global_configs)
199def setup_theme_paths(app):
200 with app.app_context():
201 front_theme_dir = os.path.join(
202 app.config["BASE_DIR"], "static", "themes", "front"
203 )
204 back_theme_dir = os.path.join(
205 app.config["BASE_DIR"], "static", "themes", "back"
206 )
207 my_loader = jinja2.ChoiceLoader(
208 [
209 app.jinja_loader,
210 jinja2.FileSystemLoader([front_theme_dir, back_theme_dir]),
211 ]
212 )
213 app.jinja_loader = my_loader
216def inject_global_vars(app, global_template_variables):
217 @app.context_processor
218 def inject_global_vars():
219 APP_NAME = "dwdwefw"
221 base_context = {
222 "APP_NAME": APP_NAME,
223 "len": len,
224 "current_user": current_user,
225 }
226 base_context.update(global_template_variables)
228 return base_context