commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] [gnuradio] 05/18: grc-refactor: fixes, type-testing-fl


From: git
Subject: [Commit-gnuradio] [gnuradio] 05/18: grc-refactor: fixes, type-testing-flags, FlowGraph.py, (more)
Date: Sun, 24 Apr 2016 19:19:37 +0000 (UTC)

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

jcorgan pushed a commit to branch master
in repository gnuradio.

commit ed6e9a484ddddbbadf19584f6606d2c9e36de823
Author: Sebastian Koslowski <address@hidden>
Date:   Sun Feb 7 13:44:59 2016 +0100

    grc-refactor: fixes, type-testing-flags, FlowGraph.py, (more)
---
 grc/gui/ActionHandler.py                  |   2 +-
 grc/gui/Block.py                          |  19 +-
 grc/gui/FlowGraph.py                      |  46 +-
 grc/gui/Port.py                           |  18 +-
 grc/model/Block.py                        |  11 +-
 grc/model/Connection.py                   |  10 +-
 grc/model/Constants.py                    |   8 +-
 grc/model/Element.py                      |  33 +-
 grc/model/FlowGraph.py                    | 763 +++++++++++-------------------
 grc/model/Param.py                        |   5 +-
 grc/model/Platform.py                     |  22 +-
 grc/model/Port.py                         |  21 +-
 grc/model/{ => generator}/Generator.py    |  18 +-
 grc/model/generator/__init__.py           |   1 +
 grc/model/{ => generator}/flow_graph.tmpl |   0
 grc/model/utils/__init__.py               |   6 +
 grc/model/utils/complexity.py             |  49 ++
 17 files changed, 451 insertions(+), 581 deletions(-)

diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 1702475..b219ed2 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -232,7 +232,7 @@ class ActionHandler:
                             if y < y_min:
                                 y_min = y
 
-                            for connection in block.get_connections():
+                            for connection in block.connections:
 
                                 # Get id of connected blocks
                                 source_id = 
