fenrir-framework 2.3.2__tar.gz → 2.3.4__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.4}/PKG-INFO +4 -4
  2. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/README.md +3 -3
  3. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/__init__.py +1 -1
  4. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/app.py +34 -8
  5. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/cli.py +15 -28
  6. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4/fenrir_framework.egg-info}/PKG-INFO +4 -4
  7. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/pyproject.toml +1 -1
  8. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_cli.py +3 -7
  9. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/LICENSE +0 -0
  10. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/background.py +0 -0
  11. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/bottle.py +0 -0
  12. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/compat.py +0 -0
  13. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/config.py +0 -0
  14. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/context.py +0 -0
  15. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/dependencies.py +0 -0
  16. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/exceptions.py +0 -0
  17. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/falcon.py +0 -0
  18. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/helpers.py +0 -0
  19. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/http2.py +0 -0
  20. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/json.py +0 -0
  21. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/logo.jpg +0 -0
  22. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/logo.png +0 -0
  23. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/middleware.py +0 -0
  24. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/openapi.py +0 -0
  25. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/pagination.py +0 -0
  26. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/pool.py +0 -0
  27. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/request.py +0 -0
  28. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/response.py +0 -0
  29. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/routing.py +0 -0
  30. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/sanic.py +0 -0
  31. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/security.py +0 -0
  32. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/sessions.py +0 -0
  33. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/signals.py +0 -0
  34. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/sse.py +0 -0
  35. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/templating.py +0 -0
  36. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/testing.py +0 -0
  37. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/upload.py +0 -0
  38. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/views.py +0 -0
  39. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir/websocket.py +0 -0
  40. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir_framework.egg-info/SOURCES.txt +0 -0
  41. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir_framework.egg-info/dependency_links.txt +0 -0
  42. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir_framework.egg-info/entry_points.txt +0 -0
  43. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir_framework.egg-info/requires.txt +0 -0
  44. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/fenrir_framework.egg-info/top_level.txt +0 -0
  45. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/setup.cfg +0 -0
  46. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_appctx.py +0 -0
  47. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_async.py +0 -0
  48. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_basic.py +0 -0
  49. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_blueprints.py +0 -0
  50. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_circular_deps.py +0 -0
  51. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_config.py +0 -0
  52. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_context.py +0 -0
  53. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_converters.py +0 -0
  54. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_custom_template.py +0 -0
  55. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_dep_overrides.py +0 -0
  56. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_dependencies.py +0 -0
  57. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_falcon_compat.py +0 -0
  58. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_form_file.py +0 -0
  59. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_helpers.py +0 -0
  60. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_instance_config.py +0 -0
  61. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_json.py +0 -0
  62. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_json_tag.py +0 -0
  63. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_logging.py +0 -0
  64. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_logo_route.py +0 -0
  65. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_middleware.py +0 -0
  66. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_new_features.py +0 -0
  67. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_new_middleware_features.py +0 -0
  68. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_regression.py +0 -0
  69. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_reqctx.py +0 -0
  70. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_request.py +0 -0
  71. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_resources.py +0 -0
  72. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_router_circular.py +0 -0
  73. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_routing.py +0 -0
  74. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_sanic_compat.py +0 -0
  75. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_security.py +0 -0
  76. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_session_interface.py +0 -0
  77. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_signals.py +0 -0
  78. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_sse.py +0 -0
  79. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_strict_content_type.py +0 -0
  80. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_subclassing.py +0 -0
  81. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_templating.py +0 -0
  82. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_testing.py +0 -0
  83. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_user_error_handler.py +0 -0
  84. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_v3_features.py +0 -0
  85. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_validation.py +0 -0
  86. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_views.py +0 -0
  87. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/tests/test_websocket.py +0 -0
  88. {fenrir_framework-2.3.2 → fenrir_framework-2.3.4}/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.4
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
@@ -98,7 +98,7 @@ logging.basicConfig(level=logging.INFO)
98
98
  logger = logging.getLogger("demo")
99
99
 
100
100
  # Initialize the Hybrid App
101
- app = Fenrir(title="Fenrir Hybrid Demo", version="2.3.2")
101
+ app = Fenrir(title="Fenrir Hybrid Demo", version="2.3.4")
102
102
 
