简体   繁体   English

在 python 文件中插入文档字符串属性

[英]Insert docstring attributes in a python file

We are using napolean style docstring for python modules.我们正在为 python 模块使用拿破仑风格的文档字符串。 But there is a need to auto populate additional attributes in the docstring called Data Owner and DAL Owner so that the given function looks like this:但是需要在名为Data OwnerDAL Owner的文档字符串中自动填充附加属性,以便给定的函数如下所示:

def func(self, arg1=None, arg2=None):
"""
Returns the timeseries for the specified arg1 and arg2.
Args:
    arg1: argument 1
    arg2: argument 2
Returns:
    DataFrame containing timeseries of arg1 for arg2.

DAL Owner: Team IT
Data Owner: Team A
"""

These additional attributes and their values for a given function are provided in a separate csv file.给定函数的这些附加属性及其值在单独的 csv 文件中提供。 The way I was thinking was to have a script (awk, sed?) that will我的想法是有一个脚本(awk,sed?)

  • extract all the function names in a given python file.提取给定 python 文件中的所有函数名称。 Can easily do it in python可以在python中轻松完成
  • for those function names, check if the owners exist in the csv file and if so create a mapping of the function name and owners.对于这些函数名称,请检查 csv 文件中是否存在所有者,如果存在,则创建函数名称和所有者的映射。 Doable可行

Now, this is the part which I havent figured out and dont know the best way forward.现在,这是我还没有弄清楚并且不知道最好的前进方式的部分。 For a given function name and owners, I need to go back into the python file and add the owners to the docstring if it exists.对于给定的函数名称和所有者,我需要返回 python 文件并将所有者添加到文档字符串(如果存在)。 I am thinking some sort of awk script but not quite sure我在想某种 awk 脚本,但不太确定

  • Find the function that matches the pattern找到与模式匹配的函数
  • For that pattern, see if doctsring exists, triple quotation marks after closing parenthesis对于那个模式,看看doctsring是否存在,右括号后加三引号
  • If docstring exists, add additional two lines for the owners before the closing triple quotation如果 docstring 存在,则在结束三重引号之前为所有者添加额外的两行
  • If docstring does not exists, then insert the two lines for owners between tripe quotations on the line after function declaration.如果 docstring 不存在,则在函数声明后的行上的三边形引号之间插入所有者的两行。

I know this is a lot of steps but can anyone provide insight with the previous 4 bullet points to insert the additional attributes to docstring given the function, attributes and the python file.我知道这是很多步骤,但任何人都可以提供前 4 个要点的见解,以在给定函数、属性和 python 文件的情况下将附加属性插入到文档字符串中。 Will a linux utility like sed, awk be more useful or should I go the python route.像 sed、awk 这样的 linux 实用程序会更有用还是我应该走 python 路线。 Is there some other option that's easier to implement.有没有其他更容易实现的选项。

The process for assigning a new docstring in an ast is:在 ast 中分配新文档字符串的过程是:

  1. Get the existing docstring using ast.get_docstring使用ast.get_docstring获取现有的文档字符串
  2. Create a new ast node with amended content使用修改后的内容创建一个新的 ast 节点
  3. If the existing dostring is None , insert the new node at the start of the parent node's body如果现有的 dostring 是None ,则在父节点主体的开头插入新节点
  4. If there was an existing docstring, replace it's node with the new node如果存在现有的文档字符串,请将其节点替换为新节点
  5. Use the unparse * tool from Cpython Tools to generate the new source (you may need to download this from github - ensure you get the version that matches your python version)使用 Cpython Tools 中的unparse *工具生成新源(您可能需要从 github 下载它 - 确保获得与您的 python 版本匹配的版本)

Here's some example code:下面是一些示例代码:

$  cat fixdocstrings.py                            
import ast                                                                               
import io
from unparse import Unparser


class DocstringWriter(ast.NodeTransformer):
    def visit_FunctionDef(self, node):
        docstring = ast.get_docstring(node)
        new_docstring_node = make_docstring_node(docstring)
        if docstring:
            # Assumes the existing docstring is the first node 
            # in the function body.
            node.body[0] = new_docstring_node
        else:
            node.body.insert(0, new_docstring_node)
        return node


def make_docstring_node(docstring):
    if docstring is None:
        content = "A new docstring"
    else:
        content = docstring + " -- amended"
    s = ast.Str(content)
    return ast.Expr(value=s)


if __name__ == "__main__":
    tree = ast.parse(open("docstringtest.py").read())
    transformer = DocstringWriter()
    new_tree = transformer.visit(tree)
    ast.fix_missing_locations(new_tree)
    buf = io.StringIO()
    Unparser(new_tree, buf)
    buf.seek(0)
    print(buf.read())

$  cat docstringtest.py 
def foo():
    pass


def bar():
    """A docstring."""

$  python fixdocstrings.py 


def foo():
    'A new docstring'
    pass

def bar():
    'A docstring. -- amended'

(I answered something similar for myself for python2.7, here ) (我在此处为 python2.7 为自己回答了类似的问题

* As of Python 3.9, the ast module provides an unparse function that can be used instead of the unparse tool: src = ast.unparse(new_tree) *从 Python 3.9 开始,ast 模块提供了一个可以用来代替unparse工具的unparse函数: src = ast.unparse(new_tree)

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

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