summaryrefslogtreecommitdiff
path: root/grc/core/Block.py
diff options
context:
space:
mode:
authorSebastian Koslowski <koslowski@kit.edu>2016-04-25 21:25:44 +0200
committerSebastian Koslowski <koslowski@kit.edu>2016-05-27 15:02:41 +0200
commit31eb4e89dc6f3b1deb12175b10127967cdb7407c (patch)
treefa92cde4c28ae18b94d4a9eb0ccfcb65a0c9da1c /grc/core/Block.py
parent5352dfd80fd238256da7bbd5efd15c154f3f5a14 (diff)
grc-refactor: start clean-up Block.py
Diffstat (limited to 'grc/core/Block.py')
-rw-r--r--grc/core/Block.py454
1 files changed, 209 insertions, 245 deletions
diff --git a/grc/core/Block.py b/grc/core/Block.py
index f67d990857..aafc5db6f1 100644
--- a/grc/core/Block.py
+++ b/grc/core/Block.py
@@ -59,183 +59,121 @@ class Block(Element):
Returns:
block a new block
"""
- # Grab the data
- self._doc = (n.find('doc') or '').strip('\n').replace('\\\n', '')
- self._imports = map(lambda i: i.strip(), n.findall('import'))
- self._make = n.find('make')
- self._var_make = n.find('var_make')
- self._checks = n.findall('check')
- self._callbacks = n.findall('callback')
- self._bus_structure_source = n.find('bus_structure_source') or ''
- self._bus_structure_sink = n.find('bus_structure_sink') or ''
- self.port_counters = [itertools.count(), itertools.count()]
-
- # Build the block
Element.__init__(self, flow_graph)
-
- # Grab the data
- params = n.findall('param')
- sources = n.findall('source')
- sinks = n.findall('sink')
self._name = n.find('name')
self._key = n.find('key')
self._category = n.find('category') or ''
self._flags = n.find('flags') or ''
+
# Backwards compatibility
if n.find('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 = map(lambda i: i.strip(), 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._grc_source = n.find('grc_source') or ''
self._block_wrapper_path = n.find('block_wrapper_path')
- self._bussify_sink = n.find('bus_sink')
- self._bussify_source = n.find('bus_source')
- self._var_value = n.find('var_value') or '$value'
+
+ params_n = n.findall('param')
+ sources_n = n.findall('source')
+ sinks_n = n.findall('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]
+ self._params = []
+ self._init_params(
+ params_n=params_n,
+ has_sinks=len(sinks_n),
+ has_sources=len(sources_n)
+ )
- # Create the param objects
- self._params = list()
-
- # Add the id param
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({
- 'name': 'ID',
- 'key': 'id',
- 'type': 'id',
- })
- ))
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({
- 'name': 'Enabled',
- 'key': '_enabled',
- 'type': 'raw',
- 'value': 'True',
- 'hide': 'all',
- })
- ))
- for param in itertools.imap(lambda n: self.get_parent().get_parent().Param(block=self, n=n), params):
- key = param.get_key()
- # Test against repeated keys
- if key in self.get_param_keys():
- raise Exception('Key "{}" already exists in params'.format(key))
- # Store the param
- self.get_params().append(param)
- # Create the source objects
- self._sources = list()
- for source in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='source'), sources):
- key = source.get_key()
- # Test against repeated keys
- if key in self.get_source_keys():
- raise Exception('Key "{}" already exists in sources'.format(key))
- # Store the port
- self.get_sources().append(source)
- self.back_ofthe_bus(self.get_sources())
- # Create the sink objects
- self._sinks = list()
- for sink in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='sink'), sinks):
- key = sink.get_key()
- # Test against repeated keys
- if key in self.get_sink_keys():
- raise Exception('Key "{}" already exists in sinks'.format(key))
- # Store the port
- self.get_sinks().append(sink)
- self.back_ofthe_bus(self.get_sinks())
+ self.port_counters = [itertools.count(), itertools.count()]
+ self._sources = self._init_ports(sources_n, direction='source')
+ self._sinks = self._init_ports(sinks_n, direction='sink')
+
+ self._epy_source_hash = -1 # for epy blocks
+ self._epy_reload_error = None
+
+ 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')
+ 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.update(kwargs)
+ param = self.get_parent().get_parent().Param(block=self, n=n)
+ self._params.append(param)
+
+ def _init_params(self, params_n, has_sources, has_sinks):
+ self._add_param(key='id', name='ID', type='id')
+ self._add_param(key='_enabled', name='Enabled', value='True', type='raw', hide='all')
# Virtual source/sink and pad source/sink blocks are
# indistinguishable from normal GR blocks. Make explicit
# checks for them here since they have no work function or
# buffers to manage.
- self.is_virtual_or_pad = self._key in (
+ self.is_virtual_or_pad = is_virtual_or_pad = self._key in (
"virtual_source", "virtual_sink", "pad_source", "pad_sink")
- self.is_variable = self._key.startswith('variable')
+ self.is_variable = is_variable = self._key.startswith('variable')
self.is_import = (self._key == 'import')
# Disable blocks that are virtual/pads or variables
if self.is_virtual_or_pad or self.is_variable:
self._flags += BLOCK_FLAG_DISABLE_BYPASS
- if not (self.is_virtual_or_pad or self.is_variable or self._key == 'options'):
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Block Alias',
- 'key': 'alias',
- 'type': 'string',
- 'hide': 'part',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
-
- if (len(sources) or len(sinks)) and not self.is_virtual_or_pad:
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Core Affinity',
- 'key': 'affinity',
- 'type': 'int_vector',
- 'hide': 'part',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
- if len(sources) and not self.is_virtual_or_pad:
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Min Output Buffer',
- 'key': 'minoutbuf',
- 'type': 'int',
- 'hide': 'part',
- 'value': '0',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Max Output Buffer',
- 'key': 'maxoutbuf',
- 'type': 'int',
- 'hide': 'part',
- 'value': '0',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
-
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Comment',
- 'key': 'comment',
- 'type': '_multiline',
- 'hide': 'part',
- 'value': '',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
+ if not (is_virtual_or_pad or is_variable or self._key == 'options'):
+ self._add_param(key='alias', name='Block Alias', type='string',
+ hide='part', tab=ADVANCED_PARAM_TAB)
- self._epy_source_hash = -1 # for epy blocks
- self._epy_reload_error = None
+ if not is_virtual_or_pad and (has_sources or has_sinks):
+ self._add_param(key='affinity', name='Core Affinity', type='int_vector',
+ hide='part', tab=ADVANCED_PARAM_TAB)
- if self._bussify_sink:
- self.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
- if self._bussify_source:
- self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+ if not is_virtual_or_pad and has_sources:
+ self._add_param(key='minoutbuf', name='Min Output Buffer', type='int',
+ hide='part', value='0', tab=ADVANCED_PARAM_TAB)
+ self._add_param(key='maxoutbuf', name='Max Output Buffer', type='int',
+ hide='part', value='0', tab=ADVANCED_PARAM_TAB)
- def get_bus_structure(self, direction):
- if direction == 'source':
- bus_structure = self._bus_structure_source
- else:
- bus_structure = self._bus_structure_sink
-
- bus_structure = self.resolve_dependencies(bus_structure)
-
- if not bus_structure:
- return '' # TODO: Don't like empty strings. should change this to None eventually
+ param_keys = set(param.get_key() for param in self._params)
+ for param_n in params_n:
+ param = self.get_parent().get_parent().Param(block=self, n=param_n)
+ key = param.get_key()
+ if key in param_keys:
+ raise Exception('Key "{}" already exists in params'.format(key))
+ param_keys.add(key)
+ self.get_params().append(param)
- try:
- clean_bus_structure = self.get_parent().evaluate(bus_structure)
- return clean_bus_structure
- except:
- return ''
+ self._add_param(key='comment', name='Comment', type='_multiline', hide='part',
+ value='', tab=ADVANCED_PARAM_TAB)
+
+ def _init_ports(self, ports_n, direction):
+ port_cls = self.get_parent().get_parent().Port
+ ports = []
+ port_keys = set()
+ for port_n in ports_n:
+ port = port_cls(block=self, n=port_n, dir=direction)
+ key = port.get_key()
+ if key in port_keys:
+ raise Exception('Key "{}" already exists in {}'.format(key, direction))
+ port_keys.add(key)
+ ports.append(port)
+ return ports
def validate(self):
"""
@@ -317,34 +255,6 @@ class Block(Element):
port._key = str(domain_specific_port_index[domain])
domain_specific_port_index[domain] += 1
- def port_controller_modify(self, direction):
- """
- Change the port controller.
-
- Args:
- direction: +1 or -1
-
- Returns:
- true for change
- """
- changed = False
- # Concat the nports string from the private nports settings of all ports
- nports_str = ' '.join([port._nports for port in self.get_ports()])
- # Modify all params whose keys appear in the nports string
- for param in self.get_params():
- if param.is_enum() or param.get_key() not in nports_str:
- continue
- # Try to increment the port controller by direction
- try:
- value = param.get_evaluated()
- value = value + direction
- if 0 < value:
- param.set_value(value)
- changed = True
- except:
- pass
- return changed
-
def get_doc(self):
platform = self.get_parent().get_parent()
documentation = platform.block_docstrings.get(self._key, {})
@@ -489,13 +399,6 @@ class Block(Element):
update_ports('out', self.get_sources(), blk_io.sources, 'source')
self.rewrite()
- def back_ofthe_bus(self, portlist):
- portlist.sort(key=lambda p: p._type == 'bus')
-
- def filter_bus_port(self, ports):
- buslist = [p for p in ports if p._type == 'bus']
- return buslist or ports
-
# Main functions to get and set the block state
# Also kept get_enabled and set_enabled to keep compatibility
def get_state(self):
@@ -656,9 +559,6 @@ class Block(Element):
##############################################
# Access Sinks
##############################################
- def get_sink_keys(self):
- return _get_keys(self._sinks)
-
def get_sink(self, key):
return _get_elem(self._sinks, key)
@@ -671,9 +571,6 @@ class Block(Element):
##############################################
# Access Sources
##############################################
- def get_source_keys(self):
- return _get_keys(self._sources)
-
def get_source(self, key):
return _get_elem(self._sources, key)
@@ -686,6 +583,10 @@ class Block(Element):
def get_connections(self):
return sum([port.get_connections() for port in self.get_ports()], [])
+ ##############################################
+ # Resolve
+ ##############################################
+
def resolve_dependencies(self, tmpl):
"""
Resolve a paramater dependency with cheetah templates.
@@ -740,6 +641,128 @@ class Block(Element):
pass
return changed
+ def port_controller_modify(self, direction):
+ """
+ Change the port controller.
+
+ Args:
+ direction: +1 or -1
+
+ Returns:
+ true for change
+ """
+ changed = False
+ # Concat the nports string from the private nports settings of all ports
+ nports_str = ' '.join([port._nports for port in self.get_ports()])
+ # Modify all params whose keys appear in the nports string
+ for param in self.get_params():
+ if param.is_enum() or param.get_key() not in nports_str:
+ continue
+ # Try to increment the port controller by direction
+ try:
+ value = param.get_evaluated()
+ value = value + direction
+ if 0 < value:
+ param.set_value(value)
+ changed = True
+ except:
+ pass
+ return changed
+
+ ##############################################
+ # Import/Export Methods
+ ##############################################
+ def export_data(self):
+ """
+ Export this block's params to nested data.
+
+ Returns:
+ a nested data odict
+ """
+ n = odict()
+ n['key'] = self.get_key()
+ n['param'] = map(lambda p: p.export_data(), sorted(self.get_params(), key=str))
+ if 'bus' in map(lambda a: a.get_type(), self.get_sinks()):
+ n['bus_sink'] = str(1)
+ if 'bus' in map(lambda a: a.get_type(), self.get_sources()):
+ n['bus_source'] = str(1)
+ return n
+
+ def import_data(self, n):
+ """
+ Import this block's params from nested data.
+ Any param keys that do not exist will be ignored.
+ Since params can be dynamically created based another param,
+ call rewrite, and repeat the load until the params stick.
+ This call to rewrite will also create any dynamic ports
+ that are needed for the connections creation phase.
+
+ Args:
+ n: the nested data odict
+ """
+ params_n = n.findall('param')
+ params = dict((param.get_key(), param) for param in self._params)
+
+ def get_hash():
+ return hash(tuple(map(hash, self._params)))
+
+ my_hash = 0
+ while get_hash() != my_hash:
+ for param_n in params_n:
+ key = param_n.find('key')
+ value = param_n.find('value')
+ try:
+ params[key].set_value(value)
+ except KeyError:
+ continue
+ # Store hash and call rewrite
+ my_hash = get_hash()
+ self.rewrite()
+
+ self._import_bus_stuff(n)
+
+ ##############################################
+ # Bus ports stuff
+ ##############################################
+
+ def get_bus_structure(self, direction):
+ if direction == 'source':
+ bus_structure = self._bus_structure_source
+ else:
+ bus_structure = self._bus_structure_sink
+
+ bus_structure = self.resolve_dependencies(bus_structure)
+
+ if not bus_structure:
+ return '' # TODO: Don't like empty strings. should change this to None eventually
+
+ try:
+ clean_bus_structure = self.get_parent().evaluate(bus_structure)
+ return clean_bus_structure
+ except:
+ return ''
+
+ def back_ofthe_bus(self, portlist):
+ portlist.sort(key=lambda p: p._type == 'bus')
+
+ def filter_bus_port(self, ports):
+ buslist = [p for p in ports if p._type == 'bus']
+ return buslist or ports
+
+ def _import_bus_stuff(self, n):
+ bussinks = n.findall('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')
+ if len(bussrcs) > 0 and not self._bussify_source:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+ elif len(bussrcs) > 0:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+
def form_bus_structure(self, direc):
if direc == 'source':
get_p = self.get_sources
@@ -794,62 +817,3 @@ class Block(Element):
for elt in get_p_gui():
get_p().remove(elt)
self.current_bus_structure[direc] = ''
-
- ##############################################
- # Import/Export Methods
- ##############################################
- def export_data(self):
- """
- Export this block's params to nested data.
-
- Returns:
- a nested data odict
- """
- n = odict()
- n['key'] = self.get_key()
- n['param'] = map(lambda p: p.export_data(), sorted(self.get_params(), key=str))
- if 'bus' in map(lambda a: a.get_type(), self.get_sinks()):
- n['bus_sink'] = str(1)
- if 'bus' in map(lambda a: a.get_type(), self.get_sources()):
- n['bus_source'] = str(1)
- return n
-
- def get_hash(self):
- return hash(tuple(map(hash, self.get_params())))
-
- def import_data(self, n):
- """
- Import this block's params from nested data.
- Any param keys that do not exist will be ignored.
- Since params can be dynamically created based another param,
- call rewrite, and repeat the load until the params stick.
- This call to rewrite will also create any dynamic ports
- that are needed for the connections creation phase.
-
- Args:
- n: the nested data odict
- """
- my_hash = 0
- while self.get_hash() != my_hash:
- params_n = n.findall('param')
- for param_n in params_n:
- key = param_n.find('key')
- value = param_n.find('value')
- # The key must exist in this block's params
- if key in self.get_param_keys():
- self.get_param(key).set_value(value)
- # Store hash and call rewrite
- my_hash = self.get_hash()
- self.rewrite()
- bussinks = n.findall('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')
- if len(bussrcs) > 0 and not self._bussify_source:
- self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
- elif len(bussrcs) > 0:
- self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
- self.bussify({'name': 'bus', 'type': 'bus'}, 'source')