diff options
-rw-r--r-- | grc/core/Block.py | 187 | ||||
-rw-r--r-- | grc/core/Platform.py | 12 | ||||
-rw-r--r-- | grc/gui/Block.py | 2 | ||||
-rw-r--r-- | grc/gui/Element.py | 7 | ||||
-rw-r--r-- | grc/gui/Platform.py | 3 | ||||
-rw-r--r-- | grc/gui/Port.py | 2 |
6 files changed, 115 insertions, 98 deletions
diff --git a/grc/core/Block.py b/grc/core/Block.py index 9bcb6e6f66..8ffb99b5bd 100644 --- a/grc/core/Block.py +++ b/grc/core/Block.py @@ -304,97 +304,6 @@ class Block(Element): def is_virtual_source(self): return self.key == 'virtual_source' - ########################################################################### - # Custom rewrite functions - ########################################################################### - - def rewrite_epy_block(self): - flowgraph = self.parent_flowgraph - platform = self.parent_platform - param_blk = self.params['_io_cache'] - param_src = self.params['_source_code'] - - src = param_src.get_value() - src_hash = hash((self.get_id(), src)) - if src_hash == self._epy_source_hash: - return - - try: - blk_io = utils.epy_block_io.extract(src) - - except Exception as e: - self._epy_reload_error = ValueError(str(e)) - try: # Load last working block io - blk_io_args = eval(param_blk.get_value()) - if len(blk_io_args) == 6: - blk_io_args += ([],) # add empty callbacks - blk_io = utils.epy_block_io.BlockIO(*blk_io_args) - except Exception: - 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] = 'import ' + self.get_id() - self._make = '{0}.{1}({2})'.format(self.get_id(), blk_io.cls, ', '.join( - '{0}=${{ {0} }}'.format(key) for key, _ in blk_io.params)) - self._callbacks = ['{0} = ${{ {0} }}'.format(attr) for attr in blk_io.callbacks] - - params = {} - for param in list(self.params): - if hasattr(param, '__epy_param__'): - params[param.key] = param - del self.params[param.key] - - for key, value in blk_io.params: - try: - param = params[key] - param.set_default(value) - except KeyError: # need to make a new param - name = key.replace('_', ' ').title() - n = dict(name=name, key=key, type='raw', value=value) - param = platform.Param(block=self, n=n) - setattr(param, '__epy_param__', True) - self.params[key] = param - - def update_ports(label, ports, port_specs, direction): - ports_to_remove = list(ports) - iter_ports = iter(ports) - ports_new = [] - 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.key == key) - ) - if reuse_port: - ports_to_remove.remove(port_current) - port, port_current = port_current, next(iter_ports, None) - else: - n = dict(name=label + str(key), type=port_type, key=key) - if port_type == 'message': - n['name'] = key - n['optional'] = '1' - 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.sinks, blk_io.sinks, 'sink') - update_ports('out', self.sources, blk_io.sources, 'source') - self.rewrite() - @property def documentation(self): documentation = self.parent_platform.block_docstrings.get(self.key, {}) @@ -803,3 +712,99 @@ class Block(Element): self.bussify({'name': 'bus', 'type': 'bus'}, 'sink') if self._bussify_source: self.bussify({'name': 'bus', 'type': 'bus'}, 'source') + + +class EPyBlock(Block): + + def __init__(self, flow_graph, n): + super(EPyBlock, self).__init__(flow_graph, n) + self._epy_source_hash = -1 # for epy blocks + self._epy_reload_error = None + + + def rewrite_epy_block(self): + flowgraph = self.parent_flowgraph + platform = self.parent_platform + param_blk = self.params['_io_cache'] + param_src = self.params['_source_code'] + + src = param_src.get_value() + src_hash = hash((self.get_id(), src)) + if src_hash == self._epy_source_hash: + return + + try: + blk_io = utils.epy_block_io.extract(src) + + except Exception as e: + self._epy_reload_error = ValueError(str(e)) + try: # Load last working block io + blk_io_args = eval(param_blk.get_value()) + if len(blk_io_args) == 6: + blk_io_args += ([],) # add empty callbacks + blk_io = utils.epy_block_io.BlockIO(*blk_io_args) + except Exception: + 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] = 'import ' + self.get_id() + self._make = '{0}.{1}({2})'.format(self.get_id(), blk_io.cls, ', '.join( + '{0}=${{ {0} }}'.format(key) for key, _ in blk_io.params)) + self._callbacks = ['{0} = ${{ {0} }}'.format(attr) for attr in blk_io.callbacks] + + params = {} + for param in list(self.params): + if hasattr(param, '__epy_param__'): + params[param.key] = param + del self.params[param.key] + + for key, value in blk_io.params: + try: + param = params[key] + param.set_default(value) + except KeyError: # need to make a new param + name = key.replace('_', ' ').title() + n = dict(name=name, key=key, type='raw', value=value) + param = platform.Param(block=self, n=n) + setattr(param, '__epy_param__', True) + self.params[key] = param + + def update_ports(label, ports, port_specs, direction): + ports_to_remove = list(ports) + iter_ports = iter(ports) + ports_new = [] + 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.key == key) + ) + if reuse_port: + ports_to_remove.remove(port_current) + port, port_current = port_current, next(iter_ports, None) + else: + n = dict(name=label + str(key), type=port_type, key=key) + if port_type == 'message': + n['name'] = key + n['optional'] = '1' + 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.sinks, blk_io.sinks, 'sink') + update_ports('out', self.sources, blk_io.sources, 'source') + self.rewrite() diff --git a/grc/core/Platform.py b/grc/core/Platform.py index 10e75d797d..e32bd9198a 100644 --- a/grc/core/Platform.py +++ b/grc/core/Platform.py @@ -32,7 +32,7 @@ from .Element import Element from .generator import Generator from .FlowGraph import FlowGraph from .Connection import Connection -from .Block import Block +from .Block import Block, EPyBlock from .Port import Port from .Param import Param @@ -45,7 +45,10 @@ class Platform(Element): Generator = Generator FlowGraph = FlowGraph Connection = Connection - Block = Block + block_classes = { + None: Block, # default + 'epy_block': EPyBlock, + } Port = Port Param = Param @@ -198,7 +201,7 @@ class Platform(Element): 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) + block = self.block_classes[None](self._flow_graph, n) key = block.key if key in self.blocks: print('Warning: Block with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file), file=sys.stderr) @@ -309,4 +312,5 @@ class Platform(Element): return list(self.blocks.values()) def get_new_block(self, flow_graph, key): - return self.Block(flow_graph, n=self._blocks_n[key]) + cls = self.block_classes.get(key, self.block_classes[None]) + return cls(flow_graph, n=self._blocks_n[key]) diff --git a/grc/gui/Block.py b/grc/gui/Block.py index c5a9f063a3..b55e471e37 100644 --- a/grc/gui/Block.py +++ b/grc/gui/Block.py @@ -41,7 +41,7 @@ class Block(CoreBlock, Element): Block constructor. Add graphics related params to the block. """ - CoreBlock.__init__(self, flow_graph, n) + super(self.__class__, self).__init__(flow_graph, n) self.states.update(_coordinate=(0, 0), _rotation=0) self.width = self.height = 0 diff --git a/grc/gui/Element.py b/grc/gui/Element.py index b51a64735f..cdbf548941 100644 --- a/grc/gui/Element.py +++ b/grc/gui/Element.py @@ -30,6 +30,13 @@ class Element(object): and methods to detect selection of those areas. """ + @classmethod + def make_cls_with_base(cls, super_cls): + name = super_cls.__name__ + bases = (super_cls,) + cls.__bases__[1:] + namespace = cls.__dict__.copy() + return type(name, bases, namespace) + def __init__(self): """ Make a new list of rectangular areas and lines, and set the coordinate and the rotation. diff --git a/grc/gui/Platform.py b/grc/gui/Platform.py index 25c755675c..b8dd6aa074 100644 --- a/grc/gui/Platform.py +++ b/grc/gui/Platform.py @@ -66,6 +66,7 @@ class Platform(CorePlatform): Config = Config FlowGraph = FlowGraph Connection = Connection - Block = Block + block_classes = {key: Block.make_cls_with_base(cls) + for key, cls in CorePlatform.block_classes.items()} Port = Port Param = Param diff --git a/grc/gui/Port.py b/grc/gui/Port.py index d8a180b7c8..4b3f6edb81 100644 --- a/grc/gui/Port.py +++ b/grc/gui/Port.py @@ -37,7 +37,7 @@ class Port(_Port, Element): Port constructor. Create list of connector coordinates. """ - _Port.__init__(self, block, n, dir) + super(Port, self).__init__(block, n, dir) Element.__init__(self) self._connector_coordinate = (0, 0) self._hovering = True |