diff --git a/menuflow/flow.py b/menuflow/flow.py index a80adf3..f264b1d 100644 --- a/menuflow/flow.py +++ b/menuflow/flow.py @@ -29,8 +29,13 @@ class Flow: nodes: Dict[str, Dict] middlewares: Dict[str, Dict] - def __init__(self, flow_mxid: str, flow_utils: Optional[FlowUtils] = None) -> None: - self.data = FlowModel.load_flow(flow_mxid=flow_mxid) + def __init__( + self, + flow_mxid: Optional[str] = None, + content: Optional[Dict] = None, + flow_utils: Optional[FlowUtils] = None, + ) -> None: + self.data = FlowModel.load_flow(flow_mxid=flow_mxid, content=content) self.nodes = self.data.get("nodes", []) self.middlewares = self.data.get("middlewares", []) self.nodes_by_id: Dict[str, Dict] = {} diff --git a/menuflow/repository/flow.py b/menuflow/repository/flow.py index 63ad68d..a4d196a 100644 --- a/menuflow/repository/flow.py +++ b/menuflow/repository/flow.py @@ -2,7 +2,7 @@ import logging from pathlib import Path -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional import yaml from attr import dataclass, ib @@ -23,20 +23,33 @@ class Flow(SerializableAttrs): flow_variables: Dict[str, Any] = ib(default={}) @classmethod - def load_flow(cls, flow_mxid: str) -> Flow: - path = Path("/data/flows") / f"{flow_mxid}.yaml" - if not path.exists(): - log.warning(f"File {flow_mxid}.yaml not found") - path.write_text(yaml.dump(Util.flow_example())) - log.warning( - f"Example flow {flow_mxid}.yaml file was generated. " - "Configure it and restart the service." - ) - - try: - flow: Dict = yaml.safe_load(path.read_text()) - except Exception as e: - log.exception(f"Error loading flow {flow_mxid}.yaml: {e}") - raise + def load_flow(cls, flow_mxid: Optional[str] = None, content: Optional[Dict] = None) -> Flow: + """ + Load a flow from a YAML file or from a dictionary. + + Args: + flow_mxid (Optional[str]): The mxid of the flow to load. + content (Optional[Dict]): The dictionary containing the flow. + + Returns: + Flow: The loaded flow. + """ + if flow_mxid: + path = Path("/data/flows") / f"{flow_mxid}.yaml" + if not path.exists(): + log.warning(f"File {flow_mxid}.yaml not found") + path.write_text(yaml.dump(Util.flow_example())) + log.warning( + f"Example flow {flow_mxid}.yaml file was generated. " + "Configure it and restart the service." + ) + + try: + flow: Dict = yaml.safe_load(path.read_text()) + except Exception as e: + log.exception(f"Error loading flow {flow_mxid}.yaml: {e}") + raise + elif content: + flow = content return cls(**flow["menu"]) diff --git a/test/conftest.py b/test/conftest.py index c4376ba..26d5101 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,3 +1,5 @@ +from unittest.mock import MagicMock + import pytest_asyncio from mautrix.client import Client from pytest_mock import MockerFixture @@ -19,7 +21,7 @@ async def config() -> Config: @pytest_asyncio.fixture async def sample_flow_1(config: Config) -> Flow: - flow = Flow(Util.flow_example(flow_index=0).get("menu")) + flow = Flow(content=Util.flow_example(flow_index=0)) for node in [Input, Location, Message, Switch]: node.config = config @@ -28,7 +30,7 @@ async def sample_flow_1(config: Config) -> Flow: @pytest_asyncio.fixture async def sample_flow_2(config: Config) -> Flow: - flow = Flow(Util.flow_example(flow_index=1).get("menu")) + flow = Flow(content=Util.flow_example(flow_index=1)) for node in [Input, Location, Message, Switch]: node.config = config @@ -36,12 +38,15 @@ async def sample_flow_2(config: Config) -> Flow: @pytest_asyncio.fixture -async def room(mocker: MockerFixture) -> Room: +async def room(mocker: MockerFixture, config: Config) -> Room: + Room.matrix_client = MagicMock() mocker.patch.object( Room, "update", ) - return Room(room_id="!foo:foo.com", node_id="start") + room = Room(room_id="!foo:foo.com", node_id="start") + room.config = config + return room @pytest_asyncio.fixture