diff options
author | Sebastian Koslowski <koslowski@kit.edu> | 2016-06-09 14:44:22 +0200 |
---|---|---|
committer | Sebastian Koslowski <koslowski@kit.edu> | 2016-06-10 14:41:52 +0200 |
commit | 435e2b16c903b4a9d16d40ffba649698c4ded190 (patch) | |
tree | a99691a8877b7fc911c9d4b223d26b0f3fa5921b | |
parent | 6375ebf0eb2b619e1a31ec8b8babc3ad0f968dd2 (diff) |
grc-refactor: rewrite tree-api in core
-rw-r--r-- | grc/core/Block.py | 65 | ||||
-rw-r--r-- | grc/core/Connection.py | 14 | ||||
-rw-r--r-- | grc/core/Element.py | 54 | ||||
-rw-r--r-- | grc/core/FlowGraph.py | 56 | ||||
-rw-r--r-- | grc/core/Param.py | 34 | ||||
-rw-r--r-- | grc/core/Platform.py | 8 | ||||
-rw-r--r-- | grc/core/Port.py | 45 | ||||
-rw-r--r-- | grc/core/generator/FlowGraphProxy.py | 2 | ||||
-rw-r--r-- | grc/core/generator/Generator.py | 9 | ||||
-rw-r--r-- | grc/core/generator/flow_graph.tmpl | 4 | ||||
-rw-r--r-- | grc/gui/ActionHandler.py | 5 | ||||
-rw-r--r-- | grc/gui/Block.py | 4 | ||||
-rw-r--r-- | grc/gui/FlowGraph.py | 12 | ||||
-rw-r--r-- | grc/gui/NotebookPage.py | 4 | ||||
-rw-r--r-- | grc/gui/Param.py | 2 | ||||
-rw-r--r-- | grc/gui/ParamWidgets.py | 8 | ||||
-rw-r--r-- | 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 b607f908fb..ff7f041dc0 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 a15fe6a2e8..2309d159c8 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 e697d293fb..a046d6beb4 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 a17d820539..16842595c8 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 a9d495d5a4..b21cbcddf1 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 403c6c87b4..2c0b83dca4 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 b0753910e6..99b5a25508 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 c673c5b005..a23c6d84ab 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 97729b3ada..c3308d6c32 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 21bcb601a2..c86808455b 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 3c6b57b482..8d4dc7841f 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 a6c31cd473..49bba4f3db 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 37a233f825..8e4a26ea7e 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 757dcbc0f8..4745035aff 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 137c5e057b..a630f5faa3 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 e0979e19f3..fbbfa93d1d 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 0fa35573c1..8c4500f960 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): """ |