hyperflask 0.5.0__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.0 → hyperflask-0.5.2}/PKG-INFO +1 -1
- {hyperflask-0.5.0 → hyperflask-0.5.2}/pyproject.toml +1 -1
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/app.py +13 -1
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/cli/__init__.py +2 -5
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/cli/runner.py +45 -35
- hyperflask-0.5.2/src/hyperflask/cli/scaffold.py +32 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/components/core.py +2 -2
- {hyperflask-0.5.0 → hyperflask-0.5.2}/README.md +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/__init__.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/__main__.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/actors.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/cli/reloader.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/cli/worker.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/components/__init__.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/components/alpine.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/components/jsx.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/components/webcomponent.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/factory.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/forms/__init__.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/forms/fields.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/forms/widgets.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/layouts/email.mjml +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/layouts/web.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/model.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/page_helpers.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/security.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/static/alpine-csp.js +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/static/alpine.js +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/static/app.css +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/static/app.js +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/static/htmx-exts.js +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/static/react.js +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/static/stimulus.js +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/static/translations.js +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Accordion.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/AccordionPanel.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Alert.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Avatar.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/AvatarGroup.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Badge.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Breadcrumbs.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/BreadcrumbsItem.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Button.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Card.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/CardActions.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/CardTitle.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/ChatBubble.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Checkbox.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/CollapsibleSubMenu.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Countdown.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Divider.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Drawer.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/DrawerContent.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/DrawerSide.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Dropdown.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/DropdownItem.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Fieldset.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FieldsetLegend.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FileInput.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Filter.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FilterItem.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Footer.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FooterLink.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/FooterNav.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Indicator.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Input.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/InputLabel.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Join.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Kbd.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Label.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/LabeledCheckbox.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/LabeledToggle.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Link.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/List.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/ListItem.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Loading.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Menu.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/MenuItem.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/MenuTitle.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Modal.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/ModalAction.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/ModalTitle.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Navbar.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Pagination.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/PaginationNext.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/PaginationPage.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/PaginationPrev.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Progress.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/README.md +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Radio.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Range.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Rating.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Select.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Stack.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Stat.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Stats.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Step.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Steps.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/SubMenu.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Swap.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Tab.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Table.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Tabs.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Textarea.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Toast.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Toggle.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/daisyui/Tooltip.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/flash.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/forms.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/icons.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/layout.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/modal.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/skeleton.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/ui/sse.html +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/utils/__init__.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/utils/freezer.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/utils/html.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/utils/htmx.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/utils/image.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/utils/markdown.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/utils/metadata.py +0 -0
- {hyperflask-0.5.0 → hyperflask-0.5.2}/src/hyperflask/utils/page_actions.py +0 -0
- {hyperflask-0.5.0 → 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,29 +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')
|
|
20
|
+
@click.option("--init-db", is_flag=True)
|
|
15
21
|
@pass_script_info
|
|
16
22
|
@click.pass_context
|
|
17
|
-
def serve_command(ctx, info, host, port,
|
|
23
|
+
def serve_command(ctx, info, host, port, gunicorn_config, init_db, **run_kwargs):
|
|
24
|
+
if init_db:
|
|
25
|
+
print("Initializing database...")
|
|
26
|
+
Popen([sys.argv[0], "db", "init"]).wait()
|
|
27
|
+
|
|
18
28
|
if os.environ.get("FLASK_DEBUG") == "1":
|
|
19
29
|
ctx.invoke(flask_run_command, host=host, port=port, **run_kwargs)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
key, value = opt.split('=', 1)
|
|
30
|
-
options[key] = int(value) if value.isdigit() else value
|
|
31
|
-
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()
|
|
32
39
|
|
|
33
40
|
|
|
34
41
|
serve_command.params = flask_run_command.params + serve_command.params
|
|
@@ -41,13 +48,9 @@ serve_command.params = flask_run_command.params + serve_command.params
|
|
|
41
48
|
@click.option('--concurrency')
|
|
42
49
|
@click.option("--extend-procfile", is_flag=True)
|
|
43
50
|
@click.option("--init-db/--no-init-db", is_flag=True, default=None)
|
|
51
|
+
@click.option('--gunicorn-config')
|
|
44
52
|
@click.option("--dev", is_flag=True)
|
|
45
|
-
def run_command(processes, host, port, concurrency, extend_procfile, init_db, dev):
|
|
46
|
-
from honcho.command import _parse_concurrency
|
|
47
|
-
from honcho.environ import parse_procfile
|
|
48
|
-
from honcho.printer import Printer
|
|
49
|
-
from honcho import environ
|
|
50
|
-
|
|
53
|
+
def run_command(processes, host, port, concurrency, extend_procfile, init_db, gunicorn_config, dev):
|
|
51
54
|
if dev:
|
|
52
55
|
os.environ["FLASK_DEBUG"] = "1"
|
|
53
56
|
|
|
@@ -59,6 +62,10 @@ def run_command(processes, host, port, concurrency, extend_procfile, init_db, de
|
|
|
59
62
|
procfile = None
|
|
60
63
|
config = load_config()
|
|
61
64
|
|
|
65
|
+
if not dev and not config.get('SECRET_KEY'):
|
|
66
|
+
print("Critical: No SECRET_KEY set, cannot run in production mode.")
|
|
67
|
+
sys.exit(1)
|
|
68
|
+
|
|
62
69
|
for filename in [f"Procfile.{config['ENV']}", "Procfile"]:
|
|
63
70
|
if os.path.exists(filename):
|
|
64
71
|
with open(filename) as f:
|
|
@@ -70,21 +77,13 @@ def run_command(processes, host, port, concurrency, extend_procfile, init_db, de
|
|
|
70
77
|
"worker": [sys.argv[0], "worker"],
|
|
71
78
|
"scheduler": [sys.argv[0], "scheduler"]
|
|
72
79
|
}
|
|
80
|
+
if gunicorn_config:
|
|
81
|
+
_processes["web"].extend(["--gunicorn-config", gunicorn_config])
|
|
73
82
|
if dev:
|
|
74
83
|
_processes["assets"] = [sys.argv[0], "assets", "dev"]
|
|
75
84
|
_processes["worker"].extend(["-p", "1", "-t", "1"])
|
|
76
85
|
else:
|
|
77
86
|
_processes["mercurehub"] = [sys.executable, "-m", "flask_mercure_sse.server", "--port", "$PORT"]
|
|
78
|
-
subscriber_secret_key = config.get("MERCURE_SUBSCRIBER_SECRET_KEY", config.get('SECRET_KEY'))
|
|
79
|
-
if subscriber_secret_key:
|
|
80
|
-
_processes["mercurehub"].extend(["--subscriber-secret", subscriber_secret_key])
|
|
81
|
-
else:
|
|
82
|
-
print("Warning: No MERCURE_SUBSCRIBER_SECRET_KEY or SECRET_KEY set, Mercure subscriber will not be authenticated.")
|
|
83
|
-
publisher_secret_key = config.get("MERCURE_PUBLISHER_SECRET_KEY", config.get('SECRET_KEY'))
|
|
84
|
-
if publisher_secret_key:
|
|
85
|
-
_processes["mercurehub"].extend(["--publisher-secret", publisher_secret_key])
|
|
86
|
-
else:
|
|
87
|
-
print("Warning: No MERCURE_PUBLISHER_SECRET_KEY or SECRET_KEY set, cannot publish Mercure messages.")
|
|
88
87
|
|
|
89
88
|
if procfile and extend_procfile:
|
|
90
89
|
_processes.update(procfile)
|
|
@@ -93,13 +92,19 @@ def run_command(processes, host, port, concurrency, extend_procfile, init_db, de
|
|
|
93
92
|
|
|
94
93
|
processes = {name: " ".join(_processes[name]) if isinstance(_processes[name], list) else _processes[name]
|
|
95
94
|
for name in _processes if not processes or name in processes}
|
|
95
|
+
env = {}
|
|
96
|
+
if not dev:
|
|
97
|
+
env = {
|
|
98
|
+
"MERCURE_SUBSCRIBER_SECRET_KEY": config.get("MERCURE_SUBSCRIBER_SECRET_KEY", config['SECRET_KEY']),
|
|
99
|
+
"MERCURE_PUBLISHER_SECRET_KEY": config.get("MERCURE_PUBLISHER_SECRET_KEY", config['SECRET_KEY']),
|
|
100
|
+
}
|
|
96
101
|
|
|
97
102
|
manager = ProcessManager(Printer(sys.stdout, colour=True))
|
|
98
|
-
|
|
99
103
|
for p in environ.expand_processes(processes,
|
|
100
104
|
concurrency=_parse_concurrency(concurrency),
|
|
101
105
|
port=port):
|
|
102
106
|
e = os.environ.copy()
|
|
107
|
+
e.update(env)
|
|
103
108
|
e.update(p.env)
|
|
104
109
|
manager.add_process(p.name, p.cmd, quiet=p.quiet, env=e)
|
|
105
110
|
|
|
@@ -130,14 +135,19 @@ class ProcessManager(BaseProcessManager):
|
|
|
130
135
|
|
|
131
136
|
|
|
132
137
|
class GunicornServer(gunicorn.app.base.BaseApplication):
|
|
133
|
-
def __init__(self, app_loader,
|
|
138
|
+
def __init__(self, app_loader, config_defaults=None, config_filename=None):
|
|
134
139
|
self.app_loader = app_loader
|
|
135
|
-
self.
|
|
140
|
+
self.config_defaults = config_defaults or {}
|
|
141
|
+
self.config_filename = config_filename
|
|
136
142
|
super().__init__()
|
|
137
143
|
|
|
138
144
|
def load_config(self):
|
|
139
|
-
config =
|
|
140
|
-
|
|
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
|
+
|
|
141
151
|
for key, value in config.items():
|
|
142
152
|
self.cfg.set(key.lower(), value)
|
|
143
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")
|
|
@@ -7,7 +7,6 @@ from jinjapy import extract_frontmatter
|
|
|
7
7
|
from ..utils.freezer import dynamic
|
|
8
8
|
import importlib
|
|
9
9
|
import re
|
|
10
|
-
import os
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class BaseComponentAdapter:
|
|
@@ -71,8 +70,9 @@ class ComponentAdapter(BaseComponentAdapter):
|
|
|
71
70
|
source, frontmatter = extract_frontmatter(f.read())
|
|
72
71
|
if not self.template:
|
|
73
72
|
frontmatter = source
|
|
73
|
+
if not frontmatter:
|
|
74
|
+
return []
|
|
74
75
|
return [m.upper() for m in http_method_funcs if re.search(rf"^(def\s+{m}\()|{m}\s*=", frontmatter, re.MULTILINE)]
|
|
75
|
-
return []
|
|
76
76
|
|
|
77
77
|
def render(self, *args, **kwargs):
|
|
78
78
|
caller = kwargs.pop('caller', None)
|
|
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
|