diff --git a/example/t01-services/synoptic/JsonMap.json b/example/t01-services/synoptic/JsonMap.json index 061b331b..bc0895cf 100644 --- a/example/t01-services/synoptic/JsonMap.json +++ b/example/t01-services/synoptic/JsonMap.json @@ -5,12 +5,12 @@ "file": "dcam1.bob", "children": [ { - "file": "ProfileCursorGraphs.bob", + "file": "techui-support/bob/ADAravis/ProfileCursorGraphs.bob", "macros": { "P": "BL01T-DI-CAM-01", "R": ":CAM:", "label": "CAM", - "IOC": "https://t01-opis.diamond.ac.uk/bl01t-di-cam-01" + "IOC": "../../../../bl01t-di-cam-01" }, "displayName": "CAM" }, @@ -72,7 +72,7 @@ "M": ":X", "P": "BL01T-MO-MOTOR-01", "label": "X1", - "IOC": "https://t01-opis.diamond.ac.uk/bl01t-mo-motor-01" + "IOC": "../../../../bl01t-mo-motor-01" }, "displayName": "X1" }, @@ -82,7 +82,7 @@ "M": ":A", "P": "BL01T-MO-MOTOR-01", "label": "A", - "IOC": "https://t01-opis.diamond.ac.uk/bl01t-mo-motor-01" + "IOC": "../../../../bl01t-mo-motor-01" }, "displayName": "A" }, diff --git a/example/t01-services/synoptic/dcam1.bob b/example/t01-services/synoptic/dcam1.bob index 12797766..ab720dd9 100644 --- a/example/t01-services/synoptic/dcam1.bob +++ b/example/t01-services/synoptic/dcam1.bob @@ -16,7 +16,7 @@

BL01T-DI-CAM-01

:CAM: - https://t01-opis.diamond.ac.uk/bl01t-di-cam-01 + ../../../../bl01t-di-cam-01 0 0 diff --git a/example/t01-services/synoptic/motor1.bob b/example/t01-services/synoptic/motor1.bob index e4abe216..2d93162d 100644 --- a/example/t01-services/synoptic/motor1.bob +++ b/example/t01-services/synoptic/motor1.bob @@ -13,10 +13,10 @@ 120 techui-support/bob/pmac/motor_embed.bob -

BL01T-MO-MOTOR-01

:X +

BL01T-MO-MOTOR-01

- https://t01-opis.diamond.ac.uk/bl01t-mo-motor-01 + ../../../../bl01t-mo-motor-01
0 0 @@ -27,10 +27,10 @@ 120 techui-support/bob/pmac/motor_embed.bob -

BL01T-MO-MOTOR-01

:A +

BL01T-MO-MOTOR-01

