สฟิงซ์ Autodoc อัตโนมัติไม่เพียงพอ


149

ฉันกำลังพยายามใช้สฟิงซ์เพื่อทำเอกสารโครงการแนว 5,000+ ใน Python มันมีประมาณ 7 โมดูลฐาน เท่าที่ฉันรู้เพื่อที่จะใช้ autodoc ฉันจำเป็นต้องเขียนโค้ดเช่นนี้สำหรับแต่ละไฟล์ในโครงการของฉัน:

.. automodule:: mods.set.tests
    :members:
    :show-inheritance:

นี่เป็นวิธีที่น่าเบื่อเกินไปเพราะฉันมีไฟล์มากมาย มันจะง่ายกว่านี้หากฉันสามารถระบุได้ว่าฉันต้องการให้เอกสาร 'mods' เป็นเอกสาร สฟิงซ์สามารถเรียกแพคเกจซ้ำแล้วซ้ำอีกและสร้างหน้าสำหรับแต่ละ submodule

มีคุณสมบัติเช่นนี้หรือไม่? ถ้าไม่ใช่ฉันสามารถเขียนสคริปต์เพื่อสร้างไฟล์. rst ทั้งหมด แต่อาจใช้เวลานานมาก


มีอะไรผิดปกติกับการเขียนสคริปต์ขนาดเล็กที่ใช้ "os.walk" และเขียนทั้งหมดนี้ BTW ฉันมีโครงการกว่า 40,000 รายการและไม่ชัดเจนในสิ่งที่คุณกำลังพูดถึง มีไฟล์เกี่ยวข้องกี่ไฟล์? การหาเส้นทางlsไปยังไฟล์นั้นทำได้ยากเพียงใด
S.Lott

125
ไม่มีใครพูดว่ามันยาก OP บอกว่ามันน่าเบื่อซึ่งมันเป็น เนื่องจากระบบเอกสารอื่นสามารถทำสิ่งนี้ได้มันไม่ได้ไร้เหตุผล
Gregg Lind

เพียงแค่ใช้pdoc
K3 --- rnc

คำตอบ:


143

คุณสามารถตรวจสอบสคริปต์นี้ที่ฉันได้ทำ ฉันคิดว่ามันสามารถช่วยคุณได้

สคริปต์นี้แยกวิเคราะห์แผนผังไดเร็กทอรีที่ค้นหาโมดูลและแพ็กเกจหลามและสร้างไฟล์ ReST อย่างเหมาะสมเพื่อสร้างเอกสารประกอบโค้ดด้วยสฟิงซ์ นอกจากนี้ยังสร้างดัชนีโมดูล

UPDATE

สคริปต์นี้เป็นส่วนหนึ่งของสฟิงซ์ 1.1 apidoc


คุณควรส่งออกไฟล์ไปที่ใด ฉันลองส่งพวกมันไปยังโฟลเดอร์ _build ที่เป็นค่าเริ่มต้นของ Sphinx แต่การรันsphinx-build -b html . ./_buildไม่ได้มารับ
Cerin

คุณควรใส่ไว้ในsource directory(. ในกรณีของคุณ) ไดเรกทอรี _build เป็นที่ที่ไฟล์ HTML จะถูกสร้างขึ้น ตรวจสอบข้อมูลเพิ่มเติม: sphinx.pocoo.org/tutorial.html#running-the-build
Etienne

1
@Erienne: สคริปต์ที่ยอดเยี่ยม! สิ่งที่ฉันกำลังมองหา หวังว่ามันจะหัวสร้างขึ้นสำหรับแต่ละชั้นเรียน (รูปลักษณ์สฟิงซ์ปกติไม่ดีที่จะเรียนพวกเขาได้หายไปในโมดูลขนาดใหญ่.)
jbenet

1
แม้แต่สฟิงซ์ - apidoc ก็ค่อนข้างพื้นฐาน สำหรับแพคเกจที่มีหนึ่งหรือสองโมดูลมันทำงานได้ดี แต่เรามีโมดูลที่ซ้อนกันอย่างลึกล้ำและสฟิงซ์ - อะพิโดคนั้นสร้างเอาต์พุตที่ไม่สามารถจัดการได้
slacy