connection.get_source().get_parent().get_id()
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 97b4e96..2439c32 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -32,7 +32,7 @@ from .Constants import (
 from . Element import Element
 from ..model.odict import odict
 from ..model.Param import num_to_str
-
+from ..model.utils.complexity import calculate_flowgraph_complexity
 from ..model.Block import Block as _Block
 
 BLOCK_MARKUP_TMPL="""\
@@ -138,10 +138,10 @@ class Block(Element, _Block):
             delta_coor: requested delta coordinate (dX, dY) to move
 
         Returns:
-            The delta coordinate possible to move while keeping the block on 
the canvas 
+            The delta coordinate possible to move while keeping the block on 
the canvas
             or the input (dX, dY) on failure
         """
-        dX, dY = delta_coor 
+        dX, dY = delta_coor
 
         try:
             fgW, fgH = self.get_parent().get_size()
@@ -150,7 +150,7 @@ class Block(Element, _Block):
                sW, sH = self.W, self.H
             else:
                sW, sH = self.H, self.W
-        
+
             if x + dX < 0:
                 dX = -x
             elif dX + x + sW >= fgW:
@@ -162,7 +162,7 @@ class Block(Element, _Block):
         except:
             pass
 
-        return ( dX, dY ) 
+        return ( dX, dY )
 
     def get_rotation(self):
         """
@@ -196,7 +196,7 @@ class Block(Element, _Block):
     def create_labels(self):
         """Create the labels for the signal block."""
         Element.create_labels(self)
-        self._bg_color = self.is_dummy_block() and 
Colors.MISSING_BLOCK_BACKGROUND_COLOR or \
+        self._bg_color = self.is_dummy_block and 
Colors.MISSING_BLOCK_BACKGROUND_COLOR or \
                          self.get_bypassed() and Colors.BLOCK_BYPASSED_COLOR 
or \
                          self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or 
Colors.BLOCK_DISABLED_COLOR
 
@@ -207,7 +207,7 @@ class Block(Element, _Block):
         layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self, 
font=BLOCK_FONT))
         self.label_width, self.label_height = layout.get_pixel_size()
         #display the params
-        if self.is_dummy_block():
+        if self.is_dummy_block:
             markups = [
                 '<span foreground="black" font_desc="{font}"><b>key: 
</b>{key}</span>'.format(font=PARAM_FONT, key=self._key)
             ]
@@ -274,7 +274,8 @@ class Block(Element, _Block):
 
         # Show the flowgraph complexity on the top block if enabled
         if Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY.get_active() and 
self.get_key() == "options":
-            complexity = "Complexity: 
{}bal".format(num_to_str(self.get_parent().get_complexity()))
+            complexity = calculate_flowgraph_complexity(self.get_parent())
+            complexity = "Complexity: {}bal".format(num_to_str(complexity))
 
         layout = gtk.DrawingArea().create_pango_layout('')
         layout.set_markup(Utils.parse_template(COMMENT_COMPLEXITY_MARKUP_TMPL,
@@ -314,7 +315,7 @@ class Block(Element, _Block):
         Element.draw(
             self, gc, window, bg_color=self._bg_color,
             border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or
-                         self.is_dummy_block() and 
Colors.MISSING_BLOCK_BORDER_COLOR or Colors.BORDER_COLOR,
+                         self.is_dummy_block and 
Colors.MISSING_BLOCK_BORDER_COLOR or Colors.BORDER_COLOR,
         )
         #draw label image
         if self.is_horizontal():
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index e975595..0c66a7e 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
 02110-1301, USA
 
 import random
 import functools
-from itertools import chain
+from itertools import chain, count
 from operator import methodcaller
 from distutils.spawn import find_executable
 
@@ -65,6 +65,22 @@ class FlowGraph(Element, _Flowgraph):
 
         self._external_updaters = {}
 
+    def _get_unique_id(self, base_id=''):
+        """
+        Get a unique id starting with the base id.
+
+        Args:
+            base_id: the id starts with this and appends a count
+
+        Returns:
+            a unique id
+        """
+        for index in count():
+            block_id = '{}_{}'.format(base_id, index)
+            if block_id not in (b.get_id() for b in self.blocks):
+                break
+        return block_id
+
     def install_external_editor(self, param):
         target = (param.get_parent().get_id(), param.get_key())
 
@@ -163,7 +179,7 @@ class FlowGraph(Element, _Flowgraph):
         #get connections between selected blocks
         connections = filter(
             lambda c: c.get_source().get_parent() in blocks and 
c.get_sink().get_parent() in blocks,
-            self.get_connections(),
+            self.connections,
         )
         clipboard = (
             (x_min, y_min),
@@ -202,7 +218,7 @@ class FlowGraph(Element, _Flowgraph):
                 if param_key == 'id':
                     old_id2block[param_value] = block
                     #if the block id is not unique, get a new block id
-                    if param_value in [bluck.get_id() for bluck in 
self.get_blocks()]:
+                    if param_value in (blk.get_id() for blk in self.blocks):
                         param_value = self._get_unique_id(param_value)
                 #set value to key
                 block.get_param(param_key).set_value(param_value)
@@ -284,7 +300,7 @@ class FlowGraph(Element, _Flowgraph):
         """
         for selected_block in self.get_selected_blocks():
             delta_coordinate = 
selected_block.bound_move_delta(delta_coordinate)
- 
+
         for selected_block in self.get_selected_blocks():
             selected_block.move(delta_coordinate)
             self.element_moved = True
@@ -346,7 +362,7 @@ class FlowGraph(Element, _Flowgraph):
 
         # draw comments first
         if Actions.TOGGLE_SHOW_BLOCK_COMMENTS.get_active():
-            for block in self.iter_blocks():
+            for block in self.blocks:
                 if block.get_enabled():
                     block.draw_comment(gc, window)
         #draw multi select rectangle
@@ -364,8 +380,8 @@ class FlowGraph(Element, _Flowgraph):
             window.draw_rectangle(gc, False, x, y, w, h)
         #draw blocks on top of connections
         hide_disabled_blocks = Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active()
-        blocks = sorted(self.iter_blocks(), key=methodcaller('get_enabled'))
-        for element in chain(self.iter_connections(), blocks):
+        blocks = sorted(self.blocks, key=methodcaller('get_enabled'))
+        for element in chain(self.connections, blocks):
             if hide_disabled_blocks and not element.get_enabled():
                 continue  # skip hidden disabled blocks and connections
             element.draw(gc, window)
@@ -452,13 +468,13 @@ class FlowGraph(Element, _Flowgraph):
             if not selected_element: continue
             # hidden disabled connections, blocks and their ports can not be 
selected
             if Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active() and (
-                selected_element.is_block() and not 
selected_element.get_enabled() or
-                selected_element.is_connection() and not 
selected_element.get_enabled() or
-                selected_element.is_port() and not 
selected_element.get_parent().get_enabled()
+                selected_element.is_block and not 
selected_element.get_enabled() or
+                selected_element.is_connection and not 
selected_element.get_enabled() or
+                selected_element.is_port and not 
selected_element.get_parent().get_enabled()
             ):
                 continue
             #update the selected port information
-            if selected_element.is_port():
+            if selected_element.is_port:
                 if not coor_m: selected_port = selected_element
                 selected_element = selected_element.get_parent()
             selected.add(selected_element)
@@ -482,7 +498,8 @@ class FlowGraph(Element, _Flowgraph):
         """
         selected = set()
         for selected_element in self.get_selected_elements():
-            if selected_element.is_connection(): selected.add(selected_element)
+            if selected_element.is_connection:
+                selected.add(selected_element)
         return list(selected)
 
     def get_selected_blocks(self):
@@ -494,7 +511,8 @@ class FlowGraph(Element, _Flowgraph):
         """
         selected = set()
         for selected_element in self.get_selected_elements():
-            if selected_element.is_block(): selected.add(selected_element)
+            if selected_element.is_block:
+                selected.add(selected_element)
         return list(selected)
 
     def get_selected_block(self):
@@ -669,7 +687,7 @@ class FlowGraph(Element, _Flowgraph):
                     adj.set_value(adj_val-SCROLL_DISTANCE)
                     adj.emit('changed')
             #remove the connection if selected in drag event
-            if len(self.get_selected_elements()) == 1 and 
self.get_selected_element().is_connection():
+            if len(self.get_selected_elements()) == 1 and 
self.get_selected_element().is_connection:
                 Actions.ELEMENT_DELETE()
             #move the selected elements and record the new coordinate
             if not self.get_ctrl_mask():
diff --git a/grc/gui/Port.py b/grc/gui/Port.py
index 28d3b4d..c281cbd 100644
--- a/grc/gui/Port.py
+++ b/grc/gui/Port.py
@@ -64,7 +64,7 @@ class Port(_Port, Element):
         rotation = self.get_rotation()
         #get all sibling ports
         ports = self.get_parent().get_sources_gui() \
-            if self.is_source() else self.get_parent().get_sinks_gui()
+            if self.is_source else self.get_parent().get_sinks_gui()
         ports = filter(lambda p: not p.get_hide(), ports)
         #get the max width
         self.W = max([port.W for port in ports] + [PORT_MIN_WIDTH])
@@ -82,27 +82,27 @@ class Port(_Port, Element):
             index = length-index-1
 
         port_separation = PORT_SEPARATION \
-            if not self.get_parent().has_busses[self.is_source()] \
+            if not self.get_parent().has_busses[self.is_source] \
             else max([port.H for port in ports]) + PORT_SPACING
 
         offset = (self.get_parent().H - (length-1)*port_separation - self.H)/2
         #create areas and connector coordinates
-        if (self.is_sink() and rotation == 0) or (self.is_source() and 
rotation == 180):
+        if (self.is_sink and rotation == 0) or (self.is_source and rotation == 
180):
             x = -W
             y = port_separation*index+offset
             self.add_area((x, y), (W, self.H))
             self._connector_coordinate = (x-1, y+self.H/2)
-        elif (self.is_source() and rotation == 0) or (self.is_sink() and 
rotation == 180):
+        elif (self.is_source and rotation == 0) or (self.is_sink and rotation 
== 180):
             x = self.get_parent().W
             y = port_separation*index+offset
             self.add_area((x, y), (W, self.H))
             self._connector_coordinate = (x+1+W, y+self.H/2)
-        elif (self.is_source() and rotation == 90) or (self.is_sink() and 
rotation == 270):
+        elif (self.is_source and rotation == 90) or (self.is_sink and rotation 
== 270):
             y = -W
             x = port_separation*index+offset
             self.add_area((x, y), (self.H, W))
             self._connector_coordinate = (x+self.H/2, y-1)
-        elif (self.is_sink() and rotation == 90) or (self.is_source() and 
rotation == 270):
+        elif (self.is_sink and rotation == 90) or (self.is_source and rotation 
== 270):
             y = self.get_parent().W
             x = port_separation*index+offset
             self.add_area((x, y), (self.H, W))
@@ -145,7 +145,7 @@ class Port(_Port, Element):
         Element.draw(
             self, gc, window, bg_color=self._bg_color,
             border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or
-                         self.get_parent().is_dummy_block() and 
Colors.MISSING_BLOCK_BORDER_COLOR or
+                         self.get_parent().is_dummy_block and 
Colors.MISSING_BLOCK_BORDER_COLOR or
                          Colors.BORDER_COLOR,
         )
         if not self._areas_list or self._label_hidden():
@@ -177,8 +177,8 @@ class Port(_Port, Element):
         Returns:
             the direction in degrees
         """
-        if self.is_source(): return self.get_rotation()
-        elif self.is_sink(): return (self.get_rotation() + 180)%360
+        if self.is_source: return self.get_rotation()
+        elif self.is_sink: return (self.get_rotation() + 180)%360
 
     def get_connector_length(self):
         """
diff --git a/grc/model/Block.py b/grc/model/Block.py
index ae3169c..8af3e98 100644
--- a/grc/model/Block.py
+++ b/grc/model/Block.py
@@ -71,6 +71,8 @@ def _get_elem(lst, key):
 
 class Block(Element):
 
+    is_block = True
+
     def __init__(self, flow_graph, n):
         """
         Make a new block from nested data.
@@ -237,6 +239,11 @@ class Block(Element):
         self._epy_source_hash = -1  # for epy blocks
         self._epy_reload_error = None
 
+        if self._bussify_sink:
+            self.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
+        if self._bussify_source:
+            self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+
     def get_bus_structure(self, direction):
         if direction == 'source':
             bus_structure = self._bus_structure_source
@@ -300,6 +307,7 @@ class Block(Element):
         """
         Add and remove ports to adjust for the nports.
         """
+        Element.rewrite(self)
         # Check and run any custom rewrite function for this block
         getattr(self, 'rewrite_' + self._key, lambda: None)()
 
@@ -601,9 +609,6 @@ class Block(Element):
     def get_id(self):
         return self.get_param('id').get_value()
 
-    def is_block(self):
-        return True
-
     def get_name(self):
         return self._name
 
diff --git a/grc/model/Connection.py b/grc/model/Connection.py
index 7cef4ad..a7b428d 100644
--- a/grc/model/Connection.py
+++ b/grc/model/Connection.py
@@ -25,6 +25,8 @@ from .odict import odict
 
 class Connection(Element):
 
+    is_connection = True
+
     def __init__(self, flow_graph, porta, portb):
         """
         Make a new connection given the parent and 2 ports.
@@ -42,9 +44,9 @@ class Connection(Element):
         source = sink = None
         # Separate the source and sink
         for port in (porta, portb):
-            if port.is_source():
+            if port.is_source:
                 source = port
-            if port.is_sink():
+            else:
                 sink = port
         if not source:
             raise ValueError('Connection could not isolate source')
@@ -57,7 +59,7 @@ class Connection(Element):
         if not len(source.get_associated_ports()) == 
len(sink.get_associated_ports()):
             raise ValueError('port connections must have same cardinality')
         # Ensure that this connection (source -> sink) is unique
-        for connection in self.get_parent().get_connections():
+        for connection in flow_graph.connections:
             if connection.get_source() is source and connection.get_sink() is 
sink:
                 raise LookupError('This connection between source and sink is 
not unique.')
         self._source = source
@@ -81,8 +83,6 @@ class Connection(Element):
             self.get_sink(),
         )
 
-    def is_connection(self): return True
-
     def is_msg(self):
         return self.get_source().get_type() == self.get_sink().get_type() == 
'msg'
 
diff --git a/grc/model/Constants.py b/grc/model/Constants.py
index d77dffc..f1dae1d 100644
--- a/grc/model/Constants.py
+++ b/grc/model/Constants.py
@@ -45,6 +45,8 @@ BLOCKS_DIRS = filter(  # filter blank strings
 DATA_DIR = os.path.dirname(__file__)
 FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd')
 BLOCK_TREE_DTD = os.path.join(DATA_DIR, 'block_tree.dtd')
+BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd')
+DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc')
 
 # File format versions:
 #  0: undefined / legacy
@@ -79,12 +81,6 @@ TOP_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | 
stat.S_IXUSR | stat.S_IRGRP
                       stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH
 HIER_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | 
stat.S_IWGRP | stat.S_IROTH
 
-# Data files
-DATA_DIR = os.path.dirname(__file__)
-FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl')
-BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd')
-DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc')
-
 # Define types, native python + numpy
 VECTOR_TYPES = (tuple, list, set, numpy.ndarray)
 COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128]
diff --git a/grc/model/Element.py b/grc/model/Element.py
index 6716cd6..c999d67 100644
--- a/grc/model/Element.py
+++ b/grc/model/Element.py
@@ -90,34 +90,17 @@ class Element(object):
         return list()
 
     ##############################################
-    # Type testing methods
+    # Type testing
     ##############################################
-    def is_element(self):
-        return True
-
-    def is_platform(self):
-        return False
-
-    def is_flow_graph(self):
-        return False
-
-    def is_connection(self):
-        return False
-
-    def is_block(self):
-        return False
+    is_platform = False
 
-    def is_dummy_block(self):
-        return False
+    is_flow_graph = False
 
-    def is_source(self):
-        return False
+    is_block = False
+    is_dummy_block = False
 
-    def is_sink(self):
-        return False
+    is_connection = False
 
-    def is_port(self):
-        return False
+    is_port = False
 
-    def is_param(self):
-        return False
+    is_param = False
diff --git a/grc/model/FlowGraph.py b/grc/model/FlowGraph.py
index 0aea145..fd391c6 100644
--- a/grc/model/FlowGraph.py
+++ b/grc/model/FlowGraph.py
@@ -1,26 +1,25 @@
-"""
-Copyright 2008-2015 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
-"""
+# Copyright 2008-2015 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA
+
 import re
 import imp
 import time
 from operator import methodcaller
-from itertools import ifilter
+from itertools import ifilter, chain
 
 from ..gui import Messages
 
@@ -38,36 +37,10 @@ _bus_struct_sink_searcher = 
re.compile('^(bus_structure_sink)$')
 _bus_struct_src_searcher = re.compile('^(bus_structure_source)$')
 
 
-def _initialize_dummy_block(block, block_n):
-    """
-    This is so ugly... dummy-fy a block
-    Modify block object to get the behaviour for a missing block
-    """
-
-    block._key = block_n.find('key')
-    block.is_dummy_block = lambda: True
-    block.is_valid = lambda: False
-    block.get_enabled = lambda: False
-    for param_n in block_n.findall('param'):
-        if param_n['key'] not in block.get_param_keys():
-            new_param_n = odict({'key': param_n['key'], 'name': 
param_n['key'], 'type': 'string'})
-            params = block.get_parent().get_parent().Param(block=block, 
n=new_param_n)
-            block.get_params().append(params)
-
-
-def _dummy_block_add_port(block, key, dir):
-    """ This is so ugly... Add a port to a dummy-field block """
-    port_n = odict({'name': '?', 'key': key, 'type': ''})
-    port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir)
-    if port.is_source():
-        block.get_sources().append(port)
-    else:
-        block.get_sinks().append(port)
-    return port
-
-
 class FlowGraph(Element):
 
