def postgres_handler(sketch: Sketch): if sketch.database == "postgres": sketch.add_requirements("psycopg2") handle_sql_db(sketch) sketch.settings["production"][ "SQLALCHEMY_DATABASE_URI"] = "postgres://<user>:<password>@<server_ip>/MY_DATABASE" return True
def create_project(args: Namespace, answers: dict): pf = pjoin(str(pathlib.Path().absolute()), args.project_name) apf = pjoin( str(pathlib.Path().absolute()), args.project_name, args.project_name.replace("-", "_"), ) sketch = Sketch(pf, apf, answers, args) make_commom(sketch) sketch.settings["default"]["DEBUG"] = False sketch.settings["development"]["DEBUG"] = True app_type_handler(sketch) database_handler(sketch) auth_handler(sketch) if "api" in sketch.app_type: api_framework_handler(sketch) handle_features(sketch) config_handler(sketch) if args.e: sketch.blueprints.extend(["examples"]) make_app(sketch) make_requirements(sketch) cleanup(sketch) if args.v: os.system(f"python -m venv {pf}/.venv")
def mysql_handler(sketch: Sketch): if sketch.database == "mysql": sketch.add_requirements("mysqlclient") handle_sql_db(sketch) sketch.settings["production"][ "SQLALCHEMY_DATABASE_URI"] = "mysql+mysqldb://<user>:<password>@<server_ip>/MY_DATABASE" return True
def none_handler(sketch: Sketch): if sketch.config_framework == "none": secrets_cfg = sort_settings(sketch.secrets)["default"] settings_cfg = {"default": {}} settings_cfg["default"].update(sketch.settings["default"]) settings_cfg["default"].update(sketch.settings["production"]) del settings_cfg["default"]["EXTENSIONS"] settings_cfg = sort_settings(settings_cfg) dev_settings_cfg = {"default": {}} dev_settings_cfg["default"].update(sketch.settings["default"]) dev_settings_cfg["default"].update(sketch.settings["development"]) del dev_settings_cfg["default"]["EXTENSIONS"] dev_settings_cfg = sort_settings(dev_settings_cfg) secrets_cfg_output = [] for k, val in secrets_cfg.items(): secrets_cfg_output.append(f'{k} = {repr(val)}\n') settings_cfg_output = [] for k, val in settings_cfg["default"].items(): settings_cfg_output.append(f'{k} = {repr(val)}\n') dev_settings_cfg_output = [] for k, val in dev_settings_cfg["default"].items(): dev_settings_cfg_output.append(f'{k} = {repr(val)}\n') with open(pjoin(sketch.project_folder, ".secrets.cfg"), "w",) as f: f.writelines(secrets_cfg_output) with open(pjoin(sketch.project_folder, "settings.cfg"), "w",) as f: f.writelines(settings_cfg_output) with open(pjoin(sketch.project_folder, "settings-dev.cfg"), "w",) as f: f.writelines(dev_settings_cfg_output) sketch.write_template( "config_none_tpl", templates.config, pjoin(sketch.app_folder, "config", "__init__.py",), ) sketch.write_template( "app_none_conf_framework_tpl", templates.app, pjoin(sketch.app_folder, "app.py"), ) return True
def none_handler(sketch: Sketch): if sketch.auth_framework == "none": if not sketch.database == "none": sketch.write_template( "no_auth_tpl", templates.commands, pjoin( sketch.app_folder, "commands", "__init__.py", ), ) return True
def __call__(self, sketch: Sketch): for handler in self.handlers: r = handler(sketch) if r: if not handler.__name__ == "none_handler": sketch.write_template( "models_auth_tpl", templates.models, pjoin( sketch.app_folder, "models", "__init__.py", ), ) return r
def web_only_handler(sketch: Sketch): if sketch.app_type == "web_only": os.makedirs(pjoin(sketch.app_folder, "site")) sketch.blueprints.extend(["site"]) sketch.write_template( "site_web_only_init_tpl", templates.site, pjoin(sketch.app_folder, "site", "__init__.py"), ) sketch.write_template( "site_web_only_views_tpl", templates.site, pjoin(sketch.app_folder, "site", "views.py"), ) return True
def handle_sql_db(sketch: Sketch): sketch.add_requirements("flask-sqlalchemy") sketch.settings["default"]["SQLALCHEMY_TRACK_MODIFICATIONS"] = False sketch.settings["development"]["SQLALCHEMY_TRACK_MODIFICATIONS"] = True sketch.settings["default"][ "SQLALCHEMY_DATABASE_URI"] = "sqlite:///db.sqlite3" sketch.add_extensions("database") sketch.write_template( "ext_sqlalchemy_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "database.py"), )
def handle_admin(sketch: Sketch): sketch.add_requirements("flask-admin") sketch.add_extensions("admin") sketch.settings["default"]["ADMIN_TEMPLATE_MODE"] = "bootstrap3" sketch.settings["development"][ "ADMIN_NAME"] = f"{sketch.project_name} (Dev)" sketch.settings["testing"][ "ADMIN_NAME"] = f"{sketch.project_name} (Testing)" sketch.settings["production"]["ADMIN_NAME"] = sketch.project_name # TODO refact this part to not use a lot of if statements if sketch.auth_framework == "security_web": sketch.write_template( "ext_admin_security_tpl", templates.ext.admin, pjoin( sketch.app_folder, "ext", "admin", "__init__.py", ), )
def handle_migrate(sketch: Sketch): sketch.add_requirements("flask-migrate") sketch.add_extensions("migrate") sketch.write_template( "ext_migrate_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "migrate.py"), )
def handle_debugtoolbar(sketch: Sketch): sketch.add_requirements("flask-debugtoolbar", dev=True) sketch.add_extensions("debugtoolbar") sketch.settings["development"]["DEBUG_TB_INTERCEPT_REDIRECTS"] = False if sketch.config_framework != "dynaconf": sketch.write_template( "ext_debugtoolbar_tpl", templates.ext, pjoin( sketch.app_folder, "ext", "debugtoolbar.py", ), )
def dynaconf_handler(sketch: Sketch): if sketch.config_framework == "dynaconf": sketch.add_requirements("dynaconf") settings_toml = sort_settings(sketch.settings) secrets_toml = sort_settings(sketch.secrets) try: sketch.extensions.remove("debugtoolbar") settings_toml["development"]["EXTENSIONS"] = [ "flask_debugtoolbar:DebugToolbarExtension", "dynaconf_merge_unique", ] except ValueError: settings_toml["development"]["EXTENSIONS"] = [ "dynaconf_merge_unique" ] settings_toml["default"]["EXTENSIONS"] = [ "{}.ext.{}:init_app".format(sketch.app_folder_name, ext) for ext in sketch.extensions ] with open(pjoin(sketch.project_folder, "settings.toml"), "w") as f: toml.dump(settings_toml, f, encoder=FlaskSketchTomlEncoder()) with open(pjoin(sketch.project_folder, ".secrets.toml"), "w") as f: toml.dump(secrets_toml, f, encoder=FlaskSketchTomlEncoder()) sketch.write_template( "config_dynaconf_tpl", templates.config, pjoin(sketch.app_folder, "config", "__init__.py",), ) sketch.write_template( "app_dynaconf_conf_tpl", templates.app, pjoin(sketch.app_folder, "app.py"), ) return True
def mongodb_handler(sketch: Sketch): if sketch.database == "mongodb": sketch.add_requirements("flask-mongoengine") return True
def login_jwt_extended_handler(sketch: Sketch): if sketch.auth_framework == "login_jwt_extended": sketch.add_requirements("flask-login", "flask-jwt-extended") return True
def security_jwt_extended_handler(sketch: Sketch): if sketch.auth_framework == "security_jwt_extended": sketch.add_requirements("flask-security-too", "flask-jwt-extended") return True
def basicauth_api_handler(sketch: Sketch): if sketch.auth_framework == "basicauth_api": sketch.add_requirements("flask-basicauth") return True
def basicauth_web_handler(sketch: Sketch): if sketch.auth_framework == "basicauth_web": sketch.add_requirements("flask-basicAuth") sketch.secrets["default"]["BASIC_AUTH_PASSWORD"] = "******" sketch.secrets["default"]["BASIC_AUTH_PASSWORD"] = random_string() return True
def security_web_handler(sketch: Sketch): if sketch.auth_framework == "security_web": sketch.add_requirements("flask-security-too", "argon2-cffi") sketch.settings["default"]["SECURITY_REGISTERABLE"] = True sketch.settings["default"]["SECURITY_POST_LOGIN_VIEW"] = "/" sketch.settings["default"]["SECURITY_PASSWORD_HASH"] = "argon2" sketch.add_extensions("auth") sketch.secrets["default"]["SECURITY_PASSWORD_SALT"] = random_string() sketch.write_template( "security_web_only_tpl", templates.commands, pjoin( sketch.app_folder, "commands", "__init__.py", ), ) sketch.write_template( "ext_security_web_only_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "auth.py"), ) sketch.write_template( "models_security_web_only_tpl", templates.models, pjoin(sketch.app_folder, "models", "user.py"), ) sketch.write_template( "examples_security_auth_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "auth_examples.py", ), ) sketch.write_template( "examples_init_security_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "__init__.py", ), ) return True
def handle_caching(sketch: Sketch): sketch.add_requirements("flask-caching") sketch.settings["development"]["CACHE_TYPE"] = "simple" sketch.settings["testing"]["CACHE_TYPE"] = "simple" sketch.settings["production"]["CACHE_TYPE"] = "simple" sketch.add_extensions("caching") sketch.write_template( "ext_caching_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "caching.py"), ) sketch.write_template( "examples_caching_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "caching_examples.py", ), ) sketch.write_template( "examples_init_caching_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "__init__.py", ), )
def sqlite_handler(sketch: Sketch): if sketch.database == "sqlite": handle_sql_db(sketch) sketch.settings["production"][ "SQLALCHEMY_DATABASE_URI"] = "sqlite:///production_db.sqlite3" return True
def handle_limiter(sketch: Sketch): sketch.add_requirements("flask-limiter") sketch.settings["default"]["RATELIMIT_DEFAULT"] = "200 per day;50 per hour" sketch.settings["default"]["RATELIMIT_ENABLED"] = True sketch.settings["development"]["RATELIMIT_ENABLED"] = False sketch.add_extensions("limiter") sketch.write_template( "ext_limiter_tpl", templates.ext, pjoin(sketch.app_folder, "ext", "limiter.py"), ) sketch.write_template( "examples_limiter_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "limiter_examples.py", ), ) sketch.write_template( "examples_init_limiter_tpl", templates.examples, pjoin( sketch.app_folder, "examples", "__init__.py", ), )