4
การตอบด้วยตนเอง: เพิ่ม.. include:: modules.rstในของคุณindex.rst
Ciro Santilli 郝海东冠状病六四事件法轮功

40

ฉันไม่ทราบว่าสฟิงซ์มีautosummaryส่วนขยายตามเวลาที่ถามคำถามเดิมหรือไม่ แต่สำหรับตอนนี้มันเป็นไปได้ทีเดียวที่จะตั้งค่ารุ่นอัตโนมัติโดยไม่ต้องใช้sphinx-apidocหรือสคริปต์ที่คล้ายกัน ด้านล่างมีการตั้งค่าที่ใช้ได้กับหนึ่งในโครงการของฉัน

  1. เปิดใช้งานautosummaryส่วนขยาย (เช่นเดียวกับautodoc) ในconf.pyไฟล์และการตั้งค่าของตัวเลือกในการautosummary_generate Trueอาจเพียงพอหากคุณไม่ได้ใช้*.rstเทมเพลตที่กำหนดเอง มิฉะนั้นเพิ่มไดเรกทอรีแม่แบบของคุณเพื่อแยกรายการหรือautosummaryจะพยายามที่จะถือว่าพวกเขาเป็นไฟล์อินพุต (ซึ่งดูเหมือนว่าจะเป็นข้อบกพร่อง)

    extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary']
    autosummary_generate = True
    templates_path = [ '_templates' ]
    exclude_patterns = ['_build', '_templates']
  2. ใช้autosummary::ในแผนผัง TOC ในindex.rstไฟล์ของคุณ ในเอกสารตัวอย่างนี้สำหรับโมดูลproject.module1และproject.module2จะถูกสร้างขึ้นโดยอัตโนมัติและวางลงใน_autosummaryไดเรกทอรี

    PROJECT
    =======
    
    .. toctree::
    
    .. autosummary::
       :toctree: _autosummary
    
       project.module1
       project.module2
  3. โดยค่าเริ่มต้นautosummaryจะสร้างข้อมูลสรุปสั้น ๆ สำหรับโมดูลและฟังก์ชั่น หากต้องการเปลี่ยนให้คุณสามารถใส่ไฟล์เทมเพลตที่กำหนดเองลงไป_templates/autosummary/module.rst(ซึ่งจะถูกวิเคราะห์ด้วยJinja2 ):

    {{ fullname }}
    {{ underline }}
    
    .. automodule:: {{ fullname }}
        :members:

โดยสรุปไม่จำเป็นต้องเก็บ_autosummaryไดเรกทอรีภายใต้การควบคุมเวอร์ชัน นอกจากนี้คุณอาจตั้งชื่อทุกอย่างที่คุณต้องการและวางไว้ที่ใดก็ได้ในแผนผังต้นไม้ (การวางไว้ด้านล่าง_buildจะไม่ทำงาน)


4
นี่เป็นความช่วยเหลือครั้งใหญ่ ในจุดที่ 2 ที่คุณมี "project.module1" และ "project.module2" มีวิธีสร้างรายการโดยอัตโนมัติสำหรับทุกโมดูลในแพ็คเกจที่กำหนดหรือไม่ หากต้องการวาง "โครงการ" และให้ดม "module1" และ "module2"
สีน้ำตาล

ค่อนข้างประหลาดใจที่ฉันไม่สามารถหาคำตอบได้ทุกที่คุณเคยทำงานกับ @Brown หรือเปล่า?
Alisdair Robertson

