summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Koslowski <koslowski@kit.edu>2016-06-03 16:17:57 +0200
committerSebastian Koslowski <koslowski@kit.edu>2016-06-09 14:49:12 +0200
commit963773b800655f2902998aedce8d46605d54e60f (patch)
tree684d4ed1119dab875c21e400152c1df6ef61d4e1
parent94c4606edd30dc8b1278580782f2809b69f04641 (diff)
grc-refactor: remove odict
-rw-r--r--grc/core/Block.py69
-rw-r--r--grc/core/Connection.py5
-rw-r--r--grc/core/FlowGraph.py52
-rw-r--r--grc/core/Param.py26
-rw-r--r--grc/core/ParseXML.py50
-rw-r--r--grc/core/Platform.py55
-rw-r--r--grc/core/Port.py17
-rw-r--r--grc/core/generator/Generator.py26
-rw-r--r--grc/core/utils/__init__.py1
-rw-r--r--grc/core/utils/odict.py113
-rw-r--r--grc/gui/FlowGraph.py12
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()))