diff --git a/src/myfasthtml/controls/InstancesDebugger.py b/src/myfasthtml/controls/InstancesDebugger.py
index c3d0057..bbc14fd 100644
--- a/src/myfasthtml/controls/InstancesDebugger.py
+++ b/src/myfasthtml/controls/InstancesDebugger.py
@@ -4,7 +4,7 @@ from fasthtml.components import Div
from myfasthtml.controls.HierarchicalCanvasGraph import HierarchicalCanvasGraph, HierarchicalCanvasGraphConf
from myfasthtml.controls.Panel import Panel
-from myfasthtml.controls.Properties import Properties
+from myfasthtml.controls.Properties import Properties, PropertiesConf
from myfasthtml.core.commands import Command
from myfasthtml.core.instances import SingleInstance, UniqueInstance, MultipleInstance, InstancesManager
@@ -73,10 +73,11 @@ class InstancesDebugger(SingleInstance):
"Commands": {"*": "commands"},
}
- return self._panel.set_right(Properties(self,
- InstancesManager.get(session, instance_id),
- properties_def,
- _id="-properties"))
+ return self._panel.set_right(Properties(
+ self,
+ conf=PropertiesConf(obj=InstancesManager.get(session, instance_id), groups=properties_def),
+ _id="-properties",
+ ))
def _get_instance_kind(self, instance) -> str:
"""Determine the instance kind for visualization.
diff --git a/src/myfasthtml/controls/Panel.py b/src/myfasthtml/controls/Panel.py
index 8223f1b..aa959ee 100644
--- a/src/myfasthtml/controls/Panel.py
+++ b/src/myfasthtml/controls/Panel.py
@@ -104,7 +104,7 @@ class Panel(MultipleInstance):
the panel with appropriate HTML elements and JavaScript for interactivity.
"""
- def __init__(self, parent, conf: Optional[PanelConf] = None, _id="-panel"):
+ def __init__(self, parent, conf: Optional[PanelConf] = None, _id=None):
super().__init__(parent, _id=_id)
self.conf = conf or PanelConf()
self.commands = Commands(self)
diff --git a/src/myfasthtml/controls/Profiler.py b/src/myfasthtml/controls/Profiler.py
index cfb44a5..4b87e20 100644
--- a/src/myfasthtml/controls/Profiler.py
+++ b/src/myfasthtml/controls/Profiler.py
@@ -161,7 +161,7 @@ class Profiler(SingleInstance):
def __init__(self, parent, _id=None):
super().__init__(parent, _id=_id)
- self._panel = Panel(self, conf=PanelConf(show_right_title=False, show_display_right=False))
+ self._panel = Panel(self, conf=PanelConf(show_right_title=False, show_display_right=False), _id="-panel")
self._panel.set_side_visible("right", True)
self._selected_id: str | None = None
self._detail_view: str = "tree"
@@ -339,8 +339,7 @@ class Profiler(SingleInstance):
kwargs_obj = SimpleNamespace(**trace.kwargs) if trace.kwargs else SimpleNamespace()
kwargs_props = Properties(
self,
- obj=kwargs_obj,
- groups={"kwargs": {"*": ""}},
+ conf=PropertiesConf(obj=kwargs_obj, groups={"kwargs": {"*": ""}}),
_id="-detail-kwargs",
)
diff --git a/src/myfasthtml/controls/Properties.py b/src/myfasthtml/controls/Properties.py
index ebc751f..942c70d 100644
--- a/src/myfasthtml/controls/Properties.py
+++ b/src/myfasthtml/controls/Properties.py
@@ -24,22 +24,18 @@ class PropertiesConf:
class Properties(MultipleInstance):
- def __init__(self, parent, obj=None, groups: dict = None, conf: PropertiesConf = None, _id=None):
+ def __init__(self, parent, conf: PropertiesConf = None, _id=None):
super().__init__(parent, _id=_id)
- if conf is not None:
- self.obj = conf.obj
- self.groups = conf.groups
- self._types = conf.types or {}
- else:
- self.obj = obj
- self.groups = groups
- self._types = {}
- self.properties_by_group = self._create_properties_by_group()
+ self.conf = conf or PropertiesConf()
+ self._refresh()
- def set_obj(self, obj, groups: dict = None):
- self.obj = obj
- self.groups = groups
- self.properties_by_group = self._create_properties_by_group()
+ def set_conf(self, conf: PropertiesConf):
+ self.conf = conf
+ self._refresh()
+
+ def _refresh(self):
+ self._types = self.conf.types or {}
+ self._properties_by_group = self._create_properties_by_group()
def _mk_group_content(self, properties: dict):
return Div(
@@ -57,7 +53,7 @@ class Properties(MultipleInstance):
def _mk_property_value(self, value):
for t, renderer in self._types.items():
if isinstance(value, t):
- return renderer(value, self.obj)
+ return renderer(value, self.conf.obj)
if isinstance(value, dict):
return self._mk_group_content(value)
@@ -73,9 +69,9 @@ class Properties(MultipleInstance):
"""Render a group's content.
When the group contains exactly one property whose type is registered in
- ``_types``, the type renderer replaces the entire group content (not just
- the value cell). This lets custom renderers (e.g. span trees) fill the
- full card width without a key/value row wrapper.
+ ``conf.types``, the type renderer replaces the entire group content (not
+ just the value cell). This lets custom renderers (e.g. span trees) fill
+ the full card width without a key/value row wrapper.
Otherwise, the standard key/value row layout is used.
@@ -90,7 +86,7 @@ class Properties(MultipleInstance):
k, v = next(iter(properties.items()))
for t, renderer in self._types.items():
if isinstance(v, t):
- return renderer(v, self.obj)
+ return renderer(v, self.conf.obj)
return self._mk_group_content(properties)
def render(self):
@@ -104,17 +100,17 @@ class Properties(MultipleInstance):
),
cls="mf-properties-group-card"
)
- for group_name, proxy in self.properties_by_group.items()
+ for group_name, proxy in self._properties_by_group.items()
],
id=self._id,
cls="mf-properties"
)
def _create_properties_by_group(self):
- if self.groups is None:
- return {None: ProxyObject(self.obj, {"*": ""})}
+ if self.conf.groups is None:
+ return {None: ProxyObject(self.conf.obj, {"*": ""})}
- return {k: ProxyObject(self.obj, v) for k, v in self.groups.items()}
+ return {k: ProxyObject(self.conf.obj, v) for k, v in self.conf.groups.items()}
def __ft__(self):
return self.render()
diff --git a/src/myfasthtml/core/instances.py b/src/myfasthtml/core/instances.py
index 82f6b6d..6c4c91f 100644
--- a/src/myfasthtml/core/instances.py
+++ b/src/myfasthtml/core/instances.py
@@ -247,7 +247,7 @@ class InstancesManager:
"""
key = (InstancesManager.get_session_id(session), instance.get_id())
- if isinstance(instance, SingleInstance) and key in InstancesManager.instances:
+ if key in InstancesManager.instances and not isinstance(instance, UniqueInstance):
raise DuplicateInstanceError(instance)
InstancesManager.instances[key] = instance