Hide keyboard shortcuts

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 

4 

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 

12 

13from shopyo.api.file import trycopy 

14 

15 

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 

26 

27 

28from shopyo_admin import DefaultModelView 

29from shopyo_admin import MyAdminIndexView 

30 

31 

32def create_app(config_name="development"): 

33 

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 

51 

52 

53def load_config_from_obj(app, config_name): 

54 

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) 

63 

64 app.config.from_object(configuration) 

65 

66 

67def load_config_from_instance(app, config_name): 

68 

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) 

72 

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 

80 

81 

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") 

85 

86 

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) 

94 

95 

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")) 

105 

106 

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) 

113 

114 

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 """ 

121 

122 for folder in os.listdir(os.path.join(base_path, "modules")): 

123 if folder.startswith("__"): # ignore __pycache__ 

124 continue 

125 

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 

147 

148 except AttributeError: 

149 pass 

150 

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 

160 

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 

172 

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 

180 

181 except AttributeError: 

182 pass 

183 

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 

195 

196 app.config.update(**global_configs) 

197 

198 

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 

214 

215 

216def inject_global_vars(app, global_template_variables): 

217 @app.context_processor 

218 def inject_global_vars(): 

219 APP_NAME = "dwdwefw" 

220 

221 base_context = { 

222 "APP_NAME": APP_NAME, 

223 "len": len, 

224 "current_user": current_user, 

225 } 

226 base_context.update(global_template_variables) 

227 

228 return base_context