commit-gnuradio
[Top][All Lists]
Advanced

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

[Commit-gnuradio] [gnuradio] 14/101: grc-refactor: rewrite tree-api in c


From: git
Subject: [Commit-gnuradio] [gnuradio] 14/101: grc-refactor: rewrite tree-api in core
Date: Thu, 16 Mar 2017 14:57:58 +0000 (UTC)

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

jcorgan pushed a commit to branch python3
in repository gnuradio.

commit 435e2b16c903b4a9d16d40ffba649698c4ded190
Author: Sebastian Koslowski <address@hidden>
Date:   Thu Jun 9 14:44:22 2016 +0200

    grc-refactor: rewrite tree-api in core
---
 grc/core/Block.py                    | 65 ++++++++++++++++++------------------
 grc/core/Connection.py               | 14 ++++----
 grc/core/Element.py                  | 54 ++++++++++++++++++++++++++++--
 grc/core/FlowGraph.py                | 56 ++++++++++++-------------------
 grc/core/Param.py                    | 34 +++++++++----------
 grc/core/Platform.py                 |  8 ++---
 grc/core/Port.py                     | 45 +++++++++++++------------
 grc/core/generator/FlowGraphProxy.py |  2 +-
 grc/core/generator/Generator.py      |  9 +++--
 grc/core/generator/flow_graph.tmpl   |  4 +--
 grc/gui/ActionHandler.py             |  5 ++-
 grc/gui/Block.py                     |  4 +--
 grc/gui/FlowGraph.py                 | 12 +++----
 grc/gui/NotebookPage.py              |  4 +--
 grc/gui/Param.py                     |  2 +-
 grc/gui/ParamWidgets.py              |  8 ++---
 grc/gui/Port.py                      | 26 +++++++--------
 17 files changed, 191 insertions(+), 161 deletions(-)

diff --git a/grc/core/Block.py b/grc/core/Block.py
index b607f90..ff7f041 100644
--- a/grc/core/Block.py
+++ b/grc/core/Block.py
@@ -63,18 +63,18 @@ class Block(Element):
         Returns:
             block a new block
         """
-        Element.__init__(self, flow_graph)
+        Element.__init__(self, parent=flow_graph)
 
         self._name = n['name']
         self._key = n['key']
         self._category = n.get('category', '')
         self._flags = n.get('flags', '')
+        self._doc = n.get('doc', '').strip('\n').replace('\\\n', '')
 
         # Backwards compatibility
         if n.get('throttle') and BLOCK_FLAG_THROTTLE not in self._flags:
             self._flags += BLOCK_FLAG_THROTTLE
 
-        self._doc = n.get('doc', '').strip('\n').replace('\\\n', '')
         self._imports = [i.strip() for i in n.get('import', [])]
         self._make = n.get('make')
         self._var_make = n.get('var_make')
@@ -90,7 +90,6 @@ class Block(Element):
         sinks_n = n.get('sink', [])
 
         # Get list of param tabs
-        n_tabs = n.get('param_tab_order', {})
         self._param_tab_labels = n.get('param_tab_order', {}).get('tab') or 
[DEFAULT_PARAM_TAB]
         self._params = []
         self._init_params(
@@ -106,22 +105,12 @@ class Block(Element):
         self._epy_source_hash = -1  # for epy blocks
         self._epy_reload_error = None
 
-        self.back_ofthe_bus(self._sources)
-        self.back_ofthe_bus(self._sinks)
-        self.current_bus_structure = {'source': '', 'sink': ''}
-        self._bus_structure_source = n.get('bus_structure_source', '')
-        self._bus_structure_sink = n.get('bus_structure_sink', '')
-        self._bussify_sink = n.get('bus_sink')
-        self._bussify_source = n.get('bus_source')
-        if self._bussify_sink:
-            self.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
-        if self._bussify_source:
-            self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+        self._init_bus_ports(n)
 
     def _add_param(self, key, name, value='', type='raw', **kwargs):
         n = {'key': key, 'name': name, 'value': value, 'type': type}
         n.update(kwargs)
-        param = self.get_parent().get_parent().Param(block=self, n=n)
+        param = self.parent_platform.Param(block=self, n=n)
         self._params.append(param)
 
     def _init_params(self, params_n, has_sources, has_sinks):
@@ -157,7 +146,7 @@ class Block(Element):
 
         param_keys = set(param.get_key() for param in self._params)
         for param_n in params_n:
-            param = self.get_parent().get_parent().Param(block=self, n=param_n)
+            param = self.parent_platform.Param(block=self, n=param_n)
             key = param.get_key()
             if key in param_keys:
                 raise Exception('Key "{}" already exists in 
params'.format(key))
@@ -168,7 +157,7 @@ class Block(Element):
                         value='', tab=ADVANCED_PARAM_TAB)
 
     def _init_ports(self, ports_n, direction):
-        port_cls = self.get_parent().get_parent().Port
+        port_cls = self.parent_platform.Port
         ports = []
         port_keys = set()
         for port_n in ports_n:
@@ -191,7 +180,7 @@ class Block(Element):
         for check in self._checks:
             check_res = self.resolve_dependencies(check)
             try:
-                if not self.get_parent().evaluate(check_res):
+                if not self.parent.evaluate(check_res):
                     self.add_error_message('Check "{}" failed.'.format(check))
             except:
                 self.add_error_message('Check "{}" did not 
evaluate.'.format(check))
@@ -201,12 +190,12 @@ class Block(Element):
             value = self._var_value
             try:
                 value = self.get_var_value()
-                self.get_parent().evaluate(value)
+                self.parent.evaluate(value)
             except Exception as err:
                 self.add_error_message('Value "{}" cannot be 
evaluated:\n{}'.format(value, err))
 
         # check if this is a GUI block and matches the selected generate option
-        current_generate_option = 
self.get_parent().get_option('generate_options')
+        current_generate_option = self.parent.get_option('generate_options')
 
         def check_generate_mode(label, flag, valid_options):
             block_requires_mode = (
@@ -237,14 +226,14 @@ class Block(Element):
                 num_ports = 1 + len(master_port.get_clones())
                 if master_port.get_hide():
                     for connection in master_port.get_connections():
-                        self.get_parent().remove_element(connection)
+                        self.parent.remove_element(connection)
                 if not nports and num_ports == 1:  # Not a master port and no 
left-over clones
                     continue
                 # Remove excess cloned ports
                 for port in master_port.get_clones()[nports-1:]:
                     # Remove excess connections
                     for connection in port.get_connections():
-                        self.get_parent().remove_element(connection)
+                        self.parent.remove_element(connection)
                     master_port.remove_clone(port)
                     ports.remove(port)
                 # Add more cloned ports
@@ -261,8 +250,7 @@ class Block(Element):
                 domain_specific_port_index[domain] += 1
 
     def get_doc(self):
-        platform = self.get_parent().get_parent()
-        documentation = platform.block_docstrings.get(self._key, {})
+        documentation = self.parent_platform.block_docstrings.get(self._key, 
{})
         from_xml = self._doc.strip()
         if from_xml:
             documentation[''] = from_xml
@@ -280,8 +268,8 @@ class Block(Element):
         """
         if raw:
             return self._imports
