Skip to content

Commit 49cabfa

Browse files
Related displays without files (#223)
* Added a try except for related displays without files * Modified to use techui-support remote screens * Added IOC macro to test files * reverted remote_screen to file * Adding new test widget * Added a condition to handle embedded screens * added a modified the exists flag got https screens * Fixed test * Removed unused function * Changed current_node, relative to paths to absolute by resolving
1 parent 2f86a73 commit 49cabfa

5 files changed

Lines changed: 92 additions & 51 deletions

File tree

src/techui_builder/builder.py

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ def _generate_json_map(
268268

269269
# Create initial node at top of .bob file
270270
current_node = JsonMap(
271-
str(screen_path.relative_to(self._write_directory)),
271+
str(screen_path.resolve().relative_to(self._write_directory.resolve())),
272272
display_name=None,
273273
)
274274

@@ -318,9 +318,7 @@ def _generate_json_map(
318318
macro_dict = self._get_macros(open_display)
319319

320320
case "embedded":
321-
file_elem = self._extract_action_button_file_from_embedded(
322-
widget_elem.file, dest_path
323-
)
321+
file_elem = widget_elem.file
324322
name_elem = widget_elem.name.text
325323
macro_dict = self._get_macros(widget_elem)
326324

@@ -359,14 +357,23 @@ def _generate_json_map(
359357
)
360358
else:
361359
child_node = JsonMap(
362-
str(file_path), display_name, exists=("IOC" in macro_dict)
360+
str(file_path),
361+
display_name,
362+
exists=("IOC" in macro_dict or ("https:/" in str(file_path))),
363363
)
364364

365-
child_node.macros = macro_dict
366-
# TODO: make this work for only list[JsonMap]
367-
assert isinstance(current_node.children, list)
368-
# TODO: fix typing
369-
current_node.children.append(child_node)
365+
if widget_type == "embedded":
366+
for embedded_child in child_node.children:
367+
embedded_child.macros = {**embedded_child.macros, **macro_dict}
368+
embedded_child.display_name = display_name
369+
current_node.children.append(embedded_child)
370+
371+
else:
372+
child_node.macros = macro_dict
373+
# TODO: make this work for only list[JsonMap]
374+
assert isinstance(current_node.children, list)
375+
# TODO: fix typing
376+
current_node.children.append(child_node)
370377

371378
except etree.ParseError as e:
372379
current_node.error = f"XML parse error: {e}"
@@ -410,34 +417,6 @@ def _get_component_label(
410417
display_name = child_labels[name_elem]
411418
return display_name
412419

413-
def _extract_action_button_file_from_embedded(
414-
self, file_elem: ObjectifiedElement, dest_path: Path
415-
) -> ObjectifiedElement:
416-
file_path = Path(file_elem.text.strip() if file_elem.text else "")
417-
file_path = dest_path.joinpath(file_path)
418-
if not file_path.exists():
419-
rel_file_path = Path(str(file_elem.base)).relative_to(
420-
dest_path.absolute(), walk_up=True
421-
)
422-
file_path = dest_path.joinpath(rel_file_path)
423-
tree = objectify.parse(file_path.absolute())
424-
root: ObjectifiedElement = tree.getroot()
425-
426-
# Find all <widget> elements
427-
widgets = [
428-
w
429-
for w in root.findall(".//widget")
430-
if w.get("type", default=None) == "action_button"
431-
]
432-
433-
for widget_elem in widgets:
434-
open_display = _get_action_group(widget_elem)
435-
if open_display is None:
436-
continue
437-
file_elem = open_display.file
438-
return file_elem
439-
return file_elem
440-
441420
def _get_macros(self, element: ObjectifiedElement):
442421
if hasattr(element, "macros"):
443422
macros = element.macros.getchildren()

src/techui_builder/generate.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,24 @@ def _allocate_widget(
193193
self, scrn_mapping: Mapping, component: Entity
194194
) -> EmbeddedDisplay | ActionButton | None | list[EmbeddedDisplay | ActionButton]:
195195
name, suffix, suffix_label = self._initialise_name_suffix(component)
196+
196197
# Get relative path to screen
197-
scrn_path = self.support_path.joinpath(f"bob/{scrn_mapping['file']}")
198-
logger_.debug(f"Screen path: {scrn_path}")
198+
file = scrn_mapping["file"]
199+
if file.startswith("$(IOC)"):
200+
scrn_path = data_scrn_path = file.replace(
201+
"$(IOC)", f"{self.beamline_url}/{component.service_name}"
202+
) # Only works with related displays as
203+
# embedded displays need to access the file to get dimensions
204+
205+
assert scrn_mapping["type"] == "related", (
206+
"Only related displays can have remote screens"
207+
)
208+
else:
209+
scrn_path = self.support_path.joinpath(f"bob/{file}")
210+
logger_.debug(f"Screen path: {scrn_path}")
199211

200-
# Path of screen relative to data/ so it knows where to open the file from
201-
data_scrn_path = scrn_path.relative_to(self.synoptic_dir, walk_up=True)
212+
# Path of screen relative to data/ so it knows where to open the file from
213+
data_scrn_path = scrn_path.relative_to(self.synoptic_dir, walk_up=True)
202214

203215
# For Gui Components with multiple components embedded, we add a suffix field
204216
# to the components, and adjust the name and suffix accordingly

tests/test_builder.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,15 @@ def test_generate_json_map(
317317

318318

319319
# TODO: write this test
320-
def test_generate_json_map_embedded_screen(
321-
builder_with_test_files, example_json_map, components
322-
):
320+
def test_generate_json_map_embedded_screen(builder_with_test_files, example_json_map):
323321
builder_with_test_files._get_component_label = Mock(
324-
side_effect=["Display", "Detector", "Embedded Display"]
322+
side_effect=[
323+
"Display",
324+
"Detector",
325+
"Embedded Display",
326+
"Embedded Display",
327+
"Embedded Display",
328+
]
325329
)
326330

327331
screen_path = Path("tests/test_files/test_bob_embedded.bob").absolute()
@@ -330,14 +334,14 @@ def test_generate_json_map_embedded_screen(
330334
example_json_map.file = "test_bob_embedded.bob"
331335
example_json_map.children.append(
332336
JsonMap(
333-
"$(IOC)/pmacAxis.pvi.bob", display_name="Embedded Display", exists=False
337+
"$(IOC)/pmacAxis.pvi.bob",
338+
display_name="Embedded Display",
339+
exists=False,
340+
macros={"M": "$(M)", "P": "$(P)"},
334341
)
335342
)
336343

337-
test_json_map = builder_with_test_files._generate_json_map(
338-
screen_path, dest_path, components
339-
)
340-
344+
test_json_map = builder_with_test_files._generate_json_map(screen_path, dest_path)
341345
assert test_json_map == example_json_map
342346

343347

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" ?>
2+
<widget type="action_button" version="2.0.0">
3+
<name>CAM</name>
4+
<x>0</x>
5+
<y>0</y>
6+
<width>100</width>
7+
<height>40</height>
8+
<pv_name/>
9+
<text>CAM</text>
10+
<actions>
11+
<action type="open_display">
12+
<description>Open Display</description>
13+
<macros>
14+
<P>BL01T-DI-IOC-01</P>
15+
<R>:CAM:</R>
16+
</macros>
17+
<file>test_url/bl01t-di-ioc-01/ADAravis_summary.bob</file>
18+
<target>tab</target>
19+
</action>
20+
</actions>
21+
</widget>

tests/test_generate.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,31 @@ def test_generator_allocate_widget(generator):
265265
assert str(widget) == xml_content
266266

267267

268+
def test_generator_allocate_widget_with_remote_screens(generator):
269+
generator._initilise_name_suffix = Mock(return_value=("CAM:", "CAM:", "R"))
270+
271+
scrn_mapping = {
272+
"file": "$(IOC)/ADAravis_summary.bob",
273+
"prefix": "$(P)$(R)",
274+
"type": "related",
275+
}
276+
component = Entity(
277+
service_name="bl01t-di-ioc-01",
278+
type="ADAravis.aravisCamera",
279+
P="BL01T-DI-IOC-01",
280+
desc=None,
281+
M=None,
282+
R=":CAM:",
283+
)
284+
widget = generator._allocate_widget(scrn_mapping, component)
285+
control_widget = Path("tests/test_files/widget_url_screen.xml")
286+
287+
with open(control_widget) as f:
288+
xml_content = f.read()
289+
print(str(widget))
290+
assert str(widget) == xml_content
291+
292+
268293
def test_generator_allocate_widget_with_suffix(generator):
269294
generator._initialise_name_suffix = Mock(return_value=(":CAM:", ":CAM:", "R"))
270295

0 commit comments

Comments
 (0)