mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Generate docstrings.
Fixes SF buf #217004 Add method fixDocstring() to CodeGenerator. It converts the Discard node containing the docstring into an assignment to __doc__.
This commit is contained in:
		
							parent
							
								
									4c1f42733c
								
							
						
					
					
						commit
						9ab019bee7
					
				
					 2 changed files with 52 additions and 6 deletions
				
			
		|  | @ -141,13 +141,16 @@ def set_lineno(self, node): | |||
|     def visitModule(self, node): | ||||
|         lnf = walk(node.node, LocalNameFinder(), 0) | ||||
|         self.locals.push(lnf.getLocals()) | ||||
|         self.setDocstring(node.doc) | ||||
|         if node.doc: | ||||
|             self.fixDocstring(node.node) | ||||
|         self.visit(node.node) | ||||
|         self.emit('LOAD_CONST', None) | ||||
|         self.emit('RETURN_VALUE') | ||||
| 
 | ||||
|     def visitFunction(self, node): | ||||
|         self._visitFuncOrLambda(node, isLambda=0) | ||||
|         if node.doc: | ||||
|             self.setDocstring(node.doc) | ||||
|         self.storeName(node.name) | ||||
| 
 | ||||
|     def visitLambda(self, node): | ||||
|  | @ -165,6 +168,8 @@ def _visitFuncOrLambda(self, node, isLambda): | |||
| 
 | ||||
|     def visitClass(self, node): | ||||
|         gen = ClassCodeGenerator(node, self.filename) | ||||
|         if node.doc: | ||||
|             self.fixDocstring(node.code) | ||||
|         walk(node.code, gen) | ||||
|         gen.finish() | ||||
|         self.set_lineno(node) | ||||
|  | @ -178,6 +183,19 @@ def visitClass(self, node): | |||
|         self.emit('BUILD_CLASS') | ||||
|         self.storeName(node.name) | ||||
| 
 | ||||
|     def fixDocstring(self, node): | ||||
|         """Rewrite the ast for a class with a docstring. | ||||
| 
 | ||||
|         The AST includes a Discard(Const(docstring)) node.  Replace | ||||
|         this with an Assign([AssName('__doc__', ...]) | ||||
|         """ | ||||
|         assert isinstance(node, ast.Stmt) | ||||
|         stmts = node.nodes | ||||
|         discard = stmts[0] | ||||
|         assert isinstance(discard, ast.Discard) | ||||
|         stmts[0] = ast.Assign([ast.AssName('__doc__', 'OP_ASSIGN')], | ||||
|                               discard.expr) | ||||
|         stmts[0].lineno = discard.lineno | ||||
|     # The rest are standard visitor methods | ||||
| 
 | ||||
|     # The next few implement control-flow statements | ||||
|  | @ -627,7 +645,7 @@ def visitAugGetattr(self, node, mode): | |||
| 
 | ||||
|     def visitAugSlice(self, node, mode): | ||||
|         if mode == "load": | ||||
|             self.visitSlice(node, 1) | ||||
|             self.visitlSice(node, 1) | ||||
|         elif mode == "store": | ||||
|             slice = 0 | ||||
|             if node.lower: | ||||
|  | @ -900,6 +918,9 @@ def __init__(self, func, filename, isLambda=0): | |||
|         self.isLambda = isLambda | ||||
|         self.super_init(filename) | ||||
| 
 | ||||
|         if not isLambda and func.doc: | ||||
|             self.setDocstring(func.doc) | ||||
| 
 | ||||
|         lnf = walk(func.code, LocalNameFinder(args), 0) | ||||
|         self.locals.push(lnf.getLocals()) | ||||
|         if func.varargs: | ||||
|  | @ -947,6 +968,8 @@ def __init__(self, klass, filename): | |||
|         lnf = walk(klass.code, LocalNameFinder(), 0) | ||||
|         self.locals.push(lnf.getLocals()) | ||||
|         self.graph.setFlag(CO_NEWLOCALS) | ||||
|         if klass.doc: | ||||
|             self.setDocstring(klass.doc) | ||||
| 
 | ||||
