Autodoc Sphinx tidak cukup otomatis


149

Saya mencoba menggunakan Sphinx untuk mendokumentasikan proyek 5.000+ line dengan Python. Ini memiliki sekitar 7 modul dasar. Sejauh yang saya tahu, Untuk menggunakan autodoc saya perlu menulis kode seperti ini untuk setiap file dalam proyek saya:

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

Ini terlalu membosankan karena saya punya banyak file. Akan lebih mudah jika saya bisa menentukan bahwa saya ingin paket 'mods' didokumentasikan. Sphinx kemudian dapat secara rekursif menelusuri paket dan membuat halaman untuk setiap submodule.

Apakah ada fitur seperti ini? Jika tidak, saya bisa menulis skrip untuk membuat semua file .rst, tetapi itu akan memakan banyak waktu.


Apa yang salah dengan menulis skrip kecil yang menggunakan "os.walk" dan menulis semua ini? BTW, saya punya proyek garis 40.000+ dan tidak jelas tentang apa yang Anda bicarakan. Berapa banyak file yang terlibat? Seberapa sulitkah untuk merutekan lske file dan mengeditnya?
S.Lott

125
Tidak ada yang mengatakan itu sulit. OP mengatakan itu membosankan , itu memang benar. Mengingat bahwa sistem dokumen lain dapat melakukan ini, itu tidak masuk akal.
Gregg Lind

Cukup gunakan pdoc .
K3 --- rnc

Jawaban:


143

Anda dapat memeriksa skrip yang saya buat ini. Saya pikir itu dapat membantu Anda.

Script ini mem-parsing pohon direktori mencari modul dan paket python dan membuat file REST tepat untuk membuat dokumentasi kode dengan Sphinx. Ini juga membuat indeks modul.

MEMPERBARUI

Skrip ini sekarang menjadi bagian dari Sphinx 1.1 sebagai apidoc .


Di mana Anda seharusnya menampilkan file? Saya mencoba mengeluarkannya ke folder _build default Sphinx, tetapi menjalankannya sphinx-build -b html . ./_buildtidak mengambilnya.
Cerin

Anda harus meletakkannya di source directory(. Dalam kasus Anda). Direktori _build adalah tempat file HTML akan dibuat. Periksa info lebih lanjut: sphinx.pocoo.org/tutorial.html#running-the-build
Etienne

1
@ Erienne: naskah fantastis! hanya apa yang saya cari. Berharap itu menghasilkan judul untuk kelas individu (tampilan sphinx biasa tidak baik untuk kelas. Mereka tersesat dalam modul yang lebih besar)
jbenet

1
Bahkan sphinx-apidoc sangat sederhana. Untuk sebuah paket dengan satu atau dua modul, ia berfungsi dengan baik, tetapi kami memiliki modul yang bersarang secara mendalam, dan sphinx-apidoc menghasilkan beberapa keluaran yang tidak dapat dikelola.
slacy

4
menjawab sendiri: tambahkan .. include:: modules.rstke Andaindex.rst
Ciro Santilli 郝海东 冠状 病 六四 事件 事件 法轮功

40

Saya tidak tahu apakah Sphinx memiliki autosummaryekstensi pada saat pertanyaan awal diajukan, tetapi untuk saat ini sangat mungkin untuk membuat generasi otomatis semacam itu tanpa menggunakan sphinx-apidocatau skrip serupa. Di bawah ini ada pengaturan yang berfungsi untuk salah satu proyek saya.

  1. Aktifkan autosummaryekstensi (dan juga autodoc) dalam conf.pyfile dan setel autosummary_generateopsi ke True. Ini mungkin cukup jika Anda tidak menggunakan *.rsttemplat khusus . Jika tidak, tambahkan direktori templat Anda untuk mengecualikan daftar, atau autosummaryakan mencoba memperlakukannya sebagai file input (yang tampaknya merupakan bug).

    extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary']
    autosummary_generate = True
    templates_path = [ '_templates' ]
    exclude_patterns = ['_build', '_templates']
  2. Gunakan autosummary::di pohon TOC dalam index.rstfile Anda . Dalam contoh ini dokumentasi untuk modul project.module1dan project.module2akan dihasilkan secara otomatis dan ditempatkan ke _autosummarydirektori.

    PROJECT
    =======
    
    .. toctree::
    
    .. autosummary::
       :toctree: _autosummary
    
       project.module1
       project.module2
  3. Secara default autosummaryakan menghasilkan ringkasan yang sangat singkat untuk modul dan fungsinya. Untuk mengubahnya Anda dapat memasukkan file template khusus _templates/autosummary/module.rst(yang akan diuraikan dengan Jinja2 ):

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

