summaryrefslogtreecommitdiff
path: root/grc/core/Platform.py
diff options
context:
space:
mode:
Diffstat (limited to 'grc/core/Platform.py')
-rw-r--r--grc/core/Platform.py160
1 files changed, 97 insertions, 63 deletions
diff --git a/grc/core/Platform.py b/grc/core/Platform.py
index b73dade2e8..73937f1299 100644
--- a/grc/core/Platform.py
+++ b/grc/core/Platform.py
@@ -17,9 +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, print_function
+
import os
import sys
+import six
+from six.moves import range
+
from . import ParseXML, Messages, Constants
from .Config import Config
@@ -27,31 +32,22 @@ from .Element import Element
from .generator import Generator
from .FlowGraph import FlowGraph
from .Connection import Connection
-from .Block import Block
-from .Port import Port
+from . import Block
+from .Port import Port, PortClone
from .Param import Param
-from .utils import odict, extract_docs
+from .utils import extract_docs
class Platform(Element):
- Config = Config
- Generator = Generator
- FlowGraph = FlowGraph
- Connection = Connection
- Block = Block
- Port = Port
- Param = Param
-
is_platform = True
def __init__(self, *args, **kwargs):
""" Make a platform for GNU Radio """
- Element.__init__(self)
+ Element.__init__(self, parent=None)
self.config = self.Config(*args, **kwargs)
-
self.block_docstrings = {}
self.block_docstrings_loaded_callback = lambda: None # dummy to be replaced by BlockTreeWindow
@@ -60,22 +56,23 @@ class Platform(Element):
callback_finished=lambda: self.block_docstrings_loaded_callback()
)
- # Create a dummy flow graph for the blocks
- self._flow_graph = Element(self)
- self._flow_graph.connections = []
-
- self.blocks = odict()
- self._blocks_n = odict()
+ self.blocks = {}
+ self._blocks_n = {}
self._block_categories = {}
self.domains = {}
self.connection_templates = {}
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.build_block_library()
def __str__(self):
- return 'Platform - {}({})'.format(self.config.key, self.config.name)
+ return 'Platform - {}'.format(self.config.name)
@staticmethod
def find_file_in_paths(filename, paths, cwd):
@@ -128,12 +125,13 @@ class Platform(Element):
return None, None
if flow_graph.get_option('generate_options').startswith('hb'):
- self.load_block_xml(generator.get_file_path_xml())
+ self.load_block_xml(generator.file_path_xml)
return flow_graph, generator.file_path
def build_block_library(self):
"""load the blocks and block tree from the search paths"""
self._docstring_extractor.start()
+
# Reset
self.blocks.clear()
self._blocks_n.clear()
@@ -155,10 +153,11 @@ class Platform(Element):
# print >> sys.stderr, 'Warning: Block validation failed:\n\t%s\n\tIgnoring: %s' % (e, xml_file)
pass
except Exception as e:
- print >> sys.stderr, 'Warning: XML parsing failed:\n\t%r\n\tIgnoring: %s' % (e, xml_file)
+ raise
+ print('Warning: XML parsing failed:\n\t%r\n\tIgnoring: %s' % (e, xml_file), file=sys.stderr)
# Add blocks to block tree
- for key, block in self.blocks.iteritems():
+ for key, block in six.iteritems(self.blocks):
category = self._block_categories.get(key, block.category)
# Blocks with empty categories are hidden
if not category:
@@ -180,26 +179,27 @@ class Platform(Element):
yield block_path
elif os.path.isdir(block_path):
for dirpath, dirnames, filenames in os.walk(block_path):
- for filename in sorted(filter(lambda f: f.endswith('.xml'), filenames)):
+ for filename in sorted(f for f in filenames if f.endswith('.xml')):
yield os.path.join(dirpath, filename)
def load_block_xml(self, xml_file):
"""Load block description from xml file"""
# Validate and import
ParseXML.validate_dtd(xml_file, Constants.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)
- key = block.get_key()
+ key = n.pop('key')
+
if key in self.blocks:
- print >> sys.stderr, 'Warning: Block with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file)
- else: # Store the block
- self.blocks[key] = block
- self._blocks_n[key] = n
+ print('Warning: Block with key "{}" already exists.\n'
+ '\tIgnoring: {}'.format(key, xml_file), file=sys.stderr)
+ return
+ # Store the block
+ self.blocks[key] = block = self.get_new_block(self._flow_graph, key, **n)
+ self._blocks_n[key] = n
self._docstring_extractor.query(
- block.get_key(),
+ key,
block.get_imports(raw=True),
block.get_make(raw=True)
)
@@ -211,62 +211,62 @@ class Platform(Element):
path = []
def load_category(cat_n):
- path.append(cat_n.find('name').strip())
- for block_key in cat_n.findall('block'):
+ path.append(cat_n.get('name').strip())
+ for block_key in cat_n.get('block', []):
if block_key not in self._block_categories:
self._block_categories[block_key] = list(path)
- for sub_cat_n in cat_n.findall('cat'):
+ for sub_cat_n in cat_n.get('cat', []):
load_category(sub_cat_n)
path.pop()
- load_category(xml.find('cat'))
+ load_category(xml.get('cat', {}))
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 >> sys.stderr, 'Warning: Domain with emtpy key.\n\tIgnoring: {}'.format(xml_file)
+ print('Warning: Domain with emtpy key.\n\tIgnoring: {}'.format(xml_file), file=sys.stderr)
return
if key in self.domains: # test against repeated keys
- print >> sys.stderr, 'Warning: Domain with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file)
+ print('Warning: Domain with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file), file=sys.stderr)
return
- #to_bool = lambda s, d: d if s is None else s.lower() not in ('false', 'off', '0', '')
+ # to_bool = lambda s, d: d if s is None else s.lower() not in ('false', 'off', '0', '')
def to_bool(s, d):
if s is not None:
return s.lower() not in ('false', 'off', '0', '')
return d
- color = n.find('color') or ''
+ color = n.get('color') or ''
try:
- import gtk # ugly but handy
- gtk.gdk.color_parse(color)
- except (ValueError, ImportError):
+ 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))
+ except ValueError:
if color: # no color is okay, default set in GUI
- print >> sys.stderr, 'Warning: Can\'t parse color code "{}" for domain "{}" '.format(color, key)
+ print('Warning: Can\'t parse color code "{}" for domain "{}" '.format(color, key), file=sys.stderr)
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 >> sys.stderr, 'Warning: Empty domain key(s) in connection template.\n\t{}'.format(xml_file)
+ print('Warning: Empty domain key(s) in connection template.\n\t{}'.format(xml_file), file=sys.stderr)
elif key in self.connection_templates:
- print >> sys.stderr, 'Warning: Connection template "{}" already exists.\n\t{}'.format(key, xml_file)
+ 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 _save_docstring_extraction_result(self, key, docstrings):
docs = {}
- for match, docstring in docstrings.iteritems():
+ for match, docstring in six.iteritems(docstrings):
if not docstring or match.endswith('_sptr'):
continue
docstring = docstring.replace('\n\n', '\n').strip()
@@ -294,14 +294,48 @@ class Platform(Element):
ParseXML.validate_dtd(flow_graph_file, Constants.FLOW_GRAPH_DTD)
return ParseXML.from_file(flow_graph_file)
+ def get_blocks(self):
+ return list(self.blocks.values())
+
+ def get_generate_options(self):
+ gen_opts = self.blocks['options'].get_param('generate_options')
+ generate_mode_default = gen_opts.get_value()
+ return [(key, name, key == generate_mode_default)
+ for key, name in zip(gen_opts.options, gen_opts.options_names)]
+
+ ##############################################
+ # Factories
+ ##############################################
+ Config = Config
+ Generator = Generator
+ FlowGraph = FlowGraph
+ Connection = Connection
+ block_classes = {
+ None: Block.Block, # default
+ 'epy_block': Block.EPyBlock,
+ '_dummy': Block.DummyBlock,
+ }
+ port_classes = {
+ None: Port, # default
+ 'clone': PortClone, # default
+ }
+ param_classes = {
+ None: Param, # default
+ }
+
def get_new_flow_graph(self):
- return self.FlowGraph(platform=self)
+ return self.FlowGraph(parent=self)
- def get_blocks(self):
- return self.blocks.values()
+ def get_new_block(self, parent, key, **kwargs):
+ cls = self.block_classes.get(key, self.block_classes[None])
+ if not kwargs:
+ kwargs = self._blocks_n[key]
+ return cls(parent, key=key, **kwargs)
- def get_new_block(self, flow_graph, key):
- return self.Block(flow_graph, n=self._blocks_n[key])
+ def get_new_param(self, parent, **kwargs):
+ cls = self.param_classes[kwargs.pop('cls_key', None)]
+ return cls(parent, **kwargs)
- def get_colors(self):
- return [(name, color) for name, key, sizeof, color in Constants.CORE_TYPES]
+ def get_new_port(self, parent, **kwargs):
+ cls = self.port_classes[kwargs.pop('cls_key', None)]
+ return cls(parent, **kwargs)