fastlifeweb 0.7.0__tar.gz → 0.7.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.
Files changed (79) hide show
  1. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/PKG-INFO +1 -1
  2. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/pyproject.toml +1 -1
  3. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/configurator/configurator.py +9 -3
  4. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/configurator/route_handler.py +3 -4
  5. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/configurator/settings.py +5 -1
  6. fastlifeweb-0.7.2/src/fastlife/middlewares/__init__.py +7 -0
  7. fastlifeweb-0.7.2/src/fastlife/middlewares/reverse_proxy/__init__.py +10 -0
  8. fastlifeweb-0.7.2/src/fastlife/middlewares/reverse_proxy/x_forwarded.py +50 -0
  9. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/testing/testclient.py +1 -1
  10. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/LICENSE +0 -0
  11. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/README.md +0 -0
  12. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/__init__.py +0 -0
  13. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/configurator/__init__.py +0 -0
  14. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/configurator/base.py +0 -0
  15. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/configurator/registry.py +0 -0
  16. {fastlifeweb-0.7.0/src/fastlife → fastlifeweb-0.7.2/src/fastlife/middlewares}/session/__init__.py +0 -0
  17. {fastlifeweb-0.7.0/src/fastlife → fastlifeweb-0.7.2/src/fastlife/middlewares}/session/middleware.py +0 -0
  18. {fastlifeweb-0.7.0/src/fastlife → fastlifeweb-0.7.2/src/fastlife/middlewares}/session/serializer.py +0 -0
  19. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/py.typed +0 -0
  20. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/request/__init__.py +0 -0
  21. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/request/form_data.py +0 -0
  22. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/request/model_result.py +0 -0
  23. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/routing/__init__.py +0 -0
  24. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/routing/router.py +0 -0
  25. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/security/__init__.py +0 -0
  26. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/security/csrf.py +0 -0
  27. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/security/policy.py +0 -0
  28. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/shared_utils/__init__.py +0 -0
  29. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/shared_utils/infer.py +0 -0
  30. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/shared_utils/resolver.py +0 -0
  31. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/A.jinja +0 -0
  32. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/Button.jinja +0 -0
  33. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/Checkbox.jinja +0 -0
  34. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/CsrfToken.jinja +0 -0
  35. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/Form.jinja +0 -0
  36. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/H1.jinja +0 -0
  37. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/H2.jinja +0 -0
  38. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/H3.jinja +0 -0
  39. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/H4.jinja +0 -0
  40. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/H5.jinja +0 -0
  41. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/H6.jinja +0 -0
  42. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/Hidden.jinja +0 -0
  43. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/Input.jinja +0 -0
  44. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/Label.jinja +0 -0
  45. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/Option.jinja +0 -0
  46. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/P.jinja +0 -0
  47. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/Radio.jinja +0 -0
  48. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/Select.jinja +0 -0
  49. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/__init__.py +0 -0
  50. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Boolean.jinja +0 -0
  51. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Checklist.jinja +0 -0
  52. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Dropdown.jinja +0 -0
  53. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Error.jinja +0 -0
  54. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Hidden.jinja +0 -0
  55. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Hint.jinja +0 -0
  56. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Model.jinja +0 -0
  57. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Sequence.jinja +0 -0
  58. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Text.jinja +0 -0
  59. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Union.jinja +0 -0
  60. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templates/pydantic_form/Widget.jinja +0 -0
  61. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/__init__.py +0 -0
  62. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/binding.py +0 -0
  63. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/__init__.py +0 -0
  64. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/abstract.py +0 -0
  65. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/jinjax.py +0 -0
  66. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/__init__.py +0 -0
  67. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/base.py +0 -0
  68. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/boolean.py +0 -0
  69. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/checklist.py +0 -0
  70. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/dropdown.py +0 -0
  71. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/factory.py +0 -0
  72. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/hidden.py +0 -0
  73. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/model.py +0 -0
  74. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/sequence.py +0 -0
  75. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/text.py +0 -0
  76. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/templating/renderer/widgets/union.py +0 -0
  77. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/testing/__init__.py +0 -0
  78. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/views/__init__.py +0 -0
  79. {fastlifeweb-0.7.0 → fastlifeweb-0.7.2}/src/fastlife/views/pydantic_form.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastlifeweb
3
- Version: 0.7.0
3
+ Version: 0.7.2
4
4
  Summary: High-level web framework
5
5
  Home-page: https://github.com/mardiros/fastlife
6
6
  License: BSD-derived
@@ -15,7 +15,7 @@ classifiers = [
15
15
  "Topic :: Software Development :: Libraries :: Python Modules",
16
16
  "Topic :: Internet :: WWW/HTTP",
17
17
  ]
18
- version = "0.7.0"
18
+ version = "0.7.2"
19
19
 
20
20
  [tool.poetry.dependencies]
21
21
  python = "^3.11"
@@ -22,7 +22,7 @@ from typing import (
22
22
  )
23
23
 
24
24
  import venusian # type: ignore
25
- from fastapi import Depends, FastAPI, Response
25
+ from fastapi import Depends, FastAPI, Request, Response
26
26
  from fastapi.params import Depends as DependsType
27
27
  from fastapi.staticfiles import StaticFiles
28
28
 
@@ -30,6 +30,7 @@ from fastlife.configurator.base import AbstractMiddleware
30
30
  from fastlife.configurator.route_handler import FastlifeRoute
31
31
  from fastlife.security.csrf import check_csrf
32
32
 
33
+ from .route_handler import FastlifeRequest
33
34
  from .settings import Settings
34
35
 
35
36
  if TYPE_CHECKING:
@@ -63,7 +64,7 @@ class Configurator:
63
64
  self._app.router.route_class = FastlifeRoute
64
65
  self.scanner = venusian.Scanner(fastlife=self)
65
66
  self.include("fastlife.views")
66
- self.include("fastlife.session")
67
+ self.include("fastlife.middlewares")
67
68
 
68
69
  def get_app(self) -> FastAPI:
69
70
  """
@@ -193,7 +194,12 @@ class Configurator:
193
194
  self, status_code_or_exc: int | Type[Exception], handler: Any
194
195
  ) -> "Configurator":
195
196
  """Add an exception handler the application."""
196
- self._app.add_exception_handler(status_code_or_exc, handler)
197
+
198
+ def exception_handler(request: Request, exc: Exception) -> Any:
199
+ req = FastlifeRequest(self.registry, request)
200
+ return handler(req, exc)
201
+
202
+ self._app.add_exception_handler(status_code_or_exc, exception_handler)
197
203
  return self
198
204
 
199
205
 
@@ -3,15 +3,14 @@ from typing import TYPE_CHECKING, Any, Callable, Coroutine
3
3
  from fastapi import Request as BaseRequest
4
4
  from fastapi.routing import APIRoute
5
5
  from starlette.responses import Response
6
- from starlette.types import Receive, Scope
7
6
 
8
7
  if TYPE_CHECKING:
9
8
  from .registry import AppRegistry # coverage: ignore
10
9
 
11
10
 
12
11
  class FastlifeRequest(BaseRequest):
13
- def __init__(self, registry: "AppRegistry", scope: Scope, receive: Receive) -> None:
14
- super().__init__(scope, receive)
12
+ def __init__(self, registry: "AppRegistry", request: BaseRequest) -> None:
13
+ super().__init__(request.scope, request.receive)
15
14
  self.registry = registry
16
15
 
17
16
 
@@ -24,7 +23,7 @@ class FastlifeRoute(APIRoute):
24
23
  orig_route_handler = super().get_route_handler()
25
24
 
26
25
  async def route_handler(request: BaseRequest) -> FastlifeRequest:
27
- req = FastlifeRequest(self.registry, request.scope, request.receive)
26
+ req = FastlifeRequest(self.registry, request)
28
27
  return await orig_route_handler(req) # type: ignore
29
28
 
30
29
  return route_handler # type: ignore
@@ -1,4 +1,5 @@
1
1
  """Settings for the fastlife."""
2
+
2
3
  from datetime import timedelta
3
4
  from typing import Literal
4
5
 
@@ -77,7 +78,7 @@ class Settings(BaseSettings):
77
78
  should be true while using https on production.
78
79
  """
