hyperflask 0.5.1__tar.gz → 0.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hyperflask-0.5.1 → hyperflask-0.5.2}/PKG-INFO +1 -1
- {hyperflask-0.5.1 → hyperflask-0.5.2}/pyproject.toml +1 -1
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/app.py +13 -1
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/cli/__init__.py +2 -5
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/cli/runner.py +29 -24
- hyperflask-0.5.2/src/hyperflask/cli/scaffold.py +32 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/README.md +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/__init__.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/__main__.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/actors.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/cli/reloader.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/cli/worker.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/components/__init__.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/components/alpine.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/components/core.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/components/jsx.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/components/webcomponent.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/factory.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/forms/__init__.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/forms/fields.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/forms/widgets.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/layouts/email.mjml +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/layouts/web.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/model.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/page_helpers.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/security.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/static/alpine-csp.js +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/static/alpine.js +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/static/app.css +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/static/app.js +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/static/htmx-exts.js +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/static/react.js +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/static/stimulus.js +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/static/translations.js +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Accordion.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/AccordionPanel.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Alert.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Avatar.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/AvatarGroup.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Badge.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Breadcrumbs.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/BreadcrumbsItem.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Button.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Card.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/CardActions.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/CardTitle.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/ChatBubble.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Checkbox.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/CollapsibleSubMenu.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Countdown.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Divider.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Drawer.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/DrawerContent.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/DrawerSide.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Dropdown.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/DropdownItem.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Fieldset.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FieldsetLegend.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FileInput.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Filter.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FilterItem.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Footer.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FooterLink.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FooterNav.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Indicator.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Input.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/InputLabel.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Join.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Kbd.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Label.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/LabeledCheckbox.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/LabeledToggle.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Link.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/List.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/ListItem.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Loading.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Menu.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/MenuItem.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/MenuTitle.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Modal.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/ModalAction.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/ModalTitle.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Navbar.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Pagination.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/PaginationNext.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/PaginationPage.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/PaginationPrev.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Progress.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/README.md +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Radio.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Range.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Rating.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Select.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Stack.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Stat.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Stats.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Step.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Steps.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/SubMenu.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Swap.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Tab.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Table.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Tabs.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Textarea.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Toast.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Toggle.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Tooltip.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/flash.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/forms.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/icons.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/layout.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/modal.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/skeleton.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/ui/sse.html +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/utils/__init__.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/utils/freezer.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/utils/html.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/utils/htmx.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/utils/image.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/utils/markdown.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/utils/metadata.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/utils/page_actions.py +0 -0
- {hyperflask-0.5.1 → hyperflask-0.5.2}/src/hyperflask/utils/tokens.py +0 -0
|
@@ -57,7 +57,7 @@ class Hyperflask(Flask):
|
|
|
57
57
|
|
|
58
58
|
def __init__(self, *args, static_mode=StaticMode.DYNAMIC, instrument=False, layouts_folder="layouts",
|
|
59
59
|
emails_folder="emails", forms_folder="forms", assets_folder="assets", pages_folder="pages", migrations_folder="migrations",
|
|
60
|
-
config=None, config_filename="config.yml", database_uri=None, proxy_fix=True, **kwargs):
|
|
60
|
+
config=None, config_filename="config.yml", database_uri=None, proxy_fix=True, healthcheck_url="/healthcheck", **kwargs):
|
|
61
61
|
|
|
62
62
|
super().__init__(*args, **kwargs)
|
|
63
63
|
if proxy_fix:
|
|
@@ -99,6 +99,7 @@ class Hyperflask(Flask):
|
|
|
99
99
|
"HSTS_HEADER": False,
|
|
100
100
|
"IMAGES_DEFAULT_LOADING": "lazy",
|
|
101
101
|
"IMAGES_DEFAULT_DECODING": "async",
|
|
102
|
+
"HEALTHCHECK_URL": healthcheck_url,
|
|
102
103
|
})
|
|
103
104
|
if config:
|
|
104
105
|
self.config.update(config)
|
|
@@ -261,6 +262,17 @@ class Hyperflask(Flask):
|
|
|
261
262
|
except TemplateNotFound:
|
|
262
263
|
return self.make_response(("500 Internal Server Error", 500))
|
|
263
264
|
|
|
265
|
+
if self.config['HEALTHCHECK_URL']:
|
|
266
|
+
@self.route(self.config['HEALTHCHECK_URL'])
|
|
267
|
+
def healthcheck():
|
|
268
|
+
if not isinstance(self.db, UndefinedDatabase):
|
|
269
|
+
try:
|
|
270
|
+
with self.db as tx:
|
|
271
|
+
tx.execute("SELECT 1")
|
|
272
|
+
except Exception:
|
|
273
|
+
return {"status": "error"}, 500
|
|
274
|
+
return {"status": "ok"}
|
|
275
|
+
|
|
264
276
|
def relative_import_name(self, name):
|
|
265
277
|
return f"{self.import_name}.{name}" if self.import_name != "__main__" else name
|
|
266
278
|
|
|
@@ -7,6 +7,7 @@ from ..security import generate_csp_policy
|
|
|
7
7
|
from ..utils.freezer import StaticMode
|
|
8
8
|
from .runner import serve_command, run_command, dev_command
|
|
9
9
|
from .worker import worker_command, scheduler_command
|
|
10
|
+
from .scaffold import gen
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
def _create_app():
|
|
@@ -25,11 +26,7 @@ cli.add_command(run_command)
|
|
|
25
26
|
cli.add_command(dev_command)
|
|
26
27
|
cli.add_command(worker_command)
|
|
27
28
|
cli.add_command(scheduler_command)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@cli.command("init")
|
|
31
|
-
def init_command():
|
|
32
|
-
pass
|
|
29
|
+
cli.add_command(gen)
|
|
33
30
|
|
|
34
31
|
|
|
35
32
|
@cli.command("build")
|
|
@@ -6,34 +6,36 @@ import multiprocessing
|
|
|
6
6
|
import gunicorn.app.base
|
|
7
7
|
from subprocess import Popen
|
|
8
8
|
from honcho.manager import Manager as BaseProcessManager
|
|
9
|
+
from honcho.command import _parse_concurrency
|
|
10
|
+
from honcho.environ import parse_procfile
|
|
11
|
+
from honcho.printer import Printer
|
|
12
|
+
from honcho import environ
|
|
13
|
+
from flask_configurator.config import Config
|
|
9
14
|
from ..factory import load_config
|
|
10
15
|
from . import reloader # import hacky patch of werkzeug reloader
|
|
11
16
|
|
|
12
17
|
|
|
13
18
|
@click.command("serve")
|
|
14
|
-
@click.option('--gunicorn-
|
|
19
|
+
@click.option('--gunicorn-config')
|
|
15
20
|
@click.option("--init-db", is_flag=True)
|
|
16
21
|
@pass_script_info
|
|
17
22
|
@click.pass_context
|
|
18
|
-
def serve_command(ctx, info, host, port,
|
|
23
|
+
def serve_command(ctx, info, host, port, gunicorn_config, init_db, **run_kwargs):
|
|
19
24
|
if init_db:
|
|
20
25
|
print("Initializing database...")
|
|
21
26
|
Popen([sys.argv[0], "db", "init"]).wait()
|
|
22
27
|
|
|
23
28
|
if os.environ.get("FLASK_DEBUG") == "1":
|
|
24
29
|
ctx.invoke(flask_run_command, host=host, port=port, **run_kwargs)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
key, value = opt.split('=', 1)
|
|
35
|
-
options[key] = int(value) if value.isdigit() else value
|
|
36
|
-
GunicornServer(info.load_app, options).run()
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
GunicornServer(info.load_app, {
|
|
33
|
+
'proc_name': 'hyperflask',
|
|
34
|
+
'bind': f'{host}:{port}',
|
|
35
|
+
'workers': 1 + multiprocessing.cpu_count() * 2,
|
|
36
|
+
'max_requests': 1000,
|
|
37
|
+
'max_requests_jitter': 100
|
|
38
|
+
}, gunicorn_config).run()
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
serve_command.params = flask_run_command.params + serve_command.params
|
|
@@ -46,13 +48,9 @@ serve_command.params = flask_run_command.params + serve_command.params
|
|
|
46
48
|
@click.option('--concurrency')
|
|
47
49
|
@click.option("--extend-procfile", is_flag=True)
|
|
48
50
|
@click.option("--init-db/--no-init-db", is_flag=True, default=None)
|
|
51
|
+
@click.option('--gunicorn-config')
|
|
49
52
|
@click.option("--dev", is_flag=True)
|
|
50
|
-
def run_command(processes, host, port, concurrency, extend_procfile, init_db, dev):
|
|
51
|
-
from honcho.command import _parse_concurrency
|
|
52
|
-
from honcho.environ import parse_procfile
|
|
53
|
-
from honcho.printer import Printer
|
|
54
|
-
from honcho import environ
|
|
55
|
-
|
|
53
|
+
def run_command(processes, host, port, concurrency, extend_procfile, init_db, gunicorn_config, dev):
|
|
56
54
|
if dev:
|
|
57
55
|
os.environ["FLASK_DEBUG"] = "1"
|
|
58
56
|
|
|
@@ -79,6 +77,8 @@ def run_command(processes, host, port, concurrency, extend_procfile, init_db, de
|
|
|
79
77
|
"worker": [sys.argv[0], "worker"],
|
|
80
78
|
"scheduler": [sys.argv[0], "scheduler"]
|
|
81
79
|
}
|
|
80
|
+
if gunicorn_config:
|
|
81
|
+
_processes["web"].extend(["--gunicorn-config", gunicorn_config])
|
|
82
82
|
if dev:
|
|
83
83
|
_processes["assets"] = [sys.argv[0], "assets", "dev"]
|
|
84
84
|
_processes["worker"].extend(["-p", "1", "-t", "1"])
|
|
@@ -135,14 +135,19 @@ class ProcessManager(BaseProcessManager):
|
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
class GunicornServer(gunicorn.app.base.BaseApplication):
|
|
138
|
-
def __init__(self, app_loader,
|
|
138
|
+
def __init__(self, app_loader, config_defaults=None, config_filename=None):
|
|
139
139
|
self.app_loader = app_loader
|
|
140
|
-
self.
|
|
140
|
+
self.config_defaults = config_defaults or {}
|
|
141
|
+
self.config_filename = config_filename
|
|
141
142
|
super().__init__()
|
|
142
143
|
|
|
143
144
|
def load_config(self):
|
|
144
|
-
config =
|
|
145
|
-
|
|
145
|
+
config = Config("", self.config_defaults, env_prefix="GUNICORN")
|
|
146
|
+
config.load(self.config_filename, default_env="production")
|
|
147
|
+
|
|
148
|
+
config = {key.lower(): value for key, value in config.items()
|
|
149
|
+
if key.lower() in self.cfg.settings and value is not None}
|
|
150
|
+
|
|
146
151
|
for key, value in config.items():
|
|
147
152
|
self.cfg.set(key.lower(), value)
|
|
148
153
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from flask.cli import AppGroup, with_appcontext
|
|
2
|
+
import random
|
|
3
|
+
import click
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
gen = AppGroup('gen', help='Generate various files and code snippets.')
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@gen.command('secret-key')
|
|
11
|
+
@click.option('--save/--no-save', is_flag=True, default=True, help='Save the generated key to the .env file.')
|
|
12
|
+
def generate_secret_key_command(save):
|
|
13
|
+
key = generate_secret_key()
|
|
14
|
+
if save:
|
|
15
|
+
save_env_var("FLASK_SECRET_KEY", key)
|
|
16
|
+
click.echo(key)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def generate_secret_key():
|
|
20
|
+
return ''.join([random.SystemRandom().choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def save_env_var(key, value):
|
|
24
|
+
env = []
|
|
25
|
+
if os.path.exists(".env"):
|
|
26
|
+
with open(".env", "r") as f:
|
|
27
|
+
env = f.readlines()
|
|
28
|
+
with open(".env", "w") as f:
|
|
29
|
+
for line in env:
|
|
30
|
+
if not line.startswith(f"{key}="):
|
|
31
|
+
f.write(f"{line}\n")
|
|
32
|
+
f.write(f"{key}={value}\n")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|