summaryrefslogtreecommitdiff
path: root/grc/python/Block.py
diff options
context:
space:
mode:
authorSebastian Koslowski <koslowski@kit.edu>2015-07-20 22:24:53 +0200
committerSebastian Koslowski <koslowski@kit.edu>2015-11-11 21:39:32 +0100
commitc9a5fabe17efe8af1c9435f746ed55c5f5790917 (patch)
tree77242850bfc2ebb159cb9c9d53eff9ea5459f8cb /grc/python/Block.py
parent8b14a84ef8b8a73db002153cb398f79f1343ebc2 (diff)
grc: add embedded python block definition and support in GRC
Diffstat (limited to 'grc/python/Block.py')
-rw-r--r--grc/python/Block.py96
1 files changed, 95 insertions, 1 deletions
diff --git a/grc/python/Block.py b/grc/python/Block.py
index 5289d5765e..accfd21913 100644
--- a/grc/python/Block.py
+++ b/grc/python/Block.py
@@ -21,11 +21,13 @@ import itertools
import collections
from .. base.Constants import BLOCK_FLAG_NEED_QT_GUI, BLOCK_FLAG_NEED_WX_GUI
+from .. base.odict import odict
+
from .. base.Block import Block as _Block
from .. gui.Block import Block as _GUIBlock
from . FlowGraph import _variable_matcher
-import extract_docs
+from . import epy_block_io, extract_docs
class Block(_Block, _GUIBlock):
@@ -59,6 +61,9 @@ class Block(_Block, _GUIBlock):
)
_GUIBlock.__init__(self)
+ self._epy_source_hash = -1 # for epy blocks
+ self._epy_reload_error = None
+
def get_bus_structure(self, direction):
if direction == 'source':
bus_structure = self._bus_structure_source;
@@ -111,12 +116,16 @@ class Block(_Block, _GUIBlock):
check_generate_mode('WX GUI', BLOCK_FLAG_NEED_WX_GUI, ('wx_gui',))
check_generate_mode('QT GUI', BLOCK_FLAG_NEED_QT_GUI, ('qt_gui', 'hb_qt_gui'))
+ if self._epy_reload_error:
+ self.add_error_message(str(self._epy_reload_error))
def rewrite(self):
"""
Add and remove ports to adjust for the nports.
"""
_Block.rewrite(self)
+ # Check and run any custom rewrite function for this block
+ getattr(self, 'rewrite_' + self._key, lambda: None)()
# adjust nports, disconnect hidden ports
for ports in (self.get_sources(), self.get_sinks()):
@@ -216,3 +225,88 @@ class Block(_Block, _GUIBlock):
def is_virtual_source(self):
return self.get_key() == 'virtual_source'
+
+ ###########################################################################
+ # Custom rewrite functions
+ ###########################################################################
+
+ def rewrite_epy_block(self):
+ flowgraph = self.get_parent()
+ platform = flowgraph.get_parent()
+ param_blk = self.get_param('_io_cache')
+ param_src = self.get_param('_source_code')
+
+ src = param_src.get_value()
+ src_hash = hash(src)
+ if src_hash == self._epy_source_hash:
+ return
+
+ try:
+ blk_io = epy_block_io.extract(src)
+
+ except Exception as e:
+ self._epy_reload_error = ValueError('Source code eval:\n' + str(e))
+ try: # load last working block io
+ blk_io = epy_block_io.BlockIO(*eval(param_blk.get_value()))
+ except:
+ return
+ else:
+ self._epy_reload_error = None # clear previous errors
+ param_blk.set_value(repr(tuple(blk_io)))
+
+ # print "Rewriting embedded python block {!r}".format(self.get_id())
+
+ self._epy_source_hash = src_hash
+ self._name = blk_io.name or blk_io.cls
+ self._doc = blk_io.doc
+ self._imports[0] = 'from {} import {}'.format(self.get_id(), blk_io.cls)
+ self._make = '{}({})'.format(blk_io.cls, ', '.join(
+ '{0}=${0}'.format(key) for key, _ in blk_io.params))
+
+ params = dict()
+ for param in list(self._params):
+ if hasattr(param, '__epy_param__'):
+ params[param.get_key()] = param
+ self._params.remove(param)
+
+ for key, value in blk_io.params:
+ if key in params:
+ param = params[key]
+ if not param.value_is_default():
+ param.set_value(value)
+ else:
+ name = key.replace('_', ' ').title()
+ n = odict(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)
+
+ def update_ports(label, ports, port_specs, direction):
+ ports_to_remove = list(ports)
+ iter_ports = iter(ports)
+ ports_new = list()
+ port_current = next(iter_ports, None)
+ for key, port_type in port_specs:
+ reuse_port = (
+ port_current is not None and
+ port_current.get_type() == port_type and
+ (key.isdigit() or port_current.get_key() == key)
+ )
+ if reuse_port:
+ 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))
+ port = platform.Port(block=self, n=n, dir=direction)
+ ports_new.append(port)
+ # replace old port list with new one
+ del ports[:]
+ ports.extend(ports_new)
+ # remove excess port connections
+ for port in ports_to_remove:
+ for connection in port.get_connections():
+ flowgraph.remove_element(connection)
+
+ update_ports('in', self.get_sinks(), blk_io.sinks, 'sink')
+ update_ports('out', self.get_sources(), blk_io.sources, 'source')
+ _Block.rewrite(self)