79
80
  session_serializer: str = Field(
80
- default="fastlife.session.serializer:SignedSessionSerializer"
81
+ default="fastlife.middlewares.session.serializer:SignedSessionSerializer"
81
82
  )
82
83
  """Cookie serializer for the session cookie."""
83
84
 
@@ -86,3 +87,6 @@ class Settings(BaseSettings):
86
87
 
87
88
  check_permission: str = Field(default="fastlife.security.policy:check_permission")
88
89
  """Handler for checking permission set on any views using the configurator."""
90
+
91
+ decode_reverse_proxy_headers: bool = Field(default=True)
92
+ """Ensure that the request object has information based on http proxy headers."""
@@ -0,0 +1,7 @@
1
+ from fastlife import Configurator, configure
2
+
3
+
4
+ @configure
5
+ def includeme(config: Configurator) -> None:
6
+ config.include(".reverse_proxy")
7
+ config.include(".session")
@@ -0,0 +1,10 @@
1
+ from fastlife import Configurator, configure
2
+
3
+ from .x_forwarded import XForwardedStar
4
+
5
+
6
+ @configure
7
+ def includeme(config: Configurator) -> None:
8
+ settings = config.registry.settings
9
+ if settings.decode_reverse_proxy_headers:
10
+ config.add_middleware(XForwardedStar)
@@ -0,0 +1,50 @@
1
+ """
2
+ A middleware that update the request scope for https behind a proxy.
3
+
4
+ The attempt of this middleware is to fix Starlette behavior that use client and scheme
5
+ header based on the header x-forwarded-* headers and the x-real-ip.
6
+
7
+ the x-forwarded-for header is not parsed to find the appropriate value,
8
+ the x-real-ip is used.
9
+ notethat the x-forwarded-port header is not used.
10
+
11
+ Note that uvicorn or hypercorn offer the same kind middleware.
12
+ """
13
+
14
+ import logging
15
+ from typing import Optional, Sequence, Tuple
16
+
17
+ from starlette.types import ASGIApp, Receive, Scope, Send
18
+
19
+ from fastlife.configurator.base import AbstractMiddleware
20
+
21
+
22
+ log = logging.getLogger(__name__)
23
+
24
+
25
+ def get_header(headers: Sequence[Tuple[bytes, bytes]], key: bytes) -> Optional[str]:
26
+ for hdr in headers:
27
+ if hdr[0].lower() == key:
28
+ return hdr[1].decode("latin1")
29
+ return None
30
+
31
+
32
+ class XForwardedStar(AbstractMiddleware):
33
+ def __init__(
34
+ self,
35
+ app: ASGIApp,
36
+ ) -> None:
37
+ self.app = app
38
+
39
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
40
+ if scope["type"] in ("http", "websocket"):
41
+
42
+ headers = scope["headers"]
43
+ new_vals = {
44
+ "client": get_header(headers, b"x-real-ip"),
45
+ "host": get_header(headers, b"x-forwarded-host"),
46
+ "scheme": get_header(headers, b"x-forwarded-proto"),
47
+ }
48
+ scope.update({key: val for key, val in new_vals.items() if val is not None})
49
+
50
+ await self.app(scope, receive, send)
@@ -14,7 +14,7 @@ from multidict import MultiDict
14
14
  from starlette.types import ASGIApp
15
15
 
16
16
  from fastlife.configurator.settings import Settings
17
- from fastlife.session.serializer import AbsractSessionSerializer
17
+ from fastlife.middlewares.session.serializer import AbsractSessionSerializer
18
18
  from fastlife.shared_utils.resolver import resolve
19
19
 
20
20
  CookieTypes = httpx._types.CookieTypes # type: ignore
File without changes
File without changes