Initial SFERA platform baseline
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# sfera-ui-semantics
|
||||
|
||||
UI structure helpers over SIR form, command, and element nodes.
|
||||
@@ -0,0 +1,11 @@
|
||||
[project]
|
||||
name = "sfera-ui-semantics"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"pydantic>=2.0",
|
||||
"sfera-sir",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
package = true
|
||||
@@ -0,0 +1,46 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from sir import EdgeKind, NodeKind, SemanticNode, SirSnapshot
|
||||
|
||||
|
||||
class FormSemantics(BaseModel):
|
||||
form: SemanticNode
|
||||
commands: list[SemanticNode] = Field(default_factory=list)
|
||||
elements: list[SemanticNode] = Field(default_factory=list)
|
||||
command_handlers: dict[str, SemanticNode] = Field(default_factory=dict)
|
||||
|
||||
|
||||
def form_semantics(snapshot: SirSnapshot) -> list[FormSemantics]:
|
||||
nodes = {node.lineage_id: node for node in snapshot.nodes}
|
||||
forms = {
|
||||
node.lineage_id: FormSemantics(form=node)
|
||||
for node in snapshot.nodes
|
||||
if node.kind == NodeKind.FORM
|
||||
}
|
||||
for edge in snapshot.edges:
|
||||
form = forms.get(edge.source_lineage)
|
||||
target = nodes.get(edge.target_lineage)
|
||||
if form is None or target is None:
|
||||
continue
|
||||
if edge.kind == EdgeKind.HAS_COMMAND:
|
||||
form.commands.append(target)
|
||||
elif edge.kind == EdgeKind.HAS_ELEMENT:
|
||||
form.elements.append(target)
|
||||
command_to_form = {
|
||||
command.lineage_id: form
|
||||
for form in forms.values()
|
||||
for command in form.commands
|
||||
}
|
||||
for edge in snapshot.edges:
|
||||
if edge.kind != EdgeKind.HANDLES:
|
||||
continue
|
||||
form = command_to_form.get(edge.source_lineage)
|
||||
handler = nodes.get(edge.target_lineage)
|
||||
if form is not None and handler is not None:
|
||||
form.command_handlers[edge.source_lineage] = handler
|
||||
return sorted(forms.values(), key=lambda item: item.form.qualified_name)
|
||||
|
||||
|
||||
__all__ = ["FormSemantics", "form_semantics"]
|
||||
@@ -0,0 +1,56 @@
|
||||
from sir import EdgeKind, NodeKind, SemanticEdge, SemanticNode, SirSnapshot, SourceRef
|
||||
from ui_semantics import form_semantics
|
||||
|
||||
|
||||
def test_form_semantics_groups_commands_and_elements():
|
||||
form = SemanticNode(
|
||||
semantic_id="form.main",
|
||||
lineage_id="lineage.form.main",
|
||||
kind=NodeKind.FORM,
|
||||
name="ФормаДокумента",
|
||||
qualified_name="Документ.Заказ.ФормаДокумента",
|
||||
source_ref=SourceRef(source_path="form.xml"),
|
||||
)
|
||||
command = SemanticNode(
|
||||
semantic_id="command.post",
|
||||
lineage_id="lineage.command.post",
|
||||
kind=NodeKind.COMMAND,
|
||||
name="Провести",
|
||||
qualified_name="Документ.Заказ.ФормаДокумента.Провести",
|
||||
source_ref=SourceRef(source_path="form.xml"),
|
||||
)
|
||||
snapshot = SirSnapshot(
|
||||
snapshot_id="snapshot.ui",
|
||||
project_id="demo",
|
||||
nodes=[
|
||||
form,
|
||||
command,
|
||||
SemanticNode(
|
||||
semantic_id="procedure.post",
|
||||
lineage_id="lineage.procedure.post",
|
||||
kind=NodeKind.PROCEDURE,
|
||||
name="ПровестиКоманда",
|
||||
qualified_name="Module.ПровестиКоманда",
|
||||
source_ref=SourceRef(source_path="module.bsl"),
|
||||
),
|
||||
],
|
||||
edges=[
|
||||
SemanticEdge(
|
||||
edge_id="edge.command",
|
||||
kind=EdgeKind.HAS_COMMAND,
|
||||
source_lineage=form.lineage_id,
|
||||
target_lineage=command.lineage_id,
|
||||
),
|
||||
SemanticEdge(
|
||||
edge_id="edge.handler",
|
||||
kind=EdgeKind.HANDLES,
|
||||
source_lineage=command.lineage_id,
|
||||
target_lineage="lineage.procedure.post",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
forms = form_semantics(snapshot)
|
||||
|
||||
assert forms[0].commands[0].name == "Провести"
|
||||
assert forms[0].command_handlers[command.lineage_id].name == "ПровестиКоманда"
|
||||
Reference in New Issue
Block a user