working on improving component loading

This commit is contained in:
2026-01-10 19:17:17 +01:00
parent 797883dac8
commit 5201858b79
5 changed files with 104 additions and 9 deletions

View File

@@ -3,7 +3,7 @@ import uuid
from typing import Optional
from myfasthtml.controls.helpers import Ids
from myfasthtml.core.utils import pascal_to_snake
from myfasthtml.core.utils import pascal_to_snake, get_class, snake_to_pascal
logger = logging.getLogger("InstancesManager")
@@ -183,16 +183,22 @@ class InstancesManager:
return instance
@staticmethod
def get(session: dict, instance_id: str):
def get(session: dict, instance_id: str, default="**__no_default__**"):
"""
Get or create an instance of the given type (from its id)
:param session:
:param instance_id:
:param default:
:return:
"""
session_id = InstancesManager.get_session_id(session)
key = (session_id, instance_id)
return InstancesManager.instances[key]
try:
session_id = InstancesManager.get_session_id(session)
key = (session_id, instance_id)
return InstancesManager.instances[key]
except KeyError:
if default != "**__non__**":
return default
raise
@staticmethod
def get_by_type(session: dict, cls: type):
@@ -202,6 +208,19 @@ class InstancesManager:
assert len(res) > 0, f"No instance of type {cls.__name__} found"
return res[0]
@staticmethod
def dynamic_get(session, component_parent: tuple, component: tuple):
parent_type, parent_id = component_parent
component_type, component_id = component
# parent should always exist
parent = InstancesManager.get(session, parent_id)
real_component_type = snake_to_pascal(component_type.removeprefix("mf-"))
component_full_type = f"myfasthtml.controls.{real_component_type}.{real_component_type}"
cls = get_class(component_full_type)
return cls(parent, _id=component_id)
@staticmethod
def get_session_id(session):
if isinstance(session, str):

View File

@@ -1,3 +1,4 @@
import importlib
import logging
import re
@@ -317,6 +318,29 @@ def make_safe_id(s: str | None):
res = re.sub('-', '_', make_html_id(s)) # replace '-' by '_'
return res.lower() # no uppercase
def get_class(qualified_class_name: str):
"""
Dynamically loads and returns a class type from its fully qualified name.
Note that the class is not instantiated.
:param qualified_class_name: Fully qualified name of the class (e.g., 'some.module.ClassName').
:return: The class object.
:raises ImportError: If the module cannot be imported.
:raises AttributeError: If the class cannot be resolved in the module.
"""
module_name, class_name = qualified_class_name.rsplit(".", 1)
try:
module = importlib.import_module(module_name)
except ModuleNotFoundError as e:
raise ImportError(f"Could not import module '{module_name}' for '{qualified_class_name}': {e}")
if not hasattr(module, class_name):
raise AttributeError(f"Component '{class_name}' not found in '{module.__name__}'.")
return getattr(module, class_name)
@utils_rt(Routes.Commands)
def post(session, c_id: str, client_response: dict = None):
"""