| 
									
										
										
										
											2001-04-09 04:28:48 +00:00
										 |  |  | """Parser for future statements
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from compiler import ast, walk | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def is_future(stmt): | 
					
						
							|  |  |  |     """Return true if statement is a well-formed future statement""" | 
					
						
							|  |  |  |     if not isinstance(stmt, ast.From): | 
					
						
							|  |  |  |         return 0 | 
					
						
							|  |  |  |     if stmt.modname == "__future__": | 
					
						
							|  |  |  |         return 1 | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FutureParser: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-18 00:07:46 +00:00
										 |  |  |     features = ("nested_scopes", "generators", "division") | 
					
						
							| 
									
										
										
										
											2001-04-09 04:28:48 +00:00
										 |  |  |      | 
					
						
							|  |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.found = {} # set | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitModule(self, node): | 
					
						
							|  |  |  |         stmt = node.node | 
					
						
							| 
									
										
										
										
											2001-08-18 00:07:46 +00:00
										 |  |  |         for s in stmt.nodes: | 
					
						
							| 
									
										
										
										
											2001-04-09 04:28:48 +00:00
										 |  |  |             if not self.check_stmt(s): | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def check_stmt(self, stmt): | 
					
						
							|  |  |  |         if is_future(stmt): | 
					
						
							|  |  |  |             for name, asname in stmt.names: | 
					
						
							|  |  |  |                 if name in self.features: | 
					
						
							|  |  |  |                     self.found[name] = 1 | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     raise SyntaxError, \ | 
					
						
							|  |  |  |                           "future feature %s is not defined" % name | 
					
						
							|  |  |  |             stmt.valid_future = 1 | 
					
						
							|  |  |  |             return 1 | 
					
						
							|  |  |  |         return 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_features(self): | 
					
						
							|  |  |  |         """Return list of features enabled by future statements""" | 
					
						
							|  |  |  |         return self.found.keys() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BadFutureParser: | 
					
						
							|  |  |  |     """Check for invalid future statements""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def visitFrom(self, node): | 
					
						
							|  |  |  |         if hasattr(node, 'valid_future'): | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         if node.modname != "__future__": | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         raise SyntaxError, "invalid future statement" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def find_futures(node): | 
					
						
							|  |  |  |     p1 = FutureParser() | 
					
						
							|  |  |  |     p2 = BadFutureParser() | 
					
						
							|  |  |  |     walk(node, p1) | 
					
						
							|  |  |  |     walk(node, p2) | 
					
						
							|  |  |  |     return p1.get_features() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     import sys | 
					
						
							|  |  |  |     from compiler import parseFile, walk | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for file in sys.argv[1:]: | 
					
						
							|  |  |  |         print file | 
					
						
							|  |  |  |         tree = parseFile(file) | 
					
						
							|  |  |  |         v = FutureParser() | 
					
						
							|  |  |  |         walk(tree, v) | 
					
						
							|  |  |  |         print v.found | 
					
						
							|  |  |  |         print | 
					
						
							|  |  |  | 
 |