-        return [i for i in sum([self.resolve_dependencies(i).split('\n')
-                                for i in self._imports], []) if i]
+        return [i for i in sum((self.resolve_dependencies(i).split('\n')
+                                for i in self._imports), []) if i]
 
     def get_make(self, raw=False):
         if raw:
@@ -319,8 +307,8 @@ class Block(Element):
     ###########################################################################
 
     def rewrite_epy_block(self):
-        flowgraph = self.get_parent()
-        platform = flowgraph.get_parent()
+        flowgraph = self.parent_flowgraph
+        platform = self.parent_block
         param_blk = self.get_param('_io_cache')
         param_src = self.get_param('_source_code')
 
@@ -743,7 +731,7 @@ class Block(Element):
             return ''  # TODO: Don't like empty strings. should change this to 
None eventually
 
         try:
-            clean_bus_structure = self.get_parent().evaluate(bus_structure)
+            clean_bus_structure = self.parent.evaluate(bus_structure)
             return clean_bus_structure
         except:
             return ''
@@ -798,15 +786,13 @@ class Block(Element):
         if direc == 'source':
             get_p = self.get_sources
             get_p_gui = self.get_sources_gui
-            bus_structure = self.get_bus_structure('source')
         else:
             get_p = self.get_sinks
             get_p_gui = self.get_sinks_gui
-            bus_structure = self.get_bus_structure('sink')
 
         for elt in get_p():
             for connect in elt.get_connections():
-                self.get_parent().remove_element(connect)
+                self.parent.remove_element(connect)
 
         if ('bus' not in [a.get_type() for a in get_p()]) and len(get_p()) > 0:
             struct = self.form_bus_structure(direc)
@@ -817,9 +803,22 @@ class Block(Element):
             for i in range(len(struct)):
                 n['key'] = str(len(get_p()))
                 n = dict(n)
-                port = self.get_parent().get_parent().Port(block=self, n=n, 
dir=direc)
+                port = self.parent.parent.Port(block=self, n=n, dir=direc)
                 get_p().append(port)
         elif 'bus' in [a.get_type() for a in get_p()]:
             for elt in get_p_gui():
                 get_p().remove(elt)
             self.current_bus_structure[direc] = ''
+
+    def _init_bus_ports(self, n):
+        self.back_ofthe_bus(self._sources)
+        self.back_ofthe_bus(self._sinks)
+        self.current_bus_structure = {'source': '', 'sink': ''}
+        self._bus_structure_source = n.get('bus_structure_source', '')
+        self._bus_structure_sink = n.get('bus_structure_sink', '')
+        self._bussify_sink = n.get('bus_sink')
+        self._bussify_source = n.get('bus_source')
+        if self._bussify_sink:
+            self.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
+        if self._bussify_source:
+            self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
diff --git a/grc/core/Connection.py b/grc/core/Connection.py
index a15fe6a..2309d15 100644
--- a/grc/core/Connection.py
+++ b/grc/core/Connection.py
@@ -24,7 +24,7 @@ import collections
 from six.moves import range
 
 from . import Constants
-from .Element import Element
+from .Element import Element, lazyproperty
 
 
 class Connection(Element):
@@ -94,7 +94,7 @@ class Connection(Element):
         The ports must match in type.
         """
         Element.validate(self)
-        platform = self.get_parent().get_parent()
+        platform = self.parent_platform
 
         source_domain = self.source_port.get_domain()
         sink_domain = self.sink_port.get_domain()
@@ -131,13 +131,13 @@ class Connection(Element):
         """
         return self.source_block.get_enabled() and 
self.sink_block.get_enabled()
 
-    @property
+    @lazyproperty
     def source_block(self):
-        return self.source_port.get_parent()
+        return self.source_port.parent_block
 
-    @property
+    @lazyproperty
     def sink_block(self):
-        return self.sink_port.get_parent()
+        return self.sink_port.parent_block
 
     ##############################################
     # Import/Export Methods
@@ -171,6 +171,6 @@ class Connection(Element):
 
             for i in range(len(sources)):
                 try:
-                    self.get_parent().connect(sources[i], sinks[i])
+                    self.parent_flowgraph.connect(sources[i], sinks[i])
                 except:
                     pass
