diff options
author | Tim O'Shea <tim.oshea753@gmail.com> | 2013-07-08 10:29:19 -0400 |
---|---|---|
committer | Johnathan Corgan <johnathan@corganlabs.com> | 2013-07-09 16:29:52 -0700 |
commit | 74eb0b9a9a685a32be21db30f097a22ddf3ec4cf (patch) | |
tree | 9d1143de24fb637f56472002acd5ab66cf688045 /grc/python | |
parent | 1e9d546b9606f9735032513d593a29b6344856c5 (diff) |
grc: Fix whitespace issue in grc to use proper spaces
Remove all \t's to match the rest of GNU Radio
Diffstat (limited to 'grc/python')
-rw-r--r-- | grc/python/Block.py | 376 | ||||
-rw-r--r-- | grc/python/Connection.py | 47 | ||||
-rw-r--r-- | grc/python/Constants.py | 60 | ||||
-rw-r--r-- | grc/python/FlowGraph.py | 419 | ||||
-rw-r--r-- | grc/python/Generator.py | 236 | ||||
-rw-r--r-- | grc/python/Param.py | 810 | ||||
-rw-r--r-- | grc/python/Platform.py | 66 | ||||
-rw-r--r-- | grc/python/Port.py | 388 | ||||
-rw-r--r-- | grc/python/block.dtd | 16 | ||||
-rw-r--r-- | grc/python/convert_hier.py | 172 | ||||
-rw-r--r-- | grc/python/default_flow_graph.grc | 70 | ||||
-rw-r--r-- | grc/python/expr_utils.py | 264 | ||||
-rw-r--r-- | grc/python/extract_docs.py | 94 | ||||
-rw-r--r-- | grc/python/flow_graph.tmpl | 380 |
14 files changed, 1668 insertions, 1730 deletions
diff --git a/grc/python/Block.py b/grc/python/Block.py index d365c43319..e13b26c12f 100644 --- a/grc/python/Block.py +++ b/grc/python/Block.py @@ -23,195 +23,187 @@ import extract_docs class Block(_Block, _GUIBlock): - def is_virtual_sink(self): return self.get_key() == 'virtual_sink' - def is_virtual_source(self): return self.get_key() == 'virtual_source' - - ##for make source to keep track of indexes - _source_count = 0 - ##for make sink to keep track of indexes - _sink_count = 0 - - - - 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 - """ - #grab the data - self._doc = n.find('doc') or '' - self._imports = map(lambda i: i.strip(), n.findall('import')) - self._make = n.find('make') - self._var_make = n.find('var_make') - self._checks = n.findall('check') - self._callbacks = n.findall('callback') - self._throttle = n.find('throttle') or '' - self._bus_structure_source = n.find('bus_structure_source') or '' - self._bus_structure_sink = n.find('bus_structure_sink') or '' - #build the block - _Block.__init__( - self, - flow_graph=flow_graph, - n=n, - ) - _GUIBlock.__init__(self) - - def get_bus_structure(self, direction): - if direction == 'source': - bus_structure = self._bus_structure_source; - else: - bus_structure = self._bus_structure_sink; - - bus_structure = self.resolve_dependencies(bus_structure); - - if not bus_structure: return '' - try: - clean_bus_structure = self.get_parent().evaluate(bus_structure) - return clean_bus_structure - - except: return '' - - def throttle(self): return bool(self._throttle) - - def validate(self): - """ - Validate this block. - Call the base class validate. - Evaluate the checks: each check must evaluate to True. - """ - _Block.validate(self) - #evaluate the checks - for check in self._checks: - check_res = self.resolve_dependencies(check) - try: - if not self.get_parent().evaluate(check_res): - self.add_error_message('Check "%s" failed.'%check) - except: self.add_error_message('Check "%s" did not evaluate.'%check) - - def rewrite(self): - """ - Add and remove ports to adjust for the nports. - """ - _Block.rewrite(self) - - def rectify(ports): - #restore integer contiguity after insertion - #rectify the port names with the index - self.back_ofthe_bus(ports); - for i, port in enumerate(ports): - port._key = str(i) - port._name = port._n['name'] - if len(ports) > 1 and not port._type == 'bus': port._name += str(i) - - def insert_port(get_ports, get_port, key): - prev_port = get_port(str(int(key)-1)) - get_ports().insert( - get_ports().index(prev_port)+1, - prev_port.copy(new_key=key), - ) - rectify(get_ports()) - - def remove_port(get_ports, get_port, key): - port = get_port(key) - for connection in port.get_connections(): - self.get_parent().remove_element(connection) - get_ports().remove(port) - rectify(get_ports()) - - #adjust nports - for get_ports, get_port in ( - (self.get_sources, self.get_source), - (self.get_sinks, self.get_sink), - ): - master_ports = filter(lambda p: p.get_nports(), get_ports()) - for i, master_port in enumerate(master_ports): - nports = master_port.get_nports() - index_first = get_ports().index(master_port) - try: index_last = get_ports().index(master_ports[i+1]) - except IndexError: index_last = len(get_ports()) - num_ports = index_last - index_first - #do nothing if nports is already num ports - if nports == num_ports: continue - #remove excess ports and connections - if nports < num_ports: - for key in reversed(map(str, range(index_first+nports, index_first+num_ports))): - remove_port(get_ports, get_port, key); - - - continue - #add more ports - if nports > num_ports: - for key in map(str, range(index_first+num_ports, index_first+nports)): - insert_port(get_ports, get_port, key) - - - continue - - - def port_controller_modify(self, direction): - """ - Change the port controller. - - Args: - direction: +1 or -1 - - Returns: - true for change - """ - changed = False - #concat the nports string from the private nports settings of all ports - nports_str = ' '.join([port._nports for port in self.get_ports()]) - #modify all params whose keys appear in the nports string - for param in self.get_params(): - if param.is_enum() or param.get_key() not in nports_str: continue - #try to increment the port controller by direction - try: - value = param.get_evaluated() - value = value + direction - if 0 < value: - param.set_value(value) - changed = True - except: pass - return changed - - def get_doc(self): - doc = self._doc.strip('\n').replace('\\\n', '') - #merge custom doc with doxygen docs - return '\n'.join([doc, extract_docs.extract(self.get_key())]).strip('\n') - - def get_category(self): - return _Block.get_category(self) - - def get_imports(self): - """ - Resolve all import statements. - Split each import statement at newlines. - Combine all import statments into a list. - Filter empty imports. - - Returns: - a list of import statements - """ - return filter(lambda i: i, sum(map(lambda i: self.resolve_dependencies(i).split('\n'), self._imports), [])) - - def get_make(self): return self.resolve_dependencies(self._make) - def get_var_make(self): return self.resolve_dependencies(self._var_make) - - def get_callbacks(self): - """ - Get a list of function callbacks for this block. - - Returns: - a list of strings - """ - def make_callback(callback): - callback = self.resolve_dependencies(callback) - if 'self.' in callback: return callback - return 'self.%s.%s'%(self.get_id(), callback) - return map(make_callback, self._callbacks) + def is_virtual_sink(self): return self.get_key() == 'virtual_sink' + def is_virtual_source(self): return self.get_key() == 'virtual_source' + + ##for make source to keep track of indexes + _source_count = 0 + ##for make sink to keep track of indexes + _sink_count = 0 + + 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 + """ + #grab the data + self._doc = n.find('doc') or '' + self._imports = map(lambda i: i.strip(), n.findall('import')) + self._make = n.find('make') + self._var_make = n.find('var_make') + self._checks = n.findall('check') + self._callbacks = n.findall('callback') + self._throttle = n.find('throttle') or '' + self._bus_structure_source = n.find('bus_structure_source') or '' + self._bus_structure_sink = n.find('bus_structure_sink') or '' + #build the block + _Block.__init__( + self, + flow_graph=flow_graph, + n=n, + ) + _GUIBlock.__init__(self) + + def get_bus_structure(self, direction): + if direction == 'source': + bus_structure = self._bus_structure_source; + else: + bus_structure = self._bus_structure_sink; + + bus_structure = self.resolve_dependencies(bus_structure); + + if not bus_structure: return '' + try: + clean_bus_structure = self.get_parent().evaluate(bus_structure) + return clean_bus_structure + + except: return '' + def throttle(self): return bool(self._throttle) + + def validate(self): + """ + Validate this block. + Call the base class validate. + Evaluate the checks: each check must evaluate to True. + """ + _Block.validate(self) + #evaluate the checks + for check in self._checks: + check_res = self.resolve_dependencies(check) + try: + if not self.get_parent().evaluate(check_res): + self.add_error_message('Check "%s" failed.'%check) + except: self.add_error_message('Check "%s" did not evaluate.'%check) + + def rewrite(self): + """ + Add and remove ports to adjust for the nports. + """ + _Block.rewrite(self) + + def rectify(ports): + #restore integer contiguity after insertion + #rectify the port names with the index + self.back_ofthe_bus(ports); + for i, port in enumerate(ports): + port._key = str(i) + port._name = port._n['name'] + if len(ports) > 1 and not port._type == 'bus': port._name += str(i) + + def insert_port(get_ports, get_port, key): + prev_port = get_port(str(int(key)-1)) + get_ports().insert( + get_ports().index(prev_port)+1, + prev_port.copy(new_key=key), + ) + rectify(get_ports()) + + def remove_port(get_ports, get_port, key): + port = get_port(key) + for connection in port.get_connections(): + self.get_parent().remove_element(connection) + get_ports().remove(port) + rectify(get_ports()) + + #adjust nports + for get_ports, get_port in ( + (self.get_sources, self.get_source), + (self.get_sinks, self.get_sink), + ): + master_ports = filter(lambda p: p.get_nports(), get_ports()) + for i, master_port in enumerate(master_ports): + nports = master_port.get_nports() + index_first = get_ports().index(master_port) + try: index_last = get_ports().index(master_ports[i+1]) + except IndexError: index_last = len(get_ports()) + num_ports = index_last - index_first + #do nothing if nports is already num ports + if nports == num_ports: continue + #remove excess ports and connections + if nports < num_ports: + for key in reversed(map(str, range(index_first+nports, index_first+num_ports))): + remove_port(get_ports, get_port, key); + continue + #add more ports + if nports > num_ports: + for key in map(str, range(index_first+num_ports, index_first+nports)): + insert_port(get_ports, get_port, key) + continue + + def port_controller_modify(self, direction): + """ + Change the port controller. + + Args: + direction: +1 or -1 + + Returns: + true for change + """ + changed = False + #concat the nports string from the private nports settings of all ports + nports_str = ' '.join([port._nports for port in self.get_ports()]) + #modify all params whose keys appear in the nports string + for param in self.get_params(): + if param.is_enum() or param.get_key() not in nports_str: continue + #try to increment the port controller by direction + try: + value = param.get_evaluated() + value = value + direction + if 0 < value: + param.set_value(value) + changed = True + except: pass + return changed + + def get_doc(self): + doc = self._doc.strip('\n').replace('\\\n', '') + #merge custom doc with doxygen docs + return '\n'.join([doc, extract_docs.extract(self.get_key())]).strip('\n') + + def get_category(self): + return _Block.get_category(self) + + def get_imports(self): + """ + Resolve all import statements. + Split each import statement at newlines. + Combine all import statments into a list. + Filter empty imports. + + Returns: + a list of import statements + """ + return filter(lambda i: i, sum(map(lambda i: self.resolve_dependencies(i).split('\n'), self._imports), [])) + + def get_make(self): return self.resolve_dependencies(self._make) + def get_var_make(self): return self.resolve_dependencies(self._var_make) + + def get_callbacks(self): + """ + Get a list of function callbacks for this block. + + Returns: + a list of strings + """ + def make_callback(callback): + callback = self.resolve_dependencies(callback) + if 'self.' in callback: return callback + return 'self.%s.%s'%(self.get_id(), callback) + return map(make_callback, self._callbacks) diff --git a/grc/python/Connection.py b/grc/python/Connection.py index 97bf61d590..7f235b190b 100644 --- a/grc/python/Connection.py +++ b/grc/python/Connection.py @@ -24,27 +24,26 @@ from .. gui.Connection import Connection as _GUIConnection class Connection(_Connection, _GUIConnection): - def __init__(self, **kwargs): - _Connection.__init__(self, **kwargs) - _GUIConnection.__init__(self) - - def is_msg(self): - return self.get_source().get_type() == self.get_sink().get_type() == 'msg' - - def is_message(self): - return self.get_source().get_type() == self.get_sink().get_type() == 'message' - - def is_bus(self): - return self.get_source().get_type() == self.get_sink().get_type() == 'bus' - def validate(self): - """ - Validate the connections. - The ports must match in io size. - """ - Element.validate(self) - source_size = Constants.TYPE_TO_SIZEOF[self.get_source().get_type()] * self.get_source().get_vlen() - sink_size = Constants.TYPE_TO_SIZEOF[self.get_sink().get_type()] * self.get_sink().get_vlen() - if source_size != sink_size: - self.add_error_message('Source IO size "%s" does not match sink IO size "%s".'%(source_size, sink_size)) - - + def __init__(self, **kwargs): + _Connection.__init__(self, **kwargs) + _GUIConnection.__init__(self) + + def is_msg(self): + return self.get_source().get_type() == self.get_sink().get_type() == 'msg' + + def is_message(self): + return self.get_source().get_type() == self.get_sink().get_type() == 'message' + + def is_bus(self): + return self.get_source().get_type() == self.get_sink().get_type() == 'bus' + + def validate(self): + """ + Validate the connections. + The ports must match in io size. + """ + Element.validate(self) + source_size = Constants.TYPE_TO_SIZEOF[self.get_source().get_type()] * self.get_source().get_vlen() + sink_size = Constants.TYPE_TO_SIZEOF[self.get_sink().get_type()] * self.get_sink().get_vlen() + if source_size != sink_size: + self.add_error_message('Source IO size "%s" does not match sink IO size "%s".'%(source_size, sink_size)) diff --git a/grc/python/Constants.py b/grc/python/Constants.py index 5666a2378b..15cc203b43 100644 --- a/grc/python/Constants.py +++ b/grc/python/Constants.py @@ -27,11 +27,11 @@ _gr_prefs = gr.prefs() PATH_SEP = {'/':':', '\\':';'}[os.path.sep] HIER_BLOCKS_LIB_DIR = os.path.join(os.path.expanduser('~'), '.grc_gnuradio') BLOCKS_DIRS = filter( #filter blank strings - lambda x: x, PATH_SEP.join([ - os.environ.get('GRC_BLOCKS_PATH', ''), - _gr_prefs.get_string('grc', 'local_blocks_path', ''), - _gr_prefs.get_string('grc', 'global_blocks_path', ''), - ]).split(PATH_SEP), + lambda x: x, PATH_SEP.join([ + os.environ.get('GRC_BLOCKS_PATH', ''), + _gr_prefs.get_string('grc', 'local_blocks_path', ''), + _gr_prefs.get_string('grc', 'global_blocks_path', ''), + ]).split(PATH_SEP), ) + [HIER_BLOCKS_LIB_DIR] #file creation modes @@ -45,40 +45,40 @@ BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd') DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc') CORE_TYPES = ( #name, key, sizeof, color - ('Complex Float 64', 'fc64', 16, '#CC8C69'), - ('Complex Float 32', 'fc32', 8, '#3399FF'), - ('Complex Integer 64', 'sc64', 16, '#66CC00'), - ('Complex Integer 32', 'sc32', 8, '#33cc66'), - ('Complex Integer 16', 'sc16', 4, '#cccc00'), - ('Complex Integer 8', 'sc8', 2, '#cc00cc'), - ('Float 64', 'f64', 8, '#66CCCC'), - ('Float 32', 'f32', 4, '#FF8C69'), - ('Integer 64', 's64', 8, '#99FF33'), - ('Integer 32', 's32', 4, '#00FF99'), - ('Integer 16', 's16', 2, '#FFFF66'), - ('Integer 8', 's8', 1, '#FF66FF'), - ('Message Queue', 'msg', 0, '#777777'), - ('Async Message', 'message', 0, '#C0C0C0'), - ('Bus Connection', 'bus', 0, '#FFFFFF'), - ('Wildcard', '', 0, '#FFFFFF'), + ('Complex Float 64', 'fc64', 16, '#CC8C69'), + ('Complex Float 32', 'fc32', 8, '#3399FF'), + ('Complex Integer 64', 'sc64', 16, '#66CC00'), + ('Complex Integer 32', 'sc32', 8, '#33cc66'), + ('Complex Integer 16', 'sc16', 4, '#cccc00'), + ('Complex Integer 8', 'sc8', 2, '#cc00cc'), + ('Float 64', 'f64', 8, '#66CCCC'), + ('Float 32', 'f32', 4, '#FF8C69'), + ('Integer 64', 's64', 8, '#99FF33'), + ('Integer 32', 's32', 4, '#00FF99'), + ('Integer 16', 's16', 2, '#FFFF66'), + ('Integer 8', 's8', 1, '#FF66FF'), + ('Message Queue', 'msg', 0, '#777777'), + ('Async Message', 'message', 0, '#C0C0C0'), + ('Bus Connection', 'bus', 0, '#FFFFFF'), + ('Wildcard', '', 0, '#FFFFFF'), ) ALIAS_TYPES = { - 'complex' : (8, '#3399FF'), - 'float' : (4, '#FF8C69'), - 'int' : (4, '#00FF99'), - 'short' : (2, '#FFFF66'), - 'byte' : (1, '#FF66FF'), + 'complex' : (8, '#3399FF'), + 'float' : (4, '#FF8C69'), + 'int' : (4, '#00FF99'), + 'short' : (2, '#FFFF66'), + 'byte' : (1, '#FF66FF'), } TYPE_TO_COLOR = dict() TYPE_TO_SIZEOF = dict() for name, key, sizeof, color in CORE_TYPES: - TYPE_TO_COLOR[key] = color - TYPE_TO_SIZEOF[key] = sizeof + TYPE_TO_COLOR[key] = color + TYPE_TO_SIZEOF[key] = sizeof for key, (sizeof, color) in ALIAS_TYPES.iteritems(): - TYPE_TO_COLOR[key] = color - TYPE_TO_SIZEOF[key] = sizeof + TYPE_TO_COLOR[key] = color + TYPE_TO_SIZEOF[key] = sizeof #coloring COMPLEX_COLOR_SPEC = '#3399FF' diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py index 89acfd89ef..22ed4f76d6 100644 --- a/grc/python/FlowGraph.py +++ b/grc/python/FlowGraph.py @@ -31,239 +31,192 @@ _bussrc_searcher = re.compile('^(bus_source)$') _bus_struct_sink_searcher = re.compile('^(bus_structure_sink)$') _bus_struct_src_searcher = re.compile('^(bus_structure_source)$') - class FlowGraph(_FlowGraph, _GUIFlowGraph): - def __init__(self, **kwargs): - _FlowGraph.__init__(self, **kwargs) - _GUIFlowGraph.__init__(self) - self._eval_cache = dict() - - def _eval(self, code, namespace, namespace_hash): - """ - Evaluate the code with the given namespace. - - Args: - code: a string with python code - namespace: a dict representing the namespace - namespace_hash: a unique hash for the namespace - - Returns: - the resultant object - """ - if not code: raise Exception, 'Cannot evaluate empty statement.' - my_hash = hash(code) ^ namespace_hash - #cache if does not exist - - if not self._eval_cache.has_key(my_hash): - self._eval_cache[my_hash] = eval(code, namespace, namespace) - #return from cache - return self._eval_cache[my_hash] - - def get_io_signaturev(self, direction): - """ - Get a list of io signatures for this flow graph. - - Args: - direction: a string of 'in' or 'out' - - Returns: - a list of dicts with: type, label, vlen, size - """ - sorted_pads = { - 'in': self.get_pad_sources(), - 'out': self.get_pad_sinks(), - }[direction] + def __init__(self, **kwargs): + _FlowGraph.__init__(self, **kwargs) + _GUIFlowGraph.__init__(self) + self._eval_cache = dict() + + def _eval(self, code, namespace, namespace_hash): + """ + Evaluate the code with the given namespace. + + Args: + code: a string with python code + namespace: a dict representing the namespace + namespace_hash: a unique hash for the namespace + + Returns: + the resultant object + """ + if not code: raise Exception, 'Cannot evaluate empty statement.' + my_hash = hash(code) ^ namespace_hash + #cache if does not exist + if not self._eval_cache.has_key(my_hash): + self._eval_cache[my_hash] = eval(code, namespace, namespace) + #return from cache + return self._eval_cache[my_hash] + + def get_io_signaturev(self, direction): + """ + Get a list of io signatures for this flow graph. + + Args: + direction: a string of 'in' or 'out' + + Returns: + a list of dicts with: type, label, vlen, size + """ + sorted_pads = { + 'in': self.get_pad_sources(), + 'out': self.get_pad_sinks(), + }[direction] # we only want stream ports - sorted_pads = filter(lambda b: b.get_param('type').get_evaluated() != 'message', sorted_pads); - expanded_pads = []; - for i in sorted_pads: - for j in range(i.get_param('num_streams').get_evaluated()): - expanded_pads.append(i); - #load io signature - return [{ - 'label': str(pad.get_param('label').get_evaluated()), - 'type': str(pad.get_param('type').get_evaluated()), - 'vlen': str(pad.get_param('vlen').get_evaluated()), - 'size': pad.get_param('type').get_opt('size'), - 'optional': bool(pad.get_param('optional').get_evaluated()), - } for pad in expanded_pads] - - def get_pad_sources(self): - """ - Get a list of pad source blocks sorted by id order. - - Returns: - a list of pad source blocks in this flow graph - """ - pads = filter(lambda b: b.get_key() == 'pad_source', self.get_enabled_blocks()) - return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id())) - - def get_pad_sinks(self): - """ - Get a list of pad sink blocks sorted by id order. - - Returns: - a list of pad sink blocks in this flow graph - """ - pads = filter(lambda b: b.get_key() == 'pad_sink', self.get_enabled_blocks()) - return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id())) - - def get_msg_pad_sources(self): - ps = self.get_pad_sources(); - return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); - - def get_msg_pad_sinks(self): - ps = self.get_pad_sinks(); - return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); - - def get_imports(self): - """ - Get a set of all import statments in this flow graph namespace. - - Returns: - a set of import statements - """ - imports = sum([block.get_imports() for block in self.get_enabled_blocks()], []) - imports = sorted(set(imports)) - return imports - - def get_variables(self): - """ - Get a list of all variables in this flow graph namespace. - Exclude paramterized variables. - - Returns: - a sorted list of variable blocks in order of dependency (indep -> dep) - """ - variables = filter(lambda b: _variable_matcher.match(b.get_key()), self.get_enabled_blocks()) - return expr_utils.sort_objects(variables, lambda v: v.get_id(), lambda v: v.get_var_make()) - - def get_parameters(self): - """ - Get a list of all paramterized variables in this flow graph namespace. - - Returns: - a list of paramterized variables - """ - parameters = filter(lambda b: _parameter_matcher.match(b.get_key()), self.get_enabled_blocks()) - return parameters - - def get_monitors(self): - """ - Get a list of all ControlPort monitors - """ - monitors = filter(lambda b: _monitors_searcher.search(b.get_key()), self.get_enabled_blocks()) - return monitors - - def get_bussink(self): - bussink = filter(lambda b: _bussink_searcher.search(b.get_key()), self.get_enabled_blocks()) - - for i in bussink: - for j in i.get_params(): - if j.get_name() == 'On/Off' and j.get_value() == 'on': - return True; - - return False - - - - def get_bussrc(self): - bussrc = filter(lambda b: _bussrc_searcher.search(b.get_key()), self.get_enabled_blocks()) - - for i in bussrc: - for j in i.get_params(): - if j.get_name() == 'On/Off' and j.get_value() == 'on': - return True; - - return False - - def get_bus_structure_sink(self): - bussink = filter(lambda b: _bus_struct_sink_searcher.search(b.get_key()), self.get_enabled_blocks()) - - return bussink - - def get_bus_structure_src(self): - bussrc = filter(lambda b: _bus_struct_src_searcher.search(b.get_key()), self.get_enabled_blocks()) - - return bussrc - - - def rewrite(self): - """ - Flag the namespace to be renewed. - """ - - - - - def reconnect_bus_blocks(): - for block in self.get_blocks(): - - if 'bus' in map(lambda a: a.get_type(), block.get_sources_gui()): - - - for i in range(len(block.get_sources_gui())): - if len(block.get_sources_gui()[i].get_connections()) > 0: - source = block.get_sources_gui()[i] - sink = [] - - for j in range(len(source.get_connections())): - sink.append(source.get_connections()[j].get_sink()); - - - for elt in source.get_connections(): - self.remove_element(elt); - for j in sink: - self.connect(source, j); - self._renew_eval_ns = True - _FlowGraph.rewrite(self); - reconnect_bus_blocks(); - - - - - - def evaluate(self, expr): - """ - Evaluate the expression. - - Args: - expr: the string expression - @throw Exception bad expression - - Returns: - the evaluated data - """ - - - if self._renew_eval_ns: - self._renew_eval_ns = False - #reload namespace - n = dict() - #load imports - for imp in self.get_imports(): - try: exec imp in n - except: pass - #load parameters - np = dict() - for parameter in self.get_parameters(): - try: - e = eval(parameter.get_param('value').to_code(), n, n) - np[parameter.get_id()] = e - except: pass - n.update(np) #merge param namespace - #load variables - for variable in self.get_variables(): - try: - e = eval(variable.get_param('value').to_code(), n, n) - n[variable.get_id()] = e - except: pass - #make namespace public - self.n = n - self.n_hash = hash(str(n)) - - #evaluate - e = self._eval(expr, self.n, self.n_hash) - - return e + sorted_pads = filter(lambda b: b.get_param('type').get_evaluated() != 'message', sorted_pads); + expanded_pads = []; + for i in sorted_pads: + for j in range(i.get_param('num_streams').get_evaluated()): + expanded_pads.append(i); + #load io signature + return [{ + 'label': str(pad.get_param('label').get_evaluated()), + 'type': str(pad.get_param('type').get_evaluated()), + 'vlen': str(pad.get_param('vlen').get_evaluated()), + 'size': pad.get_param('type').get_opt('size'), + 'optional': bool(pad.get_param('optional').get_evaluated()), + } for pad in expanded_pads] + + def get_pad_sources(self): + """ + Get a list of pad source blocks sorted by id order. + + Returns: + a list of pad source blocks in this flow graph + """ + pads = filter(lambda b: b.get_key() == 'pad_source', self.get_enabled_blocks()) + return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id())) + + def get_pad_sinks(self): + """ + Get a list of pad sink blocks sorted by id order. + + Returns: + a list of pad sink blocks in this flow graph + """ + pads = filter(lambda b: b.get_key() == 'pad_sink', self.get_enabled_blocks()) + return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id())) + + def get_msg_pad_sources(self): + ps = self.get_pad_sources(); + return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); + + def get_msg_pad_sinks(self): + ps = self.get_pad_sinks(); + return filter(lambda b: b.get_param('type').get_evaluated() == 'message', ps); + + def get_imports(self): + """ + Get a set of all import statments in this flow graph namespace. + + Returns: + a set of import statements + """ + imports = sum([block.get_imports() for block in self.get_enabled_blocks()], []) + imports = sorted(set(imports)) + return imports + + def get_variables(self): + """ + Get a list of all variables in this flow graph namespace. + Exclude paramterized variables. + + Returns: + a sorted list of variable blocks in order of dependency (indep -> dep) + """ + variables = filter(lambda b: _variable_matcher.match(b.get_key()), self.get_enabled_blocks()) + return expr_utils.sort_objects(variables, lambda v: v.get_id(), lambda v: v.get_var_make()) + + def get_parameters(self): + """ + Get a list of all paramterized variables in this flow graph namespace. + + Returns: + a list of paramterized variables + """ + parameters = filter(lambda b: _parameter_matcher.match(b.get_key()), self.get_enabled_blocks()) + return parameters + + def get_monitors(self): + """ + Get a list of all ControlPort monitors + """ + monitors = filter(lambda b: _monitors_searcher.search(b.get_key()), self.get_enabled_blocks()) + return monitors + + def rewrite(self): + """ + Flag the namespace to be renewed. + """ + def reconnect_bus_blocks(): + for block in self.get_blocks(): + + if 'bus' in map(lambda a: a.get_type(), block.get_sources_gui()): + + + for i in range(len(block.get_sources_gui())): + if len(block.get_sources_gui()[i].get_connections()) > 0: + source = block.get_sources_gui()[i] + sink = [] + + for j in range(len(source.get_connections())): + sink.append(source.get_connections()[j].get_sink()); + + + for elt in source.get_connections(): + self.remove_element(elt); + for j in sink: + self.connect(source, j); + self._renew_eval_ns = True + _FlowGraph.rewrite(self); + reconnect_bus_blocks(); + + def evaluate(self, expr): + """ + Evaluate the expression. + + Args: + expr: the string expression + @throw Exception bad expression + + Returns: + the evaluated data + """ + if self._renew_eval_ns: + self._renew_eval_ns = False + #reload namespace + n = dict() + #load imports + for imp in self.get_imports(): + try: exec imp in n + except: pass + #load parameters + np = dict() + for parameter in self.get_parameters(): + try: + e = eval(parameter.get_param('value').to_code(), n, n) + np[parameter.get_id()] = e + except: pass + n.update(np) #merge param namespace + #load variables + for variable in self.get_variables(): + try: + e = eval(variable.get_param('value').to_code(), n, n) + n[variable.get_id()] = e + except: pass + #make namespace public + self.n = n + self.n_hash = hash(str(n)) + #evaluate + e = self._eval(expr, self.n, self.n_hash) + return e diff --git a/grc/python/Generator.py b/grc/python/Generator.py index 47fe1d98fd..005ed4c2b3 100644 --- a/grc/python/Generator.py +++ b/grc/python/Generator.py @@ -24,137 +24,137 @@ import tempfile from Cheetah.Template import Template import expr_utils from Constants import \ - TOP_BLOCK_FILE_MODE, HIER_BLOCK_FILE_MODE, \ - HIER_BLOCKS_LIB_DIR, FLOW_GRAPH_TEMPLATE + TOP_BLOCK_FILE_MODE, HIER_BLOCK_FILE_MODE, \ + HIER_BLOCKS_LIB_DIR, FLOW_GRAPH_TEMPLATE import convert_hier from .. gui import Messages class Generator(object): - def __init__(self, flow_graph, file_path): - """ - Initialize the generator object. - Determine the file to generate. - - Args: - flow_graph: the flow graph object - file_path: the path to write the file to - """ - self._flow_graph = flow_graph - self._generate_options = self._flow_graph.get_option('generate_options') - if self._generate_options == 'hb': - self._mode = HIER_BLOCK_FILE_MODE - dirname = HIER_BLOCKS_LIB_DIR - else: - self._mode = TOP_BLOCK_FILE_MODE - dirname = os.path.dirname(file_path) - #handle the case where the directory is read-only - #in this case, use the system's temp directory - if not os.access(dirname, os.W_OK): - dirname = tempfile.gettempdir() - filename = self._flow_graph.get_option('id') + '.py' - self._file_path = os.path.join(dirname, filename) + def __init__(self, flow_graph, file_path): + """ + Initialize the generator object. + Determine the file to generate. + + Args: + flow_graph: the flow graph object + file_path: the path to write the file to + """ + self._flow_graph = flow_graph + self._generate_options = self._flow_graph.get_option('generate_options') + if self._generate_options == 'hb': + self._mode = HIER_BLOCK_FILE_MODE + dirname = HIER_BLOCKS_LIB_DIR + else: + self._mode = TOP_BLOCK_FILE_MODE + dirname = os.path.dirname(file_path) + #handle the case where the directory is read-only + #in this case, use the system's temp directory + if not os.access(dirname, os.W_OK): + dirname = tempfile.gettempdir() + filename = self._flow_graph.get_option('id') + '.py' + self._file_path = os.path.join(dirname, filename) - def get_file_path(self): return self._file_path + def get_file_path(self): return self._file_path - def write(self): - #do throttle warning - throttled = any(map(lambda b: b.throttle(), self._flow_graph.get_enabled_blocks())) - if not throttled and self._generate_options != 'hb': - Messages.send_warning('''\ + def write(self): + #do throttle warning + throttled = any(map(lambda b: b.throttle(), self._flow_graph.get_enabled_blocks())) + if not throttled and self._generate_options != 'hb': + Messages.send_warning('''\ This flow graph may not have flow control: no audio or usrp blocks found. \ Add a Misc->Throttle block to your flow graph to avoid CPU congestion.''') - #generate - open(self.get_file_path(), 'w').write(str(self)) - if self._generate_options == 'hb': - #convert hier block to xml wrapper - convert_hier.convert_hier(self._flow_graph, self.get_file_path()) - os.chmod(self.get_file_path(), self._mode) + #generate + open(self.get_file_path(), 'w').write(str(self)) + if self._generate_options == 'hb': + #convert hier block to xml wrapper + convert_hier.convert_hier(self._flow_graph, self.get_file_path()) + os.chmod(self.get_file_path(), self._mode) - def get_popen(self): - """ - Execute this python flow graph. - - Returns: - a popen object - """ - #extract the path to the python executable - python_exe = sys.executable + def get_popen(self): + """ + Execute this python flow graph. + + Returns: + a popen object + """ + #extract the path to the python executable + python_exe = sys.executable - #when using wx gui on mac os, execute with pythonw - #using pythonw is not necessary anymore, disabled below - #if self._generate_options == 'wx_gui' and 'darwin' in sys.platform.lower(): - # python_exe = 'pythonw' + #when using wx gui on mac os, execute with pythonw + #using pythonw is not necessary anymore, disabled below + #if self._generate_options == 'wx_gui' and 'darwin' in sys.platform.lower(): + # python_exe = 'pythonw' - #setup the command args to run - cmds = [python_exe, '-u', self.get_file_path()] #-u is unbuffered stdio + #setup the command args to run + cmds = [python_exe, '-u', self.get_file_path()] #-u is unbuffered stdio - #when in no gui mode on linux, use an xterm (looks nice) - if self._generate_options == 'no_gui' and 'linux' in sys.platform.lower(): - cmds = ['xterm', '-e'] + cmds + #when in no gui mode on linux, use an xterm (looks nice) + if self._generate_options == 'no_gui' and 'linux' in sys.platform.lower(): + cmds = ['xterm', '-e'] + cmds - p = subprocess.Popen(args=cmds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False, universal_newlines=True) - return p + p = subprocess.Popen(args=cmds, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False, universal_newlines=True) + return p - def __str__(self): - """ - Convert the flow graph to python code. - - Returns: - a string of python code - """ - title = self._flow_graph.get_option('title') or self._flow_graph.get_option('id').replace('_', ' ').title() - imports = self._flow_graph.get_imports() - variables = self._flow_graph.get_variables() - parameters = self._flow_graph.get_parameters() - monitors = self._flow_graph.get_monitors() - #list of blocks not including variables and imports and parameters and disabled - def _get_block_sort_text(block): - code = block.get_make().replace(block.get_id(), ' ') - try: code += block.get_param('notebook').get_value() #older gui markup w/ wxgui - except: pass - try: code += block.get_param('gui_hint').get_value() #newer gui markup w/ qtgui - except: pass - return code - blocks = expr_utils.sort_objects( - self._flow_graph.get_enabled_blocks(), - lambda b: b.get_id(), _get_block_sort_text - ) - #list of regular blocks (all blocks minus the special ones) - blocks = filter(lambda b: b not in (imports + parameters), blocks) - #list of connections where each endpoint is enabled - connections = filter(lambda c: not (c.is_bus() or c.is_msg() or c.is_message()), self._flow_graph.get_enabled_connections()) - messages = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections()) - messages2 = filter(lambda c: c.is_message(), self._flow_graph.get_enabled_connections()) - #list of variable names - var_ids = [var.get_id() for var in parameters + variables] - #prepend self. - replace_dict = dict([(var_id, 'self.%s'%var_id) for var_id in var_ids]) - #list of callbacks - callbacks = [ - expr_utils.expr_replace(cb, replace_dict) - for cb in sum([block.get_callbacks() for block in self._flow_graph.get_enabled_blocks()], []) - ] - #map var id to callbacks - var_id2cbs = dict( - [(var_id, filter(lambda c: expr_utils.get_variable_dependencies(c, [var_id]), callbacks)) - for var_id in var_ids] - ) - #load the namespace - namespace = { - 'title': title, - 'imports': imports, - 'flow_graph': self._flow_graph, - 'variables': variables, - 'parameters': parameters, + def __str__(self): + """ + Convert the flow graph to python code. + + Returns: + a string of python code + """ + title = self._flow_graph.get_option('title') or self._flow_graph.get_option('id').replace('_', ' ').title() + imports = self._flow_graph.get_imports() + variables = self._flow_graph.get_variables() + parameters = self._flow_graph.get_parameters() + monitors = self._flow_graph.get_monitors() + #list of blocks not including variables and imports and parameters and disabled + def _get_block_sort_text(block): + code = block.get_make().replace(block.get_id(), ' ') + try: code += block.get_param('notebook').get_value() #older gui markup w/ wxgui + except: pass + try: code += block.get_param('gui_hint').get_value() #newer gui markup w/ qtgui + except: pass + return code + blocks = expr_utils.sort_objects( + self._flow_graph.get_enabled_blocks(), + lambda b: b.get_id(), _get_block_sort_text + ) + #list of regular blocks (all blocks minus the special ones) + blocks = filter(lambda b: b not in (imports + parameters), blocks) + #list of connections where each endpoint is enabled + connections = filter(lambda c: not (c.is_bus() or c.is_msg() or c.is_message()), self._flow_graph.get_enabled_connections()) + messages = filter(lambda c: c.is_msg(), self._flow_graph.get_enabled_connections()) + messages2 = filter(lambda c: c.is_message(), self._flow_graph.get_enabled_connections()) + #list of variable names + var_ids = [var.get_id() for var in parameters + variables] + #prepend self. + replace_dict = dict([(var_id, 'self.%s'%var_id) for var_id in var_ids]) + #list of callbacks + callbacks = [ + expr_utils.expr_replace(cb, replace_dict) + for cb in sum([block.get_callbacks() for block in self._flow_graph.get_enabled_blocks()], []) + ] + #map var id to callbacks + var_id2cbs = dict( + [(var_id, filter(lambda c: expr_utils.get_variable_dependencies(c, [var_id]), callbacks)) + for var_id in var_ids] + ) + #load the namespace + namespace = { + 'title': title, + 'imports': imports, + 'flow_graph': self._flow_graph, + 'variables': variables, + 'parameters': parameters, 'monitors': monitors, - 'blocks': blocks, - 'connections': connections, - 'messages': messages, - 'messages2': messages2, - 'generate_options': self._generate_options, - 'var_id2cbs': var_id2cbs, - } - #build the template - t = Template(open(FLOW_GRAPH_TEMPLATE, 'r').read(), namespace) - return str(t) + 'blocks': blocks, + 'connections': connections, + 'messages': messages, + 'messages2': messages2, + 'generate_options': self._generate_options, + 'var_id2cbs': var_id2cbs, + } + #build the template + t = Template(open(FLOW_GRAPH_TEMPLATE, 'r').read(), namespace) + return str(t) diff --git a/grc/python/Param.py b/grc/python/Param.py index 696f16cc94..e603d6cdbe 100644 --- a/grc/python/Param.py +++ b/grc/python/Param.py @@ -34,51 +34,51 @@ _check_id_matcher = re.compile('^[a-z|A-Z]\w*$') _show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook)$') class FileParam(EntryParam): - """Provide an entry box for filename and a button to browse for a file.""" + """Provide an entry box for filename and a button to browse for a file.""" - def __init__(self, *args, **kwargs): - EntryParam.__init__(self, *args, **kwargs) - input = gtk.Button('...') - input.connect('clicked', self._handle_clicked) - self.pack_start(input, False) + def __init__(self, *args, **kwargs): + EntryParam.__init__(self, *args, **kwargs) + input = gtk.Button('...') + input.connect('clicked', self._handle_clicked) + self.pack_start(input, False) - def _handle_clicked(self, widget=None): - """ - If the button was clicked, open a file dialog in open/save format. - Replace the text in the entry with the new filename from the file dialog. - """ - #get the paths - file_path = self.param.is_valid() and self.param.get_evaluated() or '' - (dirname, basename) = os.path.isfile(file_path) and os.path.split(file_path) or (file_path, '') - if not os.path.exists(dirname): dirname = os.getcwd() #fix bad paths - #build the dialog - if self.param.get_type() == 'file_open': - file_dialog = gtk.FileChooserDialog('Open a Data File...', None, - gtk.FILE_CHOOSER_ACTION_OPEN, ('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK)) - elif self.param.get_type() == 'file_save': - file_dialog = gtk.FileChooserDialog('Save a Data File...', None, - gtk.FILE_CHOOSER_ACTION_SAVE, ('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK)) - file_dialog.set_do_overwrite_confirmation(True) - file_dialog.set_current_name(basename) #show the current filename - file_dialog.set_current_folder(dirname) #current directory - file_dialog.set_select_multiple(False) - file_dialog.set_local_only(True) - if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog - file_path = file_dialog.get_filename() #get the file path - self._input.set_text(file_path) - self._handle_changed() - file_dialog.destroy() #destroy the dialog + def _handle_clicked(self, widget=None): + """ + If the button was clicked, open a file dialog in open/save format. + Replace the text in the entry with the new filename from the file dialog. + """ + #get the paths + file_path = self.param.is_valid() and self.param.get_evaluated() or '' + (dirname, basename) = os.path.isfile(file_path) and os.path.split(file_path) or (file_path, '') + if not os.path.exists(dirname): dirname = os.getcwd() #fix bad paths + #build the dialog + if self.param.get_type() == 'file_open': + file_dialog = gtk.FileChooserDialog('Open a Data File...', None, + gtk.FILE_CHOOSER_ACTION_OPEN, ('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK)) + elif self.param.get_type() == 'file_save': + file_dialog = gtk.FileChooserDialog('Save a Data File...', None, + gtk.FILE_CHOOSER_ACTION_SAVE, ('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK)) + file_dialog.set_do_overwrite_confirmation(True) + file_dialog.set_current_name(basename) #show the current filename + file_dialog.set_current_folder(dirname) #current directory + file_dialog.set_select_multiple(False) + file_dialog.set_local_only(True) + if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog + file_path = file_dialog.get_filename() #get the file path + self._input.set_text(file_path) + self._handle_changed() + file_dialog.destroy() #destroy the dialog #blacklist certain ids, its not complete, but should help import __builtin__ ID_BLACKLIST = ['self', 'options', 'gr', 'blks2', 'wxgui', 'wx', 'math', 'forms', 'firdes'] + \ - filter(lambda x: not x.startswith('_'), dir(gr.top_block())) + dir(__builtin__) + filter(lambda x: not x.startswith('_'), dir(gr.top_block())) + dir(__builtin__) #define types, native python + numpy VECTOR_TYPES = (tuple, list, set, numpy.ndarray) COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128] REAL_TYPES = [float, numpy.float, numpy.float32, numpy.float64] INT_TYPES = [int, long, numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.uint64, - numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64] + numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64] #cast to tuple for isinstance, concat subtypes COMPLEX_TYPES = tuple(COMPLEX_TYPES + REAL_TYPES + INT_TYPES) REAL_TYPES = tuple(REAL_TYPES + INT_TYPES) @@ -86,389 +86,389 @@ INT_TYPES = tuple(INT_TYPES) class Param(_Param, _GUIParam): - def __init__(self, **kwargs): - _Param.__init__(self, **kwargs) - _GUIParam.__init__(self) - self._init = False - self._hostage_cells = list() + def __init__(self, **kwargs): + _Param.__init__(self, **kwargs) + _GUIParam.__init__(self) + self._init = False + self._hostage_cells = list() - def get_types(self): return ( - 'raw', 'enum', - 'complex', 'real', 'float', 'int', - 'complex_vector', 'real_vector', 'float_vector', 'int_vector', - 'hex', 'string', 'bool', - 'file_open', 'file_save', - 'id', 'stream_id', - 'grid_pos', 'notebook', 'gui_hint', - 'import', - ) + def get_types(self): return ( + 'raw', 'enum', + 'complex', 'real', 'float', 'int', + 'complex_vector', 'real_vector', 'float_vector', 'int_vector', + 'hex', 'string', 'bool', + 'file_open', 'file_save', + 'id', 'stream_id', + 'grid_pos', 'notebook', 'gui_hint', + 'import', + ) - def __repr__(self): - """ - Get the repr (nice string format) for this param. - - Returns: - the string representation - """ - ################################################## - # truncate helper method - ################################################## - def _truncate(string, style=0): - max_len = max(27 - len(self.get_name()), 3) - if len(string) > max_len: - if style < 0: #front truncate - string = '...' + string[3-max_len:] - elif style == 0: #center truncate - string = string[:max_len/2 -3] + '...' + string[-max_len/2:] - elif style > 0: #rear truncate - string = string[:max_len-3] + '...' - return string - ################################################## - # simple conditions - ################################################## - if not self.is_valid(): return _truncate(self.get_value()) - if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name() - ################################################## - # display logic for numbers - ################################################## - def num_to_str(num): - if isinstance(num, COMPLEX_TYPES): - num = complex(num) #cast to python complex - if num == 0: return '0' #value is zero - elif num.imag == 0: return '%s'%eng_notation.num_to_str(num.real) #value is real - elif num.real == 0: return '%sj'%eng_notation.num_to_str(num.imag) #value is imaginary - elif num.imag < 0: return '%s-%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(abs(num.imag))) - else: return '%s+%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(num.imag)) - else: return str(num) - ################################################## - # split up formatting by type - ################################################## - truncate = 0 #default center truncate - e = self.get_evaluated() - t = self.get_type() - if isinstance(e, bool): return str(e) - elif isinstance(e, COMPLEX_TYPES): dt_str = num_to_str(e) - elif isinstance(e, VECTOR_TYPES): #vector types - if len(e) > 8: - dt_str = self.get_value() #large vectors use code - truncate = 1 - else: dt_str = ', '.join(map(num_to_str, e)) #small vectors use eval - elif t in ('file_open', 'file_save'): - dt_str = self.get_value() - truncate = -1 - else: dt_str = str(e) #other types - ################################################## - # done - ################################################## - return _truncate(dt_str, truncate) + def __repr__(self): + """ + Get the repr (nice string format) for this param. + + Returns: + the string representation + """ + ################################################## + # truncate helper method + ################################################## + def _truncate(string, style=0): + max_len = max(27 - len(self.get_name()), 3) + if len(string) > max_len: + if style < 0: #front truncate + string = '...' + string[3-max_len:] + elif style == 0: #center truncate + string = string[:max_len/2 -3] + '...' + string[-max_len/2:] + elif style > 0: #rear truncate + string = string[:max_len-3] + '...' + return string + ################################################## + # simple conditions + ################################################## + if not self.is_valid(): return _truncate(self.get_value()) + if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name() + ################################################## + # display logic for numbers + ################################################## + def num_to_str(num): + if isinstance(num, COMPLEX_TYPES): + num = complex(num) #cast to python complex + if num == 0: return '0' #value is zero + elif num.imag == 0: return '%s'%eng_notation.num_to_str(num.real) #value is real + elif num.real == 0: return '%sj'%eng_notation.num_to_str(num.imag) #value is imaginary + elif num.imag < 0: return '%s-%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(abs(num.imag))) + else: return '%s+%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(num.imag)) + else: return str(num) + ################################################## + # split up formatting by type + ################################################## + truncate = 0 #default center truncate + e = self.get_evaluated() + t = self.get_type() + if isinstance(e, bool): return str(e) + elif isinstance(e, COMPLEX_TYPES): dt_str = num_to_str(e) + elif isinstance(e, VECTOR_TYPES): #vector types + if len(e) > 8: + dt_str = self.get_value() #large vectors use code + truncate = 1 + else: dt_str = ', '.join(map(num_to_str, e)) #small vectors use eval + elif t in ('file_open', 'file_save'): + dt_str = self.get_value() + truncate = -1 + else: dt_str = str(e) #other types + ################################################## + # done + ################################################## + return _truncate(dt_str, truncate) - def get_input(self, *args, **kwargs): - if self.get_type() in ('file_open', 'file_save'): return FileParam(self, *args, **kwargs) - return _GUIParam.get_input(self, *args, **kwargs) + def get_input(self, *args, **kwargs): + if self.get_type() in ('file_open', 'file_save'): return FileParam(self, *args, **kwargs) + return _GUIParam.get_input(self, *args, **kwargs) - def get_color(self): - """ - Get the color that represents this param's type. - - Returns: - a hex color code. - """ - try: - return { - #number types - 'complex': Constants.COMPLEX_COLOR_SPEC, - 'real': Constants.FLOAT_COLOR_SPEC, - 'float': Constants.FLOAT_COLOR_SPEC, - 'int': Constants.INT_COLOR_SPEC, - #vector types - 'complex_vector': Constants.COMPLEX_VECTOR_COLOR_SPEC, - 'real_vector': Constants.FLOAT_VECTOR_COLOR_SPEC, + def get_color(self): + """ + Get the color that represents this param's type. + + Returns: + a hex color code. + """ + try: + return { + #number types + 'complex': Constants.COMPLEX_COLOR_SPEC, + 'real': Constants.FLOAT_COLOR_SPEC, + 'float': Constants.FLOAT_COLOR_SPEC, + 'int': Constants.INT_COLOR_SPEC, + #vector types + 'complex_vector': Constants.COMPLEX_VECTOR_COLOR_SPEC, + 'real_vector': Constants.FLOAT_VECTOR_COLOR_SPEC, 'float_vector': Constants.FLOAT_VECTOR_COLOR_SPEC, - 'int_vector': Constants.INT_VECTOR_COLOR_SPEC, - #special - 'bool': Constants.INT_COLOR_SPEC, - 'hex': Constants.INT_COLOR_SPEC, - 'string': Constants.BYTE_VECTOR_COLOR_SPEC, - 'id': Constants.ID_COLOR_SPEC, - 'stream_id': Constants.ID_COLOR_SPEC, - 'grid_pos': Constants.INT_VECTOR_COLOR_SPEC, - 'notebook': Constants.INT_VECTOR_COLOR_SPEC, - 'raw': Constants.WILDCARD_COLOR_SPEC, - }[self.get_type()] - except: return _Param.get_color(self) + 'int_vector': Constants.INT_VECTOR_COLOR_SPEC, + #special + 'bool': Constants.INT_COLOR_SPEC, + 'hex': Constants.INT_COLOR_SPEC, + 'string': Constants.BYTE_VECTOR_COLOR_SPEC, + 'id': Constants.ID_COLOR_SPEC, + 'stream_id': Constants.ID_COLOR_SPEC, + 'grid_pos': Constants.INT_VECTOR_COLOR_SPEC, + 'notebook': Constants.INT_VECTOR_COLOR_SPEC, + 'raw': Constants.WILDCARD_COLOR_SPEC, + }[self.get_type()] + except: return _Param.get_color(self) - def get_hide(self): - """ - Get the hide value from the base class. - Hide the ID parameter for most blocks. Exceptions below. - If the parameter controls a port type, vlen, or nports, return part. - If the parameter is an empty grid position, return part. - These parameters are redundant to display in the flow graph view. - - Returns: - hide the hide property string - """ - hide = _Param.get_hide(self) - if hide: return hide - #hide ID in non variable blocks - if self.get_key() == 'id' and not _show_id_matcher.match(self.get_parent().get_key()): return 'part' - #hide port controllers for type and nports - if self.get_key() in ' '.join(map( - lambda p: ' '.join([p._type, p._nports]), self.get_parent().get_ports()) - ): return 'part' - #hide port controllers for vlen, when == 1 - if self.get_key() in ' '.join(map( - lambda p: p._vlen, self.get_parent().get_ports()) - ): - try: - if int(self.get_evaluated()) == 1: return 'part' - except: pass - #hide empty grid positions - if self.get_key() in ('grid_pos', 'notebook') and not self.get_value(): return 'part' - return hide + def get_hide(self): + """ + Get the hide value from the base class. + Hide the ID parameter for most blocks. Exceptions below. + If the parameter controls a port type, vlen, or nports, return part. + If the parameter is an empty grid position, return part. + These parameters are redundant to display in the flow graph view. + + Returns: + hide the hide property string + """ + hide = _Param.get_hide(self) + if hide: return hide + #hide ID in non variable blocks + if self.get_key() == 'id' and not _show_id_matcher.match(self.get_parent().get_key()): return 'part' + #hide port controllers for type and nports + if self.get_key() in ' '.join(map( + lambda p: ' '.join([p._type, p._nports]), self.get_parent().get_ports()) + ): return 'part' + #hide port controllers for vlen, when == 1 + if self.get_key() in ' '.join(map( + lambda p: p._vlen, self.get_parent().get_ports()) + ): + try: + if int(self.get_evaluated()) == 1: return 'part' + except: pass + #hide empty grid positions + if self.get_key() in ('grid_pos', 'notebook') and not self.get_value(): return 'part' + return hide - def validate(self): - """ - Validate the param. - A test evaluation is performed - """ - _Param.validate(self) #checks type - self._evaluated = None - try: self._evaluated = self.evaluate() - except Exception, e: self.add_error_message(str(e)) + def validate(self): + """ + Validate the param. + A test evaluation is performed + """ + _Param.validate(self) #checks type + self._evaluated = None + try: self._evaluated = self.evaluate() + except Exception, e: self.add_error_message(str(e)) - def get_evaluated(self): return self._evaluated + def get_evaluated(self): return self._evaluated - def evaluate(self): - """ - Evaluate the value. - - Returns: - evaluated type - """ - self._init = True - self._lisitify_flag = False - self._stringify_flag = False - self._hostage_cells = list() - def eval_string(v): - try: - e = self.get_parent().get_parent().evaluate(v) - if isinstance(e, str): return e - raise Exception #want to stringify - except: - self._stringify_flag = True - return v - t = self.get_type() - v = self.get_value() - ######################### - # Enum Type - ######################### - if self.is_enum(): return v - ######################### - # Numeric Types - ######################### - elif t in ('raw', 'complex', 'real', 'float', 'int', 'hex', 'bool'): - #raise exception if python cannot evaluate this value - try: e = self.get_parent().get_parent().evaluate(v) - except Exception, e: raise Exception, 'Value "%s" cannot be evaluated:\n%s'%(v, e) - #raise an exception if the data is invalid - if t == 'raw': return e - elif t == 'complex': - if not isinstance(e, COMPLEX_TYPES): - raise Exception, 'Expression "%s" is invalid for type complex.'%str(e) - return e - elif t == 'real' or t == 'float': - if not isinstance(e, REAL_TYPES): - raise Exception, 'Expression "%s" is invalid for type float.'%str(e) - return e - elif t == 'int': - if not isinstance(e, INT_TYPES): - raise Exception, 'Expression "%s" is invalid for type integer.'%str(e) - return e - elif t == 'hex': return hex(e) - elif t == 'bool': - if not isinstance(e, bool): - raise Exception, 'Expression "%s" is invalid for type bool.'%str(e) - return e - else: raise TypeError, 'Type "%s" not handled'%t - ######################### - # Numeric Vector Types - ######################### - elif t in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'): - if not v: v = '()' #turn a blank string into an empty list, so it will eval - #raise exception if python cannot evaluate this value - try: e = self.get_parent().get_parent().evaluate(v) - except Exception, e: raise Exception, 'Value "%s" cannot be evaluated:\n%s'%(v, e) - #raise an exception if the data is invalid - if t == 'complex_vector': - if not isinstance(e, VECTOR_TYPES): - self._lisitify_flag = True - e = [e] - if not all([isinstance(ei, COMPLEX_TYPES) for ei in e]): - raise Exception, 'Expression "%s" is invalid for type complex vector.'%str(e) - return e - elif t == 'real_vector' or t == 'float_vector': - if not isinstance(e, VECTOR_TYPES): - self._lisitify_flag = True - e = [e] - if not all([isinstance(ei, REAL_TYPES) for ei in e]): - raise Exception, 'Expression "%s" is invalid for type float vector.'%str(e) - return e - elif t == 'int_vector': - if not isinstance(e, VECTOR_TYPES): - self._lisitify_flag = True - e = [e] - if not all([isinstance(ei, INT_TYPES) for ei in e]): - raise Exception, 'Expression "%s" is invalid for type integer vector.'%str(e) - return e - ######################### - # String Types - ######################### - elif t in ('string', 'file_open', 'file_save'): - #do not check if file/directory exists, that is a runtime issue - e = eval_string(v) - return str(e) - ######################### - # Unique ID Type - ######################### - elif t == 'id': - #can python use this as a variable? - if not _check_id_matcher.match(v): - raise Exception, 'ID "%s" must begin with a letter and may contain letters, numbers, and underscores.'%v - ids = [param.get_value() for param in self.get_all_params(t)] - if ids.count(v) > 1: #id should only appear once, or zero times if block is disabled - raise Exception, 'ID "%s" is not unique.'%v - if v in ID_BLACKLIST: - raise Exception, 'ID "%s" is blacklisted.'%v - return v - ######################### - # Stream ID Type - ######################### - elif t == 'stream_id': - #get a list of all stream ids used in the virtual sinks - ids = [param.get_value() for param in filter( - lambda p: p.get_parent().is_virtual_sink(), - self.get_all_params(t), - )] - #check that the virtual sink's stream id is unique - if self.get_parent().is_virtual_sink(): - if ids.count(v) > 1: #id should only appear once, or zero times if block is disabled - raise Exception, 'Stream ID "%s" is not unique.'%v - #check that the virtual source's steam id is found - if self.get_parent().is_virtual_source(): - if v not in ids: - raise Exception, 'Stream ID "%s" is not found.'%v - return v - ######################### - # GUI Position/Hint - ######################### - elif t == 'gui_hint': - if ':' in v: tab, pos = v.split(':') - elif '@' in v: tab, pos = v, '' - else: tab, pos = '', v + def evaluate(self): + """ + Evaluate the value. + + Returns: + evaluated type + """ + self._init = True + self._lisitify_flag = False + self._stringify_flag = False + self._hostage_cells = list() + def eval_string(v): + try: + e = self.get_parent().get_parent().evaluate(v) + if isinstance(e, str): return e + raise Exception #want to stringify + except: + self._stringify_flag = True + return v + t = self.get_type() + v = self.get_value() + ######################### + # Enum Type + ######################### + if self.is_enum(): return v + ######################### + # Numeric Types + ######################### + elif t in ('raw', 'complex', 'real', 'float', 'int', 'hex', 'bool'): + #raise exception if python cannot evaluate this value + try: e = self.get_parent().get_parent().evaluate(v) + except Exception, e: raise Exception, 'Value "%s" cannot be evaluated:\n%s'%(v, e) + #raise an exception if the data is invalid + if t == 'raw': return e + elif t == 'complex': + if not isinstance(e, COMPLEX_TYPES): + raise Exception, 'Expression "%s" is invalid for type complex.'%str(e) + return e + elif t == 'real' or t == 'float': + if not isinstance(e, REAL_TYPES): + raise Exception, 'Expression "%s" is invalid for type float.'%str(e) + return e + elif t == 'int': + if not isinstance(e, INT_TYPES): + raise Exception, 'Expression "%s" is invalid for type integer.'%str(e) + return e + elif t == 'hex': return hex(e) + elif t == 'bool': + if not isinstance(e, bool): + raise Exception, 'Expression "%s" is invalid for type bool.'%str(e) + return e + else: raise TypeError, 'Type "%s" not handled'%t + ######################### + # Numeric Vector Types + ######################### + elif t in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'): + if not v: v = '()' #turn a blank string into an empty list, so it will eval + #raise exception if python cannot evaluate this value + try: e = self.get_parent().get_parent().evaluate(v) + except Exception, e: raise Exception, 'Value "%s" cannot be evaluated:\n%s'%(v, e) + #raise an exception if the data is invalid + if t == 'complex_vector': + if not isinstance(e, VECTOR_TYPES): + self._lisitify_flag = True + e = [e] + if not all([isinstance(ei, COMPLEX_TYPES) for ei in e]): + raise Exception, 'Expression "%s" is invalid for type complex vector.'%str(e) + return e + elif t == 'real_vector' or t == 'float_vector': + if not isinstance(e, VECTOR_TYPES): + self._lisitify_flag = True + e = [e] + if not all([isinstance(ei, REAL_TYPES) for ei in e]): + raise Exception, 'Expression "%s" is invalid for type float vector.'%str(e) + return e + elif t == 'int_vector': + if not isinstance(e, VECTOR_TYPES): + self._lisitify_flag = True + e = [e] + if not all([isinstance(ei, INT_TYPES) for ei in e]): + raise Exception, 'Expression "%s" is invalid for type integer vector.'%str(e) + return e + ######################### + # String Types + ######################### + elif t in ('string', 'file_open', 'file_save'): + #do not check if file/directory exists, that is a runtime issue + e = eval_string(v) + return str(e) + ######################### + # Unique ID Type + ######################### + elif t == 'id': + #can python use this as a variable? + if not _check_id_matcher.match(v): + raise Exception, 'ID "%s" must begin with a letter and may contain letters, numbers, and underscores.'%v + ids = [param.get_value() for param in self.get_all_params(t)] + if ids.count(v) > 1: #id should only appear once, or zero times if block is disabled + raise Exception, 'ID "%s" is not unique.'%v + if v in ID_BLACKLIST: + raise Exception, 'ID "%s" is blacklisted.'%v + return v + ######################### + # Stream ID Type + ######################### + elif t == 'stream_id': + #get a list of all stream ids used in the virtual sinks + ids = [param.get_value() for param in filter( + lambda p: p.get_parent().is_virtual_sink(), + self.get_all_params(t), + )] + #check that the virtual sink's stream id is unique + if self.get_parent().is_virtual_sink(): + if ids.count(v) > 1: #id should only appear once, or zero times if block is disabled + raise Exception, 'Stream ID "%s" is not unique.'%v + #check that the virtual source's steam id is found + if self.get_parent().is_virtual_source(): + if v not in ids: + raise Exception, 'Stream ID "%s" is not found.'%v + return v + ######################### + # GUI Position/Hint + ######################### + elif t == 'gui_hint': + if ':' in v: tab, pos = v.split(':') + elif '@' in v: tab, pos = v, '' + else: tab, pos = '', v - if '@' in tab: tab, index = tab.split('@') - else: index = '?' + if '@' in tab: tab, index = tab.split('@') + else: index = '?' - widget_str = ({ - (True, True): 'self.%(tab)s_grid_layout_%(index)s.addWidget(%(widget)s, %(pos)s)', - (True, False): 'self.%(tab)s_layout_%(index)s.addWidget(%(widget)s)', - (False, True): 'self.top_grid_layout.addWidget(%(widget)s, %(pos)s)', - (False, False): 'self.top_layout.addWidget(%(widget)s)', - }[bool(tab), bool(pos)])%{'tab': tab, 'index': index, 'widget': '%s', 'pos': pos} + widget_str = ({ + (True, True): 'self.%(tab)s_grid_layout_%(index)s.addWidget(%(widget)s, %(pos)s)', + (True, False): 'self.%(tab)s_layout_%(index)s.addWidget(%(widget)s)', + (False, True): 'self.top_grid_layout.addWidget(%(widget)s, %(pos)s)', + (False, False): 'self.top_layout.addWidget(%(widget)s)', + }[bool(tab), bool(pos)])%{'tab': tab, 'index': index, 'widget': '%s', 'pos': pos} - def gui_hint(ws, w): - if 'layout' in w: ws = ws.replace('addWidget', 'addLayout') - return ws%w + def gui_hint(ws, w): + if 'layout' in w: ws = ws.replace('addWidget', 'addLayout') + return ws%w - return lambda w: gui_hint(widget_str, w) - ######################### - # Grid Position Type - ######################### - elif t == 'grid_pos': - if not v: return '' #allow for empty grid pos - e = self.get_parent().get_parent().evaluate(v) - if not isinstance(e, (list, tuple)) or len(e) != 4 or not all([isinstance(ei, int) for ei in e]): - raise Exception, 'A grid position must be a list of 4 integers.' - row, col, row_span, col_span = e - #check row, col - if row < 0 or col < 0: - raise Exception, 'Row and column must be non-negative.' - #check row span, col span - if row_span <= 0 or col_span <= 0: - raise Exception, 'Row and column span must be greater than zero.' - #get hostage cell parent - try: my_parent = self.get_parent().get_param('notebook').evaluate() - except: my_parent = '' - #calculate hostage cells - for r in range(row_span): - for c in range(col_span): - self._hostage_cells.append((my_parent, (row+r, col+c))) - #avoid collisions - params = filter(lambda p: p is not self, self.get_all_params('grid_pos')) - for param in params: - for parent, cell in param._hostage_cells: - if (parent, cell) in self._hostage_cells: - raise Exception, 'Another graphical element is using parent "%s", cell "%s".'%(str(parent), str(cell)) - return e - ######################### - # Notebook Page Type - ######################### - elif t == 'notebook': - if not v: return '' #allow for empty notebook - #get a list of all notebooks - notebook_blocks = filter(lambda b: b.get_key() == 'notebook', self.get_parent().get_parent().get_enabled_blocks()) - #check for notebook param syntax - try: notebook_id, page_index = map(str.strip, v.split(',')) - except: raise Exception, 'Bad notebook page format.' - #check that the notebook id is valid - try: notebook_block = filter(lambda b: b.get_id() == notebook_id, notebook_blocks)[0] - except: raise Exception, 'Notebook id "%s" is not an existing notebook id.'%notebook_id - #check that page index exists - if int(page_index) not in range(len(notebook_block.get_param('labels').evaluate())): - raise Exception, 'Page index "%s" is not a valid index number.'%page_index - return notebook_id, page_index - ######################### - # Import Type - ######################### - elif t == 'import': - n = dict() #new namespace - try: exec v in n - except ImportError: raise Exception, 'Import "%s" failed.'%v - except Exception: raise Exception, 'Bad import syntax: "%s".'%v - return filter(lambda k: str(k) != '__builtins__', n.keys()) - ######################### - else: raise TypeError, 'Type "%s" not handled'%t + return lambda w: gui_hint(widget_str, w) + ######################### + # Grid Position Type + ######################### + elif t == 'grid_pos': + if not v: return '' #allow for empty grid pos + e = self.get_parent().get_parent().evaluate(v) + if not isinstance(e, (list, tuple)) or len(e) != 4 or not all([isinstance(ei, int) for ei in e]): + raise Exception, 'A grid position must be a list of 4 integers.' + row, col, row_span, col_span = e + #check row, col + if row < 0 or col < 0: + raise Exception, 'Row and column must be non-negative.' + #check row span, col span + if row_span <= 0 or col_span <= 0: + raise Exception, 'Row and column span must be greater than zero.' + #get hostage cell parent + try: my_parent = self.get_parent().get_param('notebook').evaluate() + except: my_parent = '' + #calculate hostage cells + for r in range(row_span): + for c in range(col_span): + self._hostage_cells.append((my_parent, (row+r, col+c))) + #avoid collisions + params = filter(lambda p: p is not self, self.get_all_params('grid_pos')) + for param in params: + for parent, cell in param._hostage_cells: + if (parent, cell) in self._hostage_cells: + raise Exception, 'Another graphical element is using parent "%s", cell "%s".'%(str(parent), str(cell)) + return e + ######################### + # Notebook Page Type + ######################### + elif t == 'notebook': + if not v: return '' #allow for empty notebook + #get a list of all notebooks + notebook_blocks = filter(lambda b: b.get_key() == 'notebook', self.get_parent().get_parent().get_enabled_blocks()) + #check for notebook param syntax + try: notebook_id, page_index = map(str.strip, v.split(',')) + except: raise Exception, 'Bad notebook page format.' + #check that the notebook id is valid + try: notebook_block = filter(lambda b: b.get_id() == notebook_id, notebook_blocks)[0] + except: raise Exception, 'Notebook id "%s" is not an existing notebook id.'%notebook_id + #check that page index exists + if int(page_index) not in range(len(notebook_block.get_param('labels').evaluate())): + raise Exception, 'Page index "%s" is not a valid index number.'%page_index + return notebook_id, page_index + ######################### + # Import Type + ######################### + elif t == 'import': + n = dict() #new namespace + try: exec v in n + except ImportError: raise Exception, 'Import "%s" failed.'%v + except Exception: raise Exception, 'Bad import syntax: "%s".'%v + return filter(lambda k: str(k) != '__builtins__', n.keys()) + ######################### + else: raise TypeError, 'Type "%s" not handled'%t - def to_code(self): - """ - Convert the value to code. - For string and list types, check the init flag, call evaluate(). - This ensures that evaluate() was called to set the xxxify_flags. - - Returns: - a string representing the code - """ - v = self.get_value() - t = self.get_type() - if t in ('string', 'file_open', 'file_save'): #string types - if not self._init: self.evaluate() - if self._stringify_flag: return '"%s"'%v.replace('"', '\"') - else: return v - elif t in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'): #vector types - if not self._init: self.evaluate() - if self._lisitify_flag: return '(%s, )'%v - else: return '(%s)'%v - else: return v + def to_code(self): + """ + Convert the value to code. + For string and list types, check the init flag, call evaluate(). + This ensures that evaluate() was called to set the xxxify_flags. + + Returns: + a string representing the code + """ + v = self.get_value() + t = self.get_type() + if t in ('string', 'file_open', 'file_save'): #string types + if not self._init: self.evaluate() + if self._stringify_flag: return '"%s"'%v.replace('"', '\"') + else: return v + elif t in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'): #vector types + if not self._init: self.evaluate() + if self._lisitify_flag: return '(%s, )'%v + else: return '(%s)'%v + else: return v - def get_all_params(self, type): - """ - Get all the params from the flowgraph that have the given type. - - Args: - type: the specified type - - Returns: - a list of params - """ - return sum([filter(lambda p: p.get_type() == type, block.get_params()) for block in self.get_parent().get_parent().get_enabled_blocks()], []) + def get_all_params(self, type): + """ + Get all the params from the flowgraph that have the given type. + + Args: + type: the specified type + + Returns: + a list of params + """ + return sum([filter(lambda p: p.get_type() == type, block.get_params()) for block in self.get_parent().get_parent().get_enabled_blocks()], []) diff --git a/grc/python/Platform.py b/grc/python/Platform.py index e036361ff0..f6adaf47a5 100644 --- a/grc/python/Platform.py +++ b/grc/python/Platform.py @@ -28,43 +28,43 @@ from Port import Port as _Port from Param import Param as _Param from Generator import Generator from Constants import \ - HIER_BLOCKS_LIB_DIR, BLOCK_DTD, \ - DEFAULT_FLOW_GRAPH, BLOCKS_DIRS + HIER_BLOCKS_LIB_DIR, BLOCK_DTD, \ + DEFAULT_FLOW_GRAPH, BLOCKS_DIRS import Constants COLORS = [(name, color) for name, key, sizeof, color in Constants.CORE_TYPES] class Platform(_Platform, _GUIPlatform): - def __init__(self): - """ - Make a platform for gnuradio. - """ - #ensure hier dir - if not os.path.exists(HIER_BLOCKS_LIB_DIR): os.mkdir(HIER_BLOCKS_LIB_DIR) - #convert block paths to absolute paths - block_paths = set(map(os.path.abspath, BLOCKS_DIRS)) - #init - _Platform.__init__( - self, - name='GNU Radio Companion', - version=gr.version(), - key='grc', - license=__doc__.strip(), - website='http://gnuradio.org/redmine/wiki/gnuradio/GNURadioCompanion', - block_paths=block_paths, - block_dtd=BLOCK_DTD, - default_flow_graph=DEFAULT_FLOW_GRAPH, - generator=Generator, - colors=COLORS, - ) - _GUIPlatform.__init__(self) + def __init__(self): + """ + Make a platform for gnuradio. + """ + #ensure hier dir + if not os.path.exists(HIER_BLOCKS_LIB_DIR): os.mkdir(HIER_BLOCKS_LIB_DIR) + #convert block paths to absolute paths + block_paths = set(map(os.path.abspath, BLOCKS_DIRS)) + #init + _Platform.__init__( + self, + name='GNU Radio Companion', + version=gr.version(), + key='grc', + license=__doc__.strip(), + website='http://gnuradio.org/redmine/wiki/gnuradio/GNURadioCompanion', + block_paths=block_paths, + block_dtd=BLOCK_DTD, + default_flow_graph=DEFAULT_FLOW_GRAPH, + generator=Generator, + colors=COLORS, + ) + _GUIPlatform.__init__(self) - ############################################## - # Constructors - ############################################## - FlowGraph = _FlowGraph - Connection = _Connection - Block = _Block - Port = _Port - Param = _Param + ############################################## + # Constructors + ############################################## + FlowGraph = _FlowGraph + Connection = _Connection + Block = _Block + Port = _Port + Param = _Param diff --git a/grc/python/Port.py b/grc/python/Port.py index 8ebf5c7b05..247dbed3e6 100644 --- a/grc/python/Port.py +++ b/grc/python/Port.py @@ -22,209 +22,203 @@ from .. gui.Port import Port as _GUIPort import Constants def _get_source_from_virtual_sink_port(vsp): - """ - Resolve the source port that is connected to the given virtual sink port. - Use the get source from virtual source to recursively resolve subsequent ports. - """ - try: return _get_source_from_virtual_source_port( - vsp.get_enabled_connections()[0].get_source()) - except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp + """ + Resolve the source port that is connected to the given virtual sink port. + Use the get source from virtual source to recursively resolve subsequent ports. + """ + try: return _get_source_from_virtual_source_port( + vsp.get_enabled_connections()[0].get_source()) + except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp def _get_source_from_virtual_source_port(vsp, traversed=[]): - """ - Recursively resolve source ports over the virtual connections. - Keep track of traversed sources to avoid recursive loops. - """ - if not vsp.get_parent().is_virtual_source(): return vsp - if vsp in traversed: raise Exception, 'Loop found when resolving virtual source %s'%vsp - try: return _get_source_from_virtual_source_port( - _get_source_from_virtual_sink_port( - filter(#get all virtual sinks with a matching stream id - lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(), - filter(#get all enabled blocks that are also virtual sinks - lambda b: b.is_virtual_sink(), - vsp.get_parent().get_parent().get_enabled_blocks(), - ), - )[0].get_sinks()[0] - ), traversed + [vsp], - ) - except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp + """ + Recursively resolve source ports over the virtual connections. + Keep track of traversed sources to avoid recursive loops. + """ + if not vsp.get_parent().is_virtual_source(): return vsp + if vsp in traversed: raise Exception, 'Loop found when resolving virtual source %s'%vsp + try: return _get_source_from_virtual_source_port( + _get_source_from_virtual_sink_port( + filter(#get all virtual sinks with a matching stream id + lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(), + filter(#get all enabled blocks that are also virtual sinks + lambda b: b.is_virtual_sink(), + vsp.get_parent().get_parent().get_enabled_blocks(), + ), + )[0].get_sinks()[0] + ), traversed + [vsp], + ) + except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp def _get_sink_from_virtual_source_port(vsp): - """ - Resolve the sink port that is connected to the given virtual source port. - Use the get sink from virtual sink to recursively resolve subsequent ports. - """ - try: return _get_sink_from_virtual_sink_port( - vsp.get_enabled_connections()[0].get_sink()) # Could have many connections, but use first - except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp + """ + Resolve the sink port that is connected to the given virtual source port. + Use the get sink from virtual sink to recursively resolve subsequent ports. + """ + try: return _get_sink_from_virtual_sink_port( + vsp.get_enabled_connections()[0].get_sink()) # Could have many connections, but use first + except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp def _get_sink_from_virtual_sink_port(vsp, traversed=[]): - """ - Recursively resolve sink ports over the virtual connections. - Keep track of traversed sinks to avoid recursive loops. - """ - if not vsp.get_parent().is_virtual_sink(): return vsp - if vsp in traversed: raise Exception, 'Loop found when resolving virtual sink %s'%vsp - try: return _get_sink_from_virtual_sink_port( - _get_sink_from_virtual_source_port( - filter(#get all virtual source with a matching stream id - lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(), - filter(#get all enabled blocks that are also virtual sinks - lambda b: b.is_virtual_source(), - vsp.get_parent().get_parent().get_enabled_blocks(), - ), - )[0].get_sources()[0] - ), traversed + [vsp], - ) - except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp + """ + Recursively resolve sink ports over the virtual connections. + Keep track of traversed sinks to avoid recursive loops. + """ + if not vsp.get_parent().is_virtual_sink(): return vsp + if vsp in traversed: raise Exception, 'Loop found when resolving virtual sink %s'%vsp + try: return _get_sink_from_virtual_sink_port( + _get_sink_from_virtual_source_port( + filter(#get all virtual source with a matching stream id + lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(), + filter(#get all enabled blocks that are also virtual sinks + lambda b: b.is_virtual_source(), + vsp.get_parent().get_parent().get_enabled_blocks(), + ), + )[0].get_sources()[0] + ), traversed + [vsp], + ) + except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp class Port(_Port, _GUIPort): - 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 - """ - self._n = n - if n['type'] == 'msg': n['key'] = 'msg' - if n['type'] == 'message': n['key'] = n['name'] - if dir == 'source' and not n.find('key'): - n['key'] = str(block._source_count) - block._source_count += 1 - if dir == 'sink' and not n.find('key'): - n['key'] = str(block._sink_count) - block._sink_count += 1 - #build the port - _Port.__init__( - self, - block=block, - n=n, - dir=dir, - ) - _GUIPort.__init__(self) - self._nports = n.find('nports') or '' - self._vlen = n.find('vlen') or '' - self._optional = bool(n.find('optional')) - - - def get_types(self): return Constants.TYPE_TO_SIZEOF.keys() - - def is_type_empty(self): return not self._n['type'] - - def validate(self): - _Port.validate(self) - if not self.get_enabled_connections() and not self.get_optional(): - self.add_error_message('Port is not connected.') - if not self.is_source() and (not self.get_type() == "message") and len(self.get_enabled_connections()) > 1: - self.add_error_message('Port has too many connections.') - #message port logic - if self.get_type() == 'msg': - if self.get_nports(): - self.add_error_message('A port of type "msg" cannot have "nports" set.') - if self.get_vlen() != 1: - self.add_error_message('A port of type "msg" must have a "vlen" of 1.') - - def rewrite(self): - """ - Handle the port cloning for virtual blocks. - """ - _Port.rewrite(self) - if self.is_type_empty(): - try: #clone type and vlen - source = self.resolve_empty_type() - self._type = str(source.get_type()) - self._vlen = str(source.get_vlen()) - except: #reset type and vlen - self._type = '' - self._vlen = '' - - def resolve_virtual_source(self): - if self.get_parent().is_virtual_sink(): return _get_source_from_virtual_sink_port(self) - if self.get_parent().is_virtual_source(): return _get_source_from_virtual_source_port(self) - - def resolve_empty_type(self): - if self.is_sink(): - try: - src = _get_source_from_virtual_sink_port(self) - if not src.is_type_empty(): return src - except: pass - sink = _get_sink_from_virtual_sink_port(self) - if not sink.is_type_empty(): return sink - if self.is_source(): - try: - src = _get_source_from_virtual_source_port(self) - if not src.is_type_empty(): return src - except: pass - sink = _get_sink_from_virtual_source_port(self) - if not sink.is_type_empty(): return sink - - def get_vlen(self): - """ - Get the vector length. - If the evaluation of vlen cannot be cast to an integer, return 1. - - Returns: - the vector length or 1 - """ - vlen = self.get_parent().resolve_dependencies(self._vlen) - try: return int(self.get_parent().get_parent().evaluate(vlen)) - except: return 1 - - - - - def get_nports(self): - """ - Get the number of ports. - If already blank, return a blank - If the evaluation of nports cannot be cast to an integer, return 1. - - Returns: - the number of ports or 1 - """ - nports = self.get_parent().resolve_dependencies(self._nports) - #return blank if nports is blank - if not nports: return '' - try: - nports = int(self.get_parent().get_parent().evaluate(nports)) - if 0 < nports: return nports - except: return 1 - - - - def get_optional(self): return bool(self._optional) - - def get_color(self): - """ - Get the color that represents this port's type. - Codes differ for ports where the vec length is 1 or greater than 1. - - Returns: - a hex color code. - """ - try: - color = Constants.TYPE_TO_COLOR[self.get_type()] - vlen = self.get_vlen() - if vlen == 1: return color - color_val = int(color[1:], 16) - r = (color_val >> 16) & 0xff - g = (color_val >> 8) & 0xff - b = (color_val >> 0) & 0xff - dark = (0, 0, 30, 50, 70)[min(4, vlen)] - r = max(r-dark, 0) - g = max(g-dark, 0) - b = max(b-dark, 0) - return '#%.2x%.2x%.2x'%(r, g, b) - except: return _Port.get_color(self) - - def copy(self, new_key=None): - n = self._n.copy() - #remove nports from the key so the copy cannot be a duplicator - if n.has_key('nports'): n.pop('nports') - if new_key: n['key'] = new_key - return self.__class__(self.get_parent(), n, self._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 + """ + self._n = n + if n['type'] == 'msg': n['key'] = 'msg' + if n['type'] == 'message': n['key'] = n['name'] + if dir == 'source' and not n.find('key'): + n['key'] = str(block._source_count) + block._source_count += 1 + if dir == 'sink' and not n.find('key'): + n['key'] = str(block._sink_count) + block._sink_count += 1 + #build the port + _Port.__init__( + self, + block=block, + n=n, + dir=dir, + ) + _GUIPort.__init__(self) + self._nports = n.find('nports') or '' + self._vlen = n.find('vlen') or '' + self._optional = bool(n.find('optional')) + + def get_types(self): return Constants.TYPE_TO_SIZEOF.keys() + + def is_type_empty(self): return not self._n['type'] + + def validate(self): + _Port.validate(self) + if not self.get_enabled_connections() and not self.get_optional(): + self.add_error_message('Port is not connected.') + if not self.is_source() and (not self.get_type() == "message") and len(self.get_enabled_connections()) > 1: + self.add_error_message('Port has too many connections.') + #message port logic + if self.get_type() == 'msg': + if self.get_nports(): + self.add_error_message('A port of type "msg" cannot have "nports" set.') + if self.get_vlen() != 1: + self.add_error_message('A port of type "msg" must have a "vlen" of 1.') + + def rewrite(self): + """ + Handle the port cloning for virtual blocks. + """ + _Port.rewrite(self) + if self.is_type_empty(): + try: #clone type and vlen + source = self.resolve_empty_type() + self._type = str(source.get_type()) + self._vlen = str(source.get_vlen()) + except: #reset type and vlen + self._type = '' + self._vlen = '' + + def resolve_virtual_source(self): + if self.get_parent().is_virtual_sink(): return _get_source_from_virtual_sink_port(self) + if self.get_parent().is_virtual_source(): return _get_source_from_virtual_source_port(self) + + def resolve_empty_type(self): + if self.is_sink(): + try: + src = _get_source_from_virtual_sink_port(self) + if not src.is_type_empty(): return src + except: pass + sink = _get_sink_from_virtual_sink_port(self) + if not sink.is_type_empty(): return sink + if self.is_source(): + try: + src = _get_source_from_virtual_source_port(self) + if not src.is_type_empty(): return src + except: pass + sink = _get_sink_from_virtual_source_port(self) + if not sink.is_type_empty(): return sink + + def get_vlen(self): + """ + Get the vector length. + If the evaluation of vlen cannot be cast to an integer, return 1. + + Returns: + the vector length or 1 + """ + vlen = self.get_parent().resolve_dependencies(self._vlen) + try: return int(self.get_parent().get_parent().evaluate(vlen)) + except: return 1 + + def get_nports(self): + """ + Get the number of ports. + If already blank, return a blank + If the evaluation of nports cannot be cast to an integer, return 1. + + Returns: + the number of ports or 1 + """ + nports = self.get_parent().resolve_dependencies(self._nports) + #return blank if nports is blank + if not nports: return '' + try: + nports = int(self.get_parent().get_parent().evaluate(nports)) + if 0 < nports: return nports + except: return 1 + + def get_optional(self): return bool(self._optional) + + def get_color(self): + """ + Get the color that represents this port's type. + Codes differ for ports where the vec length is 1 or greater than 1. + + Returns: + a hex color code. + """ + try: + color = Constants.TYPE_TO_COLOR[self.get_type()] + vlen = self.get_vlen() + if vlen == 1: return color + color_val = int(color[1:], 16) + r = (color_val >> 16) & 0xff + g = (color_val >> 8) & 0xff + b = (color_val >> 0) & 0xff + dark = (0, 0, 30, 50, 70)[min(4, vlen)] + r = max(r-dark, 0) + g = max(g-dark, 0) + b = max(b-dark, 0) + return '#%.2x%.2x%.2x'%(r, g, b) + except: return _Port.get_color(self) + + def copy(self, new_key=None): + n = self._n.copy() + #remove nports from the key so the copy cannot be a duplicator + if n.has_key('nports'): n.pop('nports') + if new_key: n['key'] = new_key + return self.__class__(self.get_parent(), n, self._dir) diff --git a/grc/python/block.dtd b/grc/python/block.dtd index 99d38a0d46..21ffbe09af 100644 --- a/grc/python/block.dtd +++ b/grc/python/block.dtd @@ -17,25 +17,25 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA --> <!-- - gnuradio_python.blocks.dtd - Josh Blum - The document type definition for blocks. + gnuradio_python.blocks.dtd + Josh Blum + The document type definition for blocks. --> <!-- - Top level element. - A block contains a name, ...parameters list, and list of IO ports. + Top level element. + A block contains a name, ...parameters list, and list of IO ports. --> <!ELEMENT block (name, key, category?, throttle?, import*, var_make?, make, callback*, param*, bus_sink?, bus_source?, check*, sink*, source*, bus_structure_sink?, bus_structure_source?, doc?, grc_source?)> <!-- - Sub level elements. + Sub level elements. --> <!ELEMENT param (name, key, value?, type, hide?, option*)> <!ELEMENT option (name, key, opt*)> <!ELEMENT sink (name, type, vlen?, nports?, optional?)> <!ELEMENT source (name, type, vlen?, nports?, optional?)> <!-- - Bottom level elements. - Character data only. + Bottom level elements. + Character data only. --> <!ELEMENT category (#PCDATA)> <!ELEMENT import (#PCDATA)> diff --git a/grc/python/convert_hier.py b/grc/python/convert_hier.py index de76827541..dc86daa0ef 100644 --- a/grc/python/convert_hier.py +++ b/grc/python/convert_hier.py @@ -22,89 +22,89 @@ from .. base import ParseXML from .. base import odict def convert_hier(flow_graph, python_file): - #extract info from the flow graph - input_sigs = flow_graph.get_io_signaturev('in') - output_sigs = flow_graph.get_io_signaturev('out') - input_msgp = flow_graph.get_msg_pad_sources(); - output_msgp = flow_graph.get_msg_pad_sinks(); - parameters = flow_graph.get_parameters() - bussink = flow_graph.get_bussink() - bussrc = flow_graph.get_bussrc() - bus_struct_sink = flow_graph.get_bus_structure_sink() - bus_struct_src = flow_graph.get_bus_structure_src() - block_key = flow_graph.get_option('id') - block_name = flow_graph.get_option('title') or flow_graph.get_option('id').replace('_', ' ').title() - block_category = flow_graph.get_option('category') - block_desc = flow_graph.get_option('description') - block_author = flow_graph.get_option('author') - #build the nested data - block_n = odict() - block_n['name'] = block_name - block_n['key'] = block_key - block_n['category'] = block_category - block_n['import'] = 'execfile("%s")'%python_file - #make data - if parameters: block_n['make'] = '%s(\n\t%s,\n)'%( - block_key, - ',\n\t'.join(['%s=$%s'%(param.get_id(), param.get_id()) for param in parameters]), - ) - else: block_n['make'] = '%s()'%block_key - #callback data - block_n['callback'] = ['set_%s($%s)'%(param.get_id(), param.get_id()) for param in parameters] - #param data - params_n = list() - for param in parameters: - param_n = odict() - param_n['name'] = param.get_param('label').get_value() or param.get_id() - param_n['key'] = param.get_id() - param_n['value'] = param.get_param('value').get_value() - param_n['type'] = 'raw' - params_n.append(param_n) - block_n['param'] = params_n - #sink data stream ports - if bussink: - block_n['bus_sink'] = '1'; - if bussrc: - block_n['bus_source'] = '1'; - block_n['sink'] = list() - for input_sig in input_sigs: - sink_n = odict() - sink_n['name'] = input_sig['label'] - sink_n['type'] = input_sig['type'] - sink_n['vlen'] = input_sig['vlen'] - if input_sig['optional']: sink_n['optional'] = '1' - block_n['sink'].append(sink_n) - #sink data msg ports - for input_sig in input_msgp: - sink_n = odict() - sink_n['name'] = input_sig.get_param("label").get_value(); - sink_n['type'] = "message" - sink_n['optional'] = input_sig.get_param("optional").get_value(); - block_n['sink'].append(sink_n) - #source data stream ports - block_n['source'] = list() - if bus_struct_sink: - block_n['bus_structure_sink'] = bus_struct_sink[0].get_param('struct').get_value(); - if bus_struct_src: - block_n['bus_structure_source'] = bus_struct_src[0].get_param('struct').get_value(); - for output_sig in output_sigs: - source_n = odict() - source_n['name'] = output_sig['label'] - source_n['type'] = output_sig['type'] - source_n['vlen'] = output_sig['vlen'] - if output_sig['optional']: source_n['optional'] = '1' - block_n['source'].append(source_n) - #source data msg ports - for output_sig in output_msgp: - source_n = odict() - source_n['name'] = output_sig.get_param("label").get_value(); - source_n['type'] = "message" - source_n['optional'] = output_sig.get_param("optional").get_value(); - block_n['source'].append(source_n) - #doc data - block_n['doc'] = "%s\n%s\n%s"%(block_author, block_desc, python_file) - block_n['grc_source'] = "%s"%(flow_graph.grc_file_path) - #write the block_n to file - xml_file = python_file + '.xml' - ParseXML.to_file({'block': block_n}, xml_file) - ParseXML.validate_dtd(xml_file, BLOCK_DTD) + #extract info from the flow graph + input_sigs = flow_graph.get_io_signaturev('in') + output_sigs = flow_graph.get_io_signaturev('out') + input_msgp = flow_graph.get_msg_pad_sources(); + output_msgp = flow_graph.get_msg_pad_sinks(); + parameters = flow_graph.get_parameters() + bussink = flow_graph.get_bussink() + bussrc = flow_graph.get_bussrc() + bus_struct_sink = flow_graph.get_bus_structure_sink() + bus_struct_src = flow_graph.get_bus_structure_src() + block_key = flow_graph.get_option('id') + block_name = flow_graph.get_option('title') or flow_graph.get_option('id').replace('_', ' ').title() + block_category = flow_graph.get_option('category') + block_desc = flow_graph.get_option('description') + block_author = flow_graph.get_option('author') + #build the nested data + block_n = odict() + block_n['name'] = block_name + block_n['key'] = block_key + block_n['category'] = block_category + block_n['import'] = 'execfile("%s")'%python_file + #make data + if parameters: block_n['make'] = '%s(\n %s,\n)'%( + block_key, + ',\n '.join(['%s=$%s'%(param.get_id(), param.get_id()) for param in parameters]), + ) + else: block_n['make'] = '%s()'%block_key + #callback data + block_n['callback'] = ['set_%s($%s)'%(param.get_id(), param.get_id()) for param in parameters] + #param data + params_n = list() + for param in parameters: + param_n = odict() + param_n['name'] = param.get_param('label').get_value() or param.get_id() + param_n['key'] = param.get_id() + param_n['value'] = param.get_param('value').get_value() + param_n['type'] = 'raw' + params_n.append(param_n) + block_n['param'] = params_n + #sink data stream ports + if bussink: + block_n['bus_sink'] = '1'; + if bussrc: + block_n['bus_source'] = '1'; + block_n['sink'] = list() + for input_sig in input_sigs: + sink_n = odict() + sink_n['name'] = input_sig['label'] + sink_n['type'] = input_sig['type'] + sink_n['vlen'] = input_sig['vlen'] + if input_sig['optional']: sink_n['optional'] = '1' + block_n['sink'].append(sink_n) + #sink data msg ports + for input_sig in input_msgp: + sink_n = odict() + sink_n['name'] = input_sig.get_param("label").get_value(); + sink_n['type'] = "message" + sink_n['optional'] = input_sig.get_param("optional").get_value(); + block_n['sink'].append(sink_n) + #source data stream ports + block_n['source'] = list() + if bus_struct_sink: + block_n['bus_structure_sink'] = bus_struct_sink[0].get_param('struct').get_value(); + if bus_struct_src: + block_n['bus_structure_source'] = bus_struct_src[0].get_param('struct').get_value(); + for output_sig in output_sigs: + source_n = odict() + source_n['name'] = output_sig['label'] + source_n['type'] = output_sig['type'] + source_n['vlen'] = output_sig['vlen'] + if output_sig['optional']: source_n['optional'] = '1' + block_n['source'].append(source_n) + #source data msg ports + for output_sig in output_msgp: + source_n = odict() + source_n['name'] = output_sig.get_param("label").get_value(); + source_n['type'] = "message" + source_n['optional'] = output_sig.get_param("optional").get_value(); + block_n['source'].append(source_n) + #doc data + block_n['doc'] = "%s\n%s\n%s"%(block_author, block_desc, python_file) + block_n['grc_source'] = "%s"%(flow_graph.grc_file_path) + #write the block_n to file + xml_file = python_file + '.xml' + ParseXML.to_file({'block': block_n}, xml_file) + ParseXML.validate_dtd(xml_file, BLOCK_DTD) diff --git a/grc/python/default_flow_graph.grc b/grc/python/default_flow_graph.grc index dea26f3a5e..53d39e885a 100644 --- a/grc/python/default_flow_graph.grc +++ b/grc/python/default_flow_graph.grc @@ -2,42 +2,42 @@ <!-- ################################################### ##Default Flow Graph: -## include an options block and a variable for sample rate +## include an options block and a variable for sample rate ################################################### --> <flow_graph> - <block> - <key>options</key> - <param> - <key>id</key> - <value>top_block</value> - </param> - <param> - <key>_coordinate</key> - <value>(10, 10)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> - <block> - <key>variable</key> - <param> - <key>id</key> - <value>samp_rate</value> - </param> - <param> - <key>value</key> - <value>32000</value> - </param> - <param> - <key>_coordinate</key> - <value>(10, 170)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - </block> + <block> + <key>options</key> + <param> + <key>id</key> + <value>top_block</value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>samp_rate</value> + </param> + <param> + <key>value</key> + <value>32000</value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 170)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> </flow_graph> diff --git a/grc/python/expr_utils.py b/grc/python/expr_utils.py index 67580f6ffc..85f420f04c 100644 --- a/grc/python/expr_utils.py +++ b/grc/python/expr_utils.py @@ -21,157 +21,157 @@ import string VAR_CHARS = string.letters + string.digits + '_' class graph(object): - """ - Simple graph structure held in a dictionary. - """ + """ + Simple graph structure held in a dictionary. + """ - def __init__(self): self._graph = dict() + def __init__(self): self._graph = dict() - def __str__(self): return str(self._graph) + def __str__(self): return str(self._graph) - def add_node(self, node_key): - if self._graph.has_key(node_key): return - self._graph[node_key] = set() + def add_node(self, node_key): + if self._graph.has_key(node_key): return + self._graph[node_key] = set() - def remove_node(self, node_key): - if not self._graph.has_key(node_key): return - for edges in self._graph.values(): - if node_key in edges: edges.remove(node_key) - self._graph.pop(node_key) + def remove_node(self, node_key): + if not self._graph.has_key(node_key): return + for edges in self._graph.values(): + if node_key in edges: edges.remove(node_key) + self._graph.pop(node_key) - def add_edge(self, src_node_key, dest_node_key): - self._graph[src_node_key].add(dest_node_key) + def add_edge(self, src_node_key, dest_node_key): + self._graph[src_node_key].add(dest_node_key) - def remove_edge(self, src_node_key, dest_node_key): - self._graph[src_node_key].remove(dest_node_key) + def remove_edge(self, src_node_key, dest_node_key): + self._graph[src_node_key].remove(dest_node_key) - def get_nodes(self): return self._graph.keys() + def get_nodes(self): return self._graph.keys() - def get_edges(self, node_key): return self._graph[node_key] + def get_edges(self, node_key): return self._graph[node_key] def expr_split(expr): - """ - Split up an expression by non alphanumeric characters, including underscore. - Leave strings in-tact. - #TODO ignore escaped quotes, use raw strings. - - Args: - expr: an expression string - - Returns: - a list of string tokens that form expr - """ - toks = list() - tok = '' - quote = '' - for char in expr: - if quote or char in VAR_CHARS: - if char == quote: quote = '' - tok += char - elif char in ("'", '"'): - toks.append(tok) - tok = char - quote = char - else: - toks.append(tok) - toks.append(char) - tok = '' - toks.append(tok) - return filter(lambda t: t, toks) + """ + Split up an expression by non alphanumeric characters, including underscore. + Leave strings in-tact. + #TODO ignore escaped quotes, use raw strings. + + Args: + expr: an expression string + + Returns: + a list of string tokens that form expr + """ + toks = list() + tok = '' + quote = '' + for char in expr: + if quote or char in VAR_CHARS: + if char == quote: quote = '' + tok += char + elif char in ("'", '"'): + toks.append(tok) + tok = char + quote = char + else: + toks.append(tok) + toks.append(char) + tok = '' + toks.append(tok) + return filter(lambda t: t, toks) def expr_replace(expr, replace_dict): - """ - Search for vars in the expression and add the prepend. - - Args: - expr: an expression string - replace_dict: a dict of find:replace - - Returns: - a new expression with the prepend - """ - expr_splits = expr_split(expr) - for i, es in enumerate(expr_splits): - if es in replace_dict.keys(): - expr_splits[i] = replace_dict[es] - return ''.join(expr_splits) + """ + Search for vars in the expression and add the prepend. + + Args: + expr: an expression string + replace_dict: a dict of find:replace + + Returns: + a new expression with the prepend + """ + expr_splits = expr_split(expr) + for i, es in enumerate(expr_splits): + if es in replace_dict.keys(): + expr_splits[i] = replace_dict[es] + return ''.join(expr_splits) def get_variable_dependencies(expr, vars): - """ - Return a set of variables used in this expression. - - Args: - expr: an expression string - vars: a list of variable names - - Returns: - a subset of vars used in the expression - """ - expr_toks = expr_split(expr) - return set(filter(lambda v: v in expr_toks, vars)) + """ + Return a set of variables used in this expression. + + Args: + expr: an expression string + vars: a list of variable names + + Returns: + a subset of vars used in the expression + """ + expr_toks = expr_split(expr) + return set(filter(lambda v: v in expr_toks, vars)) def get_graph(exprs): - """ - Get a graph representing the variable dependencies - - Args: - exprs: a mapping of variable name to expression - - Returns: - a graph of variable deps - """ - vars = exprs.keys() - #get dependencies for each expression, load into graph - var_graph = graph() - for var in vars: var_graph.add_node(var) - for var, expr in exprs.iteritems(): - for dep in get_variable_dependencies(expr, vars): - if dep != var: var_graph.add_edge(dep, var) - return var_graph + """ + Get a graph representing the variable dependencies + + Args: + exprs: a mapping of variable name to expression + + Returns: + a graph of variable deps + """ + vars = exprs.keys() + #get dependencies for each expression, load into graph + var_graph = graph() + for var in vars: var_graph.add_node(var) + for var, expr in exprs.iteritems(): + for dep in get_variable_dependencies(expr, vars): + if dep != var: var_graph.add_edge(dep, var) + return var_graph def sort_variables(exprs): - """ - Get a list of variables in order of dependencies. - - Args: - exprs: a mapping of variable name to expression - - Returns: - a list of variable names - @throws Exception circular dependencies - """ - var_graph = get_graph(exprs) - sorted_vars = list() - #determine dependency order - while var_graph.get_nodes(): - #get a list of nodes with no edges - indep_vars = filter(lambda var: not var_graph.get_edges(var), var_graph.get_nodes()) - if not indep_vars: raise Exception('circular dependency caught in sort_variables') - #add the indep vars to the end of the list - sorted_vars.extend(sorted(indep_vars)) - #remove each edge-less node from the graph - for var in indep_vars: var_graph.remove_node(var) - return reversed(sorted_vars) + """ + Get a list of variables in order of dependencies. + + Args: + exprs: a mapping of variable name to expression + + Returns: + a list of variable names + @throws Exception circular dependencies + """ + var_graph = get_graph(exprs) + sorted_vars = list() + #determine dependency order + while var_graph.get_nodes(): + #get a list of nodes with no edges + indep_vars = filter(lambda var: not var_graph.get_edges(var), var_graph.get_nodes()) + if not indep_vars: raise Exception('circular dependency caught in sort_variables') + #add the indep vars to the end of the list + sorted_vars.extend(sorted(indep_vars)) + #remove each edge-less node from the graph + for var in indep_vars: var_graph.remove_node(var) + return reversed(sorted_vars) def sort_objects(objects, get_id, get_expr): - """ - Sort a list of objects according to their expressions. - - Args: - objects: the list of objects to sort - get_id: the function to extract an id from the object - get_expr: the function to extract an expression from the object - - Returns: - a list of sorted objects - """ - id2obj = dict([(get_id(obj), obj) for obj in objects]) - #map obj id to expression code - id2expr = dict([(get_id(obj), get_expr(obj)) for obj in objects]) - #sort according to dependency - sorted_ids = sort_variables(id2expr) - #return list of sorted objects - return [id2obj[id] for id in sorted_ids] + """ + Sort a list of objects according to their expressions. + + Args: + objects: the list of objects to sort + get_id: the function to extract an id from the object + get_expr: the function to extract an expression from the object + + Returns: + a list of sorted objects + """ + id2obj = dict([(get_id(obj), obj) for obj in objects]) + #map obj id to expression code + id2expr = dict([(get_id(obj), get_expr(obj)) for obj in objects]) + #sort according to dependency + sorted_ids = sort_variables(id2expr) + #return list of sorted objects + return [id2obj[id] for id in sorted_ids] if __name__ == '__main__': - for i in sort_variables({'x':'1', 'y':'x+1', 'a':'x+y', 'b':'y+1', 'c':'a+b+x+y'}): print i + for i in sort_variables({'x':'1', 'y':'x+1', 'a':'x+y', 'b':'y+1', 'c':'a+b+x+y'}): print i diff --git a/grc/python/extract_docs.py b/grc/python/extract_docs.py index 1d1c738dcc..b3b87e64ca 100644 --- a/grc/python/extract_docs.py +++ b/grc/python/extract_docs.py @@ -20,55 +20,55 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA import re def _extract(key): - """ - Extract the documentation from the python __doc__ strings. - If multiple modules match, combine the docs. - - Args: - key: the block key - - Returns: - a string with documentation - """ - #extract matches - try: - module_name, constructor_name = key.split('_', 1) - module = __import__('gnuradio.'+module_name) - module = getattr(module, module_name) - except ImportError: - try: - module_name, constructor_name = key.split('_', 1) - module = __import__(module_name) - except: return '' - except: - return '' - pattern = constructor_name.replace('_', '_*').replace('x', '\w') - pattern_matcher = re.compile('^%s\w*$'%pattern) - matches = filter(lambda x: pattern_matcher.match(x), dir(module)) - #combine all matches - doc_strs = list() - for match in matches: - try: - title = ' --- ' + match + ' --- ' - doc_strs.append('\n\n'.join([title, getattr(module, match).__doc__]).strip()) - except: pass - return '\n\n'.join(doc_strs) + """ + Extract the documentation from the python __doc__ strings. + If multiple modules match, combine the docs. + + Args: + key: the block key + + Returns: + a string with documentation + """ + #extract matches + try: + module_name, constructor_name = key.split('_', 1) + module = __import__('gnuradio.'+module_name) + module = getattr(module, module_name) + except ImportError: + try: + module_name, constructor_name = key.split('_', 1) + module = __import__(module_name) + except: return '' + except: + return '' + pattern = constructor_name.replace('_', '_*').replace('x', '\w') + pattern_matcher = re.compile('^%s\w*$'%pattern) + matches = filter(lambda x: pattern_matcher.match(x), dir(module)) + #combine all matches + doc_strs = list() + for match in matches: + try: + title = ' --- ' + match + ' --- ' + doc_strs.append('\n\n'.join([title, getattr(module, match).__doc__]).strip()) + except: pass + return '\n\n'.join(doc_strs) _docs_cache = dict() def extract(key): - """ - Call the private extract and cache the result. - - Args: - key: the block key - - Returns: - a string with documentation - """ - if not _docs_cache.has_key(key): - _docs_cache[key] = _extract(key) - return _docs_cache[key] + """ + Call the private extract and cache the result. + + Args: + key: the block key + + Returns: + a string with documentation + """ + if not _docs_cache.has_key(key): + _docs_cache[key] = _extract(key) + return _docs_cache[key] if __name__ == '__main__': - import sys - print extract(sys.argv[1]) + import sys + print extract(sys.argv[1]) diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index d104d4913d..550ecd78b5 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -13,7 +13,7 @@ ##@param var_id2cbs variable id map to callback strings ######################################################## #def indent($code) -#set $code = '\n\t\t'.join(str($code).splitlines()) +#set $code = '\n '.join(str($code).splitlines()) $code#slurp #end def #import time @@ -39,304 +39,304 @@ $imp ######################################################## ##Create Class -## Write the class declaration for a top or hier block. -## The parameter names are the arguments to __init__. -## Determine the absolute icon path (wx gui only). -## Setup the IO signature (hier block only). +## Write the class declaration for a top or hier block. +## The parameter names are the arguments to __init__. +## Determine the absolute icon path (wx gui only). +## Setup the IO signature (hier block only). ######################################################## #set $class_name = $flow_graph.get_option('id') #set $param_str = ', '.join(['self'] + ['%s=%s'%(param.get_id(), param.get_make()) for param in $parameters]) #if $generate_options == 'wx_gui' - #import gtk - #set $icon = gtk.IconTheme().lookup_icon('gnuradio-grc', 32, 0) + #import gtk + #set $icon = gtk.IconTheme().lookup_icon('gnuradio-grc', 32, 0) class $(class_name)(grc_wxgui.top_block_gui): - def __init__($param_str): - grc_wxgui.top_block_gui.__init__(self, title="$title") - #if $icon - _icon_path = "$icon.get_filename()" - self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY)) - #end if + def __init__($param_str): + grc_wxgui.top_block_gui.__init__(self, title="$title") + #if $icon + _icon_path = "$icon.get_filename()" + self.SetIcon(wx.Icon(_icon_path, wx.BITMAP_TYPE_ANY)) + #end if #elif $generate_options == 'qt_gui' class $(class_name)(gr.top_block, Qt.QWidget): - def __init__($param_str): - gr.top_block.__init__(self, "$title") - Qt.QWidget.__init__(self) - self.setWindowTitle("$title") - try: - self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) - except: - pass - self.top_scroll_layout = Qt.QVBoxLayout() - self.setLayout(self.top_scroll_layout) - self.top_scroll = Qt.QScrollArea() - self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) - self.top_scroll_layout.addWidget(self.top_scroll) - self.top_scroll.setWidgetResizable(True) - self.top_widget = Qt.QWidget() - self.top_scroll.setWidget(self.top_widget) - self.top_layout = Qt.QVBoxLayout(self.top_widget) - self.top_grid_layout = Qt.QGridLayout() - self.top_layout.addLayout(self.top_grid_layout) + def __init__($param_str): + gr.top_block.__init__(self, "$title") + Qt.QWidget.__init__(self) + self.setWindowTitle("$title") + try: + self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) + except: + pass + self.top_scroll_layout = Qt.QVBoxLayout() + self.setLayout(self.top_scroll_layout) + self.top_scroll = Qt.QScrollArea() + self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) + self.top_scroll_layout.addWidget(self.top_scroll) + self.top_scroll.setWidgetResizable(True) + self.top_widget = Qt.QWidget() + self.top_scroll.setWidget(self.top_widget) + self.top_layout = Qt.QVBoxLayout(self.top_widget) + self.top_grid_layout = Qt.QGridLayout() + self.top_layout.addLayout(self.top_grid_layout) - self.settings = Qt.QSettings("GNU Radio", "$class_name") - self.restoreGeometry(self.settings.value("geometry").toByteArray()) + self.settings = Qt.QSettings("GNU Radio", "$class_name") + self.restoreGeometry(self.settings.value("geometry").toByteArray()) #elif $generate_options == 'no_gui' class $(class_name)(gr.top_block): - def __init__($param_str): - gr.top_block.__init__(self, "$title") + def __init__($param_str): + gr.top_block.__init__(self, "$title") #elif $generate_options == 'hb' - #set $in_sigs = $flow_graph.get_io_signaturev('in') - #set $out_sigs = $flow_graph.get_io_signaturev('out') + #set $in_sigs = $flow_graph.get_io_signaturev('in') + #set $out_sigs = $flow_graph.get_io_signaturev('out') class $(class_name)(gr.hier_block2): #def make_io_sig($io_sigs) - #set $size_strs = ['%s*%s'%(io_sig['size'], io_sig['vlen']) for io_sig in $io_sigs] - #if len($io_sigs) == 0 + #set $size_strs = ['%s*%s'%(io_sig['size'], io_sig['vlen']) for io_sig in $io_sigs] + #if len($io_sigs) == 0 gr.io_signature(0, 0, 0)#slurp - #elif len($io_sigs) == 1 + #elif len($io_sigs) == 1 gr.io_signature(1, 1, $size_strs[0])#slurp - #else + #else gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])#slurp - #end if + #end if #end def - def __init__($param_str): - gr.hier_block2.__init__( - self, "$title", - $make_io_sig($in_sigs), - $make_io_sig($out_sigs), - ) + def __init__($param_str): + gr.hier_block2.__init__( + self, "$title", + $make_io_sig($in_sigs), + $make_io_sig($out_sigs), + ) #end if ######################################################## ##Create Parameters -## Set the parameter to a property of self. +## Set the parameter to a property of self. ######################################################## #if $parameters - $DIVIDER - # Parameters - $DIVIDER + $DIVIDER + # Parameters + $DIVIDER #end if #for $param in $parameters - $indent($param.get_var_make()) + $indent($param.get_var_make()) #end for ######################################################## ##Create Variables ######################################################## #if $variables - $DIVIDER - # Variables - $DIVIDER + $DIVIDER + # Variables + $DIVIDER #end if #for $var in $variables - $indent($var.get_var_make()) + $indent($var.get_var_make()) #end for ######################################################## ##Create Message Queues ######################################################## #if $messages - $DIVIDER - # Message Queues - $DIVIDER + $DIVIDER + # Message Queues + $DIVIDER #end if #for $msg in $messages - $(msg.get_source().get_parent().get_id())_msgq_out = $(msg.get_sink().get_parent().get_id())_msgq_in = gr.msg_queue(2) + $(msg.get_source().get_parent().get_id())_msgq_out = $(msg.get_sink().get_parent().get_id())_msgq_in = gr.msg_queue(2) #end for ######################################################## ##Create Blocks ######################################################## #if $blocks - $DIVIDER - # Blocks - $DIVIDER + $DIVIDER + # Blocks + $DIVIDER #end if #for $blk in filter(lambda b: b.get_make(), $blocks) - #if $blk in $variables - $indent($blk.get_make()) - #else - self.$blk.get_id() = $indent($blk.get_make()) - #end if + #if $blk in $variables + $indent($blk.get_make()) + #else + self.$blk.get_id() = $indent($blk.get_make()) + #end if #end for ######################################################## ##Create Connections -## The port name should be the id of the parent block. -## However, port names for IO pads should be self. +## The port name should be the id of the parent block. +## However, port names for IO pads should be self. ######################################################## #def make_port_sig($port) - #if $port.get_parent().get_key() == 'pad_source' + #if $port.get_parent().get_key() == 'pad_source' (self, $flow_graph.get_pad_sources().index($port.get_parent()))#slurp - #elif $port.get_parent().get_key() == 'pad_sink' + #elif $port.get_parent().get_key() == 'pad_sink' (self, $flow_graph.get_pad_sinks().index($port.get_parent()))#slurp - #else + #else (self.$port.get_parent().get_id(), $port.get_key())#slurp - #end if + #end if #end def #if $connections - $DIVIDER - # Connections - $DIVIDER + $DIVIDER + # Connections + $DIVIDER #end if #for $con in $connections - #set $source = $con.get_source() - #set $sink = $con.get_sink() - ##resolve virtual sources to the actual sources - #if $source.get_parent().is_virtual_source() - #set $source = $source.resolve_virtual_source() - #end if - ##do not generate connections with virtual sinks - #if not $sink.get_parent().is_virtual_sink() - self.connect($make_port_sig($source), $make_port_sig($sink)) - #end if + #set $source = $con.get_source() + #set $sink = $con.get_sink() + ##resolve virtual sources to the actual sources + #if $source.get_parent().is_virtual_source() + #set $source = $source.resolve_virtual_source() + #end if + ##do not generate connections with virtual sinks + #if not $sink.get_parent().is_virtual_sink() + self.connect($make_port_sig($source), $make_port_sig($sink)) + #end if #end for ######################################################## ##Create Asynch Message Connections ######################################################## #if $messages2 - $DIVIDER - # Asynch Message Connections - $DIVIDER + $DIVIDER + # Asynch Message Connections + $DIVIDER #end if #for $msg in $messages2 - #set $sr = $msg.get_source() - #set $source = "self.%s"%($sr.get_parent().get_id()) - #set $source_port = $sr.get_name(); - #if $sr.get_parent().get_key() == "pad_source" - #set $source = "self" - #set $source_port = $sr.get_parent().get_param("label").get_value(); - #end if - #set $sk = $msg.get_sink() - #set $sink = "self.%s"%($sk.get_parent().get_id()) - #set $sink_port = $sk.get_name(); - #if $sk.get_parent().get_key() == "pad_sink" - #set $sink = "self" - #set $sink_port = $sk.get_parent().get_param("label").get_value(); - #end if - self.msg_connect($source, "$source_port", $sink, "$sink_port") + #set $sr = $msg.get_source() + #set $source = "self.%s"%($sr.get_parent().get_id()) + #set $source_port = $sr.get_name(); + #if $sr.get_parent().get_key() == "pad_source" + #set $source = "self" + #set $source_port = $sr.get_parent().get_param("label").get_value(); + #end if + #set $sk = $msg.get_sink() + #set $sink = "self.%s"%($sk.get_parent().get_id()) + #set $sink_port = $sk.get_name(); + #if $sk.get_parent().get_key() == "pad_sink" + #set $sink = "self" + #set $sink_port = $sk.get_parent().get_param("label").get_value(); + #end if + self.msg_connect($source, "$source_port", $sink, "$sink_port") #end for ######################################################## # QT sink close method reimplementation ######################################################## #if $generate_options == 'qt_gui' - def closeEvent(self, event): - self.settings = Qt.QSettings("GNU Radio", "$class_name") - self.settings.setValue("geometry", self.saveGeometry()) - event.accept() + def closeEvent(self, event): + self.settings = Qt.QSettings("GNU Radio", "$class_name") + self.settings.setValue("geometry", self.saveGeometry()) + event.accept() #end if ######################################################## ##Create Callbacks -## Write a set method for this variable that calls the callbacks +## Write a set method for this variable that calls the callbacks ######################################################## #for $var in $parameters + $variables - #set $id = $var.get_id() - def get_$(id)(self): - return self.$id + #set $id = $var.get_id() + def get_$(id)(self): + return self.$id - def set_$(id)(self, $id): - self.$id = $id - #for $callback in $var_id2cbs[$id] - $indent($callback) - #end for + def set_$(id)(self, $id): + self.$id = $id + #for $callback in $var_id2cbs[$id] + $indent($callback) + #end for #end for ######################################################## ##Create Main -## For top block code, generate a main routine. -## Instantiate the top block and run as gui or cli. +## For top block code, generate a main routine. +## Instantiate the top block and run as gui or cli. ######################################################## #def make_default($type, $param) - #if $type == 'eng_float' + #if $type == 'eng_float' eng_notation.num_to_str($param.get_make())#slurp - #else + #else $param.get_make()#slurp - #end if + #end if #end def #def make_short_id($param) - #set $short_id = $param.get_param('short_id').get_evaluated() - #if $short_id - #set $short_id = '-' + $short_id - #end if + #set $short_id = $param.get_param('short_id').get_evaluated() + #if $short_id + #set $short_id = '-' + $short_id + #end if $short_id#slurp #end def #if $generate_options != 'hb' if __name__ == '__main__': - parser = OptionParser(option_class=eng_option, usage="%prog: [options]") - #set $params_eq_list = list() - #for $param in $parameters - #set $type = $param.get_param('type').get_value() - #if $type - #silent $params_eq_list.append('%s=options.%s'%($param.get_id(), $param.get_id())) - parser.add_option("$make_short_id($param)", "--$param.get_id().replace('_', '-')", dest="$param.get_id()", type="$type", default=$make_default($type, $param), - help="Set $($param.get_param('label').get_evaluated() or $param.get_id()) [default=%default]") - #end if - #end for - (options, args) = parser.parse_args() - #if $flow_graph.get_option('realtime_scheduling') - if gr.enable_realtime_scheduling() != gr.RT_OK: - print "Error: failed to enable realtime scheduling." - #end if - #if $generate_options == 'wx_gui' - tb = $(class_name)($(', '.join($params_eq_list))) - #if $flow_graph.get_option('max_nouts') - tb.Run($flow_graph.get_option('run'), $flow_graph.get_option('max_nouts')) - #else - tb.Start($flow_graph.get_option('run')) + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + #set $params_eq_list = list() + #for $param in $parameters + #set $type = $param.get_param('type').get_value() + #if $type + #silent $params_eq_list.append('%s=options.%s'%($param.get_id(), $param.get_id())) + parser.add_option("$make_short_id($param)", "--$param.get_id().replace('_', '-')", dest="$param.get_id()", type="$type", default=$make_default($type, $param), + help="Set $($param.get_param('label').get_evaluated() or $param.get_id()) [default=%default]") + #end if + #end for + (options, args) = parser.parse_args() + #if $flow_graph.get_option('realtime_scheduling') + if gr.enable_realtime_scheduling() != gr.RT_OK: + print "Error: failed to enable realtime scheduling." + #end if + #if $generate_options == 'wx_gui' + tb = $(class_name)($(', '.join($params_eq_list))) + #if $flow_graph.get_option('max_nouts') + tb.Run($flow_graph.get_option('run'), $flow_graph.get_option('max_nouts')) + #else + tb.Start($flow_graph.get_option('run')) #for $m in $monitors - (tb.$m.get_id()).start() + (tb.$m.get_id()).start() #end for - tb.Wait() - #end if - #elif $generate_options == 'qt_gui' - qapp = Qt.QApplication(sys.argv) - tb = $(class_name)($(', '.join($params_eq_list))) - #if $flow_graph.get_option('run') - #if $flow_graph.get_option('max_nouts') - tb.start($flow_graph.get_option('max_nouts')) - #else - tb.start() - #end if - #end if - tb.show() + tb.Wait() + #end if + #elif $generate_options == 'qt_gui' + qapp = Qt.QApplication(sys.argv) + tb = $(class_name)($(', '.join($params_eq_list))) + #if $flow_graph.get_option('run') + #if $flow_graph.get_option('max_nouts') + tb.start($flow_graph.get_option('max_nouts')) + #else + tb.start() + #end if + #end if + tb.show() #for $m in $monitors - (tb.$m.get_id()).start() + (tb.$m.get_id()).start() #end for - qapp.exec_() - tb.stop() - tb = None #to clean up Qt widgets - #elif $generate_options == 'no_gui' - tb = $(class_name)($(', '.join($params_eq_list))) - #set $run_options = $flow_graph.get_option('run_options') - #if $run_options == 'prompt' - #if $flow_graph.get_option('max_nouts') - tb.start($flow_graph.get_option('max_nouts')) - #else - tb.start() - #end if + qapp.exec_() + tb.stop() + tb = None #to clean up Qt widgets + #elif $generate_options == 'no_gui' + tb = $(class_name)($(', '.join($params_eq_list))) + #set $run_options = $flow_graph.get_option('run_options') + #if $run_options == 'prompt' + #if $flow_graph.get_option('max_nouts') + tb.start($flow_graph.get_option('max_nouts')) + #else + tb.start() + #end if #for $m in $monitors - (tb.$m.get_id()).start() + (tb.$m.get_id()).start() #end for - raw_input('Press Enter to quit: ') - tb.stop() - #elif $run_options == 'run' - #if $flow_graph.get_option('max_nouts') - tb.start($flow_graph.get_option('max_nouts')) - #else - tb.start() - #end if - #end if + raw_input('Press Enter to quit: ') + tb.stop() + #elif $run_options == 'run' + #if $flow_graph.get_option('max_nouts') + tb.start($flow_graph.get_option('max_nouts')) + #else + tb.start() + #end if + #end if #for $m in $monitors - (tb.$m.get_id()).start() + (tb.$m.get_id()).start() #end for - tb.wait() - #end if + tb.wait() + #end if #end if |