2011-08-30 14 views
19

Tôi đang sử dụng Sphinx để tạo tài liệu cho dự án của tôi.Cách sử dụng Python để lập trình tạo một phần tài liệu Sphinx

Trong dự án này, tôi mô tả một danh sách các lệnh có sẵn trong một tập tin yaml đó, một lần nạp, kết quả trong một từ điển trong các hình thức {command-name : command-description} ví dụ:

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

Những gì tôi muốn biết, là nếu có phương pháp nhân sư tải tệp yaml trong chu kỳ make html, dịch từ điển python ở một số định dạng reStructuredText (ví dụ: definition list) và bao gồm trong đầu ra html của tôi.

Tôi mong chờ tập tin .rst của tôi trông giống như:

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

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

và được chuyển đổi trong nội bộ để:

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 

trước khi được dịch sang HTML.

+0

Đây không phải là câu trả lời đúng để tôi đặt câu trả lời đó làm nhận xét. Theo như tôi biết, không có cách nào để phân tích cú pháp một tập tin yaml với nhân sư trực tiếp, nhưng tôi nghĩ bạn có thể làm cho nó bằng cách sử dụng pyyaml ​​và sửa đổi bạn Makefile nhân sư. –

+1

Điểm viết mã YAML là gì? Tại sao không chỉ viết mô tả trong mô-đun Python và sử dụng autodoc của Sphinx? Tại sao làm cho cái gì đó phức tạp hơn * phức tạp hơn http://sphinx.pocoo.org/ext/autodoc.html? –

+0

@ S.Lott - Ý tưởng cơ bản là DNRY: lệnh được định nghĩa (và có thể bị ghi đè bởi người dùng) trong tệp yml. Ví dụ trên được đơn giản hóa để làm cho câu hỏi dễ hiểu hơn, nhưng tệp yml thực sự chứa thông tin bổ sung cho trình phân tích cú pháp như số tham số, cờ có thể, gọi lại xác thực, v.v ... Nó đơn giản có vẻ ngu ngốc (và nguồn lỗi tiềm ẩn trong tài liệu) để lặp lại cùng một thông tin trong tệp yml và chuỗi docstring. – mac

Trả lời

18

Cuối cùng, tôi tìm cách đạt được những gì tôi muốn. Dưới đây là làm thế nào để:

  1. Tạo một kịch bản python (chúng ta hãy gọi nó generate-includes.py) mà sẽ tạo ra reStructuredText và lưu nó trong file myrst.inc. (Trong ví dụ của tôi, đây sẽ là kịch bản tải và phân tích cú pháp YAML, nhưng điều này là không liên quan). Đảm bảo tệp này có thể thực thi được !!!
  2. Sử dụng include chỉ trong tài liệu .rst chính của bạn tài liệu hướng dẫn của bạn, trong điểm mà bạn muốn tài liệu được tạo tự động của bạn sẽ được chèn vào:

    .. include:: myrst.inc 
    
  3. Sửa đổi Makefile Sphinx để tạo các tệp .inc được yêu cầu tại thời điểm xây dựng:

    myrst.inc: 
        ./generate-includes.py 
    
    html: myrst.inc 
        ...(other stuff here) 
    
  4. Tạo tài liệu của bạn bình thường với make html.

+0

Hoạt động tuyệt vời. Mặc dù readthedocs không hoạt động nữa, nhưng tôi đoán đó là điều không thể tránh khỏi đối với tài liệu do python tạo ... – Mark

4

Nhân sư không có bất kỳ thứ gì được tích hợp sẵn để làm những gì bạn thích. Bạn có thể tạo một chỉ thị tùy chỉnh để xử lý các tệp của bạn hoặc tạo lại cấu trúc lại trong một bước riêng biệt và bao gồm tệp kết quả reStructuredText bằng cách sử dụng chỉ thị bao gồm.

+0

Vì vậy, tốt để biết rằng '.. ma thuật chỉ thị-đó-thực thi-python-code ::' cần phải được một cái gì đó tôi mã sau đó. Tôi đã cố gắng để có được một vết nứt ở đó và mặc dù tôi quản lý để viết một chỉ thị chèn văn bản của tôi tạo ra kịch bản tôi không thể hiểu làm thế nào tôi có thể làm cho nó phân tích cú pháp. Ví dụ: 'nodes.paragraph ('', '** text **')' sẽ xuất '** text **' chứ không phải ** 'text' **. Làm thế nào tôi có thể nói với nhân sư phân tích nó bằng cú pháp chuẩn * reStructuredText *? – mac

+0

Trong lớp con Chỉ thị của bạn, bạn sẽ có các phương thức handle_content() và handle_signature(). Bạn có thể gọi đệ quy self.state.nested_parse() và nó sẽ xử lý các kiểu dựng sẵn đúng cách. Thanh toán [Tạo các chỉ thị ReStructuredText] (http://docutils.sourceforge.net/docs/howto/rst-directives.html) –

+0

Cảm ơn bạn devin_s (+1). Như bạn có thể đã nhận thấy (xem câu trả lời của riêng tôi) cuối cùng tôi đã giải quyết bằng cách sử dụng '.. include ::' directive. Tuy nhiên, hãy kiểm tra giải pháp của bạn, càng sớm càng tốt! – mac

0

Nhân sư hỗ trợ tiện ích mở rộng tùy chỉnh có thể là cách tốt nhất để làm điều này http://sphinx.pocoo.org/ext/tutorial.html.

+0

Khi tôi đăng câu hỏi ban đầu, tôi đã xem nó, nhưng nó trông giống như một giải pháp quá phức tạp để làm những gì tôi cần. .. Tại sao bạn nghĩ nó sẽ là "cách tốt nhất"? – mac

7

tôi cần điều tương tự, vì vậy tôi đã ném cùng một chỉ thị mới mà dường như làm việc (tôi không biết gì về tùy chỉnh chỉ thị Sphinx, nhưng nó đã làm việc cho đến nay):

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) 

Nó được sử dụng như sau:

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

Một cải tiến dựa trên mã của Michael và được xây dựng trong bao gồm các chỉ:

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) 

Điều này sẽ nhập đầu ra sớm hơn để nó đi thẳng qua trình phân tích cú pháp. Nó cũng hoạt động trong Python 3.

2

Tôi biết câu hỏi này là cũ, nhưng có lẽ ai đó khác cũng sẽ thấy nó hữu ích.

Có vẻ như bạn không thực sự cần thực thi bất kỳ mã python nào, nhưng bạn chỉ cần định dạng lại nội dung tệp của mình. Trong trường hợp đó, bạn có thể muốn xem sphinx-jinja (https://pypi.python.org/pypi/sphinx-jinja).

Bạn có thể tải file YAML của bạn trong conf.py:

jinja_contexts = yaml.load(yourFileHere) 

Sau đó, bạn có thể sử dụng jinja khuôn mẫu để viết ra những nội dung và họ đã đối xử như phần còn lại đầu vào.