Added first controls

This commit is contained in:
2025-11-26 20:53:12 +01:00
parent 459c89bae2
commit ce5328fe34
68 changed files with 37849 additions and 87048 deletions

View File

@@ -1,8 +1,11 @@
import logging
import re
from bs4 import Tag
from fastcore.xml import FT
from fasthtml.fastapp import fast_app
from rich.console import Console
from rich.table import Table
from starlette.routing import Mount
from myfasthtml.core.constants import Routes, ROUTE_ROOT
@@ -60,15 +63,46 @@ def merge_classes(*args):
def debug_routes(app):
routes = []
def _clean_endpoint(endpoint):
res = str(endpoint).replace("<function ", "").replace(".<locals>", "")
return res.split(" at ")[0]
def _debug_routes(_app, _route, prefix=""):
if isinstance(_route, Mount):
for sub_route in _route.app.router.routes:
_debug_routes(_app, sub_route, prefix=_route.path)
else:
print(f"path={prefix}{_route.path}, methods={_route.methods}, endpoint={_route.endpoint}")
routes.append({
"number": len(routes),
"app": str(_app),
"name": _route.name,
"path": _route.path,
"full_path": prefix + _route.path,
"endpoint": _clean_endpoint(_route.endpoint),
"methods": _route.methods if hasattr(_route, "methods") else [],
"path_format": _route.path_format,
"path_regex": str(_route.path_regex),
})
for route in app.router.routes:
_debug_routes(app, route)
if not routes:
print("No routes found.")
return
table = Table(show_header=True, expand=True, header_style="bold")
columns = ["number", "name", "full_path", "endpoint", "methods"] # routes[0].keys()
for column in columns:
table.add_column(column)
for route in routes:
table.add_row(*[str(route[column]) for column in columns])
console = Console()
console.print(table)
def mount_utils(app):
@@ -158,19 +192,92 @@ def quoted_str(s):
return str(s)
def retrieve_user_info(session: dict):
if not session:
return {
"id": "** NOT LOGGED IN **",
"email": "** NOT LOGGED IN **",
"username": "** NOT LOGGED IN **",
"role": [],
"user_settings": {}
}
if "user_info" not in session:
return {
"id": "** UNKNOWN USER **",
"email": "** UNKNOWN USER **",
"username": "** UNKNOWN USER **",
"role": [],
"user_settings": {}
}
return session["user_info"]
def debug_session(session):
if session is None:
return "None"
if not isinstance(session, dict):
return str(session)
return session.get("user_info", {}).get("email", "** UNKNOWN USER **")
def get_id(obj):
if isinstance(obj, str):
return obj
elif hasattr(obj, "id"):
return obj.id
elif hasattr(obj, "get_id"):
return obj.get_id()
else:
return str(obj)
def pascal_to_snake(name: str) -> str:
"""Convert a PascalCase or CamelCase string to snake_case."""
if name is None:
return None
name = name.strip()
# Insert underscore before capital letters (except the first one)
s1 = re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', name)
# Handle consecutive capital letters (like 'HTTPServer' -> 'http_server')
s2 = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', s1)
return s2.lower()
def snake_to_pascal(name: str) -> str:
"""Convert a snake_case string to PascalCase."""
if name is None:
return None
name = name.strip()
if not name:
return ""
# Split on underscores and capitalize each part
parts = name.split('_')
return ''.join(word.capitalize() for word in parts if word)
@utils_rt(Routes.Commands)
def post(session, c_id: str):
def post(session, c_id: str, client_response: dict = None):
"""
Default routes for all commands.
:param session:
:param c_id:
:param c_id: id of the command set
:param client_response: extra data received from the client (from the browser)
:return:
"""
logger.debug(f"Entering {Routes.Commands} with {session=}, {c_id=}")
client_response.pop("c_id", None)
logger.debug(f"Entering {Routes.Commands} with session='{debug_session(session)}', {c_id=}, {client_response=}")
from myfasthtml.core.commands import CommandsManager
command = CommandsManager.get_command(c_id)
if command:
return command.execute()
logger.debug(f"Executing command {command.name}.")
return command.execute(client_response)
raise ValueError(f"Command with ID '{c_id}' not found.")
@@ -188,6 +295,7 @@ def post(session, b_id: str, values: dict):
from myfasthtml.core.bindings import BindingsManager
binding = BindingsManager.get_binding(b_id)
if binding:
return binding.update(values)
res = binding.update(values)
return res
raise ValueError(f"Binding with ID '{b_id}' not found.")