From 74eb0b9a9a685a32be21db30f097a22ddf3ec4cf Mon Sep 17 00:00:00 2001
From: Tim O'Shea <tim.oshea753@gmail.com>
Date: Mon, 8 Jul 2013 10:29:19 -0400
Subject: grc: Fix whitespace issue in grc to use proper spaces

Remove all \t's to match the rest of GNU Radio
---
 grc/python/Block.py               | 376 +++++++++---------
 grc/python/Connection.py          |  47 ++-
 grc/python/Constants.py           |  60 +--
 grc/python/FlowGraph.py           | 419 +++++++++-----------
 grc/python/Generator.py           | 236 +++++------
 grc/python/Param.py               | 810 +++++++++++++++++++-------------------
 grc/python/Platform.py            |  66 ++--
 grc/python/Port.py                | 388 +++++++++---------
 grc/python/block.dtd              |  16 +-
 grc/python/convert_hier.py        | 172 ++++----
 grc/python/default_flow_graph.grc |  70 ++--
 grc/python/expr_utils.py          | 264 ++++++-------
 grc/python/extract_docs.py        |  94 ++---
 grc/python/flow_graph.tmpl        | 380 +++++++++---------
 14 files changed, 1668 insertions(+), 1730 deletions(-)

(limited to 'grc/python')

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
 
-- 
cgit v1.2.3