+    is_flow_graph = True
+
     def __init__(self, platform):
         """
         Make a flow graph from the arguments.
@@ -78,214 +51,27 @@ class FlowGraph(Element):
         Returns:
             the flow graph object
         """
-        self.grc_file_path = ''
-        # Initialize
         Element.__init__(self, platform)
         self._elements = []
         self._timestamp = time.ctime()
-        # Inital blank import
-        self.import_data()
 
-        self.n = {}
-        self.n_hash = -1
-        self._renew_eval_ns = True
-        self._eval_cache = {}
+        self.platform = platform  # todo: make this a lazy prop
+        self.blocks = []
+        self.connections = []
 
-    def _get_unique_id(self, base_id=''):
-        """
-        Get a unique id starting with the base id.
+        self._eval_cache = {}
+        self.namespace = {}
 
-        Args:
-            base_id: the id starts with this and appends a count
+        self.grc_file_path = ''
 
-        Returns:
-            a unique id
-        """
-        index = 0
-        while True:
-            id = '{}_{}'.format(base_id, index)
-            index += 1
-            # Make sure that the id is not used by another block
-            if not filter(lambda b: b.get_id() == id, self.get_blocks()): 
return id
+        self.import_data()
 
     def __str__(self):
         return 'FlowGraph - {}({})'.format(self.get_option('title'), 
self.get_option('id'))
 