diff --git a/grc/core/Element.py b/grc/core/Element.py
index e697d29..a046d6b 100644
--- a/grc/core/Element.py
+++ b/grc/core/Element.py
@@ -17,11 +17,26 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
+import weakref
+
+
+class lazyproperty(object):
+    def __init__(self, func):
+        self.func = func
+
+    def __get__(self, instance, cls):
+        if instance is None:
+            return self
+        else:
+            value = self.func(instance)
+            setattr(instance, self.func.__name__, value)
+            return value
+
 
 class Element(object):
 
     def __init__(self, parent=None):
-        self._parent = parent
+        self._parent = weakref.ref(parent) if parent else lambda: None
         self._error_messages = []
 
     ##################################################
@@ -33,6 +48,7 @@ class Element(object):
         Call this base method before adding error messages in the subclass.
         """
         del self._error_messages[:]
+
         for child in self.get_children():
             child.validate()
 
@@ -88,8 +104,40 @@ class Element(object):
     ##############################################
     # Tree-like API
     ##############################################
-    def get_parent(self):
-        return self._parent
+    @property
+    def parent(self):
+        return self._parent()
+
+    def get_parent_of_type(self, cls):
+        parent = self.parent
+        if parent is None:
+            return None
+        elif isinstance(parent, cls):
+            return parent
+        else:
+            return parent.get_parent_of_type(cls)
+
+    @lazyproperty
+    def parent_platform(self):
+        from .Platform import Platform
+        return self.get_parent_of_type(Platform)
+
+    @lazyproperty
+    def parent_flowgraph(self):
+        from .FlowGraph import FlowGraph
+        return self.get_parent_of_type(FlowGraph)
+
+    @lazyproperty
+    def parent_block(self):
+        from .Block import Block
+        return self.get_parent_of_type(Block)
+
+    def reset_parents(self):
+        """Reset all lazy properties"""
+        # todo: use case?
+        for name, obj in vars(Element):
+            if isinstance(obj, lazyproperty):
+                delattr(self, name)
 
     def get_children(self):
         return list()
diff --git a/grc/core/FlowGraph.py b/grc/core/FlowGraph.py
index a17d820..1684259 100644
--- a/grc/core/FlowGraph.py
+++ b/grc/core/FlowGraph.py
@@ -54,25 +54,20 @@ class FlowGraph(Element):
             the flow graph object
         """
         Element.__init__(self, platform)
-        self._elements = []
         self._timestamp = time.ctime()
+        self._options_block = self.parent_platform.get_new_block(self, 
'options')
 
-        self.platform = platform  # todo: make this a lazy prop
-        self.blocks = []
+        self.blocks = [self._options_block]
         self.connections = []
 
         self._eval_cache = {}
         self.namespace = {}
 
         self.grc_file_path = ''
-        self._options_block = self.new_block('options')
 
     def __str__(self):
         return 'FlowGraph - {}({})'.format(self.get_option('title'), 
self.get_option('id'))
 
-    ##############################################
-    # TODO: Move these to new generator package
-    ##############################################
     def get_imports(self):
         """
         Get a set of all import statements in this flow graph namespace.
@@ -199,19 +194,6 @@ class FlowGraph(Element):
         raise KeyError('No block with ID {!r}'.format(id))
 
     def get_elements(self):
-        """
-        Get a list of all the elements.
-        Always ensure that the options block is in the list (only once).
-
-        Returns:
-            the element list
-        """
-        options_block_count = self.blocks.count(self._options_block)
-        if not options_block_count:
-            self.blocks.append(self._options_block)
-        for _ in range(options_block_count-1):
-            self.blocks.remove(self._options_block)
-
         return self.blocks + self.connections
 
     get_children = get_elements
@@ -220,7 +202,6 @@ class FlowGraph(Element):
         """
         Flag the namespace to be renewed.
         """
-
         self.renew_namespace()
         for child in chain(self.blocks, self.connections):
             child.rewrite()
@@ -297,8 +278,10 @@ class FlowGraph(Element):
         Returns:
             the new block or None if not found
         """
+        if key == 'options':
+            return self._options_block
         try:
-            block = self.platform.get_new_block(self, key)
+            block = self.parent_platform.get_new_block(self, key)
             self.blocks.append(block)
         except KeyError:
             block = None
@@ -317,7 +300,7 @@ class FlowGraph(Element):
             the new connection
         """
 
-        connection = self.platform.Connection(
+        connection = self.parent_platform.Connection(
             flow_graph=self, porta=porta, portb=portb)
         self.connections.append(connection)
         return connection
@@ -329,9 +312,12 @@ class FlowGraph(Element):
         If the element is a block, remove its connections.
         If the element is a connection, just remove the connection.
         """
+        if element is self._options_block:
+            return
+
         if element.is_port:
             # Found a port, set to parent signal block
-            element = element.get_parent()
+            element = element.parent
 
         if element in self.blocks:
             # Remove block, remove all involved connections
@@ -370,7 +356,7 @@ class FlowGraph(Element):
         n['block'] = [b.export_data() for b in blocks]
         n['connection'] = [c.export_data() for c in connections]
         instructions = collections.OrderedDict()
-        instructions['created'] = 
'.'.join(self.get_parent().config.version_parts)
+        instructions['created'] = '.'.join(self.parent.config.version_parts)
         instructions['format'] = FLOW_GRAPH_FILE_FORMAT_VERSION
         return {'flow_graph': n, '_instructions': instructions}
 
@@ -397,22 +383,22 @@ class FlowGraph(Element):
         self._timestamp = fg_n.get('timestamp', time.ctime())
 
         # build the blocks
-        self._options_block = self.new_block('options')
+        self.blocks.append(self._options_block)
         for block_n in fg_n.get('block', []):
             key = block_n['key']
-            block = self._options_block if key == 'options' else 
self.new_block(key)
+            block = self.new_block(key)
 
             if not block:
                 # we're before the initial fg update(), so no evaluated values!
                 # --> use raw value instead
                 path_param = 
