Make SubFox production-ready with parallel translation and UI controls
This commit is contained in:
parent
c40b8bed2b
commit
2b1d05f02c
6046 changed files with 798327 additions and 0 deletions
156
.venv/lib/python3.10/site-packages/starlette/templating.py
Normal file
156
.venv/lib/python3.10/site-packages/starlette/templating.py
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable, Mapping, Sequence
|
||||
from os import PathLike
|
||||
from typing import TYPE_CHECKING, Any, overload
|
||||
|
||||
from starlette.background import BackgroundTask
|
||||
from starlette.datastructures import URL
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import HTMLResponse
|
||||
from starlette.types import Receive, Scope, Send
|
||||
|
||||
try:
|
||||
import jinja2
|
||||
|
||||
# @contextfunction was renamed to @pass_context in Jinja 3.0, and was removed in 3.1
|
||||
# hence we try to get pass_context (most installs will be >=3.1)
|
||||
# and fall back to contextfunction,
|
||||
# adding a type ignore for mypy to let us access an attribute that may not exist
|
||||
if TYPE_CHECKING:
|
||||
pass_context = jinja2.pass_context
|
||||
else:
|
||||
if hasattr(jinja2, "pass_context"):
|
||||
pass_context = jinja2.pass_context
|
||||
else: # pragma: no cover
|
||||
pass_context = jinja2.contextfunction # type: ignore[attr-defined]
|
||||
except ImportError as _import_error: # pragma: no cover
|
||||
raise ImportError("jinja2 must be installed to use Jinja2Templates") from _import_error
|
||||
|
||||
|
||||
class _TemplateResponse(HTMLResponse):
|
||||
def __init__(
|
||||
self,
|
||||
template: Any,
|
||||
context: dict[str, Any],
|
||||
status_code: int = 200,
|
||||
headers: Mapping[str, str] | None = None,
|
||||
media_type: str | None = None,
|
||||
background: BackgroundTask | None = None,
|
||||
):
|
||||
self.template = template
|
||||
self.context = context
|
||||
content = template.render(context)
|
||||
super().__init__(content, status_code, headers, media_type, background)
|
||||
|
||||
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
||||
request = self.context.get("request", {})
|
||||
extensions = request.get("extensions", {})
|
||||
if "http.response.debug" in extensions: # pragma: no branch
|
||||
await send({"type": "http.response.debug", "info": {"template": self.template, "context": self.context}})
|
||||
await super().__call__(scope, receive, send)
|
||||
|
||||
|
||||
class Jinja2Templates:
|
||||
"""Jinja2 template renderer.
|
||||
|
||||
Example:
|
||||
```python
|
||||
from starlette.templating import Jinja2Templates
|
||||
|
||||
templates = Jinja2Templates(directory="templates")
|
||||
|
||||
async def homepage(request: Request) -> Response:
|
||||
return templates.TemplateResponse(request, "index.html")
|
||||
```
|
||||
"""
|
||||
|
||||
@overload
|
||||
def __init__(
|
||||
self,
|
||||
directory: str | PathLike[str] | Sequence[str | PathLike[str]],
|
||||
*,
|
||||
context_processors: list[Callable[[Request], dict[str, Any]]] | None = None,
|
||||
) -> None: ...
|
||||
|
||||
@overload
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
env: jinja2.Environment,
|
||||
context_processors: list[Callable[[Request], dict[str, Any]]] | None = None,
|
||||
) -> None: ...
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
directory: str | PathLike[str] | Sequence[str | PathLike[str]] | None = None,
|
||||
*,
|
||||
context_processors: list[Callable[[Request], dict[str, Any]]] | None = None,
|
||||
env: jinja2.Environment | None = None,
|
||||
) -> None:
|
||||
assert bool(directory) ^ bool(env), "either 'directory' or 'env' arguments must be passed"
|
||||
self.context_processors = context_processors or []
|
||||
if directory is not None:
|
||||
loader = jinja2.FileSystemLoader(directory)
|
||||
self.env = jinja2.Environment(loader=loader, autoescape=jinja2.select_autoescape())
|
||||
elif env is not None: # pragma: no branch
|
||||
self.env = env
|
||||
|
||||
self._setup_env_defaults(self.env)
|
||||
|
||||
def _setup_env_defaults(self, env: jinja2.Environment) -> None:
|
||||
@pass_context
|
||||
def url_for(
|
||||
context: dict[str, Any],
|
||||
name: str,
|
||||
/,
|
||||
**path_params: Any,
|
||||
) -> URL:
|
||||
request: Request = context["request"]
|
||||
return request.url_for(name, **path_params)
|
||||
|
||||
env.globals.setdefault("url_for", url_for)
|
||||
|
||||
def get_template(self, name: str) -> jinja2.Template:
|
||||
return self.env.get_template(name)
|
||||
|
||||
def TemplateResponse(
|
||||
self,
|
||||
request: Request,
|
||||
name: str,
|
||||
context: dict[str, Any] | None = None,
|
||||
status_code: int = 200,
|
||||
headers: Mapping[str, str] | None = None,
|
||||
media_type: str | None = None,
|
||||
background: BackgroundTask | None = None,
|
||||
) -> _TemplateResponse:
|
||||
"""
|
||||
Render a template and return an HTML response.
|
||||
|
||||
Args:
|
||||
request: The incoming request instance.
|
||||
name: The template file name to render.
|
||||
context: Variables to pass to the template.
|
||||
status_code: HTTP status code for the response.
|
||||
headers: Additional headers to include in the response.
|
||||
media_type: Media type for the response.
|
||||
background: Background task to run after response is sent.
|
||||
|
||||
Returns:
|
||||
An HTML response with the rendered template content.
|
||||
"""
|
||||
context = context or {}
|
||||
|
||||
context.setdefault("request", request)
|
||||
for context_processor in self.context_processors:
|
||||
context.update(context_processor(request))
|
||||
|
||||
template = self.get_template(name)
|
||||
return _TemplateResponse(
|
||||
template,
|
||||
context,
|
||||
status_code=status_code,
|
||||
headers=headers,
|
||||
media_type=media_type,
|
||||
background=background,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue