[英]Given a reference to function, produce it's source code without annotations in the signature
应保留默认值。
装饰器也应该被移除,但这不是一个问题。
原始来源:
# Comments
@decorator1
@decorator2(
a=1,
b=1,
)
def my_func(
a: typing.List = 14,
b: 'CustomType' = None,
c: Whatever('foo') = 42,
d: Whatever('foo') = some_function,
) -> typing.NamedTuple(
'Dummy',
[
('r1': 'CustomType'),
('21': 'CustomType2'),
]
):
...
所需来源:
def my_func(
a = 14,
b = None,
c = 42,
d = some_function,
):
...
我可以使用inspect.getsource(my_func)
获取源代码,但我需要去除注释。 我怎样才能做到这一点? 最好使用标准模块。
您可以使用ast.parse
将源解析为 AST,如果它是arg
节点,则使用ast.walk
遍历树以使annotation
无效,如果它是FunctionDef
节点,则使returns
和decorator_list
无效。 使用astunparse
将树解解析回源代码:
import inspect
import ast
import typing
import astunparse
from unittest.mock import patch
@patch('builtins.print')
def my_func(
a: int = 1,
b: typing.List = []
) -> bool:
pass
tree = ast.parse(inspect.getsource(my_func), '', 'exec')
for node in ast.walk(tree):
if isinstance(node, ast.arg):
node.annotation = None
elif isinstance(node, ast.FunctionDef):
node.returns = None
node.decorator_list = []
print(astunparse.unparse(tree))
这输出:
def my_func(a=1, b=[]):
pass
您可以将 lib2to3.refactor.RefactoringTool 子类化以使用作为lib2to3.refactor.RefactoringTool
子类的修复程序重构代码,该lib2to3.fixer_base.BaseFix
具有查找类型化参数、带有注释返回值的 function 声明或修饰定义的模式,以及从子节点中删除注释和装饰器索引的transform
方法:
from lib2to3 import fixer_base, refactor
class FixParameterAnnotations(fixer_base.BaseFix):
PATTERN = "name=tname | func=funcdef< any+ '->' any+ > | decorated"
def transform(self, node, results):
if 'name' in results:
del node.children[1:] # delete annotation to typed argument
elif 'func' in results:
del node.children[-4:-2] # delete annotation to function declaration
else:
del node.children[0] # delete decorators
return node
class Refactor(refactor.RefactoringTool):
def __init__(self, fixers):
self._fixers= [cls(None, None) for cls in fixers]
super().__init__(None)
def get_fixers(self):
return self._fixers, []
以便:
import inspect
import typing
from unittest.mock import patch
@patch('builtins.print')
def my_func(
a: int = 1, # some comment
b: typing.List = [] # more comment
) -> bool:
''' some docstring'''
pass
print(Refactor([FixParameterAnnotations]).refactor_string(inspect.getsource(my_func), ''))
输出:
def my_func(
a = 1, # some comment
b = [] # more comment
):
''' some docstring'''
pass
演示: https://repl.it/@blhsing/BrightWhirlwindBoolean
lib2to3
是往返稳定的,因此在转换后会保留所有注释和空格。 您可以在lib2to3
模块的Grammar.txt
中找到 Python 语法的定义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.