diff options
Diffstat (limited to 'grc/base')
-rw-r--r-- | grc/base/Block.py | 704 | ||||
-rw-r--r-- | grc/base/Connection.py | 183 | ||||
-rw-r--r-- | grc/base/Element.py | 132 | ||||
-rw-r--r-- | grc/base/FlowGraph.py | 552 | ||||
-rw-r--r-- | grc/base/Param.py | 314 | ||||
-rw-r--r-- | grc/base/ParseXML.py | 166 | ||||
-rw-r--r-- | grc/base/Platform.py | 310 | ||||
-rw-r--r-- | grc/base/Port.py | 173 | ||||
-rw-r--r-- | grc/base/block_tree.dtd | 6 | ||||
-rw-r--r-- | grc/base/flow_graph.dtd | 6 | ||||
-rw-r--r-- | grc/base/odict.py | 146 |
11 files changed, 1324 insertions, 1368 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() diff --git a/grc/base/Connection.py b/grc/base/Connection.py index 654eedb357..252b7deac1 100644 --- a/grc/base/Connection.py +++ b/grc/base/Connection.py @@ -22,104 +22,99 @@ from . import odict class Connection(Element): - def __init__(self, flow_graph, porta, portb): - """ - Make a new connection given the parent and 2 ports. - - Args: - flow_graph: the parent of this element - porta: a port (any direction) - portb: a port (any direction) - @throws Error cannot make connection - - Returns: - a new connection - """ - Element.__init__(self, flow_graph) - source = sink = None - #separate the source and sink - for port in (porta, portb): - if port.is_source(): source = port - if port.is_sink(): sink = port - if not source: raise ValueError('Connection could not isolate source') - if not sink: raise ValueError('Connection could not isolate sink') + def __init__(self, flow_graph, porta, portb): + """ + Make a new connection given the parent and 2 ports. + + Args: + flow_graph: the parent of this element + porta: a port (any direction) + portb: a port (any direction) + @throws Error cannot make connection + + Returns: + a new connection + """ + Element.__init__(self, flow_graph) + source = sink = None + #separate the source and sink + for port in (porta, portb): + if port.is_source(): source = port + if port.is_sink(): sink = port + if not source: raise ValueError('Connection could not isolate source') + if not sink: raise ValueError('Connection could not isolate sink') + busses = len(filter(lambda a: a.get_type() == 'bus', [source, sink]))%2 + if not busses == 0: raise ValueError('busses must get with busses') - busses = len(filter(lambda a: a.get_type() == 'bus', [source, sink]))%2 - if not busses == 0: raise ValueError('busses must get with busses') + if not len(source.get_associated_ports()) == len(sink.get_associated_ports()): + raise ValueError('port connections must have same cardinality'); + #ensure that this connection (source -> sink) is unique + for connection in self.get_parent().get_connections(): + if connection.get_source() is source and connection.get_sink() is sink: + raise Exception('This connection between source and sink is not unique.') + self._source = source + self._sink = sink + if source.get_type() == 'bus': + + sources = source.get_associated_ports(); + sinks = sink.get_associated_ports(); + + for i in range(len(sources)): + try: + flow_graph.connect(sources[i], sinks[i]); + except: + pass - if not len(source.get_associated_ports()) == len(sink.get_associated_ports()): - raise ValueError('port connections must have same cardinality'); - #ensure that this connection (source -> sink) is unique - for connection in self.get_parent().get_connections(): - if connection.get_source() is source and connection.get_sink() is sink: - raise Exception('This connection between source and sink is not unique.') - self._source = source - self._sink = sink - - if source.get_type() == 'bus': - - sources = source.get_associated_ports(); - sinks = sink.get_associated_ports(); - - for i in range(len(sources)): - try: - flow_graph.connect(sources[i], sinks[i]); - except: - pass - - - def __str__(self): - return 'Connection (\n\t%s\n\t\t%s\n\t%s\n\t\t%s\n)'%( - self.get_source().get_parent(), - self.get_source(), - self.get_sink().get_parent(), - self.get_sink(), - ) + def __str__(self): + return 'Connection (\n\t%s\n\t\t%s\n\t%s\n\t\t%s\n)'%( + self.get_source().get_parent(), + self.get_source(), + self.get_sink().get_parent(), + self.get_sink(), + ) - def is_connection(self): return True + def is_connection(self): return True - def validate(self): - """ - Validate the connections. - The ports must match in type. - """ - Element.validate(self) - source_type = self.get_source().get_type() - sink_type = self.get_sink().get_type() - if source_type != sink_type: - self.add_error_message('Source type "%s" does not match sink type "%s".'%(source_type, sink_type)) + def validate(self): + """ + Validate the connections. + The ports must match in type. + """ + Element.validate(self) + source_type = self.get_source().get_type() + sink_type = self.get_sink().get_type() + if source_type != sink_type: + self.add_error_message('Source type "%s" does not match sink type "%s".'%(source_type, sink_type)) - + def get_enabled(self): + """ + Get the enabled state of this connection. + + Returns: + true if source and sink blocks are enabled + """ + return self.get_source().get_parent().get_enabled() and \ + self.get_sink().get_parent().get_enabled() - def get_enabled(self): - """ - Get the enabled state of this connection. - - Returns: - true if source and sink blocks are enabled - """ - return self.get_source().get_parent().get_enabled() and \ - self.get_sink().get_parent().get_enabled() + ############################# + # Access Ports + ############################# + def get_sink(self): return self._sink + def get_source(self): return self._source - ############################# - # Access Ports - ############################# - def get_sink(self): return self._sink - def get_source(self): return self._source - - ############################################## - ## Import/Export Methods - ############################################## - def export_data(self): - """ - Export this connection's info. - - Returns: - a nested data odict - """ - n = odict() - n['source_block_id'] = self.get_source().get_parent().get_id() - n['sink_block_id'] = self.get_sink().get_parent().get_id() - n['source_key'] = self.get_source().get_key() - n['sink_key'] = self.get_sink().get_key() - return n + ############################################## + ## Import/Export Methods + ############################################## + def export_data(self): + """ + Export this connection's info. + + Returns: + a nested data odict + """ + n = odict() + n['source_block_id'] = self.get_source().get_parent().get_id() + n['sink_block_id'] = self.get_sink().get_parent().get_id() + n['source_key'] = self.get_source().get_key() + n['sink_key'] = self.get_sink().get_key() + return n diff --git a/grc/base/Element.py b/grc/base/Element.py index 74097eea9a..17b2234a8c 100644 --- a/grc/base/Element.py +++ b/grc/base/Element.py @@ -19,77 +19,77 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA class Element(object): - def __init__(self, parent=None): - self._parent = parent + def __init__(self, parent=None): + self._parent = parent - ################################################## - # Element Validation API - ################################################## - def validate(self): - """ - Validate this element and call validate on all children. - Call this base method before adding error messages in the subclass. - """ - self._error_messages = list() - for child in self.get_children(): child.validate() + ################################################## + # Element Validation API + ################################################## + def validate(self): + """ + Validate this element and call validate on all children. + Call this base method before adding error messages in the subclass. + """ + self._error_messages = list() + for child in self.get_children(): child.validate() - def is_valid(self): - """ - Is this element valid? - - Returns: - true when the element is enabled and has no error messages - """ - return not self.get_error_messages() or not self.get_enabled() + def is_valid(self): + """ + Is this element valid? + + Returns: + true when the element is enabled and has no error messages + """ + return not self.get_error_messages() or not self.get_enabled() - def add_error_message(self, msg): - """ - Add an error message to the list of errors. - - Args: - msg: the error message string - """ - self._error_messages.append(msg) + def add_error_message(self, msg): + """ + Add an error message to the list of errors. + + Args: + msg: the error message string + """ + self._error_messages.append(msg) - def get_error_messages(self): - """ - Get the list of error messages from this element and all of its children. - Do not include the error messages from disabled children. - Cleverly indent the children error messages for printing purposes. - - Returns: - a list of error message strings - """ - error_messages = list(self._error_messages) #make a copy - for child in filter(lambda c: c.get_enabled(), self.get_children()): - for msg in child.get_error_messages(): - error_messages.append("%s:\n\t%s"%(child, msg.replace("\n", "\n\t"))) - return error_messages + def get_error_messages(self): + """ + Get the list of error messages from this element and all of its children. + Do not include the error messages from disabled children. + Cleverly indent the children error messages for printing purposes. + + Returns: + a list of error message strings + """ + error_messages = list(self._error_messages) #make a copy + for child in filter(lambda c: c.get_enabled(), self.get_children()): + for msg in child.get_error_messages(): + error_messages.append("%s:\n\t%s"%(child, msg.replace("\n", "\n\t"))) + return error_messages - def rewrite(self): - """ - Rewrite this element and call rewrite on all children. - Call this base method before rewriting the element. - """ - for child in self.get_children(): child.rewrite() + def rewrite(self): + """ + Rewrite this element and call rewrite on all children. + Call this base method before rewriting the element. + """ + for child in self.get_children(): child.rewrite() - def get_enabled(self): return True + def get_enabled(self): return True - ############################################## - ## Tree-like API - ############################################## - def get_parent(self): return self._parent - def get_children(self): return list() + ############################################## + ## Tree-like API + ############################################## + def get_parent(self): return self._parent + def get_children(self): return list() - ############################################## - ## Type testing methods - ############################################## - def is_element(self): return True - def is_platform(self): return False - def is_flow_graph(self): return False - def is_connection(self): return False - def is_block(self): return False - def is_source(self): return False - def is_sink(self): return False - def is_port(self): return False - def is_param(self): return False + ############################################## + ## Type testing methods + ############################################## + def is_element(self): return True + def is_platform(self): return False + def is_flow_graph(self): return False + def is_connection(self): return False + def is_block(self): return False + def is_source(self): return False + def is_sink(self): return False + def is_port(self): return False + def is_param(self): return False diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py index a35afa363b..2f2d8c65e1 100644 --- a/grc/base/FlowGraph.py +++ b/grc/base/FlowGraph.py @@ -23,296 +23,288 @@ from .. gui import Messages class FlowGraph(Element): - def __init__(self, platform): - """ - Make a flow graph from the arguments. - - Args: - platform: a platforms with blocks and contrcutors - - Returns: - the flow graph object - """ - #initialize - Element.__init__(self, platform) - #inital blank import - self.import_data() + def __init__(self, platform): + """ + Make a flow graph from the arguments. + + Args: + platform: a platforms with blocks and contrcutors + + Returns: + the flow graph object + """ + #initialize + Element.__init__(self, platform) + #inital blank import + self.import_data() - def _get_unique_id(self, base_id=''): - """ - Get a unique id starting with the base id. - - Args: - base_id: the id starts with this and appends a count - - Returns: - a unique id - """ - index = 0 - while True: - id = '%s_%d'%(base_id, index) - index = index + 1 - #make sure that the id is not used by another block - if not filter(lambda b: b.get_id() == id, self.get_blocks()): return id + def _get_unique_id(self, base_id=''): + """ + Get a unique id starting with the base id. + + Args: + base_id: the id starts with this and appends a count + + Returns: + a unique id + """ + index = 0 + while True: + id = '%s_%d'%(base_id, index) + index = index + 1 + #make sure that the id is not used by another block + if not filter(lambda b: b.get_id() == id, self.get_blocks()): return id - def __str__(self): return 'FlowGraph - %s(%s)'%(self.get_option('title'), self.get_option('id')) - def rewrite(self): - def refactor_bus_structure(): - - for block in self.get_blocks(): - for direc in ['source', 'sink']: - if direc == 'source': - get_p = block.get_sources; - get_p_gui = block.get_sources_gui; - bus_structure = block.form_bus_structure('source'); - else: - get_p = block.get_sinks; - get_p_gui = block.get_sinks_gui - bus_structure = block.form_bus_structure('sink'); - - if 'bus' in map(lambda a: a.get_type(), get_p_gui()): - - - - if len(get_p_gui()) > len(bus_structure): - times = range(len(bus_structure), len(get_p_gui())); - for i in times: - for connect in get_p_gui()[-1].get_connections(): - block.get_parent().remove_element(connect); - get_p().remove(get_p_gui()[-1]); - elif len(get_p_gui()) < len(bus_structure): - n = {'name':'bus','type':'bus'}; - if True in map(lambda a: isinstance(a.get_nports(), int), get_p()): - n['nports'] = str(1); - - times = range(len(get_p_gui()), len(bus_structure)); - - for i in times: - n['key'] = str(len(get_p())); - n = odict(n); - port = block.get_parent().get_parent().Port(block=block, n=n, dir=direc); - get_p().append(port); - - - - for child in self.get_children(): child.rewrite() - refactor_bus_structure(); - + def __str__(self): return 'FlowGraph - %s(%s)'%(self.get_option('title'), self.get_option('id')) + def rewrite(self): + def refactor_bus_structure(): + + for block in self.get_blocks(): + for direc in ['source', 'sink']: + if direc == 'source': + get_p = block.get_sources; + get_p_gui = block.get_sources_gui; + bus_structure = block.form_bus_structure('source'); + else: + get_p = block.get_sinks; + get_p_gui = block.get_sinks_gui + bus_structure = block.form_bus_structure('sink'); + + if 'bus' in map(lambda a: a.get_type(), get_p_gui()): + + + + if len(get_p_gui()) > len(bus_structure): + times = range(len(bus_structure), len(get_p_gui())); + for i in times: + for connect in get_p_gui()[-1].get_connections(): + block.get_parent().remove_element(connect); + get_p().remove(get_p_gui()[-1]); + elif len(get_p_gui()) < len(bus_structure): + n = {'name':'bus','type':'bus'}; + if True in map(lambda a: isinstance(a.get_nports(), int), get_p()): + n['nports'] = str(1); + + times = range(len(get_p_gui()), len(bus_structure)); + + for i in times: + n['key'] = str(len(get_p())); + n = odict(n); + port = block.get_parent().get_parent().Port(block=block, n=n, dir=direc); + get_p().append(port); + + + + for child in self.get_children(): child.rewrite() + refactor_bus_structure(); - def get_option(self, key): - """ - Get the option for a given key. - The option comes from the special options block. - - Args: - key: the param key for the options block - - Returns: - the value held by that param - """ - return self._options_block.get_param(key).get_evaluated() + def get_option(self, key): + """ + Get the option for a given key. + The option comes from the special options block. + + Args: + key: the param key for the options block + + Returns: + the value held by that param + """ + return self._options_block.get_param(key).get_evaluated() - def is_flow_graph(self): return True + def is_flow_graph(self): return True - ############################################## - ## Access Elements - ############################################## - def get_block(self, id): return filter(lambda b: b.get_id() == id, self.get_blocks())[0] - def get_blocks_unordered(self): return filter(lambda e: e.is_block(), self.get_elements()) - def get_blocks(self): - blocks = self.get_blocks_unordered(); - for i in range(len(blocks)): - if blocks[i].get_key() == 'variable': - blk = blocks[i]; - blocks.remove(blk); - blocks.insert(1, blk); - return blocks; - def get_connections(self): return filter(lambda e: e.is_connection(), self.get_elements()) - def get_children(self): return self.get_elements() - def get_elements(self): - """ - Get a list of all the elements. - Always ensure that the options block is in the list (only once). - - Returns: - the element list - """ - options_block_count = self._elements.count(self._options_block) - if not options_block_count: - self._elements.append(self._options_block) - for i in range(options_block_count-1): - self._elements.remove(self._options_block) - return self._elements + ############################################## + ## Access Elements + ############################################## + def get_block(self, id): return filter(lambda b: b.get_id() == id, self.get_blocks())[0] + def get_blocks_unordered(self): return filter(lambda e: e.is_block(), self.get_elements()) + def get_blocks(self): + blocks = self.get_blocks_unordered(); + for i in range(len(blocks)): + if blocks[i].get_key() == 'variable': + blk = blocks[i]; + blocks.remove(blk); + blocks.insert(1, blk); + return blocks; + def get_connections(self): return filter(lambda e: e.is_connection(), self.get_elements()) + def get_children(self): return self.get_elements() + def get_elements(self): + """ + Get a list of all the elements. + Always ensure that the options block is in the list (only once). + + Returns: + the element list + """ + options_block_count = self._elements.count(self._options_block) + if not options_block_count: + self._elements.append(self._options_block) + for i in range(options_block_count-1): + self._elements.remove(self._options_block) + return self._elements - def get_enabled_blocks(self): - """ - Get a list of all blocks that are enabled. - - Returns: - a list of blocks - """ - return filter(lambda b: b.get_enabled(), self.get_blocks()) + def get_enabled_blocks(self): + """ + Get a list of all blocks that are enabled. + + Returns: + a list of blocks + """ + return filter(lambda b: b.get_enabled(), self.get_blocks()) - def get_enabled_connections(self): - """ - Get a list of all connections that are enabled. - - Returns: - a list of connections - """ - return filter(lambda c: c.get_enabled(), self.get_connections()) + def get_enabled_connections(self): + """ + Get a list of all connections that are enabled. + + Returns: + a list of connections + """ + return filter(lambda c: c.get_enabled(), self.get_connections()) - def get_new_block(self, key): - """ - Get a new block of the specified key. - Add the block to the list of elements. - - Args: - key: the block key - - Returns: - the new block or None if not found - """ - - if key not in self.get_parent().get_block_keys(): return None - block = self.get_parent().get_new_block(self, key) - self.get_elements().append(block); - if block._bussify_sink: - block.bussify({'name':'bus','type':'bus'}, 'sink') - if block._bussify_source: - block.bussify({'name':'bus','type':'bus'}, 'source') - return block; + def get_new_block(self, key): + """ + Get a new block of the specified key. + Add the block to the list of elements. + + Args: + key: the block key + + Returns: + the new block or None if not found + """ + if key not in self.get_parent().get_block_keys(): return None + block = self.get_parent().get_new_block(self, key) + self.get_elements().append(block); + if block._bussify_sink: + block.bussify({'name':'bus','type':'bus'}, 'sink') + if block._bussify_source: + block.bussify({'name':'bus','type':'bus'}, 'source') + return block; - def connect(self, porta, portb): - """ - Create a connection between porta and portb. - - Args: - porta: a port - portb: another port - @throw Exception bad connection - - Returns: - the new connection - """ - - connection = self.get_parent().Connection(flow_graph=self, porta=porta, portb=portb) - - - self.get_elements().append(connection) - return connection + def connect(self, porta, portb): + """ + Create a connection between porta and portb. + + Args: + porta: a port + portb: another port + @throw Exception bad connection + + Returns: + the new connection + """ + connection = self.get_parent().Connection(flow_graph=self, porta=porta, portb=portb) + self.get_elements().append(connection) + return connection - def remove_element(self, element): - """ - Remove the element from the list of elements. - If the element is a port, remove the whole block. - If the element is a block, remove its connections. - If the element is a connection, just remove the connection. - """ + def remove_element(self, element): + """ + Remove the element from the list of elements. + If the element is a port, remove the whole block. + If the element is a block, remove its connections. + If the element is a connection, just remove the connection. + """ + if element not in self.get_elements(): return + #found a port, set to parent signal block + if element.is_port(): + element = element.get_parent() + #remove block, remove all involved connections + if element.is_block(): + for port in element.get_ports(): + map(self.remove_element, port.get_connections()) + if element.is_connection(): + if element.is_bus(): + cons_list = [] + for i in map(lambda a: a.get_connections(), element.get_source().get_associated_ports()): + cons_list.extend(i); + map(self.remove_element, cons_list); + self.get_elements().remove(element) - if element not in self.get_elements(): return - #found a port, set to parent signal block - if element.is_port(): - element = element.get_parent() - #remove block, remove all involved connections - if element.is_block(): - for port in element.get_ports(): - map(self.remove_element, port.get_connections()) - if element.is_connection(): - if element.is_bus(): - cons_list = [] - for i in map(lambda a: a.get_connections(), element.get_source().get_associated_ports()): - cons_list.extend(i); - map(self.remove_element, cons_list); - self.get_elements().remove(element) - + def evaluate(self, expr): + """ + Evaluate the expression. + + Args: + expr: the string expression + @throw NotImplementedError + """ + raise NotImplementedError - def evaluate(self, expr): - """ - Evaluate the expression. - - Args: - expr: the string expression - @throw NotImplementedError - """ - raise NotImplementedError + ############################################## + ## Import/Export Methods + ############################################## + def export_data(self): + """ + Export this flow graph to nested data. + Export all block and connection data. + + Returns: + a nested data odict + """ + import time + n = odict() + n['timestamp'] = time.ctime() + n['block'] = [block.export_data() for block in self.get_blocks()] + n['connection'] = [connection.export_data() for connection in self.get_connections()] + return odict({'flow_graph': n}) - ############################################## - ## Import/Export Methods - ############################################## - def export_data(self): - """ - Export this flow graph to nested data. - Export all block and connection data. - - Returns: - a nested data odict - """ - import time - n = odict() - n['timestamp'] = time.ctime() - n['block'] = [block.export_data() for block in self.get_blocks()] - n['connection'] = [connection.export_data() for connection in self.get_connections()] - return odict({'flow_graph': n}) - - def import_data(self, n=None): - """ - Import blocks and connections into this flow graph. - Clear this flowgraph of all previous blocks and connections. - Any blocks or connections in error will be ignored. - - Args: - n: the nested data odict - """ - #remove previous elements - self._elements = list() - #use blank data if none provided - fg_n = n and n.find('flow_graph') or odict() - blocks_n = fg_n.findall('block') - connections_n = fg_n.findall('connection') - #create option block - self._options_block = self.get_parent().get_new_block(self, 'options') - #build the blocks - for block_n in blocks_n: - key = block_n.find('key') - if key == 'options': block = self._options_block - else: block = self.get_new_block(key) - #only load the block when the block key was valid - if block: block.import_data(block_n) - else: Messages.send_error_load('Block key "%s" not found in %s'%(key, self.get_parent())) - - #build the connections - for connection_n in connections_n: - #try to make the connection - try: - #get the block ids - source_block_id = connection_n.find('source_block_id') - sink_block_id = connection_n.find('sink_block_id') - #get the port keys - source_key = connection_n.find('source_key') - sink_key = connection_n.find('sink_key') - #verify the blocks - block_ids = map(lambda b: b.get_id(), self.get_blocks()) - if source_block_id not in block_ids: - raise LookupError('source block id "%s" not in block ids'%source_block_id) - if sink_block_id not in block_ids: - raise LookupError('sink block id "%s" not in block ids'%sink_block_id) - #get the blocks - source_block = self.get_block(source_block_id) - sink_block = self.get_block(sink_block_id) - #verify the ports - if source_key not in source_block.get_source_keys(): - raise LookupError('source key "%s" not in source block keys'%source_key) - if sink_key not in sink_block.get_sink_keys(): - raise LookupError('sink key "%s" not in sink block keys'%sink_key) - #get the ports - source = source_block.get_source(source_key) - sink = sink_block.get_sink(sink_key) - #build the connection - self.connect(source, sink) - except LookupError, e: Messages.send_error_load( - 'Connection between %s(%s) and %s(%s) could not be made.\n\t%s'%( - source_block_id, source_key, sink_block_id, sink_key, e - ) - ) - self.rewrite() #global rewrite + def import_data(self, n=None): + """ + Import blocks and connections into this flow graph. + Clear this flowgraph of all previous blocks and connections. + Any blocks or connections in error will be ignored. + + Args: + n: the nested data odict + """ + #remove previous elements + self._elements = list() + #use blank data if none provided + fg_n = n and n.find('flow_graph') or odict() + blocks_n = fg_n.findall('block') + connections_n = fg_n.findall('connection') + #create option block + self._options_block = self.get_parent().get_new_block(self, 'options') + #build the blocks + for block_n in blocks_n: + key = block_n.find('key') + if key == 'options': block = self._options_block + else: block = self.get_new_block(key) + #only load the block when the block key was valid + if block: block.import_data(block_n) + else: Messages.send_error_load('Block key "%s" not found in %s'%(key, self.get_parent())) + #build the connections + for connection_n in connections_n: + #try to make the connection + try: + #get the block ids + source_block_id = connection_n.find('source_block_id') + sink_block_id = connection_n.find('sink_block_id') + #get the port keys + source_key = connection_n.find('source_key') + sink_key = connection_n.find('sink_key') + #verify the blocks + block_ids = map(lambda b: b.get_id(), self.get_blocks()) + if source_block_id not in block_ids: + raise LookupError('source block id "%s" not in block ids'%source_block_id) + if sink_block_id not in block_ids: + raise LookupError('sink block id "%s" not in block ids'%sink_block_id) + #get the blocks + source_block = self.get_block(source_block_id) + sink_block = self.get_block(sink_block_id) + #verify the ports + if source_key not in source_block.get_source_keys(): + raise LookupError('source key "%s" not in source block keys'%source_key) + if sink_key not in sink_block.get_sink_keys(): + raise LookupError('sink key "%s" not in sink block keys'%sink_key) + #get the ports + source = source_block.get_source(source_key) + sink = sink_block.get_sink(sink_key) + #build the connection + self.connect(source, sink) + except LookupError, e: Messages.send_error_load( + 'Connection between %s(%s) and %s(%s) could not be made.\n\t%s'%( + source_block_id, source_key, sink_block_id, sink_key, e + ) + ) + self.rewrite() #global rewrite diff --git a/grc/base/Param.py b/grc/base/Param.py index 76a74d3ed7..8b8362ac1a 100644 --- a/grc/base/Param.py +++ b/grc/base/Param.py @@ -22,166 +22,166 @@ from Element import Element 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 Option(Element): - def __init__(self, param, n): - Element.__init__(self, param) - self._name = n.find('name') - self._key = n.find('key') - self._opts = dict() - opts = n.findall('opt') - #test against opts when non enum - if not self.get_parent().is_enum() and opts: - raise Exception, 'Options for non-enum types cannot have sub-options' - #extract opts - for opt in opts: - #separate the key:value - try: key, value = opt.split(':') - except: raise Exception, 'Error separating "%s" into key:value'%opt - #test against repeated keys - if self._opts.has_key(key): - raise Exception, 'Key "%s" already exists in option'%key - #store the option - self._opts[key] = value - - def __str__(self): return 'Option %s(%s)'%(self.get_name(), self.get_key()) - def get_name(self): return self._name - def get_key(self): return self._key - - ############################################## - # Access Opts - ############################################## - def get_opt_keys(self): return self._opts.keys() - def get_opt(self, key): return self._opts[key] - def get_opts(self): return self._opts.values() + def __init__(self, param, n): + Element.__init__(self, param) + self._name = n.find('name') + self._key = n.find('key') + self._opts = dict() + opts = n.findall('opt') + #test against opts when non enum + if not self.get_parent().is_enum() and opts: + raise Exception, 'Options for non-enum types cannot have sub-options' + #extract opts + for opt in opts: + #separate the key:value + try: key, value = opt.split(':') + except: raise Exception, 'Error separating "%s" into key:value'%opt + #test against repeated keys + if self._opts.has_key(key): + raise Exception, 'Key "%s" already exists in option'%key + #store the option + self._opts[key] = value + + def __str__(self): return 'Option %s(%s)'%(self.get_name(), self.get_key()) + def get_name(self): return self._name + def get_key(self): return self._key + + ############################################## + # Access Opts + ############################################## + def get_opt_keys(self): return self._opts.keys() + def get_opt(self, key): return self._opts[key] + def get_opts(self): return self._opts.values() class Param(Element): - def __init__(self, block, n): - """ - Make a new param from nested data. - - Args: - block: the parent element - n: the nested odict - """ - #grab the data - self._name = n.find('name') - self._key = n.find('key') - value = n.find('value') or '' - self._type = n.find('type') - self._hide = n.find('hide') or '' - #build the param - Element.__init__(self, block) - #create the Option objects from the n data - self._options = list() - for option in map(lambda o: Option(param=self, n=o), n.findall('option')): - key = option.get_key() - #test against repeated keys - if key in self.get_option_keys(): - raise Exception, 'Key "%s" already exists in options'%key - #store the option - self.get_options().append(option) - #test the enum options - if self.is_enum(): - #test against options with identical keys - if len(set(self.get_option_keys())) != len(self.get_options()): - raise Exception, 'Options keys "%s" are not unique.'%self.get_option_keys() - #test against inconsistent keys in options - opt_keys = self.get_options()[0].get_opt_keys() - for option in self.get_options(): - if set(opt_keys) != set(option.get_opt_keys()): - raise Exception, 'Opt keys "%s" are not identical across all options.'%opt_keys - #if a value is specified, it must be in the options keys - self._value = value if value or value in self.get_option_keys() else self.get_option_keys()[0] - if self.get_value() not in self.get_option_keys(): - raise Exception, 'The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys()) - else: self._value = value or '' - - def validate(self): - """ - Validate the param. - The value must be evaluated and type must a possible type. - """ - Element.validate(self) - if self.get_type() not in self.get_types(): - self.add_error_message('Type "%s" is not a possible type.'%self.get_type()) - - def get_evaluated(self): raise NotImplementedError - - def to_code(self): - """ - Convert the value to code. - @throw NotImplementedError - """ - raise NotImplementedError - - def get_types(self): - """ - Get a list of all possible param types. - @throw NotImplementedError - """ - raise NotImplementedError - - def get_color(self): return '#FFFFFF' - def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key()) - def is_param(self): return True - def get_name(self): return self._name - def get_key(self): return self._key - def get_hide(self): return self.get_parent().resolve_dependencies(self._hide).strip() - - def get_value(self): - value = self._value - if self.is_enum() and value not in self.get_option_keys(): - value = self.get_option_keys()[0] - self.set_value(value) - return value - - def set_value(self, value): self._value = str(value) #must be a string - - def get_type(self): return self.get_parent().resolve_dependencies(self._type) - def is_enum(self): return self._type == 'enum' - - def __repr__(self): - """ - Get the repr (nice string format) for this param. - Just return the value (special case enum). - Derived classes can handle complex formatting. - - Returns: - the string representation - """ - if self.is_enum(): return self.get_option(self.get_value()).get_name() - return self.get_value() - - ############################################## - # Access Options - ############################################## - def get_option_keys(self): return _get_keys(self.get_options()) - def get_option(self, key): return _get_elem(self.get_options(), key) - def get_options(self): return self._options - - ############################################## - # Access Opts - ############################################## - def get_opt_keys(self): return self.get_option(self.get_value()).get_opt_keys() - def get_opt(self, key): return self.get_option(self.get_value()).get_opt(key) - def get_opts(self): return self.get_option(self.get_value()).get_opts() - - ############################################## - ## Import/Export Methods - ############################################## - def export_data(self): - """ - Export this param's key/value. - - Returns: - a nested data odict - """ - n = odict() - n['key'] = self.get_key() - n['value'] = self.get_value() - return n + def __init__(self, block, n): + """ + Make a new param from nested data. + + Args: + block: the parent element + n: the nested odict + """ + #grab the data + self._name = n.find('name') + self._key = n.find('key') + value = n.find('value') or '' + self._type = n.find('type') + self._hide = n.find('hide') or '' + #build the param + Element.__init__(self, block) + #create the Option objects from the n data + self._options = list() + for option in map(lambda o: Option(param=self, n=o), n.findall('option')): + key = option.get_key() + #test against repeated keys + if key in self.get_option_keys(): + raise Exception, 'Key "%s" already exists in options'%key + #store the option + self.get_options().append(option) + #test the enum options + if self.is_enum(): + #test against options with identical keys + if len(set(self.get_option_keys())) != len(self.get_options()): + raise Exception, 'Options keys "%s" are not unique.'%self.get_option_keys() + #test against inconsistent keys in options + opt_keys = self.get_options()[0].get_opt_keys() + for option in self.get_options(): + if set(opt_keys) != set(option.get_opt_keys()): + raise Exception, 'Opt keys "%s" are not identical across all options.'%opt_keys + #if a value is specified, it must be in the options keys + self._value = value if value or value in self.get_option_keys() else self.get_option_keys()[0] + if self.get_value() not in self.get_option_keys(): + raise Exception, 'The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys()) + else: self._value = value or '' + + def validate(self): + """ + Validate the param. + The value must be evaluated and type must a possible type. + """ + Element.validate(self) + if self.get_type() not in self.get_types(): + self.add_error_message('Type "%s" is not a possible type.'%self.get_type()) + + def get_evaluated(self): raise NotImplementedError + + def to_code(self): + """ + Convert the value to code. + @throw NotImplementedError + """ + raise NotImplementedError + + def get_types(self): + """ + Get a list of all possible param types. + @throw NotImplementedError + """ + raise NotImplementedError + + def get_color(self): return '#FFFFFF' + def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key()) + def is_param(self): return True + def get_name(self): return self._name + def get_key(self): return self._key + def get_hide(self): return self.get_parent().resolve_dependencies(self._hide).strip() + + def get_value(self): + value = self._value + if self.is_enum() and value not in self.get_option_keys(): + value = self.get_option_keys()[0] + self.set_value(value) + return value + + def set_value(self, value): self._value = str(value) #must be a string + + def get_type(self): return self.get_parent().resolve_dependencies(self._type) + def is_enum(self): return self._type == 'enum' + + def __repr__(self): + """ + Get the repr (nice string format) for this param. + Just return the value (special case enum). + Derived classes can handle complex formatting. + + Returns: + the string representation + """ + if self.is_enum(): return self.get_option(self.get_value()).get_name() + return self.get_value() + + ############################################## + # Access Options + ############################################## + def get_option_keys(self): return _get_keys(self.get_options()) + def get_option(self, key): return _get_elem(self.get_options(), key) + def get_options(self): return self._options + + ############################################## + # Access Opts + ############################################## + def get_opt_keys(self): return self.get_option(self.get_value()).get_opt_keys() + def get_opt(self, key): return self.get_option(self.get_value()).get_opt(key) + def get_opts(self): return self.get_option(self.get_value()).get_opts() + + ############################################## + ## Import/Export Methods + ############################################## + def export_data(self): + """ + Export this param's key/value. + + Returns: + a nested data odict + """ + n = odict() + n['key'] = self.get_key() + n['value'] = self.get_value() + return n diff --git a/grc/base/ParseXML.py b/grc/base/ParseXML.py index e8f9b0583e..56097395dd 100644 --- a/grc/base/ParseXML.py +++ b/grc/base/ParseXML.py @@ -21,99 +21,99 @@ from lxml import etree from . import odict class XMLSyntaxError(Exception): - def __init__(self, error_log): - self._error_log = error_log - def __str__(self): - return '\n'.join(map(str, self._error_log.filter_from_errors())) + def __init__(self, error_log): + self._error_log = error_log + def __str__(self): + return '\n'.join(map(str, self._error_log.filter_from_errors())) def validate_dtd(xml_file, dtd_file=None): - """ - Validate an xml file against its dtd. - - Args: - xml_file: the xml file - dtd_file: the optional dtd file - @throws Exception validation fails - """ - #perform parsing, use dtd validation if dtd file is not specified - parser = etree.XMLParser(dtd_validation=not dtd_file) - xml = etree.parse(xml_file, parser=parser) - if parser.error_log: raise XMLSyntaxError(parser.error_log) - #perform dtd validation if the dtd file is specified - if not dtd_file: return - dtd = etree.DTD(dtd_file) - if not dtd.validate(xml.getroot()): raise XMLSyntaxError(dtd.error_log) + """ + Validate an xml file against its dtd. + + Args: + xml_file: the xml file + dtd_file: the optional dtd file + @throws Exception validation fails + """ + #perform parsing, use dtd validation if dtd file is not specified + parser = etree.XMLParser(dtd_validation=not dtd_file) + xml = etree.parse(xml_file, parser=parser) + if parser.error_log: raise XMLSyntaxError(parser.error_log) + #perform dtd validation if the dtd file is specified + if not dtd_file: return + dtd = etree.DTD(dtd_file) + if not dtd.validate(xml.getroot()): raise XMLSyntaxError(dtd.error_log) def from_file(xml_file): - """ - Create nested data from an xml file using the from xml helper. - - Args: - xml_file: the xml file path - - Returns: - the nested data - """ - xml = etree.parse(xml_file).getroot() - return _from_file(xml) + """ + Create nested data from an xml file using the from xml helper. + + Args: + xml_file: the xml file path + + Returns: + the nested data + """ + xml = etree.parse(xml_file).getroot() + return _from_file(xml) def _from_file(xml): - """ - Recursivly parse the xml tree into nested data format. - - Args: - xml: the xml tree - - Returns: - the nested data - """ - tag = xml.tag - if not len(xml): - return odict({tag: xml.text or ''}) #store empty tags (text is None) as empty string - nested_data = odict() - for elem in xml: - key, value = _from_file(elem).items()[0] - if nested_data.has_key(key): nested_data[key].append(value) - else: nested_data[key] = [value] - #delistify if the length of values is 1 - for key, values in nested_data.iteritems(): - if len(values) == 1: nested_data[key] = values[0] + """ + Recursivly parse the xml tree into nested data format. + + Args: + xml: the xml tree + + Returns: + the nested data + """ + tag = xml.tag + if not len(xml): + return odict({tag: xml.text or ''}) #store empty tags (text is None) as empty string + nested_data = odict() + for elem in xml: + key, value = _from_file(elem).items()[0] + if nested_data.has_key(key): nested_data[key].append(value) + else: nested_data[key] = [value] + #delistify if the length of values is 1 + for key, values in nested_data.iteritems(): + if len(values) == 1: nested_data[key] = values[0] - return odict({tag: nested_data}) + return odict({tag: nested_data}) def to_file(nested_data, xml_file): - """ - Write an xml file and use the to xml helper method to load it. - - Args: - nested_data: the nested data - xml_file: the xml file path - """ - xml = _to_file(nested_data)[0] - open(xml_file, 'w').write(etree.tostring(xml, xml_declaration=True, pretty_print=True)) + """ + Write an xml file and use the to xml helper method to load it. + + Args: + nested_data: the nested data + xml_file: the xml file path + """ + xml = _to_file(nested_data)[0] + open(xml_file, 'w').write(etree.tostring(xml, xml_declaration=True, pretty_print=True)) def _to_file(nested_data): - """ - Recursivly parse the nested data into xml tree format. - - Args: - nested_data: the nested data - - Returns: - the xml tree filled with child nodes - """ - nodes = list() - for key, values in nested_data.iteritems(): - #listify the values if not a list - if not isinstance(values, (list, set, tuple)): - values = [values] - for value in values: - node = etree.Element(key) - if isinstance(value, (str, unicode)): node.text = value - else: node.extend(_to_file(value)) - nodes.append(node) - return nodes + """ + Recursivly parse the nested data into xml tree format. + + Args: + nested_data: the nested data + + Returns: + the xml tree filled with child nodes + """ + nodes = list() + for key, values in nested_data.iteritems(): + #listify the values if not a list + if not isinstance(values, (list, set, tuple)): + values = [values] + for value in values: + node = etree.Element(key) + if isinstance(value, (str, unicode)): node.text = value + else: node.extend(_to_file(value)) + nodes.append(node) + return nodes if __name__ == '__main__': - """Use the main method to test parse xml's functions.""" - pass + """Use the main method to test parse xml's functions.""" + pass diff --git a/grc/base/Platform.py b/grc/base/Platform.py index f0f24a48a7..bb80e29552 100644 --- a/grc/base/Platform.py +++ b/grc/base/Platform.py @@ -30,159 +30,159 @@ from Constants import BLOCK_TREE_DTD, FLOW_GRAPH_DTD class Platform(_Element): - def __init__(self, name, version, key, - block_paths, block_dtd, default_flow_graph, generator, - license='', website=None, colors=[]): - """ - Make a platform from the arguments. - - Args: - name: the platform name - version: the version string - key: the unique platform key - block_paths: the file paths to blocks in this platform - block_dtd: the dtd validator for xml block wrappers - default_flow_graph: the default flow graph file path - generator: the generator class for this platform - colors: a list of title, color_spec tuples - license: a multi-line license (first line is copyright) - website: the website url for this platform - - Returns: - a platform object - """ - _Element.__init__(self) - self._name = name - self._version = version - self._key = key - self._license = license - self._website = website - self._block_paths = block_paths - self._block_dtd = block_dtd - self._default_flow_graph = default_flow_graph - self._generator = generator - self._colors = colors - #create a dummy flow graph for the blocks - self._flow_graph = _Element(self) - #search for *.xml files in the given search path - - self.loadblocks(); + def __init__(self, name, version, key, + block_paths, block_dtd, default_flow_graph, generator, + license='', website=None, colors=[]): + """ + Make a platform from the arguments. + + Args: + name: the platform name + version: the version string + key: the unique platform key + block_paths: the file paths to blocks in this platform + block_dtd: the dtd validator for xml block wrappers + default_flow_graph: the default flow graph file path + generator: the generator class for this platform + colors: a list of title, color_spec tuples + license: a multi-line license (first line is copyright) + website: the website url for this platform + + Returns: + a platform object + """ + _Element.__init__(self) + self._name = name + self._version = version + self._key = key + self._license = license + self._website = website + self._block_paths = block_paths + self._block_dtd = block_dtd + self._default_flow_graph = default_flow_graph + self._generator = generator + self._colors = colors + #create a dummy flow graph for the blocks + self._flow_graph = _Element(self) + #search for *.xml files in the given search path + + self.loadblocks(); - def loadblocks(self): - xml_files = list() - for block_path in self._block_paths: - if os.path.isfile(block_path): xml_files.append(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)): - xml_files.append(os.path.join(dirpath, filename)) - #load the blocks - self._blocks = odict() - self._blocks_n = odict() - self._block_tree_files = list() - for xml_file in xml_files: - try: #try to add the xml file as a block wrapper - ParseXML.validate_dtd(xml_file, self._block_dtd) - n = ParseXML.from_file(xml_file).find('block') - #inject block wrapper path - n['block_wrapper_path'] = xml_file - block = self.Block(self._flow_graph, n) - key = block.get_key() - #test against repeated keys - if key in self.get_block_keys(): - print >> sys.stderr, 'Warning: Block with key "%s" already exists.\n\tIgnoring: %s'%(key, xml_file) - #store the block - else: - self._blocks[key] = block - self._blocks_n[key] = n - except ParseXML.XMLSyntaxError, e: - try: #try to add the xml file as a block tree - ParseXML.validate_dtd(xml_file, BLOCK_TREE_DTD) - self._block_tree_files.append(xml_file) - except ParseXML.XMLSyntaxError, e: - print >> sys.stderr, 'Warning: Block validation failed:\n\t%s\n\tIgnoring: %s'%(e, xml_file) - except Exception, e: - print >> sys.stderr, 'Warning: Block loading failed:\n\t%s\n\tIgnoring: %s'%(e, xml_file) - - def parse_flow_graph(self, flow_graph_file): - """ - Parse a saved flow graph file. - Ensure that the file exists, and passes the dtd check. - - Args: - flow_graph_file: the flow graph file - - Returns: - nested data - @throws exception if the validation fails - """ - flow_graph_file = flow_graph_file or self._default_flow_graph - open(flow_graph_file, 'r') #test open - ParseXML.validate_dtd(flow_graph_file, FLOW_GRAPH_DTD) - return ParseXML.from_file(flow_graph_file) - - def load_block_tree(self, block_tree): - """ - Load a block tree with categories and blocks. - Step 1: Load all blocks from the xml specification. - Step 2: Load blocks with builtin category specifications. - - Args: - block_tree: the block tree object - """ - #recursive function to load categories and blocks - def load_category(cat_n, parent=[]): - #add this category - parent = parent + [cat_n.find('name')] - block_tree.add_block(parent) - #recursive call to load sub categories - map(lambda c: load_category(c, parent), cat_n.findall('cat')) - #add blocks in this category - for block_key in cat_n.findall('block'): - if block_key not in self.get_block_keys(): - print >> sys.stderr, 'Warning: Block key "%s" not found when loading category tree.'%(block_key) - continue - block = self.get_block(block_key) - #if it exists, the block's category overrides the block tree - if not block.get_category(): block_tree.add_block(parent, block) - #load the block tree - for block_tree_file in self._block_tree_files: - #recursivly add all blocks in the tree - load_category(ParseXML.from_file(block_tree_file).find('cat')) - #add all other blocks, use the catgory tag - for block in self.get_blocks(): - #blocks with empty categories are in the xml block tree or hidden - if not block.get_category(): continue - block_tree.add_block(block.get_category(), block) - - def __str__(self): return 'Platform - %s(%s)'%(self.get_key(), self.get_name()) - - def is_platform(self): return True - - def get_new_flow_graph(self): return self.FlowGraph(platform=self) - - def get_generator(self): return self._generator - - ############################################## - # Access Blocks - ############################################## - def get_block_keys(self): return self._blocks.keys() - def get_block(self, key): return self._blocks[key] - def get_blocks(self): return self._blocks.values() - def get_new_block(self, flow_graph, key): return self.Block(flow_graph, n=self._blocks_n[key]) - - def get_name(self): return self._name - def get_version(self): return self._version - def get_key(self): return self._key - def get_license(self): return self._license - def get_website(self): return self._website - def get_colors(self): return self._colors - - ############################################## - # Constructors - ############################################## - FlowGraph = _FlowGraph - Connection = _Connection - Block = _Block - Port = _Port - Param = _Param + def loadblocks(self): + xml_files = list() + for block_path in self._block_paths: + if os.path.isfile(block_path): xml_files.append(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)): + xml_files.append(os.path.join(dirpath, filename)) + #load the blocks + self._blocks = odict() + self._blocks_n = odict() + self._block_tree_files = list() + for xml_file in xml_files: + try: #try to add the xml file as a block wrapper + ParseXML.validate_dtd(xml_file, self._block_dtd) + n = ParseXML.from_file(xml_file).find('block') + #inject block wrapper path + n['block_wrapper_path'] = xml_file + block = self.Block(self._flow_graph, n) + key = block.get_key() + #test against repeated keys + if key in self.get_block_keys(): + print >> sys.stderr, 'Warning: Block with key "%s" already exists.\n\tIgnoring: %s'%(key, xml_file) + #store the block + else: + self._blocks[key] = block + self._blocks_n[key] = n + except ParseXML.XMLSyntaxError, e: + try: #try to add the xml file as a block tree + ParseXML.validate_dtd(xml_file, BLOCK_TREE_DTD) + self._block_tree_files.append(xml_file) + except ParseXML.XMLSyntaxError, e: + print >> sys.stderr, 'Warning: Block validation failed:\n\t%s\n\tIgnoring: %s'%(e, xml_file) + except Exception, e: + print >> sys.stderr, 'Warning: Block loading failed:\n\t%s\n\tIgnoring: %s'%(e, xml_file) + + def parse_flow_graph(self, flow_graph_file): + """ + Parse a saved flow graph file. + Ensure that the file exists, and passes the dtd check. + + Args: + flow_graph_file: the flow graph file + + Returns: + nested data + @throws exception if the validation fails + """ + flow_graph_file = flow_graph_file or self._default_flow_graph + open(flow_graph_file, 'r') #test open + ParseXML.validate_dtd(flow_graph_file, FLOW_GRAPH_DTD) + return ParseXML.from_file(flow_graph_file) + + def load_block_tree(self, block_tree): + """ + Load a block tree with categories and blocks. + Step 1: Load all blocks from the xml specification. + Step 2: Load blocks with builtin category specifications. + + Args: + block_tree: the block tree object + """ + #recursive function to load categories and blocks + def load_category(cat_n, parent=[]): + #add this category + parent = parent + [cat_n.find('name')] + block_tree.add_block(parent) + #recursive call to load sub categories + map(lambda c: load_category(c, parent), cat_n.findall('cat')) + #add blocks in this category + for block_key in cat_n.findall('block'): + if block_key not in self.get_block_keys(): + print >> sys.stderr, 'Warning: Block key "%s" not found when loading category tree.'%(block_key) + continue + block = self.get_block(block_key) + #if it exists, the block's category overrides the block tree + if not block.get_category(): block_tree.add_block(parent, block) + #load the block tree + for block_tree_file in self._block_tree_files: + #recursivly add all blocks in the tree + load_category(ParseXML.from_file(block_tree_file).find('cat')) + #add all other blocks, use the catgory tag + for block in self.get_blocks(): + #blocks with empty categories are in the xml block tree or hidden + if not block.get_category(): continue + block_tree.add_block(block.get_category(), block) + + def __str__(self): return 'Platform - %s(%s)'%(self.get_key(), self.get_name()) + + def is_platform(self): return True + + def get_new_flow_graph(self): return self.FlowGraph(platform=self) + + def get_generator(self): return self._generator + + ############################################## + # Access Blocks + ############################################## + def get_block_keys(self): return self._blocks.keys() + def get_block(self, key): return self._blocks[key] + def get_blocks(self): return self._blocks.values() + def get_new_block(self, flow_graph, key): return self.Block(flow_graph, n=self._blocks_n[key]) + + def get_name(self): return self._name + def get_version(self): return self._version + def get_key(self): return self._key + def get_license(self): return self._license + def get_website(self): return self._website + def get_colors(self): return self._colors + + ############################################## + # Constructors + ############################################## + FlowGraph = _FlowGraph + Connection = _Connection + Block = _Block + Port = _Port + Param = _Param diff --git a/grc/base/Port.py b/grc/base/Port.py index 1b2acb0582..b7de5301f1 100644 --- a/grc/base/Port.py +++ b/grc/base/Port.py @@ -21,97 +21,96 @@ from Element import Element class Port(Element): - def __init__(self, block, n, dir): - """ - Make a new port from nested data. - - Args: - block: the parent element - n: the nested odict - dir: the direction source or sink - """ - #build the port - Element.__init__(self, block) - #grab the data - self._name = n['name'] - self._key = n['key'] - self._type = n['type'] - self._dir = dir + def __init__(self, block, n, dir): + """ + Make a new port from nested data. + + Args: + block: the parent element + n: the nested odict + dir: the direction source or sink + """ + #build the port + Element.__init__(self, block) + #grab the data + self._name = n['name'] + self._key = n['key'] + self._type = n['type'] + self._dir = dir - - def validate(self): - """ - Validate the port. - The port must be non-empty and type must a possible type. - """ - Element.validate(self) - if self.get_type() not in self.get_types(): - self.add_error_message('Type "%s" is not a possible type.'%self.get_type()) + def validate(self): + """ + Validate the port. + The port must be non-empty and type must a possible type. + """ + Element.validate(self) + if self.get_type() not in self.get_types(): + self.add_error_message('Type "%s" is not a possible type.'%self.get_type()) - def __str__(self): - if self.is_source(): - return 'Source - %s(%s)'%(self.get_name(), self.get_key()) - if self.is_sink(): - return 'Sink - %s(%s)'%(self.get_name(), self.get_key()) + def __str__(self): + if self.is_source(): + return 'Source - %s(%s)'%(self.get_name(), self.get_key()) + if self.is_sink(): + return 'Sink - %s(%s)'%(self.get_name(), self.get_key()) - def get_types(self): - """ - Get a list of all possible port types. - @throw NotImplementedError - """ - raise NotImplementedError + def get_types(self): + """ + Get a list of all possible port types. + @throw NotImplementedError + """ + raise NotImplementedError - def is_port(self): return True - def get_color(self): return '#FFFFFF' - def get_name(self): - number = '' - if self.get_type() == 'bus': - busses = filter(lambda a: a._dir == self._dir, self.get_parent().get_ports_gui()); - - number = str(busses.index(self)) + '#' + str(len(self.get_associated_ports())); - return self._name + number + def is_port(self): return True + def get_color(self): return '#FFFFFF' + def get_name(self): + number = '' + if self.get_type() == 'bus': + busses = filter(lambda a: a._dir == self._dir, self.get_parent().get_ports_gui()); + + number = str(busses.index(self)) + '#' + str(len(self.get_associated_ports())); + return self._name + number - def get_key(self): return self._key - def is_sink(self): return self._dir == 'sink' - def is_source(self): return self._dir == 'source' - def get_type(self): return self.get_parent().resolve_dependencies(self._type) + def get_key(self): return self._key + def is_sink(self): return self._dir == 'sink' + def is_source(self): return self._dir == 'source' + def get_type(self): return self.get_parent().resolve_dependencies(self._type) - def get_connections(self): - """ - Get all connections that use this port. - - Returns: - a list of connection objects - """ - connections = self.get_parent().get_parent().get_connections() - connections = filter(lambda c: c.get_source() is self or c.get_sink() is self, connections) - return connections + def get_connections(self): + """ + Get all connections that use this port. + + Returns: + a list of connection objects + """ + connections = self.get_parent().get_parent().get_connections() + connections = filter(lambda c: c.get_source() is self or c.get_sink() is self, connections) + return connections - def get_enabled_connections(self): - """ - Get all enabled connections that use this port. - - Returns: - a list of connection objects - """ - return filter(lambda c: c.get_enabled(), self.get_connections()) - - def get_associated_ports(self): - if not self.get_type() == 'bus': - return [self]; - else: - if self.is_source(): - get_p = self.get_parent().get_sources; - bus_structure = self.get_parent().current_bus_structure['source']; - direc = 'source' - else: - get_p = self.get_parent().get_sinks; - bus_structure = self.get_parent().current_bus_structure['sink']; - direc = 'sink' - - ports = [i for i in get_p() if not i.get_type() == 'bus']; - if bus_structure: - busses = [i for i in get_p() if i.get_type() == 'bus']; - bus_index = busses.index(self); - ports = filter(lambda a: ports.index(a) in bus_structure[bus_index], ports); - return ports; + def get_enabled_connections(self): + """ + Get all enabled connections that use this port. + + Returns: + a list of connection objects + """ + return filter(lambda c: c.get_enabled(), self.get_connections()) + + def get_associated_ports(self): + if not self.get_type() == 'bus': + return [self]; + else: + if self.is_source(): + get_p = self.get_parent().get_sources; + bus_structure = self.get_parent().current_bus_structure['source']; + direc = 'source' + else: + get_p = self.get_parent().get_sinks; + bus_structure = self.get_parent().current_bus_structure['sink']; + direc = 'sink' + + ports = [i for i in get_p() if not i.get_type() == 'bus']; + if bus_structure: + busses = [i for i in get_p() if i.get_type() == 'bus']; + bus_index = busses.index(self); + ports = filter(lambda a: ports.index(a) in bus_structure[bus_index], ports); + return ports; diff --git a/grc/base/block_tree.dtd b/grc/base/block_tree.dtd index 7d4a13ccc3..9e23576477 100644 --- a/grc/base/block_tree.dtd +++ b/grc/base/block_tree.dtd @@ -17,9 +17,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA --> <!-- - block_tree.dtd - Josh Blum - The document type definition for a block tree category listing. + block_tree.dtd + Josh Blum + The document type definition for a block tree category listing. --> <!ELEMENT cat (name, cat*, block*)> <!ELEMENT name (#PCDATA)> diff --git a/grc/base/flow_graph.dtd b/grc/base/flow_graph.dtd index becfc21e9b..bdfe1dc059 100644 --- a/grc/base/flow_graph.dtd +++ b/grc/base/flow_graph.dtd @@ -17,9 +17,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA --> <!-- - flow_graph.dtd - Josh Blum - The document type definition for flow graph xml files. + flow_graph.dtd + Josh Blum + The document type definition for flow graph xml files. --> <!ELEMENT flow_graph (timestamp?, block*, connection*)> <!-- optional timestamp --> <!ELEMENT timestamp (#PCDATA)> diff --git a/grc/base/odict.py b/grc/base/odict.py index 302583163b..0c03d753f6 100644 --- a/grc/base/odict.py +++ b/grc/base/odict.py @@ -21,85 +21,85 @@ from UserDict import DictMixin class odict(DictMixin): - def __init__(self, d={}): - self._keys = list(d.keys()) - self._data = dict(d.copy()) + def __init__(self, d={}): + self._keys = list(d.keys()) + self._data = dict(d.copy()) - def __setitem__(self, key, value): - if key not in self._data: - self._keys.append(key) - self._data[key] = value + def __setitem__(self, key, value): + if key not in self._data: + self._keys.append(key) + self._data[key] = value - def __getitem__(self, key): - return self._data[key] + def __getitem__(self, key): + return self._data[key] - def __delitem__(self, key): - del self._data[key] - self._keys.remove(key) + def __delitem__(self, key): + del self._data[key] + self._keys.remove(key) - def keys(self): - return list(self._keys) + def keys(self): + return list(self._keys) - def copy(self): - copy_dict = odict() - copy_dict._data = self._data.copy() - copy_dict._keys = list(self._keys) - return copy_dict + def copy(self): + copy_dict = odict() + copy_dict._data = self._data.copy() + copy_dict._keys = list(self._keys) + return copy_dict - def insert_after(self, pos_key, key, val): - """ - Insert the new key, value entry after the entry given by the position key. - If the positional key is None, insert at the end. - - Args: - pos_key: the positional key - key: the key for the new entry - val: the value for the new entry - """ - index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key) - if key in self._keys: raise KeyError('Cannot insert, key "%s" already exists'%str(key)) - self._keys.insert(index+1, key) - self._data[key] = val + def insert_after(self, pos_key, key, val): + """ + Insert the new key, value entry after the entry given by the position key. + If the positional key is None, insert at the end. + + Args: + pos_key: the positional key + key: the key for the new entry + val: the value for the new entry + """ + index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key) + if key in self._keys: raise KeyError('Cannot insert, key "%s" already exists'%str(key)) + self._keys.insert(index+1, key) + self._data[key] = val - def insert_before(self, pos_key, key, val): - """ - Insert the new key, value entry before the entry given by the position key. - If the positional key is None, insert at the begining. - - Args: - pos_key: the positional key - key: the key for the new entry - val: the value for the new entry - """ - index = (pos_key is not None) and self._keys.index(pos_key) or 0 - if key in self._keys: raise KeyError('Cannot insert, key "%s" already exists'%str(key)) - self._keys.insert(index, key) - self._data[key] = val + def insert_before(self, pos_key, key, val): + """ + Insert the new key, value entry before the entry given by the position key. + If the positional key is None, insert at the begining. + + Args: + pos_key: the positional key + key: the key for the new entry + val: the value for the new entry + """ + index = (pos_key is not None) and self._keys.index(pos_key) or 0 + if key in self._keys: raise KeyError('Cannot insert, key "%s" already exists'%str(key)) + self._keys.insert(index, key) + self._data[key] = val - def find(self, key): - """ - Get the value for this key if exists. - - Args: - key: the key to search for - - Returns: - the value or None - """ - if self.has_key(key): return self[key] - return None + def find(self, key): + """ + Get the value for this key if exists. + + Args: + key: the key to search for + + Returns: + the value or None + """ + if self.has_key(key): return self[key] + return None - def findall(self, key): - """ - Get a list of values for this key. - - Args: - key: the key to search for - - Returns: - a list of values or empty list - """ - obj = self.find(key) - if obj is None: obj = list() - if isinstance(obj, list): return obj - return [obj] + def findall(self, key): + """ + Get a list of values for this key. + + Args: + key: the key to search for + + Returns: + a list of values or empty list + """ + obj = self.find(key) + if obj is None: obj = list() + if isinstance(obj, list): return obj + return [obj] |