|     def finish(self): | ||||
|         self.graph.startExitBlock() | ||||
|  |  | |||
|  | @ -141,13 +141,16 @@ def set_lineno(self, node): | |||
|     def visitModule(self, node): | ||||
|         lnf = walk(node.node, LocalNameFinder(), 0) | ||||
|         self.locals.push(lnf.getLocals()) | ||||
|         self.setDocstring(node.doc) | ||||
|         if node.doc: | ||||
|             self.fixDocstring(node.node) | ||||
|         self.visit(node.node) | ||||
|         self.emit('LOAD_CONST', None) | ||||
|         self.emit('RETURN_VALUE') | ||||
| 
 | ||||
|     def visitFunction(self, node): | ||||
|         self._visitFuncOrLambda(node, isLambda=0) | ||||
|         if node.doc: | ||||
|             self.setDocstring(node.doc) | ||||
|         self.storeName(node.name) | ||||
| 
 | ||||
|     def visitLambda(self, node): | ||||
|  | @ -165,6 +168,8 @@ def _visitFuncOrLambda(self, node, isLambda): | |||
| 
 | ||||
|     def visitClass(self, node): | ||||
|         gen = ClassCodeGenerator(node, self.filename) | ||||
|         if node.doc: | ||||
|             self.fixDocstring(node.code) | ||||
|         walk(node.code, gen) | ||||
|         gen.finish() | ||||
|         self.set_lineno(node) | ||||
|  | @ -178,6 +183,19 @@ def visitClass(self, node): | |||
|         self.emit('BUILD_CLASS') | ||||
|         self.storeName(node.name) | ||||
| 
 | ||||
|     def fixDocstring(self, node): | ||||
|         """Rewrite the ast for a class with a docstring. | ||||
| 
 | ||||
|         The AST includes a Discard(Const(docstring)) node.  Replace | ||||
|         this with an Assign([AssName('__doc__', ...]) | ||||
|         """ | ||||
|         assert isinstance(node, ast.Stmt) | ||||
|         stmts = node.nodes | ||||
|         discard = stmts[0] | ||||
|         assert isinstance(discard, ast.Discard) | ||||
|         stmts[0] = ast.Assign([ast.AssName('__doc__', 'OP_ASSIGN')], | ||||
|                               discard.expr) | ||||
|         stmts[0].lineno = discard.lineno | ||||
|     # The rest are standard visitor methods | ||||
| 
 | ||||
|     # The next few implement control-flow statements | ||||
|  | @ -627,7 +645,7 @@ def visitAugGetattr(self, node, mode): | |||
| 
 | ||||
|     def visitAugSlice(self, node, mode): | ||||
|         if mode == "load": | ||||
|             self.visitSlice(node, 1) | ||||
|             self.visitlSice(node, 1) | ||||
|         elif mode == "store": | ||||
|             slice = 0 | ||||
|             if node.lower: | ||||
|  | @ -900,6 +918,9 @@ def __init__(self, func, filename, isLambda=0): | |||
|         self.isLambda = isLambda | ||||
|         self.super_init(filename) | ||||
| 
 | ||||
|         if not isLambda and func.doc: | ||||
|             self.setDocstring(func.doc) | ||||
| 
 | ||||
|         lnf = walk(func.code, LocalNameFinder(args), 0) | ||||
|         self.locals.push(lnf.getLocals()) | ||||
|         if func.varargs: | ||||
|  | @ -947,6 +968,8 @@ def __init__(self, klass, filename): | |||
|         lnf = walk(klass.code, LocalNameFinder(), 0) | ||||
|         self.locals.push(lnf.getLocals()) | ||||
|         self.graph.setFlag(CO_NEWLOCALS) | ||||
|         if klass.doc: | ||||
|             self.setDocstring(klass.doc) | ||||
| 
 | ||||
|     def finish(self): | ||||
|         self.graph.startExitBlock() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeremy Hylton
						Jeremy Hylton