Sphinx autodoc yeterince otomatik değil


153

Python'da 5.000'den fazla satırlık bir projeyi belgelemek için Sphinx'i kullanmaya çalışıyorum. Yaklaşık 7 temel modüle sahiptir. Bildiğim kadarıyla autodoc'u kullanmak için projemdeki her dosya için şu şekilde kod yazmam gerekiyor:

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

Bu çok sıkıcı çünkü birçok dosyam var. 'Mods' paketinin belgelenmesini istediğimi belirtebilseydim çok daha kolay olurdu. Sphinx daha sonra paketi tekrar tekrar gözden geçirebilir ve her alt modül için bir sayfa oluşturabilir.

Bunun gibi bir özellik var mı? Değilse, tüm .rst dosyalarını yapmak için bir komut dosyası yazabilirdim, ama bu çok zaman alırdı.


"Os.walk" kullanan ve tüm bunları yazan küçük bir komut dosyası yazmanın nesi yanlış? BTW, 40.000'den fazla hat projem var ve neden bahsettiğiniz konusunda net değilim. Kaç dosya var? lsBir dosyaya yönlendirmek ve onu düzenlemek ne kadar zor olabilir ?
S. Lot

128
Kimse bunun zor olduğunu söylemedi. OP sıkıcı olduğunu söyledi , ki öyle. Diğer doktor sistemlerinin bunu yapabileceği düşünüldüğünde, bu mantıksız değildir.
Gregg Lind

Sadece pdoc kullanın .
K3 - rnc

Yanıtlar:


146

Yaptığım bu senaryoyu kontrol edebilirsiniz . Sana yardımcı olabileceğini düşünüyorum.

Bu komut dosyası, python modüllerini ve paketlerini arayan bir dizin ağacını ayrıştırır ve Sphinx ile kod dokümantasyonu oluşturmak için uygun şekilde ReST dosyaları oluşturur. Ayrıca bir modüller dizini oluşturur.

GÜNCELLEME

Bu script artık apidoc olarak Sphinx 1.1'in bir parçası .


1
Dosyaların çıktısını nereye koymanız gerekiyor? Bunları Sphinx'in varsayılan _build klasörüne çıkarmayı denedim, ancak çalıştırmak sphinx-build -b html . ./_buildonları almıyor.
Cerin

1
Bunları source directory(sizin durumunuzda) içine koymalısınız . _Build dizini, HTML dosyalarının oluşturulacağı yerdir. Daha fazla bilgi için kontrol edin: sphinx.pocoo.org/tutorial.html#running-the-build
Etienne

1
@Erienne: harika senaryo! Tam da aradığım şey. Bireysel sınıflar için başlıklar oluşturmasını diliyorum (normal sfenks görünümü sınıflar için hoş değil. Daha büyük modüllerde kayboluyorlar)
jbenet

1
Sphinx-apidoc bile oldukça ilkeldir. Bir veya iki modüllü bir paket için iyi çalışıyor, ancak derinlemesine iç içe geçmiş modüllerimiz var ve sphinx-apidoc oldukça yönetilemez çıktılar üretiyor.
slacy

4
öz cevaplama: eklemek .. include:: modules.rstadresinden Müşteriindex.rst
Ciro Santilli郝海东冠状病六四事件法轮功

41

autosummaryOrijinal soru sorulduğunda Sphinx'in bir uzantısı olup olmadığını bilmiyorum , ancak şimdilik bu türden otomatik üretimi sphinx-apidocveya benzer bir komut dosyası kullanmadan kurmak oldukça mümkün . Aşağıda projelerimden biri için çalışan ayarlar var.

  1. Dosyadaki autosummaryuzantıyı (yanı sıra autodoc) etkinleştirin conf.pyve autosummary_generateseçeneğini olarak ayarlayın True. Özel *.rstşablonlar kullanmıyorsanız bu yeterli olabilir . Aksi takdirde, listeyi hariç tutmak için şablonlar dizininizi ekleyin veya autosummarybunları giriş dosyaları olarak işlemeye çalışın (bu bir hata gibi görünüyor).

    extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autosummary']
    autosummary_generate = True
    templates_path = [ '_templates' ]
    exclude_patterns = ['_build', '_templates']
    
  2. Dosyanızdaki autosummary::TOC ağacında kullanın index.rst. Bu örnekte, modüller için dokümantasyon project.module1ve project.module2otomatik olarak oluşturulacak ve _autosummarydizine yerleştirilecektir .

    PROJECT
    =======
    
    .. toctree::
    
    .. autosummary::
       :toctree: _autosummary
    
       project.module1
       project.module2
    
  3. Varsayılan olarak autosummary, modüller ve işlevleri için yalnızca çok kısa özetler üretecektir. Bunu değiştirmek için içine özel bir şablon dosyası koyabilirsiniz _templates/autosummary/module.rst( Jinja2 ile ayrıştırılacaktır ):

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

Sonuç olarak, _autosummarydizini sürüm kontrolü altında tutmaya gerek yoktur . Ayrıca, istediğiniz herhangi bir şeyi adlandırabilir ve kaynak ağacında herhangi bir yere yerleştirebilirsiniz (yine de aşağıya koymak _buildişe yaramayacaktır).


4
Bu çok yardımcı oldu. "Project.module1" ve "project.module2" ye sahip olduğunuz 2. noktada, belirli bir paketteki her modül için bu listeyi otomatik olarak oluşturmanın bir yolu var mı? Sadece "proje" koymak ve "modül1" ve "modül2" yi koklamak mı?
Brown

Buna hiçbir yerde bir cevap bulamadığıma çok şaşırdım, hiç çözdün mü @ Brown?
Alisdair Robertson

3
@AlisdairRobertson Hayır, ancak sağlanan otomatik özet çözümü ihtiyaçlarımı fazlasıyla karşıladı. Yapmayı düşündüğüm diğer tek şey, index.rst dosyasını oluşturmak ve modül adlarını otomatik olarak algılamak için bir komut dosyası yazmaktı. Bununla birlikte, pratikte, modül listesi o kadar sık ​​değişmez, bu nedenle arada bir tek bir dosyayı düzenlemek o kadar mantıksız değildir. Eminim bir çözüm aramak için o dosyayı düzenlemek için gerekenden çok daha fazla zaman harcadım!
Brown

23

Sphinx sürüm 3.1'den (Haziran 2020), sphinx.ext.autosummary (nihayet!) Yineleme var.

Bu nedenle, artık otomatik paket algılamaları için modül adlarını sabit kodlamaya veya Sphinx AutoAPI veya Sphinx AutoPackageSummary gibi 3. taraf kitaplıklara güvenmeye gerek yok .

Belgelenecek Python 3.7 paketi örneği ( Github'daki koda bakın ve ReadTheDocs'taki sonuca bakın ):

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(yeni :recursive:seçeneğe dikkat edin ):

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

Some words.

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

   mypackage

Bu, derinlemesine iç içe geçmiş olmasına rağmen paketteki her modülü otomatik olarak özetlemek için yeterlidir. Her modül için, o modüldeki her öznitelik, işlev, sınıf ve istisnayı özetler.

Garip bir şekilde, varsayılan sphinx.ext.autosummaryşablonlar her bir öznitelik, işlev, sınıf ve istisna için ayrı dokümantasyon sayfaları oluşturmaz ve bunlara özet tablolarından bağlantı verir. Şablonları aşağıda gösterildiği gibi genişletmek mümkündür, ancak bunun neden varsayılan davranış olmadığını anlayamıyorum - elbette çoğu insanın isteyeceği şey budur ..? Bunu bir özellik isteği olarak dile getirdim .

Varsayılan şablonları yerel olarak kopyalayıp onlara eklemem gerekiyordu:

  • Kopya site-packages/sphinx/ext/autosummary/templates/autosummary/module.rstiçinmytoolbox/doc/source/_templates/custom-module-template.rst
  • Kopya site-packages/sphinx/ext/autosummary/templates/autosummary/class.rstiçinmytoolbox/doc/source/_templates/custom-class-template.rst

İçine kanca custom-module-template.rstiçindedir index.rstkullanılarak yukarıda :template:seçeneği. (Varsayılan site paketleri şablonlarını kullanarak ne olduğunu görmek için bu satırı silin.)

custom-module-template.rst (sağda belirtilen ek satırlar):

{{ 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 (sağda belirtilen ek satırlar):

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

Bunun için çok teşekkür ederim !!! Neredeyse pes etmek üzereydim ve sonunda bunu buldum. Bir soru. Ben kullanıyordum sys.path.insert(0, os.path.abspath('../../mypackage'))ama sen sadece kullanıyorsun '../..'. Neden bir fark yaratmıyor?
samlaf

Sorun değil, yardımcı olmasına sevindim. Sphinx, anlayana kadar beni neredeyse delirtti; şimdi hepsi güzel çalışıyor. İçinde index.rst, :recursive:docstring ayıklamanın başlamasını istediğiniz paketi açıkça adlandırmanız gerekir , yani benim örneğimde mypackage. İçinde conf.py, sadece o konuma giden rotayı sağlarsınız. Bunun nedeni benim örneğimde mypackageüst düzey bir klasör olması mytoolbox, ancak (örneğin) bir source/mypackagealt klasörde yuvalanmış conf.pyolsaydı, o zaman okurdu ../../source.
sıkıştı

12

Her pakette, __init__.pydosya .. automodule:: package.module, paketin her bölümü için bileşenlere sahip olabilir .

O zaman yapabilirsin .. automodule:: packageve çoğunlukla istediğini yapar.


init .py içindeki bu dizeyi üçlü tırnak içine mi koymalıyım?
Cory Walker

5
@Cory Walker: "A" dizesi değil. Sen - ve gereken - her dosyada üçlü alıntılanan Docstringler koyarak. Herkes. Bu, __init__.pypaketlerinizdeki dosyaları içerir . Doküman dizgisi .. automodule::, paketteki modüller de dahil olmak üzere HERHANGİ Sphinx dokümantasyon direktifini içerebilir .
S. Lot


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.