2011-08-30 76 views
19

我正在使用Sphinx來生成我的項目的文檔。如何使用Python以編程方式生成Sphinx文檔的一部分

在這個項目中,我描述了可用命令在yaml文件列表,一旦加載,導致字典的形式{command-name : command-description}例如:

commands = {"copy" : "Copy the highlighted text in the clipboard", 
      "paste" : "Paste the clipboard text to cursor location", 
      ...} 

我想知道的,是如果在獅身人面像中有一種方法在make html週期內加載yaml文件,請將某些reStructuredText格式(例如definition list)中的python字典轉換幷包含在我的html輸出中。

我希望我的.rst文件看起來像:

Available commands 
================== 
The commands available in bla-bla-bla... 

.. magic-directive-that-execute-python-code:: 
    :maybe python code or name of python file here: 

,並在內部轉換爲:被轉換爲HTML之前

Available commands 
================== 
The commands available in bla-bla-bla... 

copy 
    Copy the highlighted text in the clipboard 

paste 
    Paste the clipboard text to cursor location 

+0

這不是一個正確的答案,所以我把它作爲評論。據我所知,沒有辦法直接用sphinx解析yaml文件,但我認爲你可以使用pyyaml並修改你的sphinx Makefile。 –

+1

寫YAML代碼有什麼意義?爲什麼不直接在Python模塊中編寫描述並使用Sphinx的autodoc?爲什麼做一些比http://sphinx.pocoo.org/ext/autodoc.html更復雜的東西? –

+0

@ S.Lott - 基本思想是DNRY:在yml文件中定義命令(並可由用戶覆蓋)。上面的例子被簡化爲使問題更容易理解,但實際的yml文件實際上包含解析器的額外信息,如參數數量,可能的標誌,驗證回調等等。它看起來很愚蠢(和文檔中潛在的錯誤來源)在yml文件和模塊docstring中重複相同的信息。 – mac

回答

18

最後,我找到了一種方法來實現我想要的。下面是如何做:

  1. 創建一個python腳本(姑且稱之爲generate-includes.py),將產生reStructuredText的並將其保存在myrst.inc文件。 (在我的例子中,這將是腳本加載和解析YAML,但這是無關緊要的)。 確保此文件可執行!
  2. 要插入您的動態生成的文檔使用include指令你的文檔你的主要.rst文件中,在點:

    .. include:: myrst.inc 
    
  3. 修改Makefile的獅身人面像以便在生成時生成所需的.inc文件:

    myrst.inc: 
        ./generate-includes.py 
    
    html: myrst.inc 
        ...(other stuff here) 
    
  4. 正常建立您的文檔make html

+0

工程很棒。儘管readthedocs不起作用,但我認爲這對python生成的文檔是不可避免的... – Mark

4

獅身人面像沒有內置任何東西來做你喜歡的事情。您可以創建自定義指令來處理文件,也可以在單獨的步驟中生成reStructuredText,並使用include指令包含生成的reStructuredText文件。

+0

很高興知道'magic-directive-that-execute-python-code ::'需要成爲我編碼的東西。我試圖得到它的一個裂縫,雖然我設法編寫一個指令,插入我的腳本生成的文本,我不明白我如何能夠解析。例如:'nodes.paragraph('','** text **')'會輸出'** text **'而不是**'text' **。我如何告訴獅身人面像使用標準的* reStructuredText *語法來解析它? – mac

+0

在您的指令子類中,您將擁有handle_content()和handle_signature()方法。你可以遞歸調用self.state.nested_pa​​rse(),它會正確地處理內建的樣式。 Checkout [Creating reStructuredText Directives](http://docutils.sourceforge.net/docs/howto/rst-directives.html) –

+0

謝謝devin_s(+1)。正如你可能已經注意到的(見我自己的答案),我最終解決了使用'.. include ::'指令。儘管如此,也會檢查你的解決方案! – mac

0

斯芬克斯確實支持定製擴展,這可能是最好的方法來做到這一點http://sphinx.pocoo.org/ext/tutorial.html

+0

當我最初發布這個問題時,我看了一下,但它看起來像是一個過度複雜的解決方案,只是做我需要的。 ..你爲什麼認爲這將是「最好的方式」? – mac

7

我需要同樣的事情,所以我扔在一起,新的指令,似乎工作(我一無所知定製獅身人面像的指令,但到目前爲止,它的工作):

import sys 
from os.path import basename 
from StringIO import StringIO 

from sphinx.util.compat import Directive 
from docutils import nodes 

class ExecDirective(Directive): 
    """Execute the specified python code and insert the output into the document""" 
    has_content = True 

    def run(self): 
     oldStdout, sys.stdout = sys.stdout, StringIO() 
     try: 
      exec '\n'.join(self.content) 
      return [nodes.paragraph(text = sys.stdout.getvalue())] 
     except Exception, e: 
      return [nodes.error(None, nodes.paragraph(text = "Unable to execute python code at %s:%d:" % (basename(self.src), self.srcline)), nodes.paragraph(text = str(e)))] 
     finally: 
      sys.stdout = oldStdout 

def setup(app): 
    app.add_directive('exec', ExecDirective) 

它的使用方法如下:

.. exec:: 
    print "Python code!" 
    print "This text will show up in the document" 
12

的改進基於邁克爾的代碼,並內置包括指令:

import sys 
from os.path import basename 

try: 
    from StringIO import StringIO 
except ImportError: 
    from io import StringIO 

from sphinx.util.compat import Directive 
from docutils import nodes, statemachine 

class ExecDirective(Directive): 
    """Execute the specified python code and insert the output into the document""" 
    has_content = True 

    def run(self): 
     oldStdout, sys.stdout = sys.stdout, StringIO() 

     tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) 
     source = self.state_machine.input_lines.source(self.lineno - self.state_machine.input_offset - 1) 

     try: 
      exec('\n'.join(self.content)) 
      text = sys.stdout.getvalue() 
      lines = statemachine.string2lines(text, tab_width, convert_whitespace=True) 
      self.state_machine.insert_input(lines, source) 
      return [] 
     except Exception: 
      return [nodes.error(None, nodes.paragraph(text = "Unable to execute python code at %s:%d:" % (basename(source), self.lineno)), nodes.paragraph(text = str(sys.exc_info()[1])))] 
     finally: 
      sys.stdout = oldStdout 

def setup(app): 
    app.add_directive('exec', ExecDirective) 

這個更早的導入輸出,以便直接通過解析器。它也適用於Python 3.

2

我知道這個問題很舊,但也許別人會發現它也很有用。

這聽起來像你並不需要執行任何python代碼,但你只需要重新格式化文件的內容。在這種情況下,你可能想看看獅身人面像 - 神仙(https://pypi.python.org/pypi/sphinx-jinja)。

您可以在conf.py加載YAML文件:

jinja_contexts = yaml.load(yourFileHere) 

然後你可以使用神社模板寫出來的內容,並讓他們處理成REST輸入。

相關問題