-    def get_complexity(self):
-        """ Determines the complexity of a flowgraph """
-        dbal = 0
-        block_list = self.get_blocks()
-        for block in block_list:
-            # Skip options block
-            if block.get_key() == 'options':
-                continue
-
-            # Don't worry about optional sinks?
-            sink_list = filter(lambda c: not c.get_optional(), 
block.get_sinks())
-            source_list = filter(lambda c: not c.get_optional(), 
block.get_sources())
-            sinks = float(len(sink_list))
-            sources = float(len(source_list))
-            base = max(min(sinks, sources), 1)
-
-            # Port ratio multiplier
-            if min(sinks, sources) > 0:
-                multi = sinks / sources
-                multi = (1 / multi) if multi > 1 else multi
-            else:
-                multi = 1
-
-            # Connection ratio multiplier
-            sink_multi = max(float(sum(map(lambda c: len(c.get_connections()), 
sink_list)) / max(sinks, 1.0)), 1.0)
-            source_multi = max(float(sum(map(lambda c: 
len(c.get_connections()), source_list)) / max(sources, 1.0)), 1.0)
-            dbal = dbal + (base * multi * sink_multi * source_multi)
-
-        elements = float(len(self.get_elements()))
-        connections = float(len(self.get_connections()))
-        disabled_connections = len(filter(lambda c: not c.get_enabled(), 
self.get_connections()))
-        blocks = float(len(block_list))
-        variables = elements - blocks - connections
-        enabled = float(len(self.get_enabled_blocks()))
-
-        # Disabled multiplier
-        if enabled > 0:
-            disabled_multi = 1 / (max(1 - ((blocks - enabled) / max(blocks, 
1)), 0.05))
-        else:
-            disabled_multi = 1
-
-        # Connection multiplier (How many connections )
-        if (connections - disabled_connections) > 0:
-            conn_multi = 1 / (max(1 - (disabled_connections / max(connections, 
1)), 0.05))
-        else:
-            conn_multi = 1
-
-        final = round(max((dbal - 1) * disabled_multi * conn_multi * 
connections, 0.0) / 1000000, 6)
-        return final
-
-    def _eval(self, code, namespace, namespace_hash):
-        """
-        Evaluate the code with the given namespace.
-
-        Args:
-            code: a string with python code
-            namespace: a dict representing the namespace
-            namespace_hash: a unique hash for the namespace
-
-        Returns:
-            the resultant object
-        """
-        if not code:
-            raise Exception('Cannot evaluate empty statement.')
-        my_hash = hash(code) ^ namespace_hash
-
-        # Cache if does not exist
-        if my_hash not in self._eval_cache:
-            self._eval_cache[my_hash] = eval(code, namespace, namespace)
-        # Return from cache
-        return self._eval_cache[my_hash]
-
-    def get_hier_block_stream_io(self, direction):
-        """
-        Get a list of stream io signatures for this flow graph.
-
-        Args:
-            direction: a string of 'in' or 'out'
-
-        Returns:
-            a list of dicts with: type, label, vlen, size, optional
-        """
-        return filter(lambda p: p['type'] != "message",
-                      self.get_hier_block_io(direction))
-
-    def get_hier_block_message_io(self, direction):
-        """
-        Get a list of message io signatures for this flow graph.
-
-        Args:
-            direction: a string of 'in' or 'out'
-
-        Returns:
-            a list of dicts with: type, label, vlen, size, optional
-        """
-        return filter(lambda p: p['type'] == "message",
-                      self.get_hier_block_io(direction))
-
-    def get_hier_block_io(self, direction):
-        """
-        Get a list of io ports for this flow graph.
-
-        Args:
-            direction: a string of 'in' or 'out'
-
-        Returns:
-            a list of dicts with: type, label, vlen, size, optional
-        """
-        pads = self.get_pad_sources() if direction in ('sink', 'in') else \
-            self.get_pad_sinks() if direction in ('source', 'out') else []
-        ports = []
-        for pad in pads:
-            master = {
-                'label': str(pad.get_param('label').get_evaluated()),
-                'type': str(pad.get_param('type').get_evaluated()),
-                'vlen': str(pad.get_param('vlen').get_value()),
-                'size': pad.get_param('type').get_opt('size'),
-                'optional': bool(pad.get_param('optional').get_evaluated()),
-            }
-            num_ports = pad.get_param('num_streams').get_evaluated()
-            if num_ports > 1:
-                for i in xrange(num_ports):
-                    clone = master.copy()
-                    clone['label'] += str(i)
-                    ports.append(clone)
-            else:
-                ports.append(master)
-        return ports
-
-    def get_pad_sources(self):
-        """
-        Get a list of pad source blocks sorted by id order.
-
-        Returns:
-            a list of pad source blocks in this flow graph
-        """
-        pads = filter(lambda b: b.get_key() == 'pad_source', 
self.get_enabled_blocks())
-        return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
-
-    def get_pad_sinks(self):
-        """
-        Get a list of pad sink blocks sorted by id order.
-
-        Returns:
-            a list of pad sink blocks in this flow graph
-        """
-        pads = filter(lambda b: b.get_key() == 'pad_sink', 
self.get_enabled_blocks())
-        return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
-
-    def get_pad_port_global_key(self, port):
-        """
-        Get the key for a port of a pad source/sink to use in connect()
-        This takes into account that pad blocks may have multiple ports
-
-        Returns:
-            the key (str)
-        """
-        key_offset = 0
-        pads = self.get_pad_sources() if port.is_source() else 
self.get_pad_sinks()
-        for pad in pads:
-            # using the block param 'type' instead of the port domain here
-            # to emphasize that hier block generation is domain agnostic
-            is_message_pad = pad.get_param('type').get_evaluated() == "message"
-            if port.get_parent() == pad:
-                if is_message_pad:
-                    key = pad.get_param('label').get_value()
-                else:
-                    key = str(key_offset + int(port.get_key()))
-                return key
-            else:
-                # assuming we have either only sources or sinks
-                if not is_message_pad:
-                    key_offset += len(pad.get_ports())
-        return -1
-
+    ##############################################
+    # TODO: Move these to new generator package
+    ##############################################
     def get_imports(self):
         """
         Get a set of all import statments in this flow graph namespace.
@@ -362,7 +148,7 @@ class FlowGraph(Element):
         """
         Get an iterator of all blocks that are enabled and not bypassed.
         """
-        return ifilter(methodcaller('get_enabled'), self.iter_blocks())
+        return ifilter(methodcaller('get_enabled'), self.blocks)
 
     def get_enabled_blocks(self):
         """
@@ -380,7 +166,7 @@ class FlowGraph(Element):
         Returns:
             a list of blocks
         """
-        return filter(methodcaller('get_bypassed'), self.iter_blocks())
+        return filter(methodcaller('get_bypassed'), self.blocks)
 
     def get_enabled_connections(self):
         """
@@ -389,68 +175,7 @@ class FlowGraph(Element):
         Returns:
             a list of connections
         """
-        return filter(methodcaller('get_enabled'), self.get_connections())
-
-    def _get_new_block(self, key):
-        """
-        Get a new block of the specified key.
-        Add the block to the list of elements.
-
-        Args:
-            key: the block key
-
-        Returns:
-            the new block or None if not found
-        """
-        if key not in self.get_parent().get_block_keys():
-                return None
-        block = self.get_parent().get_new_block(self, key)
-        self.get_elements().append(block)
-        if block._bussify_sink:
-            block.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
-        if block._bussify_source:
-            block.bussify({'name': 'bus', 'type': 'bus'}, 'source')
-        return block
-
-    def connect(self, porta, portb):
-        """
-        Create a connection between porta and portb.
-
-        Args:
-            porta: a port
-            portb: another port
-        @throw Exception bad connection
-
-        Returns:
-            the new connection
-        """
-        connection = self.get_parent().Connection(flow_graph=self, 
porta=porta, portb=portb)
-        self.get_elements().append(connection)
-        return connection
-
-    def remove_element(self, element):
-        """
-        Remove the element from the list of elements.
-        If the element is a port, remove the whole block.
-        If the element is a block, remove its connections.
-        If the element is a connection, just remove the connection.
-        """
-        if element not in self.get_elements():
-            return
-        # Found a port, set to parent signal block
-        if element.is_port():
-            element = element.get_parent()
-        # Remove block, remove all involved connections
-        if element.is_block():
-            for port in element.get_ports():
-                map(self.remove_element, port.get_connections())
-        if element.is_connection():
-            if element.is_bus():
-                cons_list = []
-                for i in map(lambda a: a.get_connections(), 
element.get_source().get_associated_ports()):
-                    cons_list.extend(i)
-                map(self.remove_element, cons_list)
-        self.get_elements().remove(element)
+        return filter(methodcaller('get_enabled'), self.connections)
 
     def get_option(self, key):
         """
@@ -465,29 +190,14 @@ class FlowGraph(Element):
         """
         return self._options_block.get_param(key).get_evaluated()
 
-    def is_flow_graph(self):
-        return True
-
     ##############################################
     # Access Elements
     ##############################################
     def get_block(self, id):
-        for block in self.iter_blocks():
+        for block in self.blocks:
             if block.get_id() == id:
                 return block
-        raise KeyError('No block with ID {0!r}'.format(id))
-
-    def iter_blocks(self):
-        return ifilter(methodcaller('is_block'), self.get_elements())
-
-    def get_blocks(self):
-        return list(self.iter_blocks())
-
-    def iter_connections(self):
-        return ifilter(methodcaller('is_connection'), self.get_elements())
-
-    def get_connections(self):
-        return list(self.iter_connections())
+        raise KeyError('No block with ID {!r}'.format(id))
 
     def get_elements(self):
         """
@@ -497,75 +207,65 @@ class FlowGraph(Element):
         Returns:
             the element list
         """
-        options_block_count = self._elements.count(self._options_block)
+        options_block_count = self.blocks.count(self._options_block)
         if not options_block_count:
-            self._elements.append(self._options_block)
+            self.blocks.append(self._options_block)
         for i in range(options_block_count-1):
-            self._elements.remove(self._options_block)
-        return self._elements
+            self.blocks.remove(self._options_block)
+
+        return self.blocks + self.connections
 
     get_children = get_elements
 
-    # TODO >>> THIS SUCKS #
     def rewrite(self):
         """
         Flag the namespace to be renewed.
         """
-        def reconnect_bus_blocks():
-            for block in self.get_blocks():
-
-                if 'bus' in map(lambda a: a.get_type(), 
block.get_sources_gui()):
-                    for i in range(len(block.get_sources_gui())):
-                        if len(block.get_sources_gui()[i].get_connections()) > 
0:
-                            source = block.get_sources_gui()[i]
-                            sink = []
 
-                            for j in range(len(source.get_connections())):
-                                
sink.append(source.get_connections()[j].get_sink())
-                            for elt in source.get_connections():
-                                self.remove_element(elt)
-                            for j in sink:
-                                self.connect(source, j)
-        self._renew_eval_ns = True
-
-        def refactor_bus_structure():
-
-            for block in self.get_blocks():
-                for direc in ['source', 'sink']:
-                    if direc == 'source':
-                        get_p = block.get_sources
-                        get_p_gui = block.get_sources_gui
-                        bus_structure = block.form_bus_structure('source')
-                    else:
-                        get_p = block.get_sinks
-                        get_p_gui = block.get_sinks_gui
-                        bus_structure = block.form_bus_structure('sink')
-
-                    if 'bus' in map(lambda a: a.get_type(), get_p_gui()):
-                        if len(get_p_gui()) > len(bus_structure):
-                            times = range(len(bus_structure), len(get_p_gui()))
-                            for i in times:
-                                for connect in 
get_p_gui()[-1].get_connections():
-                                    block.get_parent().remove_element(connect)
-                                get_p().remove(get_p_gui()[-1])
-                        elif len(get_p_gui()) < len(bus_structure):
-                            n = {'name': 'bus', 'type': 'bus'}
-                            if True in map(lambda a: 
isinstance(a.get_nports(), int), get_p()):
-                                n['nports'] = str(1)
-
-                            times = range(len(get_p_gui()), len(bus_structure))
-
-                            for i in times:
-                                n['key'] = str(len(get_p()))
-                                n = odict(n)
-                                port = 
block.get_parent().get_parent().Port(block=block, n=n, dir=direc)
-                                get_p().append(port)
-
-        for child in self.get_children():
+        self.renew_namespace()
+        for child in chain(self.blocks, self.connections):
             child.rewrite()
 
-        refactor_bus_structure()
-        reconnect_bus_blocks()
+        self.bus_ports_rewrite()
+
+    def renew_namespace(self):
+        namespace = {}
+        # Load imports
+        for expr in self.get_imports():
+            try:
+                exec expr in namespace
+            except:
+                pass
+
+        for id, expr in self.get_python_modules():
+            try:
+                module = imp.new_module(id)
+                exec expr in module.__dict__
+                namespace[id] = module
+            except:
+                pass
+
+        # Load parameters
+        np = {}  # params don't know each other
+        for parameter in self.get_parameters():
+            try:
+                value = eval(parameter.get_param('value').to_code(), namespace)
+                np[parameter.get_id()] = value
+            except:
+                pass
+        namespace.update(np)  # Merge param namespace
+
+        # Load variables
+        for variable in self.get_variables():
+            try:
+                value = eval(variable.get_var_value(), namespace)
+                namespace[variable.get_id()] = value
+            except:
+                pass
+
+        self.namespace.clear()
+        self._eval_cache.clear()
+        self.namespace.update(namespace)
 
     def evaluate(self, expr):
         """
