从Python代码中提取“额外”docstrings?

问题描述:

紧跟在类或函数声明之后的Python docstrings被放置在__doc__属性中。从Python代码中提取“额外”docstrings?

问题:如何提取一个函数中稍后出现的额外“内部”文档字符串?

更新:这样的文字语句被编译器忽略。我可以通过AST获得他们(和他们的行号)吗?


为什么要问?

我有一个(不完全成熟)主意,用这样的“内部”文档字符串划定鉴于/时/然后敏捷方案的部分:

def test_adding(): 
    """Scenario: Adding two numbers""" 
    adder = Adder() 
    """When I add 2 and 3""" 
    result = adder.add(2, 3) 
    """Then the result is 5""" 
    assert result == 5 

通过提取文档字符串,所述测试运行框架能够产生输出是这样的:

Scenario: Adding two numbers 
    When I add 2 and 3 (PASS) 
    Then the result is 5 (FAIL) 

AssertionError Traceback 
... 

我认为这将是比Behave采取FreshenLettucePyCukes的方法,这需要定义一个组合通道更简洁吃了每一步的功能。我不喜欢重复步骤的文本作为函数名称(@When("I add numbers") def add_numbers())。但是与普通的单元测试不同,文档将增加打印商业可读场景的能力以供参考。

你可以使用ast模块解析您的测试,并手动行走树和安装测试等有这样做(你可以使用ast.NodeVisitorast.NodeTransfomer和访问者模式也许)的可能更好的方法,但这里有一个例子:

import ast, inspect 

def find_tests(module): 
    # generate AST from module's source 
    tree = ast.parse(inspect.getsource(module)) 
    # return tests in module, assuming they are top level function definitions 
    return [node for node in tree.body if isinstance(node, ast.FunctionDef)] 

def print_docstrings(test): 
    for node in test.body: 
     if isinstance(node, ast.Expr): 
      # print lineno and docstring 
      print node.value.lineno, node.value.s 

if __name__ == '__main__': 
    import test_adding 
    for test in find_tests(test_adding): 
     print_docstrings(test) 

您可能也有兴趣konira

+0

你可以使用'inspect.getsource(module)'获取源代码。你不需要'_ast'这个名字可以通过'ast'获得。 – jfs 2012-03-20 09:20:29

+0

谢谢,更新! – zeekay 2012-03-20 09:25:58

+0

我不确定你应该走'ast'路线,因为它本质上是为你的测试引入新的语法。如果有人忘记放置字符串会怎么样?等 也许你可以指定使用'with'语句的上下文并使用它们来构建整体测试。 – 2012-03-20 09:56:49

由于编译器忽略了字面语句,所以不能。

>>> def foo(): 
... 'docstring' 
... 3 
... 'bar' 
... 
>>> dis.dis(foo) 
    4   0 LOAD_CONST    1 (None) 
       3 RETURN_VALUE   
+0

哦,回到制图板。 – Graham 2012-03-20 07:29:11