Compare commits

...
6 Commits
5 changed files with 20 additions and 8 deletions
+11 -3
View File
@@ -4,6 +4,7 @@ import asyncio
import logging import logging
import os import os
from contextlib import suppress from contextlib import suppress
from pathlib import Path
from typing import Any from typing import Any
import uvicorn import uvicorn
@@ -19,7 +20,7 @@ def run(
*, *,
listen: str | list[str] | None = None, listen: str | list[str] | None = None,
default_port: int = 8000, default_port: int = 8000,
reload: bool = False, reload: bool | Path = False,
workers: int | None = None, workers: int | None = None,
**uvicorn_config: Any, # noqa: ANN401 **uvicorn_config: Any, # noqa: ANN401
) -> None: ) -> None:
@@ -29,7 +30,9 @@ def run(
app: The ASGI application path (e.g., "myapp.main:app") app: The ASGI application path (e.g., "myapp.main:app")
listen: Endpoint string(s) (see parse_endpoint for formats). listen: Endpoint string(s) (see parse_endpoint for formats).
default_port: Port to use when not specified in listen args. default_port: Port to use when not specified in listen args.
reload: Enable auto-reload (requires uvicorn.run, single endpoint only). reload: Enable auto-reload. If a Path is given, reload watches that
directory. True enables reload without setting a reload directory.
False disables reload and clears any reload_dirs.
workers: Number of worker processes (requires uvicorn.run, single endpoint only). workers: Number of worker processes (requires uvicorn.run, single endpoint only).
**uvicorn_config: Additional uvicorn config options (overrides all other settings). **uvicorn_config: Additional uvicorn config options (overrides all other settings).
@@ -39,7 +42,12 @@ def run(
msg = "No endpoints to serve; check listen configuration" msg = "No endpoints to serve; check listen configuration"
raise ValueError(msg) raise ValueError(msg)
conf: dict[str, object] = {"app": app, "reload": reload, "workers": workers} if isinstance(reload, Path):
uvicorn_config["reload_dirs"] = [str(reload)]
elif not reload:
uvicorn_config.pop("reload_dirs", None)
conf: dict[str, object] = {"app": app, "reload": bool(reload), "workers": workers}
proxy = os.getenv("FORWARDED_ALLOW_IPS", "127.0.0.1,::1") proxy = os.getenv("FORWARDED_ALLOW_IPS", "127.0.0.1,::1")
if proxy: if proxy:
conf["proxy_headers"] = True conf["proxy_headers"] = True
+3 -1
View File
@@ -220,7 +220,9 @@ class Frontend:
if self._catch_all: if self._catch_all:
# Register catch-all immediately (works without load) # Register catch-all immediately (works without load)
path = self._mount_path + "{path:path}" path = self._mount_path + "{path:path}"
app.api_route(path, methods=["GET", "HEAD"], name="frontend", response_model=None)(self.handle) app.api_route(path, methods=["GET", "HEAD"], name="frontend", response_model=None)(
self.handle
)
def _register_routes(self) -> None: def _register_routes(self) -> None:
"""Register individual routes for each loaded file (non-catch_all mode).""" """Register individual routes for each loaded file (non-catch_all mode)."""
+2 -1
View File
@@ -80,6 +80,7 @@ def ruff_format_content(
[ # noqa: S607 [ # noqa: S607
"ruff", "ruff",
"check", "check",
"--ignore=INP001,N999,CPY001",
"--fix", "--fix",
"--output-format=concise", "--output-format=concise",
str(temp_file), str(temp_file),
@@ -1375,7 +1376,7 @@ def cmd_setup(args: argparse.Namespace) -> int:
app_file, app_var = app_info app_file, app_var = app_info
print(f"📍 Found FastAPI app: {app_var} in {app_file.name}") print(f"📍 Found FastAPI app: {app_var} in {app_file.name}")
tpl_vars["APP_VAR"] = app_var tpl_vars["APP_VAR"] = app_var
# Dotted module path relative to project dir (e.g. "paskia.fastapi.mainapp") # Dotted module path relative to project dir (e.g. "{module_name}.api.main")
app_module = ".".join(app_file.relative_to(project_dir).with_suffix("").parts) app_module = ".".join(app_file.relative_to(project_dir).with_suffix("").parts)
tpl_vars["APP_MODULE"] = app_module tpl_vars["APP_MODULE"] = app_module
else: else:
+3 -2
View File
@@ -3,6 +3,7 @@
import argparse import argparse
import os import os
from pathlib import Path
from fastapi_vue import server from fastapi_vue import server
@@ -20,12 +21,12 @@ def main() -> None:
help=(f"Endpoint (default: localhost:{DEFAULT_PORT})."), help=(f"Endpoint (default: localhost:{DEFAULT_PORT})."),
) )
args = parser.parse_args() args = parser.parse_args()
dev = {"reload": True, "reload_dirs": ["paskia"]} if DEVMODE else {}
server.run( server.run(
"APP_MODULE:APP_VAR", "APP_MODULE:APP_VAR",
listen=args.listen, listen=args.listen,
default_port=DEFAULT_PORT, default_port=DEFAULT_PORT,
**dev, server_header=False,
reload=Path(__file__).parent if DEVMODE else False,
) )
+1 -1
View File
@@ -40,7 +40,7 @@ async def run_devserver(
viteurl, npm_install, vite = setup_vite(listen, DEFAULT_VITE_PORT) viteurl, npm_install, vite = setup_vite(listen, DEFAULT_VITE_PORT)
backurl, MODULE_NAME = setup_cli("PROJECT_CLI", backend, DEFAULT_DEV_PORT) backurl, MODULE_NAME = setup_cli("PROJECT_CLI", backend, DEFAULT_DEV_PORT)
# Tell the everyone by environment (vite proxy and backend devmode use these) # Tell everyone via environment (vite proxy and backend devmode use these)
os.environ["ENVPREFIX_VITE_URL"] = viteurl os.environ["ENVPREFIX_VITE_URL"] = viteurl
os.environ["ENVPREFIX_BACKEND_URL"] = backurl os.environ["ENVPREFIX_BACKEND_URL"] = backurl
os.environ["ENVPREFIX_DEV"] = "1" os.environ["ENVPREFIX_DEV"] = "1"