3
@AlisdairRobertson ไม่ แต่โซลูชันการสรุปอัตโนมัติที่ให้ไว้นั้นเพียงพอสำหรับความต้องการของฉัน สิ่งเดียวที่ฉันคิดว่าทำคือการเขียนสคริปต์เพื่อสร้างไฟล์ index.rst และตรวจสอบชื่อโมดูลอัตโนมัติ อย่างไรก็ตามในทางปฏิบัติรายการของโมดูลจะไม่เปลี่ยนแปลงบ่อยนักดังนั้นเพียงแค่การแก้ไขไฟล์หนึ่งครั้งเป็นครั้งคราวนั้นก็ไม่ได้ไร้เหตุผล ฉันแน่ใจว่าฉันใช้เวลามากขึ้นในการหาทางออกมากกว่าที่จะแก้ไขไฟล์เพียงไฟล์เดียว!
บราวน์

12

ในแต่ละแพ็คเกจ__init__.pyไฟล์สามารถมี.. automodule:: package.moduleส่วนประกอบสำหรับแต่ละส่วนของแพ็คเกจ

จากนั้นคุณสามารถ.. automodule:: packageและส่วนใหญ่ทำในสิ่งที่คุณต้องการ


ฉันจะใส่สตริงนั้นในเครื่องหมายคำพูดสามเท่าในinit .py ได้อย่างไร
Cory Walker

5
@Cory Walker: ไม่ใช่สตริง "" คุณสามารถ - และควร - วางเอกสารที่มีการเสนอราคาสามตัวลงในไฟล์เดียวทุกไฟล์ ทุกคน ซึ่งรวมถึง__init__.pyไฟล์ในแพ็คเกจของคุณ docstring สามารถรวมคำสั่งเอกสารใด ๆ ของสฟิงซ์รวมถึง.. automodule::โมดูลภายในแพ็คเกจ
S.Lott

2
autodocautomoduleเป็นพิมพ์ผิดก็ควรจะ แต่ขอบคุณมากสำหรับคำใบ้!
mariotomo

9

จาก Sphinx เวอร์ชั่น 3.1 (มิถุนายน 2020), sphinx.ext.autosummary(ในที่สุด!) ได้เรียกซ้ำ

ดังนั้นไม่จำเป็นต้องใช้ชื่อโมดูลรหัสฮาร์ดหรือพึ่งพาไลบรารีบุคคลที่สามเช่นSphinx AutoAPIหรือSphinx AutoPackageS บทสรุปสำหรับการตรวจสอบแพ็คเกจอัตโนมัติของพวกเขาอีกต่อไป

ตัวอย่างแพ็คเกจ Python 3.7 ไปยังเอกสาร ( ดูรหัสบน Githubและผลลัพธ์ใน ReadTheDocs ):

mytoolbox
|-- mypackage
|   |-- __init__.py
|   |-- foo.py
|   |-- mysubpackage
|       |-- __init__.py
|       |-- bar.py
|-- doc
|   |-- source
|       |--index.rst
|       |--conf.py
|       |-- _templates
|           |-- custom-module-template.rst
|           |-- custom-class-template.rst

conf.py:

import os
import sys
sys.path.insert(0, os.path.abspath('../..'))  # Source code dir relative to this file

extensions = [
    'sphinx.ext.autodoc',  # Core library for html generation from docstrings
    'sphinx.ext.autosummary',  # Create neat summary tables
]
autosummary_generate = True  # Turn on sphinx.ext.autosummary

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

index.rst(หมายเหตุ:recursive:ตัวเลือกใหม่):

Welcome to My Toolbox
=====================

Some words.

.. autosummary::
   :toctree: _autosummary
   :template: custom-module-template.rst
   :recursive:

   mypackage

ซึ่งเพียงพอที่จะสรุปทุกโมดูลในแพ็กเกจโดยอัตโนมัติ สำหรับแต่ละโมดูลจากนั้นจะสรุปทุกแอตทริบิวต์ฟังก์ชั่นคลาสและข้อยกเว้นในโมดูลนั้น

