Skip to content

Commit

Permalink
Merge pull request #257 from janezd/channels-by-id
Browse files Browse the repository at this point in the history
Refer to channels by ids, not their visible names when saving/loading
  • Loading branch information
janezd authored Jan 30, 2023
2 parents 26b1446 + 2c9209d commit 473d4d2
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 7 deletions.
2 changes: 1 addition & 1 deletion orangecanvas/registry/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
log = logging.getLogger(__name__)

# Registry hex version
VERSION_HEX = 0x000105
VERSION_HEX = 0x000106


class WidgetRegistry(object):
Expand Down
4 changes: 2 additions & 2 deletions orangecanvas/registry/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def small_testing_registry():
"zero", "zero", "Constants",
qualified_name="zero",
package=__package__,
outputs=[OutputSignal("value", "int")])
outputs=[OutputSignal("value", "int", id="val")])

one = WidgetDescription(
"one", "one", "Constants",
Expand All @@ -157,7 +157,7 @@ def small_testing_registry():
qualified_name="add",
package=__package__,
inputs=[InputSignal("left", "int", "set_left"),
InputSignal("right", "int", "set_right")],
InputSignal("right", "int", "set_right", id="droite")],
outputs=[OutputSignal("result", "int")]
)
sub = WidgetDescription(
Expand Down
12 changes: 10 additions & 2 deletions orangecanvas/scheme/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,14 @@ def input_channel(self, name):
Return the input channel matching `name`. Raise a `ValueError`
if not found.
"""
for channel in self.input_channels():
if channel.id == name:
return channel
# Fallback to channel names for backward compatibility
for channel in self.input_channels():
if channel.name == name:
return channel
raise ValueError("%r is not a valid input channel name for %r." % \
raise ValueError("%r is not a valid input channel for %r." % \
(name, self.description.name))

def output_channel(self, name):
Expand All @@ -145,10 +149,14 @@ def output_channel(self, name):
Return the output channel matching `name`. Raise an `ValueError`
if not found.
"""
for channel in self.output_channels():
if channel.id == name:
return channel
# Fallback to channel names for backward compatibility
for channel in self.output_channels():
if channel.name == name:
return channel
raise ValueError("%r is not a valid output channel name for %r." % \
raise ValueError("%r is not a valid output channel for %r." % \
(name, self.description.name))

#: The title of the node has changed
Expand Down
57 changes: 55 additions & 2 deletions orangecanvas/scheme/readwrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

from ..registry import global_registry, WidgetRegistry
from ..registry import WidgetDescription, InputSignal, OutputSignal
from ..utils import findf

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -162,7 +163,9 @@ def _terminal_value(node):
("source_node_id", str),
("sink_node_id", str),
("source_channel", str),
("source_channel_id", str),
("sink_channel", str),
("sink_channel_id", str),
("enabled", bool),
]
)
Expand Down Expand Up @@ -249,7 +252,9 @@ def parse_ows_etree_v_2_0(tree):
source_node_id=link.get("source_node_id"),
sink_node_id=link.get("sink_node_id"),
source_channel=link.get("source_channel"),
source_channel_id=link.get("source_channel_id", ""),
sink_channel=link.get("sink_channel"),
sink_channel_id=link.get("sink_channel_id", ""),
enabled=link.get("enabled") == "true",
)
links.append(params)
Expand Down Expand Up @@ -464,8 +469,10 @@ def error_handler(exc):
source = nodes_by_id[source_id]
sink = nodes_by_id[sink_id]
try:
link = SchemeLink(source, link_d.source_channel,
sink, link_d.sink_channel,
source_channel = _find_source_channel(source, link_d)
sink_channel = _find_sink_channel(sink, link_d)
link = SchemeLink(source, source_channel,
sink, sink_channel,
enabled=link_d.enabled)
except (ValueError, IncompatibleChannelTypeError) as ex:
error_handler(ex)
Expand Down Expand Up @@ -509,6 +516,48 @@ def error_handler(exc):
return scheme


def _find_source_channel(node: SchemeNode, link: _link) -> OutputSignal:
source_channel: Optional[OutputSignal] = None
if link.source_channel_id:
source_channel = findf(
node.output_channels(),
lambda c: c.id == link.source_channel_id,
)
if source_channel is not None:
return source_channel
source_channel = findf(
node.output_channels(),
lambda c: c.name == link.source_channel,
)
if source_channel is not None:
return source_channel
raise ValueError(
f"{link.source_channel!r} is not a valid output channel "
f"for {node.description.name!r}."
)


def _find_sink_channel(node: SchemeNode, link: _link) -> InputSignal:
sink_channel: Optional[InputSignal] = None
if link.sink_channel_id:
sink_channel = findf(
node.input_channels(),
lambda c: c.id == link.sink_channel_id,
)
if sink_channel is not None:
return sink_channel
sink_channel = findf(
node.input_channels(),
lambda c: c.name == link.sink_channel,
)
if sink_channel is not None:
return sink_channel
raise ValueError(
f"{link.sink_channel!r} is not a valid input channel "
f"for {node.description.name!r}."
)


def scheme_to_etree(scheme, data_format="literal", pickle_fallback=False):
"""
Return an `xml.etree.ElementTree` representation of the `scheme`.
Expand Down Expand Up @@ -556,6 +605,10 @@ def scheme_to_etree(scheme, data_format="literal", pickle_fallback=False):
"sink_channel": link.sink_channel.name,
"enabled": "true" if link.enabled else "false",
}
if link.source_channel.id:
attrs["source_channel_id"] = link.source_channel.id
if link.sink_channel.id:
attrs["sink_channel_id"] = link.sink_channel.id
builder.start("link", attrs)
builder.end("link")

Expand Down
15 changes: 15 additions & 0 deletions orangecanvas/scheme/tests/test_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,18 @@ def test_node(self):
self.assertIsInstance(channel, OutputSignal)
self.assertTrue(channel in outputs)
self.assertRaises(ValueError, node.output_channel, "%%&&&$$()[()[")

def test_channels_by_name_or_id(self):
reg = small_testing_registry()

zero_desc = reg.widget("zero")
node = SchemeNode(zero_desc)
self.assertIs(node.output_channel("value"), zero_desc.outputs[0])
self.assertIs(node.output_channel("val"), zero_desc.outputs[0])

add_desc = reg.widget("add")
node = SchemeNode(add_desc)
self.assertIs(node.input_channel("left"), add_desc.inputs[0])
self.assertIs(node.input_channel("right"), add_desc.inputs[1])
self.assertIs(node.input_channel("droite"), add_desc.inputs[1])
self.assertRaises(ValueError, node.input_channel, "gauche")

0 comments on commit 473d4d2

Please sign in to comment.