@@ -578,66 +278,76 @@ class FlowGraph(Element):
         Returns:
             the evaluated data
         """
-        if self._renew_eval_ns:
-            self._renew_eval_ns = False
-            # Reload namespace
-            n = dict()
-            # Load imports
-            for code in self.get_imports():
-                try:
-                    exec code in n
-                except:
-                    pass
-
-            for id, code in self.get_python_modules():
-                try:
-                    module = imp.new_module(id)
-                    exec code in module.__dict__
-                    n[id] = module
-                except:
-                    pass
-
-            # Load parameters
-            np = dict()
-            for parameter in self.get_parameters():
-                try:
-                    e = eval(parameter.get_param('value').to_code(), n, n)
-                    np[parameter.get_id()] = e
-                except:
-                    pass
-            n.update(np)  # Merge param namespace
-            # Load variables
-            for variable in self.get_variables():
-                try:
-                    e = eval(variable.get_var_value(), n, n)
-                    n[variable.get_id()] = e
-                except:
-                    pass
-            # Make namespace public
-            self.n = n
-            self.n_hash = hash(str(n))
         # Evaluate
-        e = self._eval(expr, self.n, self.n_hash)
-        return e
+        if not expr:
+            raise Exception('Cannot evaluate empty statement.')
+        return self._eval_cache.setdefault(expr, eval(expr, self.namespace))
+
+    ##############################################
+    # Add/remove stuff
+    ##############################################
 
     def get_new_block(self, key):
-        """Try to auto-generate the block from file if missing"""
-        block = self._get_new_block(key)
-        if not block:
-            platform = self.get_parent()
-            # we're before the initial fg rewrite(), so no evaluated values!
-            # --> use raw value instead
-            path_param = self._options_block.get_param('hier_block_src_path')
-            file_path = platform.find_file_in_paths(
-                filename=key + '.' + platform.get_key(),
-                paths=path_param.get_value(),
-                cwd=self.grc_file_path
-            )
-            if file_path:  # grc file found. load and get block
-                platform.load_and_generate_flow_graph(file_path)
-                block = self._get_new_block(key)  # can be None
+        """
+        Get a new block of the specified key.
+        Add the block to the list of elements.
+
+        Args:
+            key: the block key
+
+        Returns:
+            the new block or None if not found
+        """
+        try:
+            block = self.platform.get_new_block(self, key)
+            self.blocks.append(block)
+        except KeyError:
+            block = None
         return block
 
+    def connect(self, porta, portb):
+        """
+        Create a connection between porta and portb.
+
+        Args:
+            porta: a port
+            portb: another port
+        @throw Exception bad connection
+
+        Returns:
+            the new connection
+        """
+
+        connection = self.platform.Connection(
+            flow_graph=self, porta=porta, portb=portb)
+        self.connections.append(connection)
+        return connection
+
+    def remove_element(self, element):
+        """
+        Remove the element from the list of elements.
+        If the element is a port, remove the whole block.
+        If the element is a block, remove its connections.
+        If the element is a connection, just remove the connection.
+        """
+        if element.is_port:
+            # Found a port, set to parent signal block
+            element = element.get_parent()
+
+        if element in self.blocks:
+            # Remove block, remove all involved connections
+            for port in element.get_ports():
+                map(self.remove_element, port.get_connections())
+            self.blocks.remove(element)
+
+        elif element in self.connections:
+            if element.is_bus():
+                cons_list = []
+                for i in map(lambda a: a.get_connections(), 
element.get_source().get_associated_ports()):
+                    cons_list.extend(i)
+                map(self.remove_element, cons_list)
+            self.connections.remove(element)
+
     ##############################################
     # Import/Export Methods
     ##############################################
@@ -650,12 +360,12 @@ class FlowGraph(Element):
             a nested data odict
         """
         # sort blocks and connections for nicer diffs
