Fixed FormattingRules not being applied
This commit is contained in:
@@ -220,7 +220,10 @@ class DataGrid(MultipleInstance):
|
||||
name, namespace = (conf.name, conf.namespace) if conf else ("No name", "__default__")
|
||||
self._settings = DatagridSettings(self, save_state=save_state, name=name, namespace=namespace)
|
||||
self._state = DatagridState(self, save_state=self._settings.save_state)
|
||||
self._formatting_engine = FormattingEngine()
|
||||
self._formatting_provider = DatagridMetadataProvider(self._parent)
|
||||
self._formatting_engine = FormattingEngine(
|
||||
rule_presets_provider=lambda: self._formatting_provider.rule_presets
|
||||
)
|
||||
self._columns = None
|
||||
self.commands = Commands(self)
|
||||
|
||||
@@ -268,8 +271,7 @@ class DataGrid(MultipleInstance):
|
||||
# self._columns_manager.bind_command("SaveColumnDetails", self.commands.on_column_changed())
|
||||
|
||||
if self._settings.enable_formatting:
|
||||
provider = DatagridMetadataProvider(self._parent)
|
||||
completion_engine = FormattingCompletionEngine(provider, self.get_table_name())
|
||||
completion_engine = FormattingCompletionEngine(self._formatting_provider, self.get_table_name())
|
||||
editor_conf = DslEditorConf(engine_id=completion_engine.get_id())
|
||||
dsl = FormattingDSL()
|
||||
self._formatting_editor = DataGridFormattingEditor(self,
|
||||
|
||||
@@ -140,7 +140,7 @@ class HierarchicalCanvasGraph(MultipleInstance):
|
||||
self._query.bind_command("CancelQuery", self.commands.apply_filter())
|
||||
|
||||
# Add Menu
|
||||
self._menu = Menu(self, conf=MenuConf(["ResetView"]))
|
||||
self._menu = Menu(self, conf=MenuConf(["ResetView"]), _id="-menu")
|
||||
|
||||
logger.debug(f"HierarchicalCanvasGraph created with id={self._id}, "
|
||||
f"nodes={len(conf.nodes)}, edges={len(conf.edges)}")
|
||||
|
||||
@@ -15,12 +15,12 @@ from myfasthtml.core.formatting.dataclasses import RulePreset
|
||||
from myfasthtml.core.formatting.presets import (
|
||||
DEFAULT_FORMATTER_PRESETS, DEFAULT_STYLE_PRESETS, DEFAULT_RULE_PRESETS,
|
||||
)
|
||||
from myfasthtml.core.instances import SingleInstance, InstancesManager
|
||||
from myfasthtml.core.instances import UniqueInstance, InstancesManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DatagridMetadataProvider(SingleInstance, BaseMetadataProvider):
|
||||
class DatagridMetadataProvider(UniqueInstance, BaseMetadataProvider):
|
||||
"""Concrete session-scoped metadata provider for DataGrid DSL engines.
|
||||
|
||||
Implements BaseMetadataProvider by delegating live data queries to
|
||||
@@ -36,8 +36,7 @@ class DatagridMetadataProvider(SingleInstance, BaseMetadataProvider):
|
||||
all_tables_formats: Global format rules applied to all tables.
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None, session: Optional[dict] = None,
|
||||
_id: Optional[str] = None):
|
||||
def __init__(self, parent=None, session: Optional[dict] = None, _id: Optional[str] = None):
|
||||
super().__init__(parent, session, _id)
|
||||
self.style_presets: dict = DEFAULT_STYLE_PRESETS.copy()
|
||||
self.formatter_presets: dict = DEFAULT_FORMATTER_PRESETS.copy()
|
||||
|
||||
@@ -31,7 +31,8 @@ class FormattingEngine:
|
||||
style_presets: dict = None,
|
||||
formatter_presets: dict = None,
|
||||
rule_presets: dict = None,
|
||||
lookup_resolver: Callable[[str, str, str], dict] = None
|
||||
lookup_resolver: Callable[[str, str, str], dict] = None,
|
||||
rule_presets_provider: Callable[[], dict] = None,
|
||||
):
|
||||
"""
|
||||
Initialize the FormattingEngine.
|
||||
@@ -41,11 +42,20 @@ class FormattingEngine:
|
||||
formatter_presets: Custom formatter presets. If None, uses defaults.
|
||||
rule_presets: Named rule presets (list of FormatRule dicts). If None, uses defaults.
|
||||
lookup_resolver: Function for resolving enum datagrid sources.
|
||||
rule_presets_provider: Callable returning the current rule_presets dict.
|
||||
When provided, takes precedence over rule_presets on every apply_format call.
|
||||
Use this to keep the engine in sync with a shared provider.
|
||||
"""
|
||||
self._condition_evaluator = ConditionEvaluator()
|
||||
self._style_resolver = StyleResolver(style_presets)
|
||||
self._formatter_resolver = FormatterResolver(formatter_presets, lookup_resolver)
|
||||
self._rule_presets = rule_presets if rule_presets is not None else DEFAULT_RULE_PRESETS
|
||||
self._rule_presets_provider = rule_presets_provider
|
||||
|
||||
def _get_rule_presets(self) -> dict:
|
||||
if self._rule_presets_provider is not None:
|
||||
return self._rule_presets_provider()
|
||||
return self._rule_presets
|
||||
|
||||
def apply_format(
|
||||
self,
|
||||
@@ -99,8 +109,8 @@ class FormattingEngine:
|
||||
"""
|
||||
Replace any FormatRule that references a rule preset with the preset's rules.
|
||||
|
||||
A rule is a rule preset reference when its formatter has a preset name
|
||||
that exists in rule_presets (and not in formatter_presets).
|
||||
A rule is a rule preset reference when its formatter or style has a preset name
|
||||
that exists in rule_presets.
|
||||
|
||||
Args:
|
||||
rules: Original list of FormatRule
|
||||
@@ -108,22 +118,26 @@ class FormattingEngine:
|
||||
Returns:
|
||||
Expanded list with preset references replaced by their FormatRules
|
||||
"""
|
||||
rule_presets = self._get_rule_presets()
|
||||
expanded = []
|
||||
for rule in rules:
|
||||
preset_name = self._get_rule_preset_name(rule)
|
||||
preset_name = self._get_rule_preset_name(rule, rule_presets)
|
||||
if preset_name:
|
||||
expanded.extend(self._rule_presets[preset_name].rules)
|
||||
expanded.extend(rule_presets[preset_name].rules)
|
||||
else:
|
||||
expanded.append(rule)
|
||||
return expanded
|
||||
|
||||
def _get_rule_preset_name(self, rule: FormatRule) -> str | None:
|
||||
"""Return the preset name if the rule's formatter references a rule preset, else None."""
|
||||
if rule.formatter is None:
|
||||
return None
|
||||
preset = getattr(rule.formatter, "preset", None)
|
||||
if preset and preset in self._rule_presets:
|
||||
return preset
|
||||
|
||||
def _get_rule_preset_name(self, rule: FormatRule, rule_presets: dict) -> str | None:
|
||||
"""Return the preset name if the rule references a rule preset via format() or style(), else None."""
|
||||
if rule.formatter is not None:
|
||||
preset = getattr(rule.formatter, "preset", None)
|
||||
if preset and preset in rule_presets:
|
||||
return preset
|
||||
if rule.style is not None:
|
||||
preset = getattr(rule.style, "preset", None)
|
||||
if preset and preset in rule_presets:
|
||||
return preset
|
||||
return None
|
||||
|
||||
def _get_matching_rules(
|
||||
|
||||
@@ -5,7 +5,7 @@ from typing import Optional, Literal
|
||||
from myfasthtml.controls.helpers import Ids
|
||||
from myfasthtml.core.commands import BoundCommand, Command
|
||||
from myfasthtml.core.constants import NO_DEFAULT_VALUE
|
||||
from myfasthtml.core.utils import pascal_to_snake, get_class, snake_to_pascal
|
||||
from myfasthtml.core.utils import pascal_to_snake, get_class, snake_to_pascal, debug_session
|
||||
|
||||
VERBOSE_VERBOSE = False
|
||||
|
||||
@@ -36,7 +36,13 @@ class BaseInstance:
|
||||
session = args[1] if len(args) > 1 and isinstance(args[1], dict) else kwargs.get("session", None)
|
||||
_id = args[2] if len(args) > 2 and isinstance(args[2], str) else kwargs.get("_id", None)
|
||||
if VERBOSE_VERBOSE:
|
||||
logger.debug(f" parent={parent}, session={session}, _id={_id}")
|
||||
logger.debug(f" parent={parent}, session={debug_session(session)}, _id={_id}")
|
||||
|
||||
# for UniqueInstance, the parent is always the ultimate root parent
|
||||
if issubclass(cls, UniqueInstance):
|
||||
parent = BaseInstance.get_ultimate_root_parent(parent)
|
||||
if VERBOSE_VERBOSE:
|
||||
logger.debug(f" UniqueInstance detected. parent is set to ultimate root {parent=}")
|
||||
|
||||
# Compute _id
|
||||
_id = cls.compute_id(_id, parent)
|
||||
@@ -163,7 +169,7 @@ class BaseInstance:
|
||||
def compute_id(cls, _id: Optional[str], parent: Optional['BaseInstance']):
|
||||
if _id is None:
|
||||
prefix = cls.compute_prefix()
|
||||
if issubclass(cls, SingleInstance):
|
||||
if issubclass(cls, (SingleInstance, UniqueInstance)):
|
||||
_id = prefix
|
||||
else:
|
||||
_id = f"{prefix}-{str(uuid.uuid4())}"
|
||||
@@ -173,6 +179,17 @@ class BaseInstance:
|
||||
return f"{parent.get_id()}{_id}"
|
||||
|
||||
return _id
|
||||
|
||||
@staticmethod
|
||||
def get_ultimate_root_parent(instance):
|
||||
if instance is None:
|
||||
return None
|
||||
|
||||
parent = instance
|
||||
while True:
|
||||
if parent.get_parent() is None:
|
||||
return parent
|
||||
parent = parent.get_parent()
|
||||
|
||||
|
||||
class SingleInstance(BaseInstance):
|
||||
@@ -200,7 +217,7 @@ class UniqueInstance(BaseInstance):
|
||||
_id: Optional[str] = None,
|
||||
auto_register: bool = True,
|
||||
on_init=None):
|
||||
super().__init__(parent, session, _id, auto_register)
|
||||
super().__init__(BaseInstance.get_ultimate_root_parent(parent), session, _id, auto_register)
|
||||
if on_init is not None:
|
||||
on_init()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user