Kesimpulannya, tidak perlu menyimpan _autosummarydirektori di bawah kontrol versi. Juga, Anda dapat memberi nama apa pun yang Anda inginkan dan menempatkannya di mana saja di pohon sumber (meletakkannya di bawah _buildtidak akan berfungsi, meskipun).


4
Ini sangat membantu. Di poin 2, di mana Anda memiliki "project.module1" dan "project.module2", apakah ada cara untuk secara otomatis menghasilkan daftar itu untuk setiap modul dalam paket yang diberikan? Untuk hanya meletakkan "project" dan minta "module1" dan "module2" keluar?
Brown

Cukup terkejut. Saya tidak dapat menemukan jawaban untuk ini di mana pun, apakah Anda pernah mengatasinya?
Alisdair Robertson

3
@AlisdairRobertson Tidak, tetapi solusi autosummary yang disediakan ternyata lebih dari cukup untuk kebutuhan saya. Satu-satunya hal lain yang saya pikirkan adalah menulis skrip untuk menghasilkan file index.rst dan mendeteksi secara otomatis nama-nama modul. Namun, dalam praktiknya, daftar modul tidak sering berubah, jadi hanya mengedit satu file sesekali bukan hal yang tidak masuk akal. Saya yakin saya sudah menghabiskan lebih banyak waktu untuk mencari solusi daripada hanya perlu mengedit satu file!
Brown

12

Di setiap paket, __init__.pyfile dapat memiliki .. automodule:: package.modulekomponen untuk setiap bagian dari paket.

Maka Anda bisa .. automodule:: packagedan kebanyakan melakukan apa yang Anda inginkan.


saya hanya memasukkan string dalam tanda kutip tiga di init .py?
Cory Walker

5
@Cory Walker: Ini bukan string "a". Anda dapat - dan harus - meletakkan dokumen dengan tiga kutip di setiap file. Semua orang. Itu termasuk __init__.pyfile dalam paket Anda. Docstring dapat mencakup arahan dokumentasi APAPUN Sphinx, termasuk .. automodule::untuk modul dalam paket.
S.Lott

2
autodocadalah kesalahan ketik, seharusnya automodule. tapi terima kasih banyak atas petunjuknya!
mariotomo

9

Dari Sphinx versi 3.1 (Juni 2020), sphinx.ext.autosummary(akhirnya!) Memiliki rekursi.

Jadi tidak perlu nama kode modul keras atau mengandalkan perpustakaan pihak ke-3 seperti Sphinx AutoAPI atau Sphinx AutoPackageSummary untuk deteksi paket otomatis mereka lagi.

Paket contoh Python 3.7 untuk didokumentasikan ( lihat kode pada Github dan hasil pada 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(perhatikan :recursive:opsi baru ):

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

Some words.

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

   mypackage

Ini cukup untuk secara otomatis merangkum setiap modul dalam paket, betapapun bersarangnya. Untuk setiap modul, modul ini merangkum setiap atribut, fungsi, kelas dan pengecualian dalam modul itu.

Anehnya, sphinx.ext.autosummarytemplat default tidak melanjutkan untuk menghasilkan halaman dokumentasi terpisah untuk setiap atribut, fungsi, kelas dan pengecualian, dan tautan ke mereka dari tabel ringkasan. Dimungkinkan untuk memperluas templat untuk melakukan ini, seperti yang ditunjukkan di bawah ini, tetapi saya tidak dapat memahami mengapa ini bukan perilaku default - tentu itu yang diinginkan kebanyakan orang ..? Saya telah mengangkatnya sebagai permintaan fitur .

Saya harus menyalin template default secara lokal, dan kemudian menambahkannya:

  • Salin site-packages/sphinx/ext/autosummary/templates/autosummary/module.rstkemytoolbox/doc/source/_templates/custom-module-template.rst
  • Salin site-packages/sphinx/ext/autosummary/templates/autosummary/class.rstkemytoolbox/doc/source/_templates/custom-class-template.rst

Kait ke dalam custom-module-template.rstada di index.rstatas, menggunakan :template:opsi. (Hapus baris itu untuk melihat apa yang terjadi dengan menggunakan templat paket situs standar.)

custom-module-template.rst (baris tambahan dicatat di sebelah kanan):

{{ 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 (baris tambahan dicatat di sebelah kanan):

{{ 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 %}


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.