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.

Files changed (88) hide show
  1. {fenrir_framework-2.3.2/fenrir_framework.egg-info → fenrir_framework-2.3.3}/PKG-INFO +1 -1
  2. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/__init__.py +1 -1
  3. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/app.py +34 -8
  4. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/cli.py +15 -28
  5. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3/fenrir_framework.egg-info}/PKG-INFO +1 -1
  6. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/pyproject.toml +1 -1
  7. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_cli.py +3 -7
  8. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/LICENSE +0 -0
  9. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/README.md +0 -0
  10. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/background.py +0 -0
  11. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/bottle.py +0 -0
  12. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/compat.py +0 -0
  13. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/config.py +0 -0
  14. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/context.py +0 -0
  15. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/dependencies.py +0 -0
  16. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/exceptions.py +0 -0
  17. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/falcon.py +0 -0
  18. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/helpers.py +0 -0
  19. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/http2.py +0 -0
  20. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/json.py +0 -0
  21. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/logo.jpg +0 -0
  22. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/logo.png +0 -0
  23. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/middleware.py +0 -0
  24. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/openapi.py +0 -0
  25. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/pagination.py +0 -0
  26. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/pool.py +0 -0
  27. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/request.py +0 -0
  28. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/response.py +0 -0
  29. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/routing.py +0 -0
  30. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/sanic.py +0 -0
  31. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/security.py +0 -0
  32. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/sessions.py +0 -0
  33. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/signals.py +0 -0
  34. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/sse.py +0 -0
  35. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/templating.py +0 -0
  36. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/testing.py +0 -0
  37. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/upload.py +0 -0
  38. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/views.py +0 -0
  39. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir/websocket.py +0 -0
  40. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/SOURCES.txt +0 -0
  41. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/dependency_links.txt +0 -0
  42. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/entry_points.txt +0 -0
  43. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/requires.txt +0 -0
  44. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/fenrir_framework.egg-info/top_level.txt +0 -0
  45. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/setup.cfg +0 -0
  46. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_appctx.py +0 -0
  47. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_async.py +0 -0
  48. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_basic.py +0 -0
  49. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_blueprints.py +0 -0
  50. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_circular_deps.py +0 -0
  51. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_config.py +0 -0
  52. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_context.py +0 -0
  53. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_converters.py +0 -0
  54. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_custom_template.py +0 -0
  55. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_dep_overrides.py +0 -0
  56. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_dependencies.py +0 -0
  57. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_falcon_compat.py +0 -0
  58. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_form_file.py +0 -0
  59. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_helpers.py +0 -0
  60. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_instance_config.py +0 -0
  61. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_json.py +0 -0
  62. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_json_tag.py +0 -0
  63. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_logging.py +0 -0
  64. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_logo_route.py +0 -0
  65. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_middleware.py +0 -0
  66. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_new_features.py +0 -0
  67. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_new_middleware_features.py +0 -0
  68. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_regression.py +0 -0
  69. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_reqctx.py +0 -0
  70. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_request.py +0 -0
  71. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_resources.py +0 -0
  72. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_router_circular.py +0 -0
  73. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_routing.py +0 -0
  74. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_sanic_compat.py +0 -0
  75. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_security.py +0 -0
  76. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_session_interface.py +0 -0
  77. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_signals.py +0 -0
  78. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_sse.py +0 -0
  79. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_strict_content_type.py +0 -0
  80. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_subclassing.py +0 -0
  81. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_templating.py +0 -0
  82. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_testing.py +0 -0
  83. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_user_error_handler.py +0 -0
  84. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_v3_features.py +0 -0
  85. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_validation.py +0 -0
  86. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_views.py +0 -0
  87. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_websocket.py +0 -0
  88. {fenrir_framework-2.3.2 → fenrir_framework-2.3.3}/tests/test_yield_deps.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fenrir-framework
3
- Version: 2.3.2
3
+ Version: 2.3.3
4
4
  Summary: A hybrid Python web framework combining Flask, FastAPI, Bottle, Falcon, and Sanic
5
5
  Requires-Python: >=3.8
6
6
  Description-Content-Type: text/markdown
@@ -68,7 +68,7 @@ from fenrir.sessions import (
68
68
  # Re-export Annotated for convenient use with param markers
69
69
  from fenrir.compat import Annotated
70
70
 
71
- __version__ = "2.3.2"
71
+ __version__ = "2.3.3"
72
72
  __all__ = [
73
73
  # Core app
74
74
  "Fenrir",
@@ -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.2",
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 v2.2.2 ASGI worker."""
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
- # Store our application instance globally so Asteri's worker process can import it
818
- global _active_app
819
- _active_app = self
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="fenrir.app:_active_app",
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
- # Check if watchdog is installed
158
- has_watchdog = False
159
- if reload_mode:
160
- try:
161
- import watchdog
162
- has_watchdog = True
163
- except ImportError:
164
- has_watchdog = False
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.2")
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.2</span>
672
+ <span class="info-value">Fenrir v2.3.3</span>
686
673
  </div>
687
674
  </div>
688
675
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fenrir-framework
3
- Version: 2.3.2
3
+ Version: 2.3.3
4
4
  Summary: A hybrid Python web framework combining Flask, FastAPI, Bottle, Falcon, and Sanic
5
5
  Requires-Python: >=3.8
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fenrir-framework"
7
- version = "2.3.2"
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.object(app, "run") as mock_run:
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
- mock_run.assert_called_once_with(
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):