103
103
  # --- 1. FastAPI-Style Validation & DI ---
104
104
  class UserRegister(BaseModel):
@@ -144,7 +144,7 @@ if __name__ == "__main__":
144
144
 
145
145
  ## 🔺 Trie-Based Routing
146
146
 
147
- Fenrir v2.3.2 uses a trie-based routing index for O(k) route matching, where k is the path depth. This is significantly faster than linear O(n) matching when you have many routes.
147
+ Fenrir v2.3.4 uses a trie-based routing index for O(k) route matching, where k is the path depth. This is significantly faster than linear O(n) matching when you have many routes.
148
148
 
149
149
  ```python
150
150
  from fenrir import Fenrir
@@ -356,7 +356,7 @@ PYTHONPATH=. pytest -v
356
356
 
357
357
  ## 🔄 Changelog
358
358
 
359
- ### v2.3.2 — Architecture & Performance Upgrade
359
+ ### v2.3.4 — Architecture & Performance Upgrade
360
360
 
361
361
  Major architecture improvements, new features, and performance optimizations:
362
362
 
@@ -81,7 +81,7 @@ logging.basicConfig(level=logging.INFO)
81
81
  logger = logging.getLogger("demo")
82
82
 
83
83
  # Initialize the Hybrid App
84
- app = Fenrir(title="Fenrir Hybrid Demo", version="2.3.2")
84
+ app = Fenrir(title="Fenrir Hybrid Demo", version="2.3.4")
85
85
 
86
86
  # --- 1. FastAPI-Style Validation & DI ---
87
87
  class UserRegister(BaseModel):
@@ -127,7 +127,7 @@ if __name__ == "__main__":
127
127
 
128
128
  ## 🔺 Trie-Based Routing
129
129
 
130
- Fenrir v2.3.2 uses a trie-based routing index for O(k) route matching, where k is the path depth. This is significantly faster than linear O(n) matching when you have many routes.
130
+ Fenrir v2.3.4 uses a trie-based routing index for O(k) route matching, where k is the path depth. This is significantly faster than linear O(n) matching when you have many routes.
131
131
 
132
132
  ```python
133
133
  from fenrir import Fenrir
@@ -339,7 +339,7 @@ PYTHONPATH=. pytest -v
339
339
 
340
340
  ## 🔄 Changelog
341
341
 
342
- ### v2.3.2 — Architecture & Performance Upgrade
342
+ ### v2.3.4 — Architecture & Performance Upgrade
343
343
 
344
344
  Major architecture improvements, new features, and performance optimizations:
345
345
 
@@ -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.4"
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.4",
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.4")
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.4</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.4
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
@@ -98,7 +98,7 @@ logging.basicConfig(level=logging.INFO)
98
98
  logger = logging.getLogger("demo")
99
99
 
100
100
  # Initialize the Hybrid App
101
- app = Fenrir(title="Fenrir Hybrid Demo", version="2.3.2")
101
+ app = Fenrir(title="Fenrir Hybrid Demo", version="2.3.4")
102
102
 
103
103
  # --- 1. FastAPI-Style Validation & DI ---
104
104
  class UserRegister(BaseModel):
@@ -144,7 +144,7 @@ if __name__ == "__main__":
144
144
 
145
145
  ## 🔺 Trie-Based Routing
146
146
 
147
- Fenrir v2.3.2 uses a trie-based routing index for O(k) route matching, where k is the path depth. This is significantly faster than linear O(n) matching when you have many routes.
147
+ Fenrir v2.3.4 uses a trie-based routing index for O(k) route matching, where k is the path depth. This is significantly faster than linear O(n) matching when you have many routes.
148
148
 
149
149
  ```python
150
150
  from fenrir import Fenrir
@@ -356,7 +356,7 @@ PYTHONPATH=. pytest -v
356
356
 
357
357
  ## 🔄 Changelog
358
358
 
359
- ### v2.3.2 — Architecture & Performance Upgrade
359
+ ### v2.3.4 — Architecture & Performance Upgrade
360
360
 
361
361
  Major architecture improvements, new features, and performance optimizations:
362
362
 
@@ -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.4"
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):