commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 01/08: grc: allow for multiple sources over


From: git
Subject: [Commit-gnuradio] [gnuradio] 01/08: grc: allow for multiple sources over virtual connections (#1166)
Date: Thu, 26 Jan 2017 14:46:37 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch maint
in repository gnuradio.

commit aa461c535ef987d8e8805834d07f27ab51948a5f
Author: Sebastian Koslowski <address@hidden>
Date:   Fri Jan 13 21:24:09 2017 +0100

    grc: allow for multiple sources over virtual connections (#1166)
---
 grc/core/Port.py                | 184 +++++++++++++++++++++-------------------
 grc/core/generator/Generator.py |   6 +-
 2 files changed, 102 insertions(+), 88 deletions(-)

diff --git a/grc/core/Port.py b/grc/core/Port.py
index 8808bc4..9114246 100644
--- a/grc/core/Port.py
+++ b/grc/core/Port.py
@@ -1,5 +1,5 @@
 """
-Copyright 2008-2015 Free Software Foundation, Inc.
+Copyright 2008-2017 Free Software Foundation, Inc.
 This file is part of GNU Radio
 
 GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,85 +17,116 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
+from itertools import chain
+
 from .Constants import DEFAULT_DOMAIN, GR_STREAM_DOMAIN, GR_MESSAGE_DOMAIN
 from .Element import Element
 
 from . import Constants
 
 
-def _get_source_from_virtual_sink_port(vsp):
+class LoopError(Exception):
+    pass
+
+
+def _upstream_ports(port):
+    if port.is_sink:
+        return _sources_from_virtual_sink_port(port)
+    else:
+        return _sources_from_virtual_source_port(port)
+
+
+def _sources_from_virtual_sink_port(sink_port, _traversed=None):
     """
     Resolve the source port that is connected to the given virtual sink port.
     Use the get source from virtual source to recursively resolve subsequent 
ports.
     """
-    try:
-        return _get_source_from_virtual_source_port(
-            vsp.get_enabled_connections()[0].get_source())
-    except:
-        raise Exception('Could not resolve source for virtual sink port 
{0}'.format(vsp))
+    source_ports_per_virtual_connection = (
+        # there can be multiple ports per virtual connection
+        _sources_from_virtual_source_port(c.get_source(), _traversed)  # type: 
list
+        for c in sink_port.get_enabled_connections()
+    )
+    return list(chain(*source_ports_per_virtual_connection))  # concatenate 
generated lists of ports
 
 
-def _get_source_from_virtual_source_port(vsp, traversed=[]):
+def _sources_from_virtual_source_port(source_port, _traversed=None):
     """
     Recursively resolve source ports over the virtual connections.
     Keep track of traversed sources to avoid recursive loops.
     """
-    if not vsp.get_parent().is_virtual_source():
-        return vsp
-    if vsp in traversed:
-        raise Exception('Loop found when resolving virtual source 
{0}'.format(vsp))
-    try:
-        return _get_source_from_virtual_source_port(
-            _get_source_from_virtual_sink_port(
-                filter(  # Get all virtual sinks with a matching stream id
-                    lambda vs: vs.get_param('stream_id').get_value() == 
vsp.get_parent().get_param('stream_id').get_value(),
-                    filter(  # Get all enabled blocks that are also virtual 
sinks
-                        lambda b: b.is_virtual_sink(),
-                        vsp.get_parent().get_parent().get_enabled_blocks(),
-                    ),
-                )[0].get_sinks()[0]
-            ), traversed + [vsp],
-        )
-    except:
-        raise Exception('Could not resolve source for virtual source port 
{0}'.format(vsp))
-
-
-def _get_sink_from_virtual_source_port(vsp):
+    _traversed = set(_traversed or [])  # a new set!
+    if source_port in _traversed:
+        raise LoopError('Loop found when resolving port type')
+    _traversed.add(source_port)
+
+    block = source_port.get_parent()
+    flow_graph = block.get_parent()
+
+    if not block.is_virtual_source():
+        return [source_port]  # nothing to resolve, we're done
+
+    stream_id = block.get_param('stream_id').get_value()
+
+    # currently the validation does not allow multiple virtual sinks and one 
virtual source
+    # but in the future it may...
+    connected_virtual_sink_blocks = (
+        b for b in flow_graph.get_enabled_blocks()
+        if b.is_virtual_sink() and b.get_param('stream_id').get_value() == 
stream_id
+    )
+    source_ports_per_virtual_connection = (
+        _sources_from_virtual_sink_port(b.get_sinks()[0], _traversed)  # type: 
list
+        for b in connected_virtual_sink_blocks
+    )
+    return list(chain(*source_ports_per_virtual_connection))  # concatenate 
generated lists of ports
+
+
+def _downstream_ports(port):
+    if port.is_source:
+        return _sinks_from_virtual_source_port(port)
+    else:
+        return _sinks_from_virtual_sink_port(port)
+
+
+def _sinks_from_virtual_source_port(source_port, _traversed=None):
     """
     Resolve the sink port that is connected to the given virtual source port.
     Use the get sink from virtual sink to recursively resolve subsequent ports.
     """
-    try:
-        # Could have many connections, but use first
-        return _get_sink_from_virtual_sink_port(
-            vsp.get_enabled_connections()[0].get_sink())
-    except:
-        raise Exception('Could not resolve source for virtual source port 
{0}'.format(vsp))
+    sink_ports_per_virtual_connection = (
+        # there can be multiple ports per virtual connection
+        _sinks_from_virtual_sink_port(c.get_sink(), _traversed)  # type: list
+        for c in source_port.get_enabled_connections()
+    )
+    return list(chain(*sink_ports_per_virtual_connection))  # concatenate 
generated lists of ports
 
 
-def _get_sink_from_virtual_sink_port(vsp, traversed=[]):
+def _sinks_from_virtual_sink_port(sink_port, _traversed=None):
     """
     Recursively resolve sink ports over the virtual connections.
     Keep track of traversed sinks to avoid recursive loops.
     """
-    if not vsp.get_parent().is_virtual_sink():
-        return vsp
-    if vsp in traversed:
-        raise Exception('Loop found when resolving virtual sink 
{0}'.format(vsp))
-    try:
-        return _get_sink_from_virtual_sink_port(
-            _get_sink_from_virtual_source_port(
-                filter(  # Get all virtual source with a matching stream id
-                    lambda vs: vs.get_param('stream_id').get_value() == 
vsp.get_parent().get_param('stream_id').get_value(),
-                    filter(  # Get all enabled blocks that are also virtual 
sinks
-                        lambda b: b.is_virtual_source(),
-                        vsp.get_parent().get_parent().get_enabled_blocks(),
-                    ),
-                )[0].get_sources()[0]
-            ), traversed + [vsp],
-        )
-    except:
-        raise Exception('Could not resolve source for virtual sink port 
{0}'.format(vsp))
+    _traversed = set(_traversed or [])  # a new set!
+    if sink_port in _traversed:
+        raise LoopError('Loop found when resolving port type')
+    _traversed.add(sink_port)
+
+    block = sink_port.get_parent()
+    flow_graph = block.get_parent()
+
+    if not block.is_virtual_sink():
+        return [sink_port]
+
+    stream_id = block.get_param('stream_id').get_value()
+
+    connected_virtual_source_blocks = (
+        b for b in flow_graph.get_enabled_blocks()
+        if b.is_virtual_source() and b.get_param('stream_id').get_value() == 
stream_id
+    )
+    sink_ports_per_virtual_connection = (
+        _sinks_from_virtual_source_port(b.get_sources()[0], _traversed)  # 
type: list
+        for b in connected_virtual_source_blocks
+    )
+    return list(chain(*sink_ports_per_virtual_connection))  # concatenate 
generated lists of ports
 
 
 class Port(Element):
@@ -173,15 +204,7 @@ class Port(Element):
         Handle the port cloning for virtual blocks.
         """
         if self.is_type_empty():
-            try:
-                # Clone type and vlen
-                source = self.resolve_empty_type()
-                self._type = str(source.get_type())
-                self._vlen = str(source.get_vlen())
-            except:
-                # Reset type and vlen
-                self._type = ''
-                self._vlen = ''
+            self.resolve_empty_type()
 
         Element.rewrite(self)
         hide = 
self.get_parent().resolve_dependencies(self._hide).strip().lower()
@@ -197,32 +220,23 @@ class Port(Element):
             self._key = '0'  # Is rectified in rewrite()
 
     def resolve_virtual_source(self):
-        if self.get_parent().is_virtual_sink():
-            return _get_source_from_virtual_sink_port(self)
-        if self.get_parent().is_virtual_source():
-            return _get_source_from_virtual_source_port(self)
+        """Only used by Generator after validation is passed"""
+        return _upstream_ports(self)
 
     def resolve_empty_type(self):
-        if self.is_sink:
-            try:
-                src = _get_source_from_virtual_sink_port(self)
-                if not src.is_type_empty():
-                    return src
-            except:
-                pass
-            sink = _get_sink_from_virtual_sink_port(self)
-            if not sink.is_type_empty():
-                return sink
-        if self.is_source:
+        def find_port(finder):
             try:
-                src = _get_source_from_virtual_source_port(self)
-                if not src.is_type_empty():
-                    return src
-            except:
+                return next((p for p in finder(self) if not 
p.is_type_empty()), None)
+            except (StopIteration, Exception) as error:
                 pass
-            sink = _get_sink_from_virtual_source_port(self)
-            if not sink.is_type_empty():
-                return sink
+
+        try:
+            port = find_port(_upstream_ports) or find_port(_downstream_ports)
+            self._type = str(port.get_type())
+            self._vlen = str(port.get_vlen())
+        except Exception:
+            # Reset type and vlen
+            self._type = self._vlen = ''
 
     def get_vlen(self):
         """
diff --git a/grc/core/generator/Generator.py b/grc/core/generator/Generator.py
index 1e43e37..1ed7d2d 100644
--- a/grc/core/generator/Generator.py
+++ b/grc/core/generator/Generator.py
@@ -171,10 +171,10 @@ class TopBlockGenerator(object):
         # Get the virtual blocks and resolve their connections
         virtual = filter(lambda c: 
c.get_source().get_parent().is_virtual_source(), connections)
         for connection in virtual:
-            source = connection.get_source().resolve_virtual_source()
             sink = connection.get_sink()
-            resolved = fg.get_parent().Connection(flow_graph=fg, porta=source, 
portb=sink)
-            connections.append(resolved)
+            for source in connection.get_source().resolve_virtual_source():
+                resolved = fg.get_parent().Connection(flow_graph=fg, 
porta=source, portb=sink)
+                connections.append(resolved)
             # Remove the virtual connection
             connections.remove(connection)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]