self._options_block.get_param('hier_block_src_path')
-                file_path = self.platform.find_file_in_paths(
+                file_path = self.parent_platform.find_file_in_paths(
                     filename=key + '.grc',
                     paths=path_param.get_value(),
                     cwd=self.grc_file_path
                 )
                 if file_path:  # grc file found. load and get block
-                    self.platform.load_and_generate_flow_graph(file_path)
+                    
self.parent_platform.load_and_generate_flow_graph(file_path)
                     block = self.new_block(key)  # can be None
 
             if not block:  # looks like this block key cannot be found
@@ -488,22 +474,22 @@ class FlowGraph(Element):
 
                 if 'bus' in [a.get_type() for a in get_p_gui()]:
                     if len(get_p_gui()) > len(bus_structure):
-                        times = list(range(len(bus_structure), 
len(get_p_gui())))
+                        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)
+                                block.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 any(isinstance(a.get_nports(), int) for a in 
get_p()):
                             n['nports'] = str(1)
 
-                        times = list(range(len(get_p_gui()), 
len(bus_structure)))
+                        times = range(len(get_p_gui()), len(bus_structure))
 
                         for i in times:
                             n['key'] = str(len(get_p()))
                             n = dict(n)
-                            port = block.get_parent().get_parent().Port(
+                            port = block.parent.parent.Port(
                                 block=block, n=n, dir=direc)
                             get_p().append(port)
 
@@ -576,14 +562,14 @@ def _initialize_dummy_block(block, block_n):
     for param_n in block_n.get('param', []):
         if param_n['key'] not in block.get_param_keys():
             new_param_n = {'key': param_n['key'], 'name': param_n['key'], 
'type': 'string'}
-            params = block.get_parent().get_parent().Param(block=block, 
n=new_param_n)
+            params = block.parent_platform.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 = {'name': '?', 'key': key, 'type': ''}
-    port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir)
+    port = block.parent_platform.Port(block=block, n=port_n, dir=dir)
     if port.is_source:
         block.get_sources().append(port)
     else:
diff --git a/grc/core/Param.py b/grc/core/Param.py
index a9d495d..b21cbcd 100644
--- a/grc/core/Param.py
+++ b/grc/core/Param.py
@@ -84,7 +84,7 @@ class Option(Element):
         self._opts = dict()
         opts = n.get('opt', [])
         # Test against opts when non enum