-        blocks = sorted(self.iter_blocks(), key=lambda b: (
+        blocks = sorted(self.blocks, key=lambda b: (
             b.get_key() != 'options',  # options to the front
             not b.get_key().startswith('variable'),  # then vars
             str(b)
         ))
-        connections = sorted(self.get_connections(), key=str)
+        connections = sorted(self.connections, key=str)
         n = odict()
         n['timestamp'] = self._timestamp
         n['block'] = [b.export_data() for b in blocks]
@@ -676,11 +386,13 @@ class FlowGraph(Element):
             n: the nested data odict
         """
         errors = False
-        self._elements = list()  # remove previous elements
+        # Remove previous elements
+        del self.blocks[:]
+        del self.connections[:]
         # set file format
         try:
             instructions = n.find('_instructions') or {}
-            file_format = int(instructions.get('format', '0')) or 
self._guess_file_format_1(n)
+            file_format = int(instructions.get('format', '0')) or 
_guess_file_format_1(n)
         except:
             file_format = 0
 
@@ -693,6 +405,20 @@ class FlowGraph(Element):
             key = block_n.find('key')
             block = self._options_block if key == 'options' else 
self.get_new_block(key)
 
+            if not block:
+                platform = self.get_parent()
+                # we're before the initial fg rewrite(), so no evaluated 
values!
+                # --> use raw value instead
+                path_param = 
self._options_block.get_param('hier_block_src_path')
+                file_path = platform.find_file_in_paths(
+                    filename=key + '.' + platform.get_key(),
+                    paths=path_param.get_value(),
+                    cwd=self.grc_file_path
+                )
+                if file_path:  # grc file found. load and get block
+                    platform.load_and_generate_flow_graph(file_path)
+                    block = self.get_new_block(key)  # can be None
+
             if not block:  # looks like this block key cannot be found
                 # create a dummy block instead
                 block = self.get_new_block('dummy_block')
@@ -745,40 +471,125 @@ class FlowGraph(Element):
         self.rewrite()  # global rewrite
         return errors
 
-    @staticmethod
-    def _update_old_message_port_keys(source_key, sink_key, source_block, 
sink_block):
-        """
-        Backward compatibility for message port keys
+    ##############################################
+    # Needs to go
+    ##############################################
+    def bus_ports_rewrite(self):
+        # todo: move to block.rewrite()
+        for block in self.blocks:
+            for direc in ['source', 'sink']:
+                if direc == 'source':
+                    get_p = block.get_sources
+                    get_p_gui = block.get_sources_gui
+                    bus_structure = block.form_bus_structure('source')
+                else:
+                    get_p = block.get_sinks
+                    get_p_gui = block.get_sinks_gui
+                    bus_structure = block.form_bus_structure('sink')
+
+                if 'bus' in map(lambda a: a.get_type(), get_p_gui()):
+                    if len(get_p_gui()) > len(bus_structure):
+                        times = range(len(bus_structure), len(get_p_gui()))
+                        for i in times:
+                            for connect in get_p_gui()[-1].get_connections():
+                                block.get_parent().remove_element(connect)
+                            get_p().remove(get_p_gui()[-1])
+                    elif len(get_p_gui()) < len(bus_structure):
+                        n = {'name': 'bus', 'type': 'bus'}
+                        if True in map(
+                                lambda a: isinstance(a.get_nports(), int),
+                                get_p()):
+                            n['nports'] = str(1)
+
+                        times = range(len(get_p_gui()), len(bus_structure))
+
+                        for i in times:
+                            n['key'] = str(len(get_p()))
+                            n = odict(n)
+                            port = block.get_parent().get_parent().Port(
+                                block=block, n=n, dir=direc)
+                            get_p().append(port)
+
+                if 'bus' in map(lambda a: a.get_type(),
+                                block.get_sources_gui()):
+                    for i in range(len(block.get_sources_gui())):
+                        if len(block.get_sources_gui()[
+                                   i].get_connections()) > 0:
+                            source = block.get_sources_gui()[i]
+                            sink = []
+
+                            for j in range(len(source.get_connections())):
+                                sink.append(
+                                    source.get_connections()[j].get_sink())
+                            for elt in source.get_connections():
+                                self.remove_element(elt)
+                            for j in sink:
+                                self.connect(source, j)
 
-        Message ports use their names as key (like in the 'connect' method).
-        Flowgraph files from former versions still have numeric keys stored for
-        message connections. These have to be replaced by the name of the
-        respective port. The correct message port is deduced from the integer
-        value of the key (assuming the order has not changed).
 
-        The connection ends are updated only if both ends translate into a
-        message port.
-        """
-        try:
-            # get ports using the "old way" (assuming liner indexed keys)
-            source_port = source_block.get_sources()[int(source_key)]
-            sink_port = sink_block.get_sinks()[int(sink_key)]
-            if source_port.get_type() == "message" and sink_port.get_type() == 
"message":
-                source_key, sink_key = source_port.get_key(), 
sink_port.get_key()
-        except (ValueError, IndexError):
-            pass
-        return source_key, sink_key  # do nothing
-
-    @staticmethod
-    def _guess_file_format_1(n):
-        """ Try to guess the file format for flow-graph files without version 
tag """
-        try:
-            has_non_numeric_message_keys = any(not (
-                connection_n.find('source_key').isdigit() and
-                connection_n.find('sink_key').isdigit()
-            ) for connection_n in n.find('flow_graph').findall('connection'))
-            if has_non_numeric_message_keys:
-                return 1
-        except:
-            pass
-        return 0
+def _update_old_message_port_keys(source_key, sink_key, source_block, 
sink_block):
+    """
+    Backward compatibility for message port keys
+
+    Message ports use their names as key (like in the 'connect' method).
+    Flowgraph files from former versions still have numeric keys stored for
+    message connections. These have to be replaced by the name of the
+    respective port. The correct message port is deduced from the integer
+    value of the key (assuming the order has not changed).
+
+    The connection ends are updated only if both ends translate into a
+    message port.
+    """
+    try:
+        # get ports using the "old way" (assuming liner indexed keys)
+        source_port = source_block.get_sources()[int(source_key)]
+        sink_port = sink_block.get_sinks()[int(sink_key)]
+        if source_port.get_type() == "message" and sink_port.get_type() == 
"message":
+            source_key, sink_key = source_port.get_key(), sink_port.get_key()
+    except (ValueError, IndexError):
+        pass
+    return source_key, sink_key  # do nothing
+
+
+def _guess_file_format_1(n):
+    """
+    Try to guess the file format for flow-graph files without version tag
+    """
+    try:
+        has_non_numeric_message_keys = any(not (
+            connection_n.find('source_key').isdigit() and
+            connection_n.find('sink_key').isdigit()
+        ) for connection_n in n.find('flow_graph').findall('connection'))
+        if has_non_numeric_message_keys:
+            return 1
+    except:
+        pass
+    return 0
+
+
+def _initialize_dummy_block(block, block_n):
+    """
+    This is so ugly... dummy-fy a block
+    Modify block object to get the behaviour for a missing block
+    """
+
+    block._key = block_n.find('key')
+    block.is_dummy_block = lambda: True
+    block.is_valid = lambda: False
+    block.get_enabled = lambda: False
+    for param_n in block_n.findall('param'):
+        if param_n['key'] not in block.get_param_keys():
+            new_param_n = odict({'key': param_n['key'], 'name': 
param_n['key'], 'type': 'string'})
+            params = block.get_parent().get_parent().Param(block=block, 
n=new_param_n)
+            block.get_params().append(params)
+
+
+def _dummy_block_add_port(block, key, dir):
+    """ This is so ugly... Add a port to a dummy-field block """
+    port_n = odict({'name': '?', 'key': key, 'type': ''})
+    port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir)
+    if port.is_source():
+        block.get_sources().append(port)
+    else:
+        block.get_sinks().append(port)
+    return port
diff --git a/grc/model/Param.py b/grc/model/Param.py
index e00be7e..f064097 100644
--- a/grc/model/Param.py
+++ b/grc/model/Param.py
@@ -121,6 +121,8 @@ class Option(Element):
 
 class Param(Element):
 
+    is_param = True
+
     def __init__(self, block, n):
         """
         Make a new param from nested data.
@@ -666,9 +668,6 @@ class Param(Element):
     def get_tab_label(self):
         return self._tab_label
 
-    def is_param(self):
-        return True
-
     def get_name(self):
         return self.get_parent().resolve_dependencies(self._name).strip()
 
diff --git a/grc/model/Platform.py b/grc/model/Platform.py
index c08a8ed..f04dd04 100644
--- a/grc/model/Platform.py
+++ b/grc/model/Platform.py
@@ -19,25 +19,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
MA  02110-1301, USA
 
 import os
 import sys
-
 from gnuradio import gr
 
-from .Constants import BLOCK_TREE_DTD, FLOW_GRAPH_DTD, DOMAIN_DTD
-from .Element import Element
-
-from . import ParseXML
-from .odict import odict
-
-from . import extract_docs
+from . import ParseXML, extract_docs
 from .Constants import (
+    BLOCK_TREE_DTD, FLOW_GRAPH_DTD, DOMAIN_DTD,
     HIER_BLOCKS_LIB_DIR, BLOCK_DTD, DEFAULT_FLOW_GRAPH, BLOCKS_DIRS,
     PREFS_FILE, CORE_TYPES, PREFS_FILE_OLD,
 )
-from .Generator import Generator
-from .. gui import Messages
+from .Element import Element
+from .odict import odict
+from ..gui import Messages
+from .generator import Generator
 
 
 class Platform(Element):
+
+    is_platform = True
+
     def __init__(self):
         """
         Make a platform for gnuradio.
@@ -341,9 +340,6 @@ class Platform(Element):
     def __str__(self):
         return 'Platform - {}({})'.format(self.get_key(), self.get_name())
 
-    def is_platform(self):
-        return True
-
     def get_new_flow_graph(self):
         return self.FlowGraph(platform=self)
 
diff --git a/grc/model/Port.py b/grc/model/Port.py
index ede7735..bfa4810 100644
--- a/grc/model/Port.py
+++ b/grc/model/Port.py
@@ -100,6 +100,8 @@ def _get_sink_from_virtual_sink_port(vsp, traversed=[]):
 
 class Port(Element):
 
+    is_port = True
+
     def __init__(self, block, n, dir):
         """
         Make a new port from nested data.
@@ -139,9 +141,9 @@ class Port(Element):
         self._clones = []  # References to cloned ports (for nports > 1)
 
     def __str__(self):
-        if self.is_source():
+        if self.is_source:
             return 'Source - {}({})'.format(self.get_name(), self.get_key())
-        if self.is_sink():
+        if self.is_sink:
             return 'Sink - {}({})'.format(self.get_name(), self.get_key())
 
     def get_types(self):
@@ -180,9 +182,11 @@ class Port(Element):
                 # Reset type and vlen
                 self._type = ''
                 self._vlen = ''
+
         Element.rewrite(self)
         hide = 
self.get_parent().resolve_dependencies(self._hide).strip().lower()
         self._hide_evaluated = False if hide in ('false', 'off', '0') else 
bool(hide)
+
         # Update domain if was deduced from (dynamic) port type
         type_ = self.get_type()
         if self._domain == GR_STREAM_DOMAIN and type_ == "message":
@@ -199,7 +203,7 @@ class Port(Element):
             return _get_source_from_virtual_source_port(self)
 
     def resolve_empty_type(self):
-        if self.is_sink():
+        if self.is_sink:
             try:
                 src = _get_source_from_virtual_sink_port(self)
                 if not src.is_type_empty():
@@ -209,7 +213,7 @@ class Port(Element):
             sink = _get_sink_from_virtual_sink_port(self)
             if not sink.is_type_empty():
                 return sink
-        if self.is_source():
+        if self.is_source:
             try:
                 src = _get_source_from_virtual_source_port(self)
                 if not src.is_type_empty():
@@ -344,15 +348,14 @@ class Port(Element):
     def get_key(self):
         return self._key
 
+    @property
     def is_sink(self):
         return self._dir == 'sink'
 
+    @property
     def is_source(self):
         return self._dir == 'source'
 
-    def is_port(self):
-        return True
-
     def get_type(self):
         return self.get_parent().resolve_dependencies(self._type)
 
@@ -369,7 +372,7 @@ class Port(Element):
         Returns:
             a list of connection objects
         """
-        connections = self.get_parent().get_parent().get_connections()
+        connections = self.get_parent().get_parent().connections
         connections = filter(lambda c: c.get_source() is self or c.get_sink() 
is self, connections)
         return connections
 
@@ -386,7 +389,7 @@ class Port(Element):
         if not self.get_type() == 'bus':
             return [self]
         else:
-            if self.is_source():
+            if self.is_source:
                 get_ports = self.get_parent().get_sources
                 bus_structure = 
self.get_parent().current_bus_structure['source']
             else:
diff --git a/grc/model/Generator.py b/grc/model/generator/Generator.py
similarity index 98%
rename from grc/model/Generator.py
rename to grc/model/generator/Generator.py
index f11766f..27cb24a 100644
--- a/grc/model/Generator.py
+++ b/grc/model/generator/Generator.py
@@ -28,17 +28,19 @@ from distutils.spawn import find_executable
 
 from Cheetah.Template import Template
 
-from . import ParseXML
-from .odict import odict
-from .Constants import BLOCK_FLAG_NEED_QT_GUI
+from .. import ParseXML, expr_utils
+from ..odict import odict
 
-from . import expr_utils
-from . Constants import (
-    TOP_BLOCK_FILE_MODE, FLOW_GRAPH_TEMPLATE,
+from grc.model.Constants import (
+    TOP_BLOCK_FILE_MODE, BLOCK_FLAG_NEED_QT_GUI,
     XTERM_EXECUTABLE, HIER_BLOCK_FILE_MODE, HIER_BLOCKS_LIB_DIR, BLOCK_DTD
 )
 
-from .. gui import Messages
+from grc.gui import Messages
+
+
+DATA_DIR = os.path.dirname(__file__)
+FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl')
 
 
 class Generator(object):
@@ -184,7 +186,7 @@ class TopBlockGenerator(object):
             return code
 
         blocks = expr_utils.sort_objects(
-            filter(lambda b: b.get_enabled() and not b.get_bypassed(), 
fg.iter_blocks()),
+            filter(lambda b: b.get_enabled() and not b.get_bypassed(), 
fg.blocks),
             lambda b: b.get_id(), _get_block_sort_text
         )
         # List of regular blocks (all blocks minus the special ones)
diff --git a/grc/model/generator/__init__.py b/grc/model/generator/__init__.py
new file mode 100644
index 0000000..fb1e441
--- /dev/null
+++ b/grc/model/generator/__init__.py
@@ -0,0 +1 @@
+from .Generator import Generator
diff --git a/grc/model/flow_graph.tmpl b/grc/model/generator/flow_graph.tmpl
similarity index 100%
rename from grc/model/flow_graph.tmpl
rename to grc/model/generator/flow_graph.tmpl
diff --git a/grc/model/utils/__init__.py b/grc/model/utils/__init__.py
new file mode 100644
index 0000000..805d6f4
--- /dev/null
+++ b/grc/model/utils/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+""""""
+
+__author__ = "Sebastian Koslowski"
+__email__ = "address@hidden"
+__copyright__ = "Copyright 2015, Sebastian Koslowski"
diff --git a/grc/model/utils/complexity.py b/grc/model/utils/complexity.py
new file mode 100644
index 0000000..baa8040
--- /dev/null
+++ b/grc/model/utils/complexity.py
@@ -0,0 +1,49 @@
+
+def calculate_flowgraph_complexity(flowgraph):
+    """ Determines the complexity of a flowgraph """
+    dbal = 0
+    for block in flowgraph.blocks:
+        # Skip options block
+        if block.get_key() == 'options':
+            continue
+
+        # Don't worry about optional sinks?
+        sink_list = filter(lambda c: not c.get_optional(), block.get_sinks())
+        source_list = filter(lambda c: not c.get_optional(), 
block.get_sources())
+        sinks = float(len(sink_list))
+        sources = float(len(source_list))
+        base = max(min(sinks, sources), 1)
+
+        # Port ratio multiplier
+        if min(sinks, sources) > 0:
+            multi = sinks / sources
+            multi = (1 / multi) if multi > 1 else multi
+        else:
+            multi = 1
+
+        # Connection ratio multiplier
+        sink_multi = max(float(sum(map(lambda c: len(c.get_connections()), 
sink_list)) / max(sinks, 1.0)), 1.0)
+        source_multi = max(float(sum(map(lambda c: len(c.get_connections()), 
source_list)) / max(sources, 1.0)), 1.0)
+        dbal = dbal + (base * multi * sink_multi * source_multi)
+
+    blocks = float(len(flowgraph.blocks))
+    connections = float(len(flowgraph.connections))
+    elements = blocks + connections
+    disabled_connections = len(filter(lambda c: not c.get_enabled(), 
flowgraph.connections))
+    variables = elements - blocks - connections
+    enabled = float(len(flowgraph.get_enabled_blocks()))
+
+    # Disabled multiplier
+    if enabled > 0:
+        disabled_multi = 1 / (max(1 - ((blocks - enabled) / max(blocks, 1)), 
0.05))
+    else:
+        disabled_multi = 1
+
+    # Connection multiplier (How many connections )
+    if (connections - disabled_connections) > 0:
+        conn_multi = 1 / (max(1 - (disabled_connections / max(connections, 
1)), 0.05))
+    else:
+        conn_multi = 1
+
+    final = round(max((dbal - 1) * disabled_multi * conn_multi * connections, 
0.0) / 1000000, 6)
+    return final



reply via email to

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