- https://t01-opis.diamond.ac.uk/bl01t-mo-motor-01 + ../../../../bl01t-mo-motor-01
0 150 diff --git a/src/techui_builder/generate.py b/src/techui_builder/generate.py index fbb3f456..ca472230 100644 --- a/src/techui_builder/generate.py +++ b/src/techui_builder/generate.py @@ -183,6 +183,12 @@ def _update_macros(self, component: Entity) -> tuple[str, dict[str, str]]: return component_name, new_macros + def resolve_service_dir(self, service_name: str, screen_dir: Path) -> str: + """A service's screen directory, relative to the screen linking to it.""" + # Service directories sit alongside the synoptic directory, not inside it + service_dir = self.synoptic_dir.resolve().parent / service_name + return str(service_dir.relative_to(screen_dir.resolve(), walk_up=True)) + def _allocate_widget( self, screen_mapping: SupportEntityScreen, component: Entity ) -> EmbeddedDisplay | ActionButton | None | list[EmbeddedDisplay | ActionButton]: @@ -193,7 +199,8 @@ def _allocate_widget( file = Template(screen_mapping.file).render(component.macros) if file.startswith("$(IOC)"): screen_path = support_screen_path = file.replace( - "$(IOC)", f"{self.beamline_url}/{component.service_name}" + "$(IOC)", + self.resolve_service_dir(component.service_name, self.synoptic_dir), ) # Only works with related displays as # embedded displays need to access the file to get dimensions @@ -252,7 +259,12 @@ def _allocate_widget( # TODO: Change this to pvi_button if True: - new_widget.macro("IOC", f"{self.beamline_url}/{component.service_name}") + new_widget.macro( + "IOC", + self.resolve_service_dir( + component.service_name, Path(screen_path).parent + ), + ) # The only other option is for related displays else: diff --git a/src/techui_builder/generate_jsonmap.py b/src/techui_builder/generate_jsonmap.py index 3fc3c936..5ebc9c03 100644 --- a/src/techui_builder/generate_jsonmap.py +++ b/src/techui_builder/generate_jsonmap.py @@ -72,7 +72,6 @@ def __post_init__(self): def generate_json_map( self, screen_path: Path, - dest_path: Path, current_component_name: str | None = None, name_elem: str | None = None, ) -> ScreenNode: @@ -80,9 +79,8 @@ def generate_json_map( ctx = CrawlContext( components=self.techui_yaml.components, synoptic_dir=self._parent_path, - link_base_dir=dest_path, component_name=current_component_name, - service_name="", + screen=screen_path, ) return crawl(screen_path, ctx, link_name=name_elem) @@ -95,7 +93,7 @@ def write_json_map( f"Cannot generate json map for {self.bob_path}. Has it been generated?" ) - json_map = self.generate_json_map(self.bob_path, self._parent_path) + json_map = self.generate_json_map(self.bob_path) with open(self._write_directory / "JsonMap.json", "w") as f: f.write( json.dumps(json_map, indent=4, default=lambda o: serialise_node(o)) diff --git a/src/techui_builder/jsonmap/crawl.py b/src/techui_builder/jsonmap/crawl.py index 3ca47672..53d46425 100644 --- a/src/techui_builder/jsonmap/crawl.py +++ b/src/techui_builder/jsonmap/crawl.py @@ -1,18 +1,17 @@ """Recursively crawl a tree of .bob screens into a tree of ScreenNodes.""" +import logging from collections.abc import Mapping -from dataclasses import dataclass, replace +from dataclasses import dataclass, field, replace from pathlib import Path from lxml import etree, objectify -from lxml.objectify import ObjectifiedElement from techui_builder.jsonmap.links import ( WidgetLink, - WidgetType, - assumed_exists, extract_links, - find_local_screen, + resolve_link, + substitute_macros, ) from techui_builder.jsonmap.naming import ( find_techui_label, @@ -21,6 +20,9 @@ ) from techui_builder.jsonmap.nodes import ScreenNode from techui_builder.models import Component +from techui_builder.utils import WidgetType + +logger_ = logging.getLogger(__name__) @dataclass @@ -29,23 +31,30 @@ class CrawlContext: components: Mapping[str, Component] synoptic_dir: Path # ScreenNode.file is relative to this - link_base_dir: Path # link files are resolved against this; never changes component_name: str | None - service_name: str - - def with_screen_component(self, screen_path: Path) -> "CrawlContext": - """A copy for the screen's component, if it is one and none is set yet.""" - if self.component_name is not None or screen_path.stem not in self.components: - return self - - component_name = screen_path.stem - # We know from the if statement that it exists - component = self.components.get(component_name) - assert isinstance(component, Component) - # TODO: How to find the screens if PV prefix is not the service name??? - return replace( - self, component_name=component_name, service_name=component.prefix.lower() - ) + screen: Path # the screen being crawled + macros: dict[str, str] = field(default_factory=dict) # including inherited ones + + def with_screen(self, screen: Path) -> "CrawlContext": + """A copy for crawling a screen's links, in its component if it names one.""" + component_name = self.component_name + if component_name is None and screen.stem in self.components: + component_name = screen.stem + + return replace(self, screen=screen, component_name=component_name) + + +def format_screen(screen: Path, synoptic_dir: Path) -> str: + """The screen's path, relative to the synoptic directory.""" + return str(screen.resolve().relative_to(synoptic_dir.resolve(), walk_up=True)) + + +def inherit_macros( + parent_macros: Mapping[str, str], macros: Mapping[str, str] +) -> dict[str, str]: + """The parent's macros overridden by a link's macros, expanded like Phoebus.""" + expanded = {k: substitute_macros(v, parent_macros) for k, v in macros.items()} + return {**parent_macros, **expanded} def crawl_link( @@ -57,42 +66,43 @@ def crawl_link( If it can't be found, a leaf ScreenNode is returned. """ - local_path = find_local_screen(link.file, ctx.link_base_dir, ctx.service_name) + macros = inherit_macros(ctx.macros, link.macros) + screen = resolve_link(link.file, macros, ctx.screen) + + if not screen.is_file(): + logger_.debug(f"Link {link.file} -> {screen}: not found") + return ScreenNode( + format_screen(screen, ctx.synoptic_dir), + display_name, + exists=False, + macros=macros, + ) + + logger_.debug(f"Link {link.file} -> {screen}: found") # Crawl the next file - if local_path is not None: - # TODO: investigate non-recursive approaches? - return crawl(local_path, ctx, link_name=link.name) - - return ScreenNode( - link.file, - display_name, - exists=assumed_exists(link.file, link.macros), - ) + # TODO: investigate non-recursive approaches? + node = crawl(screen, replace(ctx, macros=macros), link_name=link.name) + node.macros = macros + return node -def crawl( - screen_path: Path, ctx: CrawlContext, link_name: str | None = None -) -> ScreenNode: +def crawl(screen: Path, ctx: CrawlContext, link_name: str | None = None) -> ScreenNode: """Crawl a .bob screen and the screens it links to into a ScreenNode.""" # Create initial node at top of .bob file current_node = ScreenNode( - str( - screen_path.resolve().relative_to(ctx.synoptic_dir.resolve(), walk_up=True) - ), - display_name=None, + format_screen(screen, ctx.synoptic_dir), display_name=None ) - ctx = ctx.with_screen_component(screen_path) + ctx = ctx.with_screen(screen) try: # Create xml tree from .bob file - tree = objectify.parse(screen_path.absolute()) - root: ObjectifiedElement = tree.getroot() + root = objectify.parse(screen.absolute()).getroot() # Label for the linking widget, else the screen's own , else file stem - own_name = name_or_file_stem(root.name.text, screen_path) + own_name = name_or_file_stem(root.name.text, screen) label = find_techui_label(ctx.components, ctx.component_name, link_name) current_node.display_name = label if label is not None else own_name @@ -107,15 +117,10 @@ def crawl( if link.type == WidgetType.EMBEDDED: for embedded_child in child_node.children: - embedded_child.macros = {**embedded_child.macros, **link.macros} embedded_child.display_name = display_name - embedded_child.exists = "IOC" in link.macros or ( - "https://" in str(embedded_child.file) - ) current_node.children.append(embedded_child) else: - child_node.macros = link.macros # TODO: make this work for only list[ScreenNode] assert isinstance(current_node.children, list) # TODO: fix typing diff --git a/src/techui_builder/jsonmap/links.py b/src/techui_builder/jsonmap/links.py index 7184dabf..070e6bc5 100644 --- a/src/techui_builder/jsonmap/links.py +++ b/src/techui_builder/jsonmap/links.py @@ -1,5 +1,6 @@ """Links from a .bob screen to other screens.""" +import logging import re from collections.abc import Iterator, Mapping from dataclasses import dataclass @@ -14,7 +15,9 @@ _get_nav_tabs, ) -PVI_FILE_RE = re.compile(r"^(?:\$\(IOC\))\/([a-zA-Z]+[.a-zA-Z]+)$") +logger_ = logging.getLogger(__name__) + +MACRO_RE = re.compile(r"\$(?:\((\w+)\)|\{(\w+)\})") @dataclass @@ -29,13 +32,13 @@ class WidgetLink: def extract_file_text(file_elem: ObjectifiedElement) -> str: """The stripped text of a element.""" - # Keep raw string to preserve urls + # Keep the raw string; macros are expanded later return file_elem.text.strip() if file_elem.text else "" def is_bob(file: str) -> bool: - """Whether the file is a .bob screen.""" - return Path(file).suffix == ".bob" + """Whether the link is to a .bob screen""" + return file.endswith(".bob") def extract_links(root: ObjectifiedElement) -> Iterator[WidgetLink]: @@ -82,6 +85,7 @@ def extract_links(root: ObjectifiedElement) -> Iterator[WidgetLink]: file = extract_file_text(file_elem) # Skip links that are not .bob screens if not is_bob(file): + logger_.debug(f"Skipping link to {file}: not a .bob screen") continue yield WidgetLink(file, name, widget_type, macros) @@ -95,29 +99,21 @@ def extract_links(root: ObjectifiedElement) -> Iterator[WidgetLink]: file = extract_file_text(file_elem) # Skip links that are not .bob screens if not is_bob(file): + logger_.debug(f"Skipping link to {file}: not a .bob screen") continue yield WidgetLink(file, name, widget_type, macros) -def resolve_link_path(file: str, base_dir: Path, service_name: str) -> Path: - """Resolve a link's file to a local path.""" - - match = PVI_FILE_RE.fullmatch(file) - # The file path is a PVI screen, so attempt to find that screen - if match: - file_name = match.group(1) - return base_dir / f"../{service_name}/{file_name}" - - return base_dir / file - - -def find_local_screen(file: str, base_dir: Path, service_name: str) -> Path | None: - """Resolve a link's file, returning the path if it can be crawled locally.""" - path = resolve_link_path(file, base_dir, service_name) - return path if path.is_file() else None +def substitute_macros(text: str, macros: Mapping[str, str]) -> str: + """Replace $(NAME) and ${NAME} with macro values, leaving unknown macros as-is.""" + return MACRO_RE.sub( + lambda m: macros.get(m.group(1) or m.group(2), m.group(0)), text + ) -def assumed_exists(file: str, macros: Mapping[str, str]) -> bool: - """Whether a link's file that could not be found locally is assumed to exist.""" - return "IOC" in macros or ("https:/" in file) +def resolve_link(file: str, macros: Mapping[str, str], screen: Path) -> Path: + """Resolve a link's file to a local path, relative to the linking screen.""" + file = substitute_macros(file, macros) + # Phoebus resolves relative files against the display containing the link + return screen.parent / file diff --git a/src/techui_builder/jsonmap/nodes.py b/src/techui_builder/jsonmap/nodes.py index 849f4f3c..8e964f4c 100644 --- a/src/techui_builder/jsonmap/nodes.py +++ b/src/techui_builder/jsonmap/nodes.py @@ -11,7 +11,6 @@ class ScreenNode: file: str display_name: str | None exists: bool = True - duplicate: bool = False children: list["ScreenNode"] = field(default_factory=list) macros: dict[str, str] = field(default_factory=dict) error: str = "" diff --git a/tests/conftest.py b/tests/conftest.py index 78fbfb5f..15b4e5e8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -16,6 +16,8 @@ from techui_builder.status import GenerateStatusPvs from techui_builder.validator import Validator +TESTS_DIR = Path(__file__).parent + @pytest.fixture def tmp_t01_services(tmp_path) -> Path: @@ -251,19 +253,17 @@ def example_json_map_pvi_screens(): file="motor1.bob", display_name="motor1", exists=True, - duplicate=False, children=[ ScreenNode( file="../bl01t-mo-motor-01/pmacAxis.pvi.bob", display_name="X1", exists=True, - duplicate=False, children=[], macros={ "M": ":X", "P": "BL01T-MO-MOTOR-01", "label": "X1", - "IOC": "https://t01-opis.diamond.ac.uk/bl01t-mo-motor-01", + "IOC": "../../../../bl01t-mo-motor-01", }, error="", ), @@ -271,13 +271,12 @@ def example_json_map_pvi_screens(): file="../bl01t-mo-motor-01/pmacAxis.pvi.bob", display_name="A", exists=True, - duplicate=False, children=[], macros={ "M": ":A", "P": "BL01T-MO-MOTOR-01", "label": "A", - "IOC": "https://t01-opis.diamond.ac.uk/bl01t-mo-motor-01", + "IOC": "../../../../bl01t-mo-motor-01", }, error="", ), @@ -285,7 +284,6 @@ def example_json_map_pvi_screens(): file="techui-support/bob/pmac/pmacController.bob", display_name="pmacController", exists=True, - duplicate=False, children=[], macros={"P": "BL01T-MO-BRICK-01"}, error="", @@ -511,7 +509,7 @@ def example_pgen_embedded_widget(): embedded_widget.macro("P", "BL01T-DI-IOC-01") embedded_widget.macro("R", ":CAM:") embedded_widget.macro("label", "CAM") - embedded_widget.macro("IOC", "test_url/bl01t-di-ioc-01") + embedded_widget.macro("IOC", "../../../../bl01t-di-ioc-01") return embedded_widget diff --git a/tests/jsonmap/test_crawl.py b/tests/jsonmap/test_crawl.py index 3c89504d..2b18a823 100644 --- a/tests/jsonmap/test_crawl.py +++ b/tests/jsonmap/test_crawl.py @@ -3,8 +3,11 @@ import pytest from techui_builder.jsonmap.crawl import CrawlContext, crawl, crawl_link -from techui_builder.jsonmap.links import WidgetLink, WidgetType +from techui_builder.jsonmap.links import WidgetLink from techui_builder.jsonmap.nodes import ScreenNode +from techui_builder.utils import WidgetType + +MOTOR_IOC = "../bl01t-mo-motor-01" @pytest.fixture @@ -13,9 +16,8 @@ def t01_ctx(json_map_generator) -> CrawlContext: return CrawlContext( components=json_map_generator.techui_yaml.components, synoptic_dir=synoptic, - link_base_dir=synoptic, component_name=None, - service_name="", + screen=synoptic / "index.bob", ) @@ -38,8 +40,8 @@ def test_crawl_component_screen(t01_ctx): assert motor.display_name == "Motor Stage" assert [(c.file, c.display_name) for c in motor.children] == [ - ("../bl01t-mo-motor-01/pmacAxis.pvi.bob", "X1"), - ("../bl01t-mo-motor-01/pmacAxis.pvi.bob", "A"), + (f"{MOTOR_IOC}/pmacAxis.pvi.bob", "X1"), + (f"{MOTOR_IOC}/pmacAxis.pvi.bob", "A"), ("techui-support/bob/pmac/pmacController.bob", "pmacController"), ] @@ -61,12 +63,14 @@ def test_crawl_link(t01_ctx): assert missing == ScreenNode("missing.bob", "Missing", exists=False) -def test_with_screen_component(t01_ctx): - motor_ctx = t01_ctx.with_screen_component(Path("motor1.bob")) +def test_with_screen(t01_ctx): + motor_ctx = t01_ctx.with_screen(Path("motor1.bob")) - assert motor_ctx.component_name == "motor1" - assert motor_ctx.service_name == "bl01t-mo-motor-01" + assert (motor_ctx.screen, motor_ctx.component_name) == ( + Path("motor1.bob"), + "motor1", + ) # Not a component - assert t01_ctx.with_screen_component(Path("index.bob")) is t01_ctx + assert t01_ctx.with_screen(Path("index.bob")).component_name is None # Already inside a component - assert motor_ctx.with_screen_component(Path("dcam1.bob")) is motor_ctx + assert motor_ctx.with_screen(Path("dcam1.bob")).component_name == "motor1" diff --git a/tests/jsonmap/test_links.py b/tests/jsonmap/test_links.py index 47d3d46b..cb827e59 100644 --- a/tests/jsonmap/test_links.py +++ b/tests/jsonmap/test_links.py @@ -4,12 +4,11 @@ from techui_builder.jsonmap.links import ( WidgetLink, - WidgetType, - assumed_exists, extract_links, - find_local_screen, - resolve_link_path, + is_bob, + resolve_link, ) +from techui_builder.utils import WidgetType def button(name: str, *actions: str, widget_type="action_button") -> str: @@ -63,26 +62,26 @@ def test_extract_links(): ] -def test_resolve_link_path(): - dest = Path("/beamline/synoptic") - svc = "bl01t-mo-motor-01" +def test_resolve_link(): + screen = Path("/services/synoptic/techui-support/bob/slits/slit.bob") + macros = {"IOC": "../../../../bl01t-di-cam-01"} - assert resolve_link_path("sub/screen.bob", dest, svc) == dest / "sub/screen.bob" - assert ( - resolve_link_path("$(IOC)/Simple.pvi.bob", dest, svc) - == dest / f"../{svc}/Simple.pvi.bob" + # Local files are relative to the screen containing the link + assert resolve_link("../pmac/motor.bob", macros, screen) == Path( + "/services/synoptic/techui-support/bob/slits/../pmac/motor.bob" ) - - -def test_find_local_screen(tmp_path: Path): - (tmp_path / "screen.bob").touch() - - assert find_local_screen("screen.bob", tmp_path, "") == tmp_path / "screen.bob" - for file in ["missing.bob", "", "https://example.invalid/x/screen.bob"]: - assert find_local_screen(file, tmp_path, "") is None - - -def test_assumed_exists(): - assert assumed_exists("$(IOC)/x.pvi.bob", {"IOC": "https://example.invalid"}) - assert assumed_exists("https://example.invalid/x/screen.bob", {}) - assert not assumed_exists("missing.bob", {"P": "BL01T-MO-MOTOR-01"}) + # Macros are substituted, and unknown ones are left alone + service_screen = screen.parent / "../../../../bl01t-di-cam-01/ADUVC.pvi.bob" + assert resolve_link("$(IOC)/ADUVC.pvi.bob", macros, screen) == service_screen + assert resolve_link("${IOC}/ADUVC.pvi.bob", macros, screen) == service_screen + assert resolve_link("$(IOC)/x.bob", {}, screen) == screen.parent / "$(IOC)/x.bob" + + +def test_is_bob(): + assert is_bob("dcam1.bob") + assert is_bob("$(IOC)/dcam1.bob") + assert is_bob("../bl01t-di-cam-01/ADUVC.pvi.bob") + # Screens Phoebus can open but the builder does not crawl + assert not is_bob("dcam1.opi") + assert not is_bob("index.html") + assert not is_bob("") diff --git a/tests/jsonmap/test_nodes.py b/tests/jsonmap/test_nodes.py index b6560c7c..7cfd4b3e 100644 --- a/tests/jsonmap/test_nodes.py +++ b/tests/jsonmap/test_nodes.py @@ -22,7 +22,6 @@ def test_field_default(): "file": MISSING, "display_name": MISSING, "exists": True, - "duplicate": False, "children": [], "macros": {}, "error": "", diff --git a/tests/test_files/widget.xml b/tests/test_files/widget.xml index d0d7ac00..f91d87f9 100644 --- a/tests/test_files/widget.xml +++ b/tests/test_files/widget.xml @@ -10,6 +10,6 @@

