diff options
author | Sebastian Koslowski <koslowski@kit.edu> | 2016-06-03 16:17:57 +0200 |
---|---|---|
committer | Sebastian Koslowski <koslowski@kit.edu> | 2016-06-09 14:49:12 +0200 |
commit | 963773b800655f2902998aedce8d46605d54e60f (patch) | |
tree | 684d4ed1119dab875c21e400152c1df6ef61d4e1 | |
parent | 94c4606edd30dc8b1278580782f2809b69f04641 (diff) |
grc-refactor: remove odict
-rw-r--r-- | grc/core/Block.py | 69 | ||||
-rw-r--r-- | grc/core/Connection.py | 5 | ||||
-rw-r--r-- | grc/core/FlowGraph.py | 52 | ||||
-rw-r--r-- | grc/core/Param.py | 26 | ||||
-rw-r--r-- | grc/core/ParseXML.py | 50 | ||||
-rw-r--r-- | grc/core/Platform.py | 55 | ||||
-rw-r--r-- | grc/core/Port.py | 17 | ||||
-rw-r--r-- | grc/core/generator/Generator.py | 26 | ||||
-rw-r--r-- | grc/core/utils/__init__.py | 1 | ||||
-rw-r--r-- | grc/core/utils/odict.py | 113 | ||||
-rw-r--r-- | grc/gui/FlowGraph.py | 12 |
11 files changed, 172 insertions, 254 deletions
diff --git a/grc/core/Block.py b/grc/core/Block.py index 062598e9d1..b607f908fb 100644 --- a/grc/core/Block.py +++ b/grc/core/Block.py @@ -26,7 +26,7 @@ from six.moves import map, range from Cheetah.Template import Template -from .utils import epy_block_io, odict +from .utils import epy_block_io from . Constants import ( BLOCK_FLAG_NEED_QT_GUI, BLOCK_FLAG_NEED_WX_GUI, ADVANCED_PARAM_TAB, DEFAULT_PARAM_TAB, @@ -64,33 +64,34 @@ class Block(Element): block a new block """ Element.__init__(self, flow_graph) - self._name = n.find('name') - self._key = n.find('key') - self._category = n.find('category') or '' - self._flags = n.find('flags') or '' + + self._name = n['name'] + self._key = n['key'] + self._category = n.get('category', '') + self._flags = n.get('flags', '') # Backwards compatibility - if n.find('throttle') and BLOCK_FLAG_THROTTLE not in self._flags: + if n.get('throttle') and BLOCK_FLAG_THROTTLE not in self._flags: self._flags += BLOCK_FLAG_THROTTLE - self._doc = (n.find('doc') or '').strip('\n').replace('\\\n', '') - self._imports = [i.strip() for i in n.findall('import')] - self._make = n.find('make') - self._var_make = n.find('var_make') - self._var_value = n.find('var_value') or '$value' - self._checks = n.findall('check') - self._callbacks = n.findall('callback') + 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') + self._var_value = n.get('var_value', '$value') + self._checks = n.get('check', []) + self._callbacks = n.get('callback', []) - self._grc_source = n.find('grc_source') or '' - self._block_wrapper_path = n.find('block_wrapper_path') + self._grc_source = n.get('grc_source', '') + self._block_wrapper_path = n.get('block_wrapper_path') - params_n = n.findall('param') - sources_n = n.findall('source') - sinks_n = n.findall('sink') + params_n = n.get('param', []) + sources_n = n.get('source', []) + sinks_n = n.get('sink', []) # Get list of param tabs - n_tabs = n.find('param_tab_order') or None - self._param_tab_labels = n_tabs.findall('tab') if n_tabs is not None else [DEFAULT_PARAM_TAB] + 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( params_n=params_n, @@ -108,17 +109,17 @@ class Block(Element): self.back_ofthe_bus(self._sources) self.back_ofthe_bus(self._sinks) self.current_bus_structure = {'source': '', 'sink': ''} - self._bus_structure_source = n.find('bus_structure_source') or '' - self._bus_structure_sink = n.find('bus_structure_sink') or '' - self._bussify_sink = n.find('bus_sink') - self._bussify_source = n.find('bus_source') + 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') def _add_param(self, key, name, value='', type='raw', **kwargs): - n = odict({'key': key, 'name': name, 'value': value, 'type': type}) + n = {'key': key, 'name': name, 'value': value, 'type': type} n.update(kwargs) param = self.get_parent().get_parent().Param(block=self, n=n) self._params.append(param) @@ -366,7 +367,7 @@ class Block(Element): param.set_default(value) except KeyError: # need to make a new param name = key.replace('_', ' ').title() - n = odict(dict(name=name, key=key, type='raw', value=value)) + n = dict(name=name, key=key, type='raw', value=value) param = platform.Param(block=self, n=n) setattr(param, '__epy_param__', True) self._params.append(param) @@ -386,7 +387,7 @@ class Block(Element): ports_to_remove.remove(port_current) port, port_current = port_current, next(iter_ports, None) else: - n = odict(dict(name=label + str(key), type=port_type, key=key)) + n = dict(name=label + str(key), type=port_type, key=key) if port_type == 'message': n['name'] = key n['optional'] = '1' @@ -684,7 +685,7 @@ class Block(Element): Returns: a nested data odict """ - n = odict() + n = collections.OrderedDict() n['key'] = self.get_key() n['param'] = [p.export_data() for p in sorted(self.get_params(), key=str)] if 'bus' in [a.get_type() for a in self.get_sinks()]: @@ -705,7 +706,7 @@ class Block(Element): Args: n: the nested data odict """ - params_n = n.findall('param') + params_n = n.get('param', []) params = dict((param.get_key(), param) for param in self._params) def get_hash(): @@ -714,8 +715,8 @@ class Block(Element): my_hash = 0 while get_hash() != my_hash: for param_n in params_n: - key = param_n.find('key') - value = param_n.find('value') + key = param_n['key'] + value = param_n['value'] try: params[key].set_value(value) except KeyError: @@ -755,13 +756,13 @@ class Block(Element): return buslist or ports def _import_bus_stuff(self, n): - bussinks = n.findall('bus_sink') + bussinks = n.get('bus_sink', []) if len(bussinks) > 0 and not self._bussify_sink: self.bussify({'name': 'bus', 'type': 'bus'}, 'sink') elif len(bussinks) > 0: self.bussify({'name': 'bus', 'type': 'bus'}, 'sink') self.bussify({'name': 'bus', 'type': 'bus'}, 'sink') - bussrcs = n.findall('bus_source') + bussrcs = n.get('bus_source', []) if len(bussrcs) > 0 and not self._bussify_source: self.bussify({'name': 'bus', 'type': 'bus'}, 'source') elif len(bussrcs) > 0: @@ -815,7 +816,7 @@ class Block(Element): for i in range(len(struct)): n['key'] = str(len(get_p())) - n = odict(n) + n = dict(n) port = self.get_parent().get_parent().Port(block=self, n=n, dir=direc) get_p().append(port) elif 'bus' in [a.get_type() for a in get_p()]: diff --git a/grc/core/Connection.py b/grc/core/Connection.py index ddc6c0256f..9ae99debe7 100644 --- a/grc/core/Connection.py +++ b/grc/core/Connection.py @@ -19,11 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA from __future__ import absolute_import +import collections + from six.moves import range from . import Constants from .Element import Element -from .utils import odict class Connection(Element): @@ -157,7 +158,7 @@ class Connection(Element): Returns: a nested data odict """ - n = odict() + n = collections.OrderedDict() n['source_block_id'] = self.get_source().get_parent().get_id() n['sink_block_id'] = self.get_sink().get_parent().get_id() n['source_key'] = self.get_source().get_key() diff --git a/grc/core/FlowGraph.py b/grc/core/FlowGraph.py index 9edd4f24d8..b0f52dbe74 100644 --- a/grc/core/FlowGraph.py +++ b/grc/core/FlowGraph.py @@ -22,13 +22,14 @@ import time import re from itertools import chain from operator import methodcaller, attrgetter +import collections 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)') @@ -364,20 +365,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.get_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: @@ -388,18 +388,18 @@ 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') + for block_n in fg_n.get('block', []): + key = block_n['key'] block = self._options_block if key == 'options' else self.new_block(key) if not block: @@ -442,12 +442,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) @@ -502,7 +502,7 @@ class FlowGraph(Element): for i in times: n['key'] = str(len(get_p())) - n = odict(n) + n = dict(n) port = block.get_parent().get_parent().Port( block=block, n=n, dir=direc) get_p().append(port) @@ -553,9 +553,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: @@ -569,20 +569,20 @@ 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'}) + 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) 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_n = {'name': '?', 'key': key, 'type': ''} port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir) if port.is_source: block.get_sources().append(port) diff --git a/grc/core/Param.py b/grc/core/Param.py index 45f0187d27..a9d495d5a4 100644 --- a/grc/core/Param.py +++ b/grc/core/Param.py @@ -22,12 +22,12 @@ from __future__ import absolute_import import ast import weakref import re +import collections from six.moves import builtins, filter, map, range, zip from . import Constants from .Element import Element -from .utils import odict # Blacklist certain ids, its not complete, but should help ID_BLACKLIST = ['self', 'options', 'gr', 'blks2', 'wxgui', 'wx', 'math', 'forms', 'firdes'] + dir(builtins) @@ -79,10 +79,10 @@ class Option(Element): def __init__(self, param, n): Element.__init__(self, param) - self._name = n.find('name') - self._key = n.find('key') + self._name = n.get('name') + self._key = n.get('key') self._opts = dict() - opts = n.findall('opt') + opts = n.get('opt', []) # Test against opts when non enum if not self.get_parent().is_enum() and opts: raise Exception('Options for non-enum types cannot have sub-options') @@ -155,7 +155,7 @@ class Param(Element): n: the nested odict """ # If the base key is a valid param key, copy its data and overlay this params data - base_key = n.find('base_key') + base_key = n.get('base_key') if base_key and base_key in block.get_param_keys(): n_expanded = block.get_param(base_key)._n.copy() n_expanded.update(n) @@ -163,12 +163,12 @@ class Param(Element): # Save odict in case this param will be base for another self._n = n # Parse the data - self._name = n.find('name') - self._key = n.find('key') - value = n.find('value') or '' - self._type = n.find('type') or 'raw' - self._hide = n.find('hide') or '' - self._tab_label = n.find('tab') or block.get_param_tab_labels()[0] + self._name = n['name'] + self._key = n['key'] + value = n.get('value', '') + self._type = n.get('type', 'raw') + self._hide = n.get('hide', '') + self._tab_label = n.get('tab', block.get_param_tab_labels()[0]) if self._tab_label not in block.get_param_tab_labels(): block.get_param_tab_labels().append(self._tab_label) # Build the param @@ -176,7 +176,7 @@ class Param(Element): # Create the Option objects from the n data self._options = list() self._evaluated = None - for o_n in n.findall('option'): + for o_n in n.get('option', []): option = Option(param=self, n=o_n) key = option.get_key() # Test against repeated keys @@ -703,7 +703,7 @@ class Param(Element): Returns: a nested data odict """ - n = odict() + n = collections.OrderedDict() n['key'] = self.get_key() n['value'] = self.get_value() return n diff --git a/grc/core/ParseXML.py b/grc/core/ParseXML.py index d1306fcab4..163289ba06 100644 --- a/grc/core/ParseXML.py +++ b/grc/core/ParseXML.py @@ -24,7 +24,6 @@ from lxml import etree import six from six.moves import map -from .utils import odict xml_failures = {} etree.set_default_parser(etree.XMLParser(remove_comments=True)) @@ -80,19 +79,35 @@ def from_file(xml_file): the nested data with grc version information """ xml = etree.parse(xml_file) - nested_data = _from_file(xml.getroot()) + + tag, nested_data = _from_file(xml.getroot()) + nested_data = {tag: nested_data, '_instructions': {}} # Get the embedded instructions and build a dictionary item - nested_data['_instructions'] = {} xml_instructions = xml.xpath('/processing-instruction()') for inst in xml_instructions: if inst.target != 'grc': continue - nested_data['_instructions'] = odict(inst.attrib) + nested_data['_instructions'] = dict(inst.attrib) return nested_data -def _from_file(xml): +WANT_A_LIST = { + '/block': 'import callback param check sink source'.split(), + '/block/param_tab_order': 'tab'.split(), + '/block/param': 'option'.split(), + '/block/param/option': 'opt'.split(), + '/flow_graph': 'block connection'.split(), + '/flow_graph/block': 'param'.split(), + '/cat': 'cat block'.split(), + '/cat/cat': 'cat block'.split(), + '/cat/cat/cat': 'cat block'.split(), + '/cat/cat/cat/cat': 'cat block'.split(), + '/domain': 'connection'.split(), +} + + +def _from_file(xml, parent_tag=''): """ Recursively parse the xml tree into nested data format. @@ -103,21 +118,24 @@ def _from_file(xml): the nested data """ tag = xml.tag + tag_path = parent_tag + '/' + tag + if not len(xml): - return odict({tag: xml.text or ''}) # store empty tags (text is None) as empty string - nested_data = odict() + return tag, xml.text or '' # store empty tags (text is None) as empty string + + nested_data = {} for elem in xml: - key, value = list(_from_file(elem).items())[0] - if key in nested_data: - nested_data[key].append(value) + key, value = _from_file(elem, tag_path) + + if key in WANT_A_LIST.get(tag_path, []): + try: + nested_data[key].append(value) + except KeyError: + nested_data[key] = [value] else: - nested_data[key] = [value] - # Delistify if the length of values is 1 - for key, values in six.iteritems(nested_data): - if len(values) == 1: - nested_data[key] = values[0] + nested_data[key] = value - return odict({tag: nested_data}) + return tag, nested_data def to_file(nested_data, xml_file): diff --git a/grc/core/Platform.py b/grc/core/Platform.py index 25f415639a..403c6c87b4 100644 --- a/grc/core/Platform.py +++ b/grc/core/Platform.py @@ -17,11 +17,14 @@ 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 -from __future__ import print_function +from __future__ import absolute_import, print_function + import os import sys +import six +from six.moves import range + from . import ParseXML, Messages, Constants from .Config import Config @@ -33,10 +36,7 @@ from .Block import Block from .Port import Port from .Param import Param -from .utils import odict, extract_docs -import six -from six.moves import map -from six.moves import range +from .utils import extract_docs class Platform(Element): @@ -72,9 +72,9 @@ class Platform(Element): self._flow_graph = Element(self) self._flow_graph.connections = [] - self.blocks = None - self._blocks_n = None - self._category_trees_n = None + self.blocks = {} + self._blocks_n = {} + self._category_trees_n = [] self.domains = {} self.connection_templates = {} @@ -141,13 +141,15 @@ class Platform(Element): def load_blocks(self): """load the blocks and block tree from the search paths""" self._docstring_extractor.start() + # Reset - self.blocks = odict() - self._blocks_n = odict() - self._category_trees_n = list() + self.blocks.clear() + self._blocks_n.clear() + del self._category_trees_n[:] self.domains.clear() self.connection_templates.clear() ParseXML.xml_failures.clear() + # Try to parse and load blocks for xml_file in self.iter_xml_files(): try: @@ -161,6 +163,7 @@ class Platform(Element): # print >> sys.stderr, 'Warning: Block validation failed:\n\t%s\n\tIgnoring: %s' % (e, xml_file) pass except Exception as e: + raise print('Warning: XML parsing failed:\n\t%r\n\tIgnoring: %s' % (e, xml_file), file=sys.stderr) self._docstring_extractor.finish() @@ -180,7 +183,7 @@ class Platform(Element): """Load block description from xml file""" # Validate and import ParseXML.validate_dtd(xml_file, self._block_dtd) - n = ParseXML.from_file(xml_file).find('block') + n = ParseXML.from_file(xml_file).get('block', {}) n['block_wrapper_path'] = xml_file # inject block wrapper path # Get block instance and add it to the list of blocks block = self.Block(self._flow_graph, n) @@ -200,15 +203,15 @@ class Platform(Element): def load_category_tree_xml(self, xml_file): """Validate and parse category tree file and add it to list""" ParseXML.validate_dtd(xml_file, Constants.BLOCK_TREE_DTD) - n = ParseXML.from_file(xml_file).find('cat') + n = ParseXML.from_file(xml_file).get('cat', {}) self._category_trees_n.append(n) def load_domain_xml(self, xml_file): """Load a domain properties and connection templates from XML""" ParseXML.validate_dtd(xml_file, Constants.DOMAIN_DTD) - n = ParseXML.from_file(xml_file).find('domain') + n = ParseXML.from_file(xml_file).get('domain') - key = n.find('key') + key = n.get('key') if not key: print('Warning: Domain with emtpy key.\n\tIgnoring: {}'.format(xml_file), file=sys.stderr) return @@ -222,7 +225,7 @@ class Platform(Element): return s.lower() not in ('false', 'off', '0', '') return d - color = n.find('color') or '' + color = n.get('color') or '' try: chars_per_color = 2 if len(color) > 4 else 1 tuple(int(color[o:o + 2], 16) / 255.0 for o in range(1, 3 * chars_per_color, chars_per_color)) @@ -232,19 +235,19 @@ class Platform(Element): color = None self.domains[key] = dict( - name=n.find('name') or key, - multiple_sinks=to_bool(n.find('multiple_sinks'), True), - multiple_sources=to_bool(n.find('multiple_sources'), False), + name=n.get('name') or key, + multiple_sinks=to_bool(n.get('multiple_sinks'), True), + multiple_sources=to_bool(n.get('multiple_sources'), False), color=color ) - for connection_n in n.findall('connection'): - key = (connection_n.find('source_domain'), connection_n.find('sink_domain')) + for connection_n in n.get('connection', []): + key = (connection_n.get('source_domain'), connection_n.get('sink_domain')) if not all(key): print('Warning: Empty domain key(s) in connection template.\n\t{}'.format(xml_file), file=sys.stderr) elif key in self.connection_templates: print('Warning: Connection template "{}" already exists.\n\t{}'.format(key, xml_file), file=sys.stderr) else: - self.connection_templates[key] = connection_n.find('make') or '' + self.connection_templates[key] = connection_n.get('make') or '' def load_block_tree(self, block_tree): """ @@ -258,13 +261,13 @@ class Platform(Element): # Recursive function to load categories and blocks def load_category(cat_n, parent=None): # Add this category - parent = (parent or []) + [cat_n.find('name')] + parent = (parent or []) + [cat_n.get('name')] block_tree.add_block(parent) # Recursive call to load sub categories - for cat in cat_n.findall('cat'): + for cat in cat_n.get('cat', []): load_category(cat, parent) # Add blocks in this category - for block_key in cat_n.findall('block'): + for block_key in cat_n.get('block', []): if block_key not in self.blocks: print('Warning: Block key "{}" not found when loading category tree.'.format(block_key), file=sys.stderr) continue diff --git a/grc/core/Port.py b/grc/core/Port.py index a24262da6b..34edb8d0b4 100644 --- a/grc/core/Port.py +++ b/grc/core/Port.py @@ -124,23 +124,24 @@ class Port(Element): n['type'] = 'message' # For port color if n['type'] == 'msg': n['key'] = 'msg' - if not n.find('key'): - n['key'] = str(next(block.port_counters[dir == 'source'])) + + n.setdefault('key', str(next(block.port_counters[dir == 'source']))) # Build the port Element.__init__(self, block) # Grab the data self._name = n['name'] self._key = n['key'] - self._type = n['type'] or '' - self._domain = n['domain'] - self._hide = n.find('hide') or '' + self._type = n.get('type', '') + self._domain = n.get('domain') + self._hide = n.get('hide', '') self._dir = dir self._hide_evaluated = False # Updated on rewrite() - self._nports = n.find('nports') or '' - self._vlen = n.find('vlen') or '' - self._optional = bool(n.find('optional')) + self._nports = n.get('nports', '') + self._vlen = n.get('vlen', '') + self._optional = bool(n.get('optional')) + self.di_optional = bool(n.get('optional')) self._clones = [] # References to cloned ports (for nports > 1) def __str__(self): diff --git a/grc/core/generator/Generator.py b/grc/core/generator/Generator.py index c9b065372d..c27e926c79 100644 --- a/grc/core/generator/Generator.py +++ b/grc/core/generator/Generator.py @@ -17,12 +17,15 @@ from __future__ import absolute_import + import codecs import os import tempfile import operator +import collections from Cheetah.Template import Template +import six from .FlowGraphProxy import FlowGraphProxy from .. import ParseXML, Messages @@ -30,7 +33,7 @@ from ..Constants import ( TOP_BLOCK_FILE_MODE, BLOCK_FLAG_NEED_QT_GUI, HIER_BLOCK_FILE_MODE, BLOCK_DTD ) -from ..utils import expr_utils, odict +from ..utils import expr_utils DATA_DIR = os.path.dirname(__file__) FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl') @@ -299,7 +302,7 @@ class HierBlockGenerator(TopBlockGenerator): return name # Build the nested data - block_n = odict() + block_n = collections.OrderedDict() block_n['name'] = self._flow_graph.get_option('title') or \ self._flow_graph.get_option('id').replace('_', ' ').title() block_n['key'] = block_key @@ -324,7 +327,7 @@ class HierBlockGenerator(TopBlockGenerator): # Parameters block_n['param'] = list() for param in parameters: - param_n = odict() + param_n = collections.OrderedDict() param_n['name'] = param.get_param('label').get_value() or param.get_id() param_n['key'] = param.get_id() param_n['value'] = param.get_param('value').get_value() @@ -341,7 +344,7 @@ class HierBlockGenerator(TopBlockGenerator): for direction in ('sink', 'source'): block_n[direction] = list() for port in self._flow_graph.get_hier_block_io(direction): - port_n = odict() + port_n = collections.OrderedDict() port_n['name'] = port['label'] port_n['type'] = port['type'] if port['type'] != "message": @@ -374,14 +377,18 @@ class QtHierBlockGenerator(HierBlockGenerator): def _build_block_n_from_flow_graph_io(self): n = HierBlockGenerator._build_block_n_from_flow_graph_io(self) - block_n = n['block'] + block_n = collections.OrderedDict() + + # insert flags after category + for key, value in six.iteritems(n['block']): + block_n[key] = value + if key == 'category': + block_n['flags'] = BLOCK_FLAG_NEED_QT_GUI if not block_n['name'].upper().startswith('QT GUI'): block_n['name'] = 'QT GUI ' + block_n['name'] - block_n.insert_after('category', 'flags', BLOCK_FLAG_NEED_QT_GUI) - - gui_hint_param = odict() + gui_hint_param = collections.OrderedDict() gui_hint_param['name'] = 'GUI Hint' gui_hint_param['key'] = 'gui_hint' gui_hint_param['value'] = '' @@ -393,4 +400,5 @@ class QtHierBlockGenerator(HierBlockGenerator): "\n#set $win = 'self.%s' % $id" "\n${gui_hint()($win)}" ) - return n + + return {'block': block_n} diff --git a/grc/core/utils/__init__.py b/grc/core/utils/__init__.py index 0d84f7131d..66393fdc1b 100644 --- a/grc/core/utils/__init__.py +++ b/grc/core/utils/__init__.py @@ -21,4 +21,3 @@ from . import expr_utils from . import epy_block_io from . import extract_docs -from .odict import odict diff --git a/grc/core/utils/odict.py b/grc/core/utils/odict.py deleted file mode 100644 index 38f898a97f..0000000000 --- a/grc/core/utils/odict.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -Copyright 2008-2015 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -GNU Radio Companion is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from __future__ import absolute_import - -from UserDict import DictMixin - - -class odict(DictMixin): - - def __init__(self, d={}): - self._keys = list(d.keys()) - self._data = dict(d.copy()) - - def __setitem__(self, key, value): - if key not in self._data: - self._keys.append(key) - self._data[key] = value - - def __getitem__(self, key): - return self._data[key] - - def __delitem__(self, key): - del self._data[key] - self._keys.remove(key) - - def keys(self): - return list(self._keys) - - def copy(self): - copy_dict = odict() - copy_dict._data = self._data.copy() - copy_dict._keys = list(self._keys) - return copy_dict - - def insert_after(self, pos_key, key, val): - """ - Insert the new key, value entry after the entry given by the position key. - If the positional key is None, insert at the end. - - Args: - pos_key: the positional key - key: the key for the new entry - val: the value for the new entry - """ - index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key) - if key in self._keys: - raise KeyError('Cannot insert, key "{}" already exists'.format(str(key))) - self._keys.insert(index+1, key) - self._data[key] = val - - def insert_before(self, pos_key, key, val): - """ - Insert the new key, value entry before the entry given by the position key. - If the positional key is None, insert at the begining. - - Args: - pos_key: the positional key - key: the key for the new entry - val: the value for the new entry - """ - index = (pos_key is not None) and self._keys.index(pos_key) or 0 - if key in self._keys: - raise KeyError('Cannot insert, key "{}" already exists'.format(str(key))) - self._keys.insert(index, key) - self._data[key] = val - - def find(self, key): - """ - Get the value for this key if exists. - - Args: - key: the key to search for - - Returns: - the value or None - """ - if key in self: - return self[key] - return None - - def findall(self, key): - """ - Get a list of values for this key. - - Args: - key: the key to search for - - Returns: - a list of values or empty list - """ - obj = self.find(key) - if obj is None: - obj = list() - if isinstance(obj, list): - return obj - return [obj] diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py index 50e146b4db..8f35222d42 100644 --- a/grc/gui/FlowGraph.py +++ b/grc/gui/FlowGraph.py @@ -213,15 +213,15 @@ class FlowGraph(Element, _Flowgraph): x_off, y_off = 0, 0 #create blocks for block_n in blocks_n: - block_key = block_n.find('key') - if block_key == 'options': continue + block_key = block_n.get('key') + if block_key == 'options': + continue block = self.new_block(block_key) if not block: continue # unknown block was pasted (e.g. dummy block) selected.add(block) #set params - params = dict((n.find('key'), n.find('value')) - for n in block_n.findall('param')) + params = {n['key']: n['value'] for n in block_n.get('param', [])} if block_key == 'epy_block': block.get_param('_io_cache').set_value(params.pop('_io_cache')) block.get_param('_source_code').set_value(params.pop('_source_code')) @@ -241,8 +241,8 @@ class FlowGraph(Element, _Flowgraph): self.update() #create connections for connection_n in connections_n: - source = old_id2block[connection_n.find('source_block_id')].get_source(connection_n.find('source_key')) - sink = old_id2block[connection_n.find('sink_block_id')].get_sink(connection_n.find('sink_key')) + source = old_id2block[connection_n.get('source_block_id')].get_source(connection_n.get('source_key')) + sink = old_id2block[connection_n.get('sink_block_id')].get_sink(connection_n.get('sink_key')) self.connect(source, sink) #set all pasted elements selected for block in selected: selected = selected.union(set(block.get_connections())) |