Initial SFERA platform baseline
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# sfera-transaction-topology
|
||||
|
||||
Deterministic transaction write topology derived from SIR `WRITES` edges.
|
||||
@@ -0,0 +1,11 @@
|
||||
[project]
|
||||
name = "sfera-transaction-topology"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"pydantic>=2.0",
|
||||
"sfera-sir",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
package = true
|
||||
@@ -0,0 +1,62 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from sir import EdgeKind, SemanticNode, SirSnapshot
|
||||
|
||||
|
||||
class TransactionWriteSet(BaseModel):
|
||||
routine: SemanticNode
|
||||
writes: list[SemanticNode] = Field(default_factory=list)
|
||||
|
||||
|
||||
class TransactionTargetWriters(BaseModel):
|
||||
target: SemanticNode
|
||||
routines: list[SemanticNode] = Field(default_factory=list)
|
||||
|
||||
|
||||
def transaction_write_sets(snapshot: SirSnapshot) -> list[TransactionWriteSet]:
|
||||
nodes = {node.lineage_id: node for node in snapshot.nodes}
|
||||
result: dict[str, TransactionWriteSet] = {}
|
||||
for edge in snapshot.edges:
|
||||
if edge.kind != EdgeKind.WRITES:
|
||||
continue
|
||||
routine = nodes.get(edge.source_lineage)
|
||||
target = nodes.get(edge.target_lineage)
|
||||
if routine is None or target is None:
|
||||
continue
|
||||
result.setdefault(routine.lineage_id, TransactionWriteSet(routine=routine)).writes.append(target)
|
||||
write_sets = list(result.values())
|
||||
write_sets.sort(key=lambda item: item.routine.qualified_name)
|
||||
return write_sets
|
||||
|
||||
|
||||
def transaction_targets(snapshot: SirSnapshot) -> list[TransactionTargetWriters]:
|
||||
result: dict[str, TransactionTargetWriters] = {}
|
||||
for write_set in transaction_write_sets(snapshot):
|
||||
for target in write_set.writes:
|
||||
result.setdefault(target.lineage_id, TransactionTargetWriters(target=target)).routines.append(write_set.routine)
|
||||
targets = list(result.values())
|
||||
targets.sort(key=lambda item: item.target.qualified_name)
|
||||
return targets
|
||||
|
||||
|
||||
def routines_touching_target(snapshot: SirSnapshot, target_name: str) -> list[SemanticNode]:
|
||||
wanted = target_name.casefold()
|
||||
routines: list[SemanticNode] = []
|
||||
for write_set in transaction_write_sets(snapshot):
|
||||
if any(
|
||||
target.name.casefold() == wanted or target.qualified_name.casefold() == wanted
|
||||
for target in write_set.writes
|
||||
):
|
||||
routines.append(write_set.routine)
|
||||
return routines
|
||||
|
||||
|
||||
__all__ = [
|
||||
"TransactionTargetWriters",
|
||||
"TransactionWriteSet",
|
||||
"routines_touching_target",
|
||||
"transaction_targets",
|
||||
"transaction_write_sets",
|
||||
]
|
||||
@@ -0,0 +1,46 @@
|
||||
from pathlib import Path
|
||||
|
||||
from semantic_kernel import index_project
|
||||
from transaction_topology import routines_touching_target, transaction_targets, transaction_write_sets
|
||||
|
||||
|
||||
def test_transaction_write_sets_find_register_writes(tmp_path: Path):
|
||||
module = tmp_path / "demo_module.bsl"
|
||||
module.write_text(
|
||||
"""
|
||||
Процедура Проведение()
|
||||
Движения.ОстаткиТоваров.Записать();
|
||||
КонецПроцедуры
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
snapshot = index_project(tmp_path, project_id="demo")
|
||||
|
||||
write_sets = transaction_write_sets(snapshot)
|
||||
|
||||
assert write_sets[0].routine.name == "Проведение"
|
||||
assert write_sets[0].writes[0].name == "ОстаткиТоваров"
|
||||
assert routines_touching_target(snapshot, "ОстаткиТоваров")[0].name == "Проведение"
|
||||
|
||||
|
||||
def test_transaction_targets_group_multiple_writers_by_register(tmp_path: Path):
|
||||
module = tmp_path / "demo_module.bsl"
|
||||
module.write_text(
|
||||
"""
|
||||
Процедура Проведение()
|
||||
Движения.ОстаткиТоваров.Записать();
|
||||
КонецПроцедуры
|
||||
|
||||
Процедура Корректировка()
|
||||
Набор = РегистрыНакопления.ОстаткиТоваров.СоздатьНаборЗаписей();
|
||||
Набор.Записать();
|
||||
КонецПроцедуры
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
snapshot = index_project(tmp_path, project_id="transaction-targets")
|
||||
|
||||
targets = transaction_targets(snapshot)
|
||||
|
||||
assert [target.target.qualified_name for target in targets] == ["РегистрНакопления.ОстаткиТоваров"]
|
||||
assert {routine.name for routine in targets[0].routines} == {"Проведение", "Корректировка"}
|
||||
Reference in New Issue
Block a user