ถึงแม้ว่าsphinx.ext.autosummaryเทมเพลตเริ่มต้นจะไม่สร้างเพจเอกสารแยกต่างหากสำหรับแต่ละแอททริบิวต์ฟังก์ชั่นคลาสและข้อยกเว้นและลิงก์ไปยังเพจเหล่านั้นจากตารางสรุป เป็นไปได้ที่จะขยายเทมเพลตให้ทำตามที่แสดงด้านล่าง แต่ฉันไม่เข้าใจว่าทำไมนี่ไม่ใช่พฤติกรรมเริ่มต้น - แน่นอนว่าเป็นสิ่งที่คนส่วนใหญ่ต้องการ .. ผมเคยยกมันขึ้นมาตามคำขอของคุณลักษณะ

ฉันต้องคัดลอกแม่แบบเริ่มต้นในเครื่องแล้วเพิ่มไปยังพวกเขา:

  • คัดลอกsite-packages/sphinx/ext/autosummary/templates/autosummary/module.rstไปยังmytoolbox/doc/source/_templates/custom-module-template.rst
  • คัดลอกsite-packages/sphinx/ext/autosummary/templates/autosummary/class.rstไปยังmytoolbox/doc/source/_templates/custom-class-template.rst

เบ็ดเข้าไปcustom-module-template.rstอยู่ในindex.rstข้างต้นโดยใช้:template:ตัวเลือก (ลบบรรทัดนั้นเพื่อดูว่าเกิดอะไรขึ้นโดยใช้แม่แบบแพ็คเกจไซต์เริ่มต้น)

custom-module-template.rst (บรรทัดเพิ่มเติมที่ระบุไว้ทางด้านขวา):

{{ fullname | escape | underline}}

.. automodule:: {{ fullname }}
  
   {% block attributes %}
   {% if attributes %}
   .. rubric:: Module Attributes

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in attributes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block functions %}
   {% if functions %}
   .. rubric:: {{ _('Functions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in functions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block classes %}
   {% if classes %}
   .. rubric:: {{ _('Classes') }}

   .. autosummary::
      :toctree:                                          <-- add this line
      :template: custom-class-template.rst               <-- add this line
   {% for item in classes %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block exceptions %}
   {% if exceptions %}
   .. rubric:: {{ _('Exceptions') }}

   .. autosummary::
      :toctree:                                          <-- add this line
   {% for item in exceptions %}
      {{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

{% block modules %}
{% if modules %}
.. rubric:: Modules

.. autosummary::
   :toctree:
   :template: custom-module-template.rst                 <-- add this line
   :recursive:
{% for item in modules %}
   {{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

custom-class-template.rst (บรรทัดเพิ่มเติมที่ระบุไว้ทางด้านขวา):

{{ fullname | escape | underline}}

.. currentmodule:: {{ module }}

.. autoclass:: {{ objname }}
   :members:                                    <-- add at least this line
   :show-inheritance:                           <-- plus I want to show inheritance...
   :inherited-members:                          <-- ...and inherited members too

   {% block methods %}
   .. automethod:: __init__

   {% if methods %}
   .. rubric:: {{ _('Methods') }}

   .. autosummary::
   {% for item in methods %}
      ~{{ name }}.{{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

   {% block attributes %}
   {% if attributes %}
   .. rubric:: {{ _('Attributes') }}

   .. autosummary::
   {% for item in attributes %}
      ~{{ name }}.{{ item }}
   {%- endfor %}
   {% endif %}
   {% endblock %}

6

สฟิงซ์ AutoAPIทำสิ่งนี้


1
คุณพระช่วย! มันใช้งานได้ดีกว่าอย่างอื่นมาก โปรดทราบว่านี่ไม่ใช่ "autodoc" หรือ "apidoc" เป็นส่วนขยายที่แตกต่างอย่างสิ้นเชิง
ropeladder

2
เหมือนกัน สิ่งนี้ทำให้ "auto" ใน "autodoc" .... นี่คือสิ่งที่โครงการของเราต้องทำเพื่อสลับ: สลับไปยัง autoapi จาก autodoc โดย nealmcb ·ดึงคำขอ \ # 7 · gwexploratoryaudits / r2b2
nealmcb

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.