-        if not self.get_parent().is_enum() and opts:
+        if not self.parent.is_enum() and opts:
             raise Exception('Options for non-enum types cannot have 
sub-options')
         # Extract opts
         for opt in opts:
@@ -304,17 +304,17 @@ class Param(Element):
         Returns:
             hide the hide property string
         """
-        hide = self.get_parent().resolve_dependencies(self._hide).strip()
+        hide = self.parent.resolve_dependencies(self._hide).strip()
         if hide:
             return hide
         # Hide ID in non variable blocks
-        if self.get_key() == 'id' and not 
_show_id_matcher.match(self.get_parent().get_key()):
+        if self.get_key() == 'id' and not 
_show_id_matcher.match(self.parent.get_key()):
             return 'part'
         # Hide port controllers for type and nports
-        if self.get_key() in ' '.join([' '.join([p._type, p._nports]) for p in 
self.get_parent().get_ports()]):
+        if self.get_key() in ' '.join([' '.join([p._type, p._nports]) for p in 
self.parent.get_ports()]):
             return 'part'
         # Hide port controllers for vlen, when == 1
-        if self.get_key() in ' '.join(p._vlen for p in 
self.get_parent().get_ports()):
+        if self.get_key() in ' '.join(p._vlen for p in 
self.parent.get_ports()):
             try:
                 if int(self.get_evaluated()) == 1:
                     return 'part'
@@ -369,7 +369,7 @@ class Param(Element):
         elif t in ('raw', 'complex', 'real', 'float', 'int', 'hex', 'bool'):
             # Raise exception if python cannot evaluate this value
             try:
-                e = self.get_parent().get_parent().evaluate(v)
+                e = self.parent_flowgraph.evaluate(v)
             except Exception as e:
                 raise Exception('Value "{}" cannot be 
evaluated:\n{}'.format(v, e))
             # Raise an exception if the data is invalid
@@ -404,7 +404,7 @@ class Param(Element):
                 v = '()'
             # Raise exception if python cannot evaluate this value
             try:
-                e = self.get_parent().get_parent().evaluate(v)
+                e = self.parent.parent.evaluate(v)
             except Exception as e:
                 raise Exception('Value "{}" cannot be 
evaluated:\n{}'.format(v, e))
             # Raise an exception if the data is invalid
@@ -435,7 +435,7 @@ class Param(Element):
         elif t in ('string', 'file_open', 'file_save', '_multiline', 
'_multiline_python_external'):
             # Do not check if file/directory exists, that is a runtime issue
             try:
-                e = self.get_parent().get_parent().evaluate(v)
+                e = self.parent.parent.evaluate(v)
                 if not isinstance(e, str):
                     raise Exception()
             except:
@@ -466,16 +466,16 @@ class Param(Element):
         elif t == 'stream_id':
             # Get a list of all stream ids used in the virtual sinks
             ids = [param.get_value() for param in filter(
-                lambda p: p.get_parent().is_virtual_sink(),
+                lambda p: p.parent.is_virtual_sink(),
                 self.get_all_params(t),
             )]
             # Check that the virtual sink's stream id is unique
-            if self.get_parent().is_virtual_sink():
+            if self.parent.is_virtual_sink():
                 # Id should only appear once, or zero times if block is 
disabled
                 if ids.count(v) > 1:
                     raise Exception('Stream ID "{}" is not unique.'.format(v))
             # Check that the virtual source's steam id is found
-            if self.get_parent().is_virtual_source():
+            if self.parent.is_virtual_source():
                 if v not in ids:
                     raise Exception('Stream ID "{}" is not found.'.format(v))
             return v
@@ -523,7 +523,7 @@ class Param(Element):
             if not v:
                 # Allow for empty grid pos
                 return ''
-            e = self.get_parent().get_parent().evaluate(v)
+            e = self.parent_flowgraph.evaluate(v)
             if not isinstance(e, (list, tuple)) or len(e) != 4 or not 
all([isinstance(ei, int) for ei in e]):
                 raise Exception('A grid position must be a list of 4 
integers.')
             row, col, row_span, col_span = e
@@ -535,7 +535,7 @@ class Param(Element):
                 raise Exception('Row and column span must be greater than 
zero.')
             # Get hostage cell parent
             try:
-                my_parent = self.get_parent().get_param('notebook').evaluate()
+                my_parent = self.parent.get_param('notebook').evaluate()
             except:
                 my_parent = ''
             # Calculate hostage cells
@@ -558,7 +558,7 @@ class Param(Element):
                 return ''
 
             # Get a list of all notebooks
-            notebook_blocks = [b for b in 
self.get_parent().get_parent().get_enabled_blocks() if b.get_key() == 
'notebook']
+            notebook_blocks = [b for b in 
self.parent_flowgraph.get_enabled_blocks() if b.get_key() == 'notebook']
             # Check for notebook param syntax
             try:
                 notebook_id, page_index = map(str.strip, v.split(','))
@@ -634,7 +634,7 @@ class Param(Element):
             a list of params
         """
         params = []
-        for block in self.get_parent().get_parent().get_enabled_blocks():
+        for block in self.parent_flowgraph.get_enabled_blocks():
             params.extend(p for p in block.get_params() if p.get_type() == 
type)
         return params
 
@@ -658,13 +658,13 @@ class Param(Element):
         self._default = str(value)
 
     def get_type(self):
-        return self.get_parent().resolve_dependencies(self._type)
+        return self.parent.resolve_dependencies(self._type)
 
     def get_tab_label(self):
         return self._tab_label
 
     def get_name(self):
-        return self.get_parent().resolve_dependencies(self._name).strip()
+        return self.parent.resolve_dependencies(self._name).strip()
 
     def get_key(self):
         return self._key
diff --git a/grc/core/Platform.py b/grc/core/Platform.py
index 403c6c8..2c0b83d 100644
--- a/grc/core/Platform.py
+++ b/grc/core/Platform.py
@@ -68,10 +68,6 @@ class Platform(Element):
         self._block_dtd = Constants.BLOCK_DTD
         self._default_flow_graph = Constants.DEFAULT_FLOW_GRAPH
 
-        # Create a dummy flow graph for the blocks
-        self._flow_graph = Element(self)
-        self._flow_graph.connections = []
-
         self.blocks = {}
         self._blocks_n = {}
         self._category_trees_n = []
@@ -80,6 +76,10 @@ class Platform(Element):
 
         self._auto_hier_block_generate_chain = set()
 
+        # Create a dummy flow graph for the blocks
+        self._flow_graph = Element.__new__(FlowGraph)
+        Element.__init__(self._flow_graph, self)
+        self._flow_graph.connections = []
         self.load_blocks()
 
     def __str__(self):
diff --git a/grc/core/Port.py b/grc/core/Port.py
index b075391..99b5a25 100644
--- a/grc/core/Port.py
+++ b/grc/core/Port.py
@@ -43,7 +43,7 @@ def _get_source_from_virtual_source_port(vsp, traversed=[]):
     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():
+    if not vsp.parent.is_virtual_source():
         return vsp
     if vsp in traversed:
         raise Exception('Loop found when resolving virtual source 
{}'.format(vsp))
@@ -51,10 +51,10 @@ def _get_source_from_virtual_source_port(vsp, traversed=[]):
         return _get_source_from_virtual_source_port(
             _get_source_from_virtual_sink_port(
                 list(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(),
+                    lambda vs: vs.get_param('stream_id').get_value() == 
vsp.parent.get_param('stream_id').get_value(),
                     list(filter(  # Get all enabled blocks that are also 
virtual sinks
                         lambda b: b.is_virtual_sink(),
-                        vsp.get_parent().get_parent().get_enabled_blocks(),
+                        vsp.parent.parent.get_enabled_blocks(),
                     )),
                 ))[0].get_sinks()[0]
             ), traversed + [vsp],
@@ -81,7 +81,7 @@ def _get_sink_from_virtual_sink_port(vsp, traversed=[]):
     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():
+    if not vsp.parent.is_virtual_sink():
         return vsp
     if vsp in traversed:
         raise Exception('Loop found when resolving virtual sink 
{}'.format(vsp))
@@ -89,10 +89,10 @@ def _get_sink_from_virtual_sink_port(vsp, traversed=[]):
         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(),
+                    lambda vs: vs.get_param('stream_id').get_value() == 
vsp.parent.get_param('stream_id').get_value(),
                     list(filter(  # Get all enabled blocks that are also 
virtual sinks
                         lambda b: b.is_virtual_source(),
-                        vsp.get_parent().get_parent().get_enabled_blocks(),
+                        vsp.parent.parent.get_enabled_blocks(),
                     )),
                 )[0].get_sources()[0]
             ), traversed + [vsp],
@@ -160,7 +160,7 @@ class Port(Element):
         Element.validate(self)
         if self.get_type() not in self.get_types():
             self.add_error_message('Type "{}" is not a possible 
type.'.format(self.get_type()))
-        platform = self.get_parent().get_parent().get_parent()
+        platform = self.parent.parent.parent
         if self.get_domain() not in platform.domains:
             self.add_error_message('Domain key "{}" is not 
registered.'.format(self.get_domain()))
         if not self.get_enabled_connections() and not self.get_optional():
@@ -188,7 +188,7 @@ class Port(Element):
                 self._vlen = ''
 
         Element.rewrite(self)
-        hide = 
self.get_parent().resolve_dependencies(self._hide).strip().lower()
+        hide = self.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
@@ -201,9 +201,9 @@ class Port(Element):
             self._key = '0'  # Is rectified in rewrite()
 
     def resolve_virtual_source(self):
-        if self.get_parent().is_virtual_sink():
+        if self.parent.is_virtual_sink():
             return _get_source_from_virtual_sink_port(self)
-        if self.get_parent().is_virtual_source():
+        if self.parent.is_virtual_source():
             return _get_source_from_virtual_source_port(self)
 
     def resolve_empty_type(self):
@@ -236,9 +236,9 @@ class Port(Element):
         Returns:
             the vector length or 1
         """
-        vlen = self.get_parent().resolve_dependencies(self._vlen)
+        vlen = self.parent.resolve_dependencies(self._vlen)
         try:
-            return int(self.get_parent().get_parent().evaluate(vlen))
+            return int(self.parent.parent.evaluate(vlen))
         except:
             return 1
 
@@ -254,9 +254,9 @@ class Port(Element):
         if self._nports == '':
             return ''
 
-        nports = self.get_parent().resolve_dependencies(self._nports)
+        nports = self.parent.resolve_dependencies(self._nports)
         try:
-            return max(1, int(self.get_parent().get_parent().evaluate(nports)))
+            return max(1, int(self.parent.parent.evaluate(nports)))
         except:
             return 1
 
@@ -325,7 +325,7 @@ class Port(Element):
         n['key'] = '99999' if self._key.isdigit() else n['name']
 
         # Clone
-        port = self.__class__(self.get_parent(), n, self._dir)
+        port = self.__class__(self.parent, n, self._dir)
         self._clones.append(port)
         return port
 
@@ -345,7 +345,7 @@ class Port(Element):
     def get_name(self):
         number = ''
         if self.get_type() == 'bus':
-            busses = [a for a in self.get_parent().get_ports_gui() if a._dir 
== self._dir]
+            busses = [a for a in self.parent.get_ports_gui() if a._dir == 
self._dir]
             number = str(busses.index(self)) + '#' + 
str(len(self.get_associated_ports()))
         return self._name + number
 
@@ -361,7 +361,7 @@ class Port(Element):
         return self._dir == 'source'
 
     def get_type(self):
-        return self.get_parent().resolve_dependencies(self._type)
+        return self.parent_block.resolve_dependencies(self._type)
 
     def get_domain(self):
         return self._domain
@@ -376,7 +376,7 @@ class Port(Element):
         Returns:
             a list of connection objects
         """
-        connections = self.get_parent().get_parent().connections
+        connections = self.parent_flowgraph.connections
         connections = [c for c in connections if c.source_port is self or 
c.sink_port is self]
         return connections
 
@@ -393,12 +393,13 @@ class Port(Element):
         if not self.get_type() == 'bus':
             return [self]
         else:
+            flowgraph = self.parent_flowgraph
             if self.is_source:
-                get_ports = self.get_parent().get_sources
-                bus_structure = 
self.get_parent().current_bus_structure['source']
+                get_ports = flowgraph.get_sources
+                bus_structure = flowgraph.current_bus_structure['source']
             else:
-                get_ports = self.get_parent().get_sinks
-                bus_structure = self.get_parent().current_bus_structure['sink']
+                get_ports = flowgraph.get_sinks
+                bus_structure = flowgraph.current_bus_structure['sink']
 
             ports = [i for i in get_ports() if not i.get_type() == 'bus']
             if bus_structure:
diff --git a/grc/core/generator/FlowGraphProxy.py 
b/grc/core/generator/FlowGraphProxy.py
index c673c5b..a23c6d8 100644
--- a/grc/core/generator/FlowGraphProxy.py
+++ b/grc/core/generator/FlowGraphProxy.py
@@ -117,7 +117,7 @@ class FlowGraphProxy(object):
             # 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 port.parent == pad:
                 if is_message_pad:
                     key = pad.get_param('label').get_value()
                 else:
diff --git a/grc/core/generator/Generator.py b/grc/core/generator/Generator.py
index 97729b3..c3308d6 100644
--- a/grc/core/generator/Generator.py
+++ b/grc/core/generator/Generator.py
@@ -175,7 +175,7 @@ class TopBlockGenerator(object):
         for connection in virtual:
             source = connection.source.resolve_virtual_source()
             sink = connection.sink_port
-            resolved = fg.get_parent().Connection(flow_graph=fg, porta=source, 
portb=sink)
+            resolved = fg.parent.Connection(flow_graph=fg, porta=source, 
portb=sink)
             connections.append(resolved)
             # Remove the virtual connection
             connections.remove(connection)
@@ -202,7 +202,7 @@ class TopBlockGenerator(object):
                     # Ignore disabled connections
                     continue
                 sink_port = sink.sink_port
-                connection = fg.get_parent().Connection(flow_graph=fg, 
porta=source_port, portb=sink_port)
+                connection = fg.parent.Connection(flow_graph=fg, 
porta=source_port, portb=sink_port)
                 connections.append(connection)
                 # Remove this sink connection
                 connections.remove(sink)
@@ -215,7 +215,7 @@ class TopBlockGenerator(object):
             c.source_block.get_id(), c.sink_block.get_id()
         ))
 
-        connection_templates = fg.get_parent().connection_templates
+        connection_templates = fg.parent.connection_templates
         msgs = [c for c in fg.get_enabled_connections() if c.is_msg()]
 
         # List of variable names
@@ -265,9 +265,8 @@ class HierBlockGenerator(TopBlockGenerator):
             file_path: where to write the py file (the xml goes into 
HIER_BLOCK_LIB_DIR)
         """
         TopBlockGenerator.__init__(self, flow_graph, file_path)
-        platform = flow_graph.get_parent()
 
-        hier_block_lib_dir = platform.config.hier_block_lib_dir
+        hier_block_lib_dir = 
flow_graph.parent_platform.config.hier_block_lib_dir
         if not os.path.exists(hier_block_lib_dir):
             os.mkdir(hier_block_lib_dir)
 
diff --git a/grc/core/generator/flow_graph.tmpl 
b/grc/core/generator/flow_graph.tmpl
index 21bcb60..c868084 100644
--- a/grc/core/generator/flow_graph.tmpl
+++ b/grc/core/generator/flow_graph.tmpl
@@ -241,11 +241,11 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), 
[$(', '.join($size_strs))])
 ##  However, port names for IO pads should be self.
 ########################################################
 #def make_port_sig($port)
-    #if $port.get_parent().get_key() in ('pad_source', 'pad_sink')
+    #if $port.parent.get_key() in ('pad_source', 'pad_sink')
         #set block = 'self'
         #set key = $flow_graph.get_pad_port_global_key($port)
     #else
-        #set block = 'self.' + $port.get_parent().get_id()
+        #set block = 'self.' + $port.parent.get_id()
         #set key = $port.get_key()
     #end if
     #if not $key.isdigit()
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 3c6b57b..8d4dc78 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -384,12 +384,11 @@ class ActionHandler:
         # Window stuff
         ##################################################
         elif action == Actions.ABOUT_WINDOW_DISPLAY:
-            platform = flow_graph.get_parent()
-            Dialogs.AboutDialog(platform.config)
+            Dialogs.AboutDialog(self.platform.config)
         elif action == Actions.HELP_WINDOW_DISPLAY:
             Dialogs.HelpDialog()
         elif action == Actions.TYPES_WINDOW_DISPLAY:
-            Dialogs.TypesDialog(flow_graph.get_parent())
+            Dialogs.TypesDialog(self.platform)
         elif action == Actions.ERRORS_WINDOW_DISPLAY:
             Dialogs.ErrorsDialog(flow_graph)
         elif action == Actions.TOGGLE_CONSOLE_WINDOW:
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index a6c31cd..49bba4f 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -181,7 +181,7 @@ class Block(Element, _Block):
 
         # Show the flow graph complexity on the top block if enabled
         if Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY.get_active() and 
self.get_key() == "options":
-            complexity = calculate_flowgraph_complexity(self.get_parent())
+            complexity = calculate_flowgraph_complexity(self.parent)
             markups.append(
                 '<span foreground="#444" size="medium" font_desc="{font}">'
                 '<b>Complexity: 
{num}bal</b></span>'.format(num=num_to_str(complexity), font=BLOCK_FONT)
@@ -201,7 +201,7 @@ class Block(Element, _Block):
         width, height = layout.get_pixel_size()
         if width and height:
             padding = BLOCK_LABEL_PADDING
-            pixmap = self.get_parent().new_pixmap(width + 2 * padding,
+            pixmap = self.parent.new_pixmap(width + 2 * padding,
                                                   height + 2 * padding)
             gc = pixmap.new_gc()
             gc.set_foreground(Colors.COMMENT_BACKGROUND_COLOR)
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index 37a233f..8e4a26e 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -88,12 +88,12 @@ class FlowGraph(Element, _Flowgraph):
         return block_id
 
     def install_external_editor(self, param):
-        target = (param.get_parent().get_id(), param.get_key())
+        target = (param.parent_block.get_id(), param.get_key())
 
         if target in self._external_updaters:
             editor = self._external_updaters[target]
         else:
-            config = self.get_parent().config
+            config = self.parent_platform.config
             editor = (find_executable(config.editor) or
                       Dialogs.ChooseEditorDialog(config))
             if not editor:
@@ -112,7 +112,7 @@ class FlowGraph(Element, _Flowgraph):
             # Problem launching the editor. Need to select a new editor.
             Messages.send('>>> Error opening an external editor. Please select 
a different editor.\n')
             # Reset the editor to force the user to select a new one.
-            self.get_parent().config.editor = ''
+            self.parent_platform.config.editor = ''
 
     def handle_external_editor_change(self, new_value, target):
         try:
@@ -452,9 +452,9 @@ class FlowGraph(Element, _Flowgraph):
         for selected in selected_elements:
             if selected in elements: continue
             selected_elements.remove(selected)
-        if self._old_selected_port and self._old_selected_port.get_parent() 
not in elements:
+        if self._old_selected_port and self._old_selected_port.parent not in 
elements:
             self._old_selected_port = None
-        if self._new_selected_port and self._new_selected_port.get_parent() 
not in elements:
+        if self._new_selected_port and self._new_selected_port.parent not in 
elements:
             self._new_selected_port = None
         #update highlighting
         for element in elements:
@@ -532,7 +532,7 @@ class FlowGraph(Element, _Flowgraph):
             #update the selected port information
             if selected_element.is_port:
                 if not coor_m: selected_port = selected_element
-                selected_element = selected_element.get_parent()
+                selected_element = selected_element.parent_block
             selected.add(selected_element)
             #place at the end of the list
             self.get_elements().remove(element)
diff --git a/grc/gui/NotebookPage.py b/grc/gui/NotebookPage.py
index 757dcbc..4745035 100644
--- a/grc/gui/NotebookPage.py
+++ b/grc/gui/NotebookPage.py
@@ -49,7 +49,7 @@ class NotebookPage(Gtk.HBox):
         self.saved = True
 
         # import the file
-        initial_state = flow_graph.get_parent().parse_flow_graph(file_path)
+        initial_state = flow_graph.parent_platform.parse_flow_graph(file_path)
         flow_graph.import_data(initial_state)
         self.state_cache = StateCache(initial_state)
 
@@ -97,7 +97,7 @@ class NotebookPage(Gtk.HBox):
         Returns:
             generator
         """
-        platform = self.flow_graph.get_parent()
+        platform = self.flow_graph.parent_platform
         return platform.Generator(self.flow_graph, self.file_path)
 
     def _handle_button(self, button):
diff --git a/grc/gui/Param.py b/grc/gui/Param.py
index 137c5e0..a630f5f 100644
--- a/grc/gui/Param.py
+++ b/grc/gui/Param.py
@@ -62,7 +62,7 @@ class Param(Element, _Param):
         return input_widget_cls(self, *args, **kwargs)
 
     def format_label_markup(self, have_pending_changes=False):
-        block = self.get_parent()
+        block = self.parent
         # fixme: using non-public attribute here
         has_callback = \
             hasattr(block, 'get_callbacks') and \
diff --git a/grc/gui/ParamWidgets.py b/grc/gui/ParamWidgets.py
index e0979e1..fbbfa93 100644
--- a/grc/gui/ParamWidgets.py
+++ b/grc/gui/ParamWidgets.py
@@ -173,8 +173,7 @@ class PythonEditorParam(InputParam):
         self.pack_start(button, True)
 
     def open_editor(self, widget=None):
-        flowgraph = self.param.get_parent().get_parent()
-        flowgraph.install_external_editor(self.param)
+        self.param.parent_flowgraph.install_external_editor(self.param)
 
     def get_text(self):
         pass  # we never update the value from here
@@ -274,9 +273,8 @@ class FileParam(EntryParam):
         if self.param.get_key() == 'qt_qss_theme':
             dirname = os.path.dirname(dirname)  # trim filename
             if not os.path.exists(dirname):
-               platform = self.param.get_parent().get_parent().get_parent()
-               dirname = os.path.join(platform.config.install_prefix,
-                                      '/share/gnuradio/themes')
+               config = self.param.parent_platform.config
+               dirname = os.path.join(config.install_prefix, 
'/share/gnuradio/themes')
         if not os.path.exists(dirname):
             dirname = os.getcwd()  # fix bad paths
 
diff --git a/grc/gui/Port.py b/grc/gui/Port.py
index 0fa3557..8c4500f 100644
--- a/grc/gui/Port.py
+++ b/grc/gui/Port.py
@@ -67,8 +67,8 @@ class Port(_Port, Element):
         #get current rotation
         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()
+        ports = self.parent.get_sources_gui() \
+            if self.is_source else self.parent.get_sinks_gui()
         ports = [p for p in ports if not p.get_hide()]
         #get the max width
         self.W = max([port.W for port in ports] + [PORT_MIN_WIDTH])
@@ -85,10 +85,10 @@ class Port(_Port, Element):
             index = len(ports)-index-1
 
         port_separation = PORT_SEPARATION \
-            if not self.get_parent().has_busses[self.is_source] \
+            if not self.parent.has_busses[self.is_source] \
             else max([port.H for port in ports]) + PORT_SPACING
 
-        offset = (self.get_parent().H - (len(ports)-1)*port_separation - 
self.H)/2
+        offset = (self.parent.H - (len(ports)-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):
             x = -W
@@ -96,7 +96,7 @@ class Port(_Port, Element):
             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):
-            x = self.get_parent().W
+            x = self.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)
@@ -106,7 +106,7 @@ class Port(_Port, Element):
             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):
