diff options
Diffstat (limited to 'grc/base/Block.py')
-rw-r--r-- | grc/base/Block.py | 704 |
1 files changed, 337 insertions, 367 deletions
diff --git a/grc/base/Block.py b/grc/base/Block.py index 1fb0db9ad8..b0b96422a7 100644 --- a/grc/base/Block.py +++ b/grc/base/Block.py @@ -25,376 +25,346 @@ from UserDict import UserDict from .. gui import Actions class TemplateArg(UserDict): - """ - A cheetah template argument created from a param. - The str of this class evaluates to the param's to code method. - The use of this class as a dictionary (enum only) will reveal the enum opts. - The __call__ or () method can return the param evaluated to a raw python data type. - """ - - def __init__(self, param): - UserDict.__init__(self) - self._param = param - if param.is_enum(): - for key in param.get_opt_keys(): - self[key] = str(param.get_opt(key)) - - def __str__(self): - return str(self._param.to_code()) - - def __call__(self): - return self._param.get_evaluated() + """ + A cheetah template argument created from a param. + The str of this class evaluates to the param's to code method. + The use of this class as a dictionary (enum only) will reveal the enum opts. + The __call__ or () method can return the param evaluated to a raw python data type. + """ + + def __init__(self, param): + UserDict.__init__(self) + self._param = param + if param.is_enum(): + for key in param.get_opt_keys(): + self[key] = str(param.get_opt(key)) + + def __str__(self): + return str(self._param.to_code()) + + def __call__(self): + return self._param.get_evaluated() def _get_keys(lst): return [elem.get_key() for elem in lst] def _get_elem(lst, key): - try: return lst[_get_keys(lst).index(key)] - except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst)) + try: return lst[_get_keys(lst).index(key)] + except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst)) class Block(Element): - def __init__(self, flow_graph, n): - """ - Make a new block from nested data. - - Args: - flow: graph the parent element - n: the nested odict - - Returns: - block a new block - """ - #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._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') - - - #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 map(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 "%s" already exists in params'%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 "%s" already exists in sources'%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 "%s" already exists in sinks'%key - #store the port - self.get_sinks().append(sink) - self.back_ofthe_bus(self.get_sinks()) - self.current_bus_structure = {'source':'','sink':''}; - - - def back_ofthe_bus(self, portlist): - portlist.sort(key=lambda a: a.get_type() == 'bus'); - - - def filter_bus_port(self, ports): - buslist = [i for i in ports if i.get_type() == 'bus']; - if len(buslist) == 0: - return ports; - else: - return buslist; - - def get_enabled(self): - """ - Get the enabled state of the block. - - Returns: - true for enabled - """ - try: return eval(self.get_param('_enabled').get_value()) - except: return True - - def set_enabled(self, enabled): - """ - Set the enabled state of the block. - - Args: - enabled: true for enabled - """ - self.get_param('_enabled').set_value(str(enabled)) - - def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(), self.get_name(), self.get_key()) - - def get_id(self): return self.get_param('id').get_value() - def is_block(self): return True - def get_name(self): return self._name - def get_key(self): return self._key - def get_category(self): return self._category - def get_doc(self): return '' - def get_ports(self): return self.get_sources() + self.get_sinks() - def get_ports_gui(self): return self.filter_bus_port(self.get_sources()) + self.filter_bus_port(self.get_sinks()); - - - - def get_children(self): return self.get_ports() + self.get_params() - def get_children_gui(self): return self.get_ports_gui() + self.get_params() - def get_block_wrapper_path(self): return self._block_wrapper_path - - ############################################## - # Access Params - ############################################## - def get_param_keys(self): return _get_keys(self._params) - def get_param(self, key): return _get_elem(self._params, key) - def get_params(self): return self._params - - ############################################## - # Access Sinks - ############################################## - def get_sink_keys(self): return _get_keys(self._sinks) - def get_sink(self, key): return _get_elem(self._sinks, key) - def get_sinks(self): return self._sinks - def get_sinks_gui(self): return self.filter_bus_port(self.get_sinks()) - - ############################################## - # Access Sources - ############################################## - def get_source_keys(self): return _get_keys(self._sources) - def get_source(self, key): return _get_elem(self._sources, key) - def get_sources(self): return self._sources - def get_sources_gui(self): return self.filter_bus_port(self.get_sources()); - - - - def get_connections(self): - return sum([port.get_connections() for port in self.get_ports()], []) - - def resolve_dependencies(self, tmpl): - """ - Resolve a paramater dependency with cheetah templates. - - Args: - tmpl: the string with dependencies - - Returns: - the resolved value - """ - tmpl = str(tmpl) - if '$' not in tmpl: return tmpl - n = dict((p.get_key(), TemplateArg(p)) for p in self.get_params()) - - try: return str(Template(tmpl, n)) - except Exception, e: return "-------->\n%s: %s\n<--------"%(e, tmpl) - - ############################################## - # Controller Modify - ############################################## - def type_controller_modify(self, direction): - """ - Change the type controller. - - Args: - direction: +1 or -1 - - Returns: - true for change - """ - changed = False - type_param = None - for param in filter(lambda p: p.is_enum(), self.get_params()): - children = self.get_ports() + self.get_params() - #priority to the type controller - if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param - #use param if type param is unset - if not type_param: type_param = param - if type_param: - #try to increment the enum by direction - try: - keys = type_param.get_option_keys() - old_index = keys.index(type_param.get_value()) - new_index = (old_index + direction + len(keys))%len(keys) - type_param.set_value(keys[new_index]) - changed = True - except: pass - return changed - - def port_controller_modify(self, direction): - """ - Change the port controller. - - Args: - direction: +1 or -1 - - Returns: - true for change - """ - return False - - - def form_bus_structure(self, direc): - if direc == 'source': - get_p = self.get_sources; - get_p_gui = self.get_sources_gui; - bus_structure = self.get_bus_structure('source'); - else: - get_p = self.get_sinks; - get_p_gui = self.get_sinks_gui - bus_structure = self.get_bus_structure('sink'); - - struct = [range(len(get_p()))]; - if True in map(lambda a: isinstance(a.get_nports(), int), get_p()): - - - structlet = []; - last = 0; - for j in [i.get_nports() for i in get_p() if isinstance(i.get_nports(), int)]: - structlet.extend(map(lambda a: a+last, range(j))); - last = structlet[-1] + 1; - struct = [structlet]; - if bus_structure: - - struct = bus_structure - - self.current_bus_structure[direc] = struct; - return struct - - def bussify(self, n, direc): - if direc == 'source': - get_p = self.get_sources; - get_p_gui = self.get_sources_gui; - bus_structure = self.get_bus_structure('source'); - else: - get_p = self.get_sinks; - get_p_gui = self.get_sinks_gui - bus_structure = self.get_bus_structure('sink'); - - - for elt in get_p(): - for connect in elt.get_connections(): - self.get_parent().remove_element(connect); - - - - - - - if (not 'bus' in map(lambda a: a.get_type(), get_p())) and len(get_p()) > 0: - - struct = self.form_bus_structure(direc); - self.current_bus_structure[direc] = struct; - if get_p()[0].get_nports(): - n['nports'] = str(1); - - for i in range(len(struct)): - n['key'] = str(len(get_p())); - n = odict(n); - port = self.get_parent().get_parent().Port(block=self, n=n, dir=direc); - get_p().append(port); - - - - - elif 'bus' in map(lambda a: a.get_type(), get_p()): - 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(), self.get_params()) - 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 - """ - - get_hash = lambda: hash(tuple(map(hash, self.get_params()))) - my_hash = 0 - while 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 = 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') - + def __init__(self, flow_graph, n): + """ + Make a new block from nested data. + + Args: + flow: graph the parent element + n: the nested odict + + Returns: + block a new block + """ + #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._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') + #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 map(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 "%s" already exists in params'%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 "%s" already exists in sources'%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 "%s" already exists in sinks'%key + #store the port + self.get_sinks().append(sink) + self.back_ofthe_bus(self.get_sinks()) + self.current_bus_structure = {'source':'','sink':''}; + + + def back_ofthe_bus(self, portlist): + portlist.sort(key=lambda a: a.get_type() == 'bus'); + + + def filter_bus_port(self, ports): + buslist = [i for i in ports if i.get_type() == 'bus']; + if len(buslist) == 0: + return ports; + else: + return buslist; + + def get_enabled(self): + """ + Get the enabled state of the block. + + Returns: + true for enabled + """ + try: return eval(self.get_param('_enabled').get_value()) + except: return True + + def set_enabled(self, enabled): + """ + Set the enabled state of the block. + + Args: + enabled: true for enabled + """ + self.get_param('_enabled').set_value(str(enabled)) + + def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(), self.get_name(), self.get_key()) + + def get_id(self): return self.get_param('id').get_value() + def is_block(self): return True + def get_name(self): return self._name + def get_key(self): return self._key + def get_category(self): return self._category + def get_doc(self): return '' + def get_ports(self): return self.get_sources() + self.get_sinks() + def get_ports_gui(self): return self.filter_bus_port(self.get_sources()) + self.filter_bus_port(self.get_sinks()); + def get_children(self): return self.get_ports() + self.get_params() + def get_children_gui(self): return self.get_ports_gui() + self.get_params() + def get_block_wrapper_path(self): return self._block_wrapper_path + + ############################################## + # Access Params + ############################################## + def get_param_keys(self): return _get_keys(self._params) + def get_param(self, key): return _get_elem(self._params, key) + def get_params(self): return self._params + + ############################################## + # Access Sinks + ############################################## + def get_sink_keys(self): return _get_keys(self._sinks) + def get_sink(self, key): return _get_elem(self._sinks, key) + def get_sinks(self): return self._sinks + def get_sinks_gui(self): return self.filter_bus_port(self.get_sinks()) + + ############################################## + # Access Sources + ############################################## + def get_source_keys(self): return _get_keys(self._sources) + def get_source(self, key): return _get_elem(self._sources, key) + def get_sources(self): return self._sources + def get_sources_gui(self): return self.filter_bus_port(self.get_sources()); + + def get_connections(self): + return sum([port.get_connections() for port in self.get_ports()], []) + + def resolve_dependencies(self, tmpl): + """ + Resolve a paramater dependency with cheetah templates. + + Args: + tmpl: the string with dependencies + + Returns: + the resolved value + """ + tmpl = str(tmpl) + if '$' not in tmpl: return tmpl + n = dict((p.get_key(), TemplateArg(p)) for p in self.get_params()) + try: return str(Template(tmpl, n)) + except Exception, e: return "-------->\n%s: %s\n<--------"%(e, tmpl) + + ############################################## + # Controller Modify + ############################################## + def type_controller_modify(self, direction): + """ + Change the type controller. + + Args: + direction: +1 or -1 + + Returns: + true for change + """ + changed = False + type_param = None + for param in filter(lambda p: p.is_enum(), self.get_params()): + children = self.get_ports() + self.get_params() + #priority to the type controller + if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param + #use param if type param is unset + if not type_param: type_param = param + if type_param: + #try to increment the enum by direction + try: + keys = type_param.get_option_keys() + old_index = keys.index(type_param.get_value()) + new_index = (old_index + direction + len(keys))%len(keys) + type_param.set_value(keys[new_index]) + changed = True + except: pass + return changed + + def port_controller_modify(self, direction): + """ + Change the port controller. + + Args: + direction: +1 or -1 + + Returns: + true for change + """ + return False + + def form_bus_structure(self, direc): + if direc == 'source': + get_p = self.get_sources; + get_p_gui = self.get_sources_gui; + bus_structure = self.get_bus_structure('source'); + else: + get_p = self.get_sinks; + get_p_gui = self.get_sinks_gui + bus_structure = self.get_bus_structure('sink'); + + struct = [range(len(get_p()))]; + if True in map(lambda a: isinstance(a.get_nports(), int), get_p()): + + + structlet = []; + last = 0; + for j in [i.get_nports() for i in get_p() if isinstance(i.get_nports(), int)]: + structlet.extend(map(lambda a: a+last, range(j))); + last = structlet[-1] + 1; + struct = [structlet]; + if bus_structure: + + struct = bus_structure + + self.current_bus_structure[direc] = struct; + return struct + + def bussify(self, n, direc): + if direc == 'source': + get_p = self.get_sources; + get_p_gui = self.get_sources_gui; + bus_structure = self.get_bus_structure('source'); + else: + get_p = self.get_sinks; + get_p_gui = self.get_sinks_gui + bus_structure = self.get_bus_structure('sink'); + + + for elt in get_p(): + for connect in elt.get_connections(): + self.get_parent().remove_element(connect); + + + + + + + if (not 'bus' in map(lambda a: a.get_type(), get_p())) and len(get_p()) > 0: + + struct = self.form_bus_structure(direc); + self.current_bus_structure[direc] = struct; + if get_p()[0].get_nports(): + n['nports'] = str(1); + + for i in range(len(struct)): + n['key'] = str(len(get_p())); + n = odict(n); + port = self.get_parent().get_parent().Port(block=self, n=n, dir=direc); + get_p().append(port); + + + + + elif 'bus' in map(lambda a: a.get_type(), get_p()): + 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(), self.get_params()) + 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 + """ + get_hash = lambda: hash(tuple(map(hash, self.get_params()))) + my_hash = 0 + while 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 = get_hash() + self.rewrite() |