fenrir-framework 2.3.2__tar.gz → 2.3.3__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.
Potentially problematic release.
This version of fenrir-framework might be problematic. Click here for more details.
- {fenrir_framework-2.3.2/fenrir_framework.egg-info → fenrir_framework-2.3.3}/PKG-INFO +1 -1
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/__init__.py +1 -1
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/app.py +34 -8
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/cli.py +15 -28
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3/fenrir_framework.egg-info}/PKG-INFO +1 -1
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/pyproject.toml +1 -1
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_cli.py +3 -7
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/LICENSE +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/README.md +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/background.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/bottle.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/compat.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/config.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/context.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/dependencies.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/exceptions.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/falcon.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/helpers.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/http2.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/json.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/logo.jpg +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/logo.png +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/middleware.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/openapi.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/pagination.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/pool.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/request.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/response.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/routing.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/sanic.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/security.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/sessions.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/signals.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/sse.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/templating.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/testing.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/upload.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/views.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/websocket.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/SOURCES.txt +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/dependency_links.txt +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/entry_points.txt +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/requires.txt +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/top_level.txt +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/setup.cfg +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_appctx.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_async.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_basic.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_blueprints.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_circular_deps.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_config.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_context.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_converters.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_custom_template.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_dep_overrides.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_dependencies.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_falcon_compat.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_form_file.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_helpers.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_instance_config.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_json.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_json_tag.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_logging.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_logo_route.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_middleware.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_new_features.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_new_middleware_features.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_regression.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_reqctx.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_request.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_resources.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_router_circular.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_routing.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_sanic_compat.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_security.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_session_interface.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_signals.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_sse.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_strict_content_type.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_subclassing.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_templating.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_testing.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_user_error_handler.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_v3_features.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_validation.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_views.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_websocket.py +0 -0
- {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_yield_deps.py +0 -0
|
@@ -90,7 +90,7 @@ class Fenrir:
|
|
|
90
90
|
self,
|
|
91
91
|
import_name: str = None,
|
|
92
92
|
title: str = "Fenrir API",
|
|
93
|
-
version: str = "2.3.
|
|
93
|
+
version: str = "2.3.3",
|
|
94
94
|
template_folder: str = "templates",
|
|
95
95
|
renderer: Any = None,
|
|
96
96
|
docs_url: str = "/docs",
|
|
@@ -809,18 +809,44 @@ class Fenrir:
|
|
|
809
809
|
return JSONResponse({"detail": "Internal Server Error"}, status=500)
|
|
810
810
|
|
|
811
811
|
# Server runner using Asteri
|
|
812
|
-
def run(self, host: str = "127.0.0.1", port: int = 8000, workers: int = 1, **kwargs):
|
|
813
|
-
"""Run the Fenrir app locally using Asteri
|
|
812
|
+
def run(self, host: str = "127.0.0.1", port: int = 8000, workers: int = 1, app_path: str = None, **kwargs):
|
|
813
|
+
"""Run the Fenrir app locally using Asteri ASGI worker.
|
|
814
|
+
|
|
815
|
+
Args:
|
|
816
|
+
host: Host address to bind to
|
|
817
|
+
port: Port to listen on
|
|
818
|
+
workers: Number of worker processes
|
|
819
|
+
app_path: Import path for the app (e.g. 'demo_app:app').
|
|
820
|
+
If None, auto-detects from caller's module.
|
|
821
|
+
"""
|
|
814
822
|
from asteri.arbiter import Arbiter
|
|
815
823
|
from asteri.workers.asgi import ASGIWorker
|
|
816
824
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
825
|
+
if app_path is None:
|
|
826
|
+
# Auto-detect: find the caller's module and variable name
|
|
827
|
+
try:
|
|
828
|
+
frame = sys._getframe(1)
|
|
829
|
+
caller_file = frame.f_globals.get("__file__")
|
|
830
|
+
caller_var = frame.f_locals.get("app")
|
|
831
|
+
if caller_file and caller_var is self:
|
|
832
|
+
import importlib
|
|
833
|
+
mod_name = frame.f_globals.get("__name__")
|
|
834
|
+
if mod_name and mod_name != "__main__":
|
|
835
|
+
app_path = f"{mod_name}:app"
|
|
836
|
+
else:
|
|
837
|
+
mod_path = os.path.splitext(os.path.relpath(caller_file))[0].replace(os.sep, ".")
|
|
838
|
+
app_path = f"{mod_path}:app"
|
|
839
|
+
except Exception:
|
|
840
|
+
pass
|
|
841
|
+
|
|
842
|
+
if app_path is None:
|
|
843
|
+
raise RuntimeError(
|
|
844
|
+
"Could not auto-detect app_path. Pass it explicitly: "
|
|
845
|
+
"app.run(app_path='myapp:app')"
|
|
846
|
+
)
|
|
820
847
|
|
|
821
|
-
# Tell Asteri to load 'fenrir.app:_active_app'
|
|
822
848
|
arbiter = Arbiter(
|
|
823
|
-
app_path=
|
|
849
|
+
app_path=app_path,
|
|
824
850
|
worker_class=ASGIWorker,
|
|
825
851
|
num_workers=workers,
|
|
826
852
|
binds=[f"{host}:{port}"],
|
|
@@ -153,35 +153,22 @@ def cmd_run(args):
|
|
|
153
153
|
|
|
154
154
|
# Print our beautiful blue banner
|
|
155
155
|
print_banner(app.title)
|
|
156
|
+
print(f"\033[94mStarting Fenrir App '{app.title}' v{app.version}...\033[0m")
|
|
156
157
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if reload_mode and not has_watchdog:
|
|
167
|
-
def serve():
|
|
168
|
-
app_to_serve = load_app(args.target)
|
|
169
|
-
print(f"\033[94mStarting Fenrir App '{app_to_serve.title}' v{app_to_serve.version}...\033[0m")
|
|
170
|
-
app_to_serve.run(
|
|
171
|
-
host=args.host,
|
|
172
|
-
port=args.port,
|
|
173
|
-
workers=args.workers,
|
|
174
|
-
reload=False,
|
|
175
|
-
)
|
|
176
|
-
run_with_reloader(serve)
|
|
177
|
-
else:
|
|
178
|
-
print(f"\033[94mStarting Fenrir App '{app.title}' v{app.version}...\033[0m")
|
|
179
|
-
app.run(
|
|
180
|
-
host=args.host,
|
|
181
|
-
port=args.port,
|
|
182
|
-
workers=args.workers,
|
|
158
|
+
try:
|
|
159
|
+
from asteri.arbiter import Arbiter
|
|
160
|
+
from asteri.workers.asgi import ASGIWorker
|
|
161
|
+
|
|
162
|
+
arbiter = Arbiter(
|
|
163
|
+
app_path=args.target,
|
|
164
|
+
worker_class=ASGIWorker,
|
|
165
|
+
num_workers=args.workers,
|
|
166
|
+
binds=[f"{args.host}:{args.port}"],
|
|
183
167
|
reload=reload_mode,
|
|
184
168
|
)
|
|
169
|
+
arbiter.start()
|
|
170
|
+
except KeyboardInterrupt:
|
|
171
|
+
pass
|
|
185
172
|
|
|
186
173
|
|
|
187
174
|
def cmd_routes(args):
|
|
@@ -375,7 +362,7 @@ def cmd_new(args):
|
|
|
375
362
|
import os
|
|
376
363
|
import sys
|
|
377
364
|
|
|
378
|
-
app = Fenrir(title="My Fenrir Application", version="2.3.
|
|
365
|
+
app = Fenrir(title="My Fenrir Application", version="2.3.3")
|
|
379
366
|
|
|
380
367
|
@app.get("/")
|
|
381
368
|
async def home():
|
|
@@ -682,7 +669,7 @@ if __name__ == "__main__":
|
|
|
682
669
|
</div>
|
|
683
670
|
<div class="info-item">
|
|
684
671
|
<span class="info-label">Framework Engine</span>
|
|
685
|
-
<span class="info-value">Fenrir v2.3.
|
|
672
|
+
<span class="info-value">Fenrir v2.3.3</span>
|
|
686
673
|
</div>
|
|
687
674
|
</div>
|
|
688
675
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fenrir-framework"
|
|
7
|
-
version = "2.3.
|
|
7
|
+
version = "2.3.3"
|
|
8
8
|
description = "A hybrid Python web framework combining Flask, FastAPI, Bottle, Falcon, and Sanic"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -74,16 +74,12 @@ def test_cli_shell(mock_load_app):
|
|
|
74
74
|
|
|
75
75
|
def test_cli_run(mock_load_app):
|
|
76
76
|
app = MockApp()
|
|
77
|
+
mock_arbiter = mock.MagicMock()
|
|
77
78
|
with mock.patch("fenrir.cli.load_app", return_value=app):
|
|
78
|
-
with mock.patch.
|
|
79
|
+
with mock.patch("asteri.arbiter.Arbiter", return_value=mock_arbiter):
|
|
79
80
|
with mock.patch("sys.argv", ["fenrir", "run", "mock_module:app", "-p", "8888", "--dev"]):
|
|
80
81
|
main()
|
|
81
|
-
|
|
82
|
-
host="127.0.0.1",
|
|
83
|
-
port=8888,
|
|
84
|
-
workers=1,
|
|
85
|
-
reload=True
|
|
86
|
-
)
|
|
82
|
+
mock_arbiter.start.assert_called_once()
|
|
87
83
|
|
|
88
84
|
|
|
89
85
|
def test_cli_bench(mock_load_app):
|
|
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
|
{fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/entry_points.txt
RENAMED
|
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
|