BL01T-DI-IOC-01

:CAM: - test_url/bl01t-di-ioc-01 + ../../../../bl01t-di-ioc-01 diff --git a/tests/test_files/widget_url_screen.xml b/tests/test_files/widget_service_screen.xml similarity index 88% rename from tests/test_files/widget_url_screen.xml rename to tests/test_files/widget_service_screen.xml index 9def9f7d..7fecf82b 100644 --- a/tests/test_files/widget_url_screen.xml +++ b/tests/test_files/widget_service_screen.xml @@ -15,7 +15,7 @@ :CAM: - test_url/bl01t-di-ioc-01/ADUVC.pvi.bob + ../bl01t-di-ioc-01/ADUVC.pvi.bob tab diff --git a/tests/test_generate.py b/tests/test_generate.py index a30cdd23..69b2c275 100644 --- a/tests/test_generate.py +++ b/tests/test_generate.py @@ -240,7 +240,7 @@ def test_generator_allocate_widget(generator, tmp_test_files): assert str(widget) == xml_content -def test_generator_allocate_widget_with_remote_screens(generator, tmp_test_files): +def test_generator_allocate_widget_with_service_screens(generator, tmp_test_files): generator._update_macros = Mock( return_value=("CAM", {"P": "BL01T-DI-IOC-01", "R": ":CAM:", "label": "CAM"}) ) @@ -256,7 +256,7 @@ def test_generator_allocate_widget_with_remote_screens(generator, tmp_test_files macros={"P": "BL01T-DI-IOC-01", "R": ":CAM:"}, ) widget = generator._allocate_widget(scrn_mapping, component) - control_widget = tmp_test_files / "widget_url_screen.xml" + control_widget = tmp_test_files / "widget_service_screen.xml" with open(control_widget) as f: xml_content = f.read() diff --git a/tests/test_generate_jsonmap.py b/tests/test_generate_jsonmap.py index b64ef3e0..0899c2a0 100644 --- a/tests/test_generate_jsonmap.py +++ b/tests/test_generate_jsonmap.py @@ -67,7 +67,6 @@ def test_write_json_map(json_map_generator, tmp_test_files): def test_generate_json_map(json_map_generator_with_test_files, example_json_map): test_json_map = json_map_generator_with_test_files.generate_json_map( json_map_generator_with_test_files.bob_path, - json_map_generator_with_test_files._write_directory, ) assert test_json_map == example_json_map @@ -92,7 +91,6 @@ def test_generate_json_map_embedded_screen( test_json_map = json_map_generator_with_test_files.generate_json_map( json_map_generator_with_test_files.bob_path, - json_map_generator_with_test_files._write_directory, ) assert test_json_map == example_json_map @@ -114,7 +112,6 @@ def test_generate_json_map_nav_tabs( test_json_map = json_map_generator_with_test_files.generate_json_map( json_map_generator_with_test_files.bob_path, - json_map_generator_with_test_files._write_directory, ) assert test_json_map == example_json_map_root @@ -125,7 +122,6 @@ def test_generate_json_map_child_file_crawl_pvi_screen( ): jsonmap = json_map_generator.generate_json_map( screen_path=tmp_t01_services / "synoptic/motor1.bob", - dest_path=tmp_t01_services / "synoptic", ) assert example_json_map_pvi_screens == jsonmap @@ -150,7 +146,6 @@ def test_generate_json_map_get_macros( test_json_map = json_map_generator_with_test_files.generate_json_map( json_map_generator_with_test_files.bob_path, - json_map_generator_with_test_files._write_directory, ) assert test_json_map == example_json_map @@ -162,7 +157,6 @@ def test_generate_json_map_xml_parse_error( test_json_map = json_map_generator_with_test_files.generate_json_map( json_map_generator_with_test_files.bob_path, - json_map_generator_with_test_files._write_directory, ) assert test_json_map.error.startswith("XML parse error:") @@ -177,7 +171,6 @@ def test_generate_json_map_other_exception( test_json_map = json_map_generator_with_test_files.generate_json_map( json_map_generator_with_test_files.bob_path, - json_map_generator_with_test_files._write_directory, ) assert test_json_map.error != ""