Skip to content

Commit

Permalink
Merge pull request biolab#1810 from ales-erjavec/input-output-signal-…
Browse files Browse the repository at this point in the history
…replacement-declarations

[ENH] Input/output signal replacement declarations
  • Loading branch information
janezd authored and astaric committed Jan 4, 2017
1 parent 1580db3 commit 818d146
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Orange/canvas/registry/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
log = logging.getLogger(__name__)

# Registry hex version
VERSION_HEX = 0x000102
VERSION_HEX = 0x000103


class WidgetRegistry(object):
Expand Down
12 changes: 8 additions & 4 deletions Orange/canvas/registry/description.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,17 @@ class InputSignal(object):
A unique id of the input signal.
doc : str, optional
A docstring documenting the channel.
replaces : List[str]
A list of names this input replaces.
"""
def __init__(self, name, type, handler, flags=Single + NonDefault,
id=None, doc=None):
id=None, doc=None, replaces=[]):
self.name = name
self.type = type
self.handler = handler
self.id = id
self.doc = doc
self.replaces = list(replaces)

if isinstance(flags, str):
# flags are stored as strings
Expand Down Expand Up @@ -130,14 +132,16 @@ class OutputSignal(object):
A unique id of the output signal.
doc : str, optional
A docstring documenting the channel.
replaces : List[str]
A list of names this output replaces.
"""
def __init__(self, name, type, flags=Single + NonDefault,
id=None, doc=None):
id=None, doc=None, replaces=[]):
self.name = name
self.type = type
self.id = id
self.doc = doc
self.replaces = list(replaces)

if isinstance(flags, str):
# flags are stored as strings
Expand Down
41 changes: 38 additions & 3 deletions Orange/canvas/scheme/readwrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from .errors import IncompatibleChannelTypeError

from ..registry import global_registry
from ..registry import WidgetDescription, InputSignal, OutputSignal

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -607,12 +608,26 @@ def resolve_1_0(scheme_desc, registry):

def resolve_replaced(scheme_desc, registry):
widgets = registry.widgets()
nodes_by_id = {} # type: Dict[str, _node]
replacements = {}
for desc in widgets:
replacements_channels = {} # type: Dict[str, Tuple[dict, dict]]
# collect all the replacement mappings
for desc in widgets: # type: WidgetDescription
if desc.replaces:
for repl_qname in desc.replaces:
replacements[repl_qname] = desc.qualified_name

input_repl = {}
for idesc in desc.inputs or []: # type: InputSignal
for repl_qname in idesc.replaces or []: # type: str
input_repl[repl_qname] = idesc.name
output_repl = {}
for odesc in desc.outputs: # type: OutputSignal
for repl_qname in odesc.replaces or []: # type: str
output_repl[repl_qname] = odesc.name
replacements_channels[desc.qualified_name] = (input_repl, output_repl)

# replace the nodes
nodes = scheme_desc.nodes
for i, node in list(enumerate(nodes)):
if not registry.has_widget(node.qualified_name) and \
Expand All @@ -621,8 +636,28 @@ def resolve_replaced(scheme_desc, registry):
desc = registry.widget(qname)
nodes[i] = node._replace(qualified_name=desc.qualified_name,
project_name=desc.project_name)

return scheme_desc._replace(nodes=nodes)
nodes_by_id[node.id] = nodes[i]

# replace links
links = scheme_desc.links
for i, link in list(enumerate(links)): # type: _link
nsource = nodes_by_id[link.source_node_id]
nsink = nodes_by_id[link.sink_node_id]

_, source_rep = replacements_channels.get(
nsource.qualified_name, ({}, {}))
sink_rep, _ = replacements_channels.get(
nsink.qualified_name, ({}, {}))

if link.source_channel in source_rep:
link = link._replace(
source_channel=source_rep[link.source_channel])
if link.sink_channel in sink_rep:
link = link._replace(
sink_channel=sink_rep[link.sink_channel])
links[i] = link

return scheme_desc._replace(nodes=nodes, links=links)


def scheme_load(scheme, stream, registry=None, error_handler=None):
Expand Down
18 changes: 15 additions & 3 deletions Orange/widgets/visualize/owtreeviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,21 @@ class OWTreeGraph(OWTreeViewer2D):
name = "Tree Viewer"
icon = "icons/TreeViewer.svg"
priority = 35
inputs = [("Tree", TreeModel, "ctree")]
outputs = [("Selected Data", Table, widget.Default),
(ANNOTATED_DATA_SIGNAL_NAME, Table)]
inputs = [
widget.InputSignal(
"Tree", TreeModel, "ctree",
# Had different input names before merging from
# Classification/Regression tree variants
replaces=["Classification Tree", "Regression Tree"])
]
outputs = [
widget.OutputSignal(
"Selected Data", Table, widget.Default, id="selected-data",
),
widget.OutputSignal(
ANNOTATED_DATA_SIGNAL_NAME, Table, id="annotated-data")
]


settingsHandler = ClassValuesContextHandler()
target_class_index = ContextSetting(0)
Expand Down

0 comments on commit 818d146

Please sign in to comment.