-            y = self.get_parent().W
+            y = self.parent.W
             x = port_separation*index+offset
             self.add_area((x, y), (self.H, W))
             self._connector_coordinate = (x+self.H/2, y+1+W)
@@ -125,7 +125,7 @@ class Port(_Port, Element):
         """
         border_color = (
             Colors.HIGHLIGHT_COLOR if self.is_highlighted() else
-            Colors.MISSING_BLOCK_BORDER_COLOR if 
self.get_parent().is_dummy_block else
+            Colors.MISSING_BLOCK_BORDER_COLOR if self.parent.is_dummy_block 
else
             Colors.BORDER_COLOR
         )
         Element.draw(self, widget, cr, border_color, self._bg_color)
@@ -186,7 +186,7 @@ class Port(_Port, Element):
         Returns:
             the parent's rotation
         """
-        return self.get_parent().get_rotation()
+        return self.parent.get_rotation()
 
     def move(self, delta_coor):
         """
@@ -195,7 +195,7 @@ class Port(_Port, Element):
         Args:
             delta_corr: the (delta_x, delta_y) tuple
         """
-        self.get_parent().move(delta_coor)
+        self.parent.move(delta_coor)
 
     def rotate(self, direction):
         """
@@ -204,7 +204,7 @@ class Port(_Port, Element):
         Args:
             direction: degrees to rotate
         """
-        self.get_parent().rotate(direction)
+        self.parent.rotate(direction)
 
     def get_coordinate(self):
         """
@@ -213,7 +213,7 @@ class Port(_Port, Element):
         Returns:
             the parents coordinate
         """
-        return self.get_parent().get_coordinate()
+        return self.parent.get_coordinate()
 
     def set_highlighted(self, highlight):
         """
@@ -222,7 +222,7 @@ class Port(_Port, Element):
         Args:
             highlight: true to enable highlighting
         """
-        self.get_parent().set_highlighted(highlight)
+        self.parent.set_highlighted(highlight)
 
     def is_highlighted(self):
         """
@@ -231,7 +231,7 @@ class Port(_Port, Element):
         Returns:
             the parent's highlighting status
         """
-        return self.get_parent().is_highlighted()
+        return self.parent.is_highlighted()
 
     def _label_hidden(self):
         """



reply via email to

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