diff options
Diffstat (limited to 'grc/core/FlowGraph.py')
-rw-r--r-- | grc/core/FlowGraph.py | 157 |
1 files changed, 71 insertions, 86 deletions
diff --git a/grc/core/FlowGraph.py b/grc/core/FlowGraph.py index 949eecaa71..67e86f3e6e 100644 --- a/grc/core/FlowGraph.py +++ b/grc/core/FlowGraph.py @@ -15,17 +15,21 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +from __future__ import absolute_import, print_function + import imp import time -from itertools import ifilter, chain +import re +from itertools import chain from operator import methodcaller, attrgetter +import collections -import re +from six.moves import filter from . import Messages from .Constants import FLOW_GRAPH_FILE_FORMAT_VERSION from .Element import Element -from .utils import odict, expr_utils +from .utils import expr_utils _parameter_matcher = re.compile('^(parameter)$') _monitors_searcher = re.compile('(ctrlport_monitor)') @@ -49,26 +53,21 @@ class FlowGraph(Element): Returns: the flow graph object """ - Element.__init__(self, platform) - self._elements = [] + Element.__init__(self, parent=platform) 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. @@ -87,7 +86,7 @@ class FlowGraph(Element): Returns: a sorted list of variable blocks in order of dependency (indep -> dep) """ - variables = filter(attrgetter('is_variable'), self.iter_enabled_blocks()) + variables = list(filter(attrgetter('is_variable'), self.iter_enabled_blocks())) return expr_utils.sort_objects(variables, methodcaller('get_id'), methodcaller('get_var_make')) def get_parameters(self): @@ -97,15 +96,14 @@ class FlowGraph(Element): Returns: a list of parameterized variables """ - parameters = filter(lambda b: _parameter_matcher.match(b.get_key()), self.iter_enabled_blocks()) + parameters = [b for b in self.iter_enabled_blocks() if _parameter_matcher.match(b.get_key())] return parameters def get_monitors(self): """ Get a list of all ControlPort monitors """ - monitors = filter(lambda b: _monitors_searcher.search(b.get_key()), - self.iter_enabled_blocks()) + monitors = [b for b in self.iter_enabled_blocks() if _monitors_searcher.search(b.get_key())] return monitors def get_python_modules(self): @@ -115,7 +113,7 @@ class FlowGraph(Element): yield block.get_id(), block.get_param('source_code').get_value() def get_bussink(self): - bussink = filter(lambda b: _bussink_searcher.search(b.get_key()), self.get_enabled_blocks()) + bussink = [b for b in self.get_enabled_blocks() if _bussink_searcher.search(b.get_key())] for i in bussink: for j in i.get_params(): @@ -124,7 +122,7 @@ class FlowGraph(Element): return False def get_bussrc(self): - bussrc = filter(lambda b: _bussrc_searcher.search(b.get_key()), self.get_enabled_blocks()) + bussrc = [b for b in self.get_enabled_blocks() if _bussrc_searcher.search(b.get_key())] for i in bussrc: for j in i.get_params(): @@ -133,18 +131,18 @@ class FlowGraph(Element): return False def get_bus_structure_sink(self): - bussink = filter(lambda b: _bus_struct_sink_searcher.search(b.get_key()), self.get_enabled_blocks()) + bussink = [b for b in self.get_enabled_blocks() if _bus_struct_sink_searcher.search(b.get_key())] return bussink def get_bus_structure_src(self): - bussrc = filter(lambda b: _bus_struct_src_searcher.search(b.get_key()), self.get_enabled_blocks()) + bussrc = [b for b in self.get_enabled_blocks() if _bus_struct_src_searcher.search(b.get_key())] return bussrc def iter_enabled_blocks(self): """ Get an iterator of all blocks that are enabled and not bypassed. """ - return ifilter(methodcaller('get_enabled'), self.blocks) + return filter(methodcaller('get_enabled'), self.blocks) def get_enabled_blocks(self): """ @@ -162,7 +160,7 @@ class FlowGraph(Element): Returns: a list of blocks """ - return filter(methodcaller('get_bypassed'), self.blocks) + return list(filter(methodcaller('get_bypassed'), self.blocks)) def get_enabled_connections(self): """ @@ -171,7 +169,7 @@ class FlowGraph(Element): Returns: a list of connections """ - return filter(methodcaller('get_enabled'), self.connections) + return list(filter(methodcaller('get_enabled'), self.connections)) def get_option(self, key): """ @@ -196,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 i in range(options_block_count-1): - self.blocks.remove(self._options_block) - return self.blocks + self.connections get_children = get_elements @@ -217,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() @@ -229,14 +213,14 @@ class FlowGraph(Element): # Load imports for expr in self.get_imports(): try: - exec expr in namespace + exec(expr, namespace) except: pass for id, expr in self.get_python_modules(): try: module = imp.new_module(id) - exec expr in module.__dict__ + exec(expr, module.__dict__) namespace[id] = module except: pass @@ -294,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 @@ -314,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 @@ -326,22 +312,25 @@ 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 for port in element.get_ports(): - map(self.remove_element, port.get_connections()) + for connection in port.get_connections(): + self.remove_element(connection) self.blocks.remove(element) elif element in self.connections: if element.is_bus(): - cons_list = [] - for i in map(lambda a: a.get_connections(), element.get_source().get_associated_ports()): - cons_list.extend(i) - map(self.remove_element, cons_list) + for port in element.source_port.get_associated_ports(): + for connection in port.get_connections(): + self.remove_element(connection) self.connections.remove(element) ############################################## @@ -362,20 +351,19 @@ class FlowGraph(Element): str(b) )) connections = sorted(self.connections, key=str) - n = odict() + n = collections.OrderedDict() n['timestamp'] = self._timestamp n['block'] = [b.export_data() for b in blocks] n['connection'] = [c.export_data() for c in connections] - instructions = odict({ - 'created': '.'.join(self.get_parent().config.version_parts), - 'format': FLOW_GRAPH_FILE_FORMAT_VERSION, - }) - return odict({'flow_graph': n, '_instructions': instructions}) + instructions = collections.OrderedDict() + instructions['created'] = '.'.join(self.parent.config.version_parts) + instructions['format'] = FLOW_GRAPH_FILE_FORMAT_VERSION + return {'flow_graph': n, '_instructions': instructions} def import_data(self, n): """ Import blocks and connections into this flow graph. - Clear this flowgraph of all previous blocks and connections. + Clear this flow graph of all previous blocks and connections. Any blocks or connections in error will be ignored. Args: @@ -386,31 +374,31 @@ class FlowGraph(Element): del self.connections[:] # set file format try: - instructions = n.find('_instructions') or {} + instructions = n.get('_instructions', {}) file_format = int(instructions.get('format', '0')) or _guess_file_format_1(n) except: file_format = 0 - fg_n = n and n.find('flow_graph') or odict() # use blank data if none provided - self._timestamp = fg_n.find('timestamp') or time.ctime() + fg_n = n and n.get('flow_graph', {}) # use blank data if none provided + self._timestamp = fg_n.get('timestamp', time.ctime()) # build the blocks - self._options_block = self.new_block('options') - for block_n in fg_n.findall('block'): - key = block_n.find('key') - block = self._options_block if key == 'options' else self.new_block(key) + self.blocks.append(self._options_block) + for block_n in fg_n.get('block', []): + key = block_n['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 @@ -440,12 +428,12 @@ class FlowGraph(Element): return port errors = False - for connection_n in fg_n.findall('connection'): + for connection_n in fg_n.get('connection', []): # get the block ids and port keys - source_block_id = connection_n.find('source_block_id') - sink_block_id = connection_n.find('sink_block_id') - source_key = connection_n.find('source_key') - sink_key = connection_n.find('sink_key') + source_block_id = connection_n.get('source_block_id') + sink_block_id = connection_n.get('sink_block_id') + source_key = connection_n.get('source_key') + sink_key = connection_n.get('sink_key') try: source_block = self.get_block(source_block_id) sink_block = self.get_block(sink_block_id) @@ -484,31 +472,28 @@ class FlowGraph(Element): get_p_gui = block.get_sinks_gui bus_structure = block.form_bus_structure('sink') - if 'bus' in map(lambda a: a.get_type(), get_p_gui()): + if 'bus' in [a.get_type() for a in get_p_gui()]: if len(get_p_gui()) > len(bus_structure): times = range(len(bus_structure), len(get_p_gui())) for i in times: for connect in get_p_gui()[-1].get_connections(): - block.get_parent().remove_element(connect) + 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 True in map( - lambda a: isinstance(a.get_nports(), int), - get_p()): + if any(isinstance(a.get_nports(), int) for a in get_p()): n['nports'] = str(1) times = range(len(get_p_gui()), len(bus_structure)) for i in times: n['key'] = str(len(get_p())) - n = odict(n) - port = block.get_parent().get_parent().Port( + n = dict(n) + port = block.parent.parent.Port( block=block, n=n, dir=direc) get_p().append(port) - if 'bus' in map(lambda a: a.get_type(), - block.get_sources_gui()): + if 'bus' in [a.get_type() for a in block.get_sources_gui()]: for i in range(len(block.get_sources_gui())): if len(block.get_sources_gui()[ i].get_connections()) > 0: @@ -517,7 +502,7 @@ class FlowGraph(Element): for j in range(len(source.get_connections())): sink.append( - source.get_connections()[j].get_sink()) + source.get_connections()[j].sink_port) for elt in source.get_connections(): self.remove_element(elt) for j in sink: @@ -554,9 +539,9 @@ def _guess_file_format_1(n): """ try: has_non_numeric_message_keys = any(not ( - connection_n.find('source_key').isdigit() and - connection_n.find('sink_key').isdigit() - ) for connection_n in n.find('flow_graph').findall('connection')) + connection_n.get('source_key', '').isdigit() and + connection_n.get('sink_key', '').isdigit() + ) for connection_n in n.get('flow_graph', []).get('connection', [])) if has_non_numeric_message_keys: return 1 except: @@ -570,21 +555,21 @@ def _initialize_dummy_block(block, block_n): Modify block object to get the behaviour for a missing block """ - block._key = block_n.find('key') + block._key = block_n.get('key') block.is_dummy_block = lambda: True block.is_valid = lambda: False block.get_enabled = lambda: False - for param_n in block_n.findall('param'): + for param_n in block_n.get('param', []): if param_n['key'] not in block.get_param_keys(): - new_param_n = odict({'key': param_n['key'], 'name': param_n['key'], 'type': 'string'}) - params = block.get_parent().get_parent().Param(block=block, n=new_param_n) + new_param_n = {'key': param_n['key'], 'name': param_n['key'], 'type': 'string'} + 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 = odict({'name': '?', 'key': key, 'type': ''}) - port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir) + port_n = {'name': '?', 'key': key, 'type': ''} + port = block.parent_platform.Port(block=block, n=port_n, dir=dir) if port.is_source: block.get_sources().append(port) else: |