简体   繁体   English

用源代码注释字符串中的 Python 函数调用

[英]Comment Python function calls in a string with source code

I'm trying to comment function calls from a Python source code.我正在尝试注释来自 Python 源代码的函数调用。

I read the source code in a string, and then I'm trying to apply some regex to to comment method calls.我阅读了一个字符串中的源代码,然后我尝试将一些正则表达式应用于注释方法调用。

Here is an simple example working:这是一个简单的工作示例:

s = open(path, 'r').read()
# comment method calls
result = re.sub('(^[.\w]+\(.*\))', r'#\1', s, flags=re.MULTILINE)

As you can see, I'm commenting functions in the first indentation level of the source(code outside __name__ == '__main__' , methods, and classes)如您所见,我在源代码的第一个缩进级别中注释函数( __name__ == '__main__'之外的代码、方法和类)

But, how can I make this regex work with multiple line calls?但是,如何使这个正则表达式适用于多行调用?

Example, if I have the following code into string:例如,如果我将以下代码转换为字符串:

Builder.load_string('''
    type: 'example'
    callback: my_callback()
''')

How can I comment each line of this call?我如何评论这个电话的每一行?

This will give you the line numbers you need to comment:这将为您提供您需要评论的行号:

mod = "test1"
mod = importlib.import_module(mod)
p = ast.parse(inspect.getsource(mod))


for n in p.body:
    if isinstance(n, ast.Expr):
        for node in ast.walk(n):
            if isinstance(node, ast.Call):
                print(node.lineno)

For a file like:对于像这样的文件:

import math

class Foo:
    def __init__(self):
        self.foo = 4
    def bar(self):
        print("hello world")

    def foo(self):
        return self.bar()

def bar():
    return 123

f = Foo()    
f.bar()    
bar()

It will output 16 and 18 the two calls.它会输出1618这两个调用。

It is just a matter of ignoring those lines and writing the new source or doing whatever you want with the updates content:只需忽略这些行并编写新源或对更新内容做任何您想做的事情:

import inspect
import importlib
import ast

def get_call_lines(mod):
    mod = importlib.import_module(mod)
    p = ast.parse(inspect.getsource(mod))
    for n in p.body:
        if isinstance(n, ast.Expr):
            for node in ast.walk(n):
                if isinstance(node, ast.Call):
                    yield(node.lineno)


from StringIO import StringIO
new = StringIO()
with open("test1.py") as f:
    st = set(get_call_lines("test1"))
    for ind, line in enumerate(f, 1):
        if ind not in st:
            new.write(line)

new.seek(0)
print(new.read())

new will contain:新将包含:

import math
class Foo:
    def __init__(self):
        self.foo = 4
    def bar(self):
        print("hello world")

    def foo(self):
        return self.bar()

def bar():
    return 123

f = Foo()

You could change the code at runtime with ast.NodeTransformer but it is not such a trivial task to remove nodes, the simplest approach for what you want would be to simply ignore the Call lines in the body您可以在运行时使用ast.NodeTransformer更改代码,但删除节点并不是一项微不足道的任务,您想要的最简单的方法是简单地忽略正文中的 Call 行

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM