Jednou ze zásadních součástí každého kvalitního Python projektu je dokumentace. Protože chceme, abyste vytvářeli kvalitní projekty, podíváme se tedy i na dokumentaci.
Nejpoužívanějším nástrojem na vytváření dokumentace Python projektů je Sphinx. Když jste se dívali do dokumentace Flasku, requests, clicku, flexmocku, pytestu, betamaxu či Pythonu samotného, viděli jste dokumentaci vytvořenou ve Sphinxu.
Pro vytvoření základní kostry dokumentace se používá jednoduchý průvodce,
sphinx.quickstart
.
Postupujte podle následující ukázky. Jsou v ní zobrazeny jen věci,
kde nestačí nechat výchozí hodnota; u ostatních otázek stačí výchozí hodnotu
potvrdit (Enter).
K modulům autodoc
a doctest
se dostaneme později.
$ . __venv__/bin/activate
(__venv__) $ python -m pip install sphinx
(__venv__) $ mkdir docs
(__venv__) $ cd docs
(__venv__) $ python -m sphinx.quickstart
Welcome to the Sphinx 1.8.1 quickstart utility.
Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).
Selected root path: .
You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]:
Inside the root directory, two more directories will be created; "_templates"
for custom HTML templates and "_static" for custom stylesheets and other static
files. You can enter another prefix (such as ".") to replace the underscore.
> Name prefix for templates and static dir [_]:
The project name will occur in several places in the built documentation.
> Project name: coolthing
> Author name(s): Pythonista Dokumentarista
> Project release []: 0.1
...
Please indicate if you want to use one of the following Sphinx extensions:
> autodoc: automatically insert docstrings from modules (y/n) [n]: y
> doctest: automatically test code snippets in doctest blocks (y/n) [n]: y
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]: y
...
Finished: An initial directory structure has been created.
Průvodce vytvoří ve složce docs
několik souborů:
conf.py
– konfigurační soubor,index.rst
– vlastní text dokumantace,Makefile
, make.bat
– spouštěcí soubory,_static
– adresář na obrázky, CSS apod.,_templates
– Adresář na vlastní šablony,_build
– adresář pro výstup, tedy hotovou dokumentaci.Do gitu patří všechny nyní vytvořené soubory, kromě složky docs/_build
,
která by měla být ignorována.
Zatím se nebudeme zabývat obsahem těchto souborů, ale zkusíme základní kostru dokumentace sestavit do HTML.
Sphinx umí generovat dokumentaci ve více formátech (LaTeX, manuálové stránky atd.), pro nás bude podstatné především HTML.
(__venv__) $ make html
...
The HTML pages are in _build/html.
Ve zmíněné složce byste měli najít index.html
, ten si můžete prohlédnout
v prohlížeči.
Text dokumentace začíná v souboru index.rst
a píše se ve značkovacím formátu
reStructuredText neboli rst. Bohužel nelze psát v Markdownu, ačkoli existují
složité triky, jak docílit nějaké konverze.
reStructuredText se od Markdownu liší v syntaxi, která je komplikovanější na psaní, ale umožňuje dělat komplexnější věci.
Pro přehled o tom, co reStructuredText umí a jakou má syntaxi, můžete použít přehled z dokumentace Sphinxu, případně tahák.
V index.rst
je seznam kapitol:
.. toctree::
:maxdepth: 2
Tam můžete přidat další kapitoly:
.. toctree::
:maxdepth: 2
intro
tutorial/foo
tutorial/bar
...
Soubory s kapitolami je třeba vytvořit ve složce docs
s příponou .rst
(např. tutorial/foo.rst
).
Text lze pak přidávat samozřejmě do těchto souborů i do
index.rst
.
Chcete-li odkazovat na některou sekci, označíme si ji pomocí .. _label:
:
.. _my-reference-label:
Section to cross-reference
--------------------------
This is the text of the section.
Poté na ni lze odkazovat odkudkoli z dokumentace pomocí konstrukce ref:
It refers to the section itself, see :ref:`my-reference-label`.
It could refer to a different section as well :)
Teď, když víte jak něco napsat, pojďme si povědět co vlastně psát. K čemu dokumentace vlastně je?
Dobrá dokumentace vysvětluje, proč a jak by váš projekt měl někdo používat. Jak říká Eric Holscher v jedné své prezentaci,
Když lidi neví, že váš projekt existuje,
nebudou ho používat.
Když lidi nepřijdou na to, jak váš projekt nainstalovat,
nebudou ho používat.
Když lidi nepřijdou na to, jak váš projekt použít,
nebudou ho používat.
Pokud pracujete v malém týmu, teoreticky jde to všechno kolegům prostě říct, ale potom se musíte spoléhat na to, že to nezapomenete (a neodejdete z týmu). Mnohem lepší je dokumentaci sepsat co nejdřív, dokud máte všechno čerstvě v hlavě.
Nechce-li se vám nastavovat Sphinx, můžete informace napsat aspoň do malého README. Ale i tam by měl být stejný druh informací jako ve „velké“ dokumentaci.
Na první stránce dokumentace (nebo v README) typicky najdeme:
Delší dokumentace knihoven pak většinou obsahuje:
doctest
je modul ze standardní knihovny, který najde v dokumentaci bloky kódu
a otestuje, jestli odpovídají ukázanému výstupu.
Pro nás to bude způsob, jak testovat dokumentaci – tedy jestli jsou ukázky kódu v ní stále platné. Dá se sice použít i k testování samotného kódu, ale na to existují lepší nástroje.
V kombinaci se Sphinxem se dá použít rozšíření doctest
, které jsme v průvodci
aktivovali. Můžete to dělat dvěma způsoby. První je mít v dokumentaci
příklad vypadající jako interaktivní konzole.
Takový příklad nemusí být odsazený ani ničím uvozený; stačí >>>
na začátku.
>>> 1 + 1
2
Doctest v tomto případě otestuje, že vše funguje, jak má. V tomto případě se provede součet a zkontroluje se, zda výsledek je 2.
Druhý způsob je mít v dokumentaci nejdříve kód:
print('foo')
A dále někde jinde výstup volání:
foo
K tomu všemu složí několik direktiv:
Direktiva pro potřebný kód, který se musí provést, aby příklad fungoval, ale nebude v dokumentaci zobrazen (např. kód pro vytvoření falešného objektu, import...).
Podobná direktiva jako .. testsetup::
provedená po skončení testů.
V dokumentaci nebude kód zobrazen.
Test s interaktivní konzolí. V dokumentaci bude zobrazen, pokud nepoužijete flag
:hide:
.
Kód testu bez interaktivní konzole, co chcete kontrolovat, musíte dát na
standardní výstup. V dokumentaci bude zobrazen, pokud nepoužijete flag
:hide:
.
Výstup posledního testcode bloku. V dokumentaci bude kód zobrazen, pokud
nepoužijete flag :hide:
.
Zde můžete vidět výše zmíněné direktivy použité dohromady.
Jedná se o umělý příklad, kdy použitou třídu připravíme v direktivě testsetup
.
V praxi pak doctestem testujeme, jestli naše dokumentace odpovídá chování
naší implementace, třídu Parrot
bychom tedy odněkud naimportovali.
The parrot module
=================
.. testsetup::
class Parrot:
def voom(self, voltage):
print('This parrot wouldn\'t voom if you put {} volts through it!'.format(voltage))
def die(self):
return 'RIP'
parrot = Parrot()
The parrot module is a module about parrots.
Doctest example:
.. doctest::
>>> parrot.voom(3000)
This parrot wouldn't voom if you put 3000 volts through it!
Test-Output example:
.. testcode::
parrot.voom(3000)
This would output:
.. testoutput::
This parrot wouldn't voom if you put 3000 volts through it!
You can use other values:
.. testcode::
parrot.voom(230)
.. testoutput::
:hide:
This parrot wouldn't voom if you put 230 volts through it!
.. testcleanup::
parrot.die()
Testy se také dají zařazovat do skupin, více v dokumentaci.
(__venv__) $ make doctest
...
Document: intro
---------------
1 items passed all tests:
3 tests in default
3 tests in 1 items.
3 passed and 0 failed.
Test passed.
1 items passed all tests:
1 tests in default (cleanup code)
1 tests in 1 items.
1 passed and 0 failed.
Test passed.
Doctest summary
===============
3 tests
0 failures in tests
0 failures in setup code
0 failures in cleanup code
...
Pokud nemáte nainstalovaný vlastní balíček a budete z něj chtít v doctestu
importovat, pravděpodobně dostanete ImportError
.
V takovém případě pomůže drobná editace na začátku conf.py
.
Musíte přidat adresář, ze kterého lze váš kód importovat, do sys.path
.
Pokud jste postupovali podle návodu výše, máte dokumentaci v adresáři docs
,
je tedy potřeba přidat nadřazený adresář (..
):
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
Neexistuje žádný unifikovaný způsob, jak specifikovat závislosti pro sestavení
dokumentace. Proto, pokud chcete mít nějaký jednoduchý způsob, jak pouštět
doctesty na Travisu, vytvořte například soubor docs/requirements.txt
a do něj dejte závislosti potřebné pro sestavení dokumentace.
Je na vás, jestli tam budou pouze extra závislosti oproti těm v setup.py
(většinou pouze sphinx
), nebo všechny závislosti, aby šel použít soubor
samostatně.
Poté na Travisu můžete udělat něco jako:
language: python
python:
- '3.7'
install:
- python setup.py install
- pip install -r docs/requirements.txt
script:
- python setup.py test --addopts -v
- cd docs && make doctest
Pro dokumentaci API lze použít autodoc
, rozšíření Sphinxu, které jsme povolili
v průvodci.
Nemáte-li toto rozšíření povolené, přidejte jej do conf.py
:
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
]
Rozšíření autodoc
se používá takto:
.. automodule:: mymodule
:members:
Tento příklad na dané místo vygeneruje dokumentaci složenou z dokumentačních
řetězců jednotlivých funkcí, tříd a metod v modulu mymodule
.
Pokud chcete selektivně vybrat, dokumentaci čeho chcete generovat, můžete použít i jiné direktivy.
Pro vygenerování hezké struktury si můžete pomoci příkazem apidoc
:
(__venv__) $ python -m sphinx.apidoc -o docs mymodule
V dokumentačních řetězcích samozřejmě můžete použít reStructuredText a je to dokonce žádoucí.
Zde je ukázka z betamaxu (Copyright 2013 Ian Cordasco):
class Betamax:
"""This object contains the main API of the request-vcr library.
This object is entirely a context manager so all you have to do is:
.. code::
s = requests.Session()
with Betamax(s) as vcr:
vcr.use_cassette('example')
r = s.get('https://httpbin.org/get')
Or more concisely, you can do:
.. code::
s = requests.Session()
with Betamax(s).use_cassette('example') as vcr:
r = s.get('https://httpbin.org/get')
This object allows for the user to specify the cassette library directory
and default cassette options.
.. code::
s = requests.Session()
with Betamax(s, cassette_library_dir='tests/cassettes') as vcr:
vcr.use_cassette('example')
r = s.get('https://httpbin.org/get')
with Betamax(s, default_cassette_options={
're_record_interval': 1000
}) as vcr:
vcr.use_cassette('example')
r = s.get('https://httpbin.org/get')
"""
Existují různé způsoby, jak dokumentovat argumenty, návratové hodnoty apod. Zvídavým studentům doporučujeme podívat se na rozšíření Napoleon.
Máte-li zdokumentovaný modul, funkci, třídu, metodu apod., je možné na ni
odkázat pomocí konstrukce :mod:
, :func:
, :class:
, :meth:
a dalších
ze Sphinxové domény Python:
To test the parrot's electrical resistance, use :meth:`parrot.voom()`.
V této části dokumentace Sphinxu též najdete způsob, jak dokumentovat API
bez použití autodoc
.
Všechny zdokumentované objekty se automaticky přidávají do rejstříku. Chcete-li do rejstříku přidat něco navíc, použijte direktivu index.
Když už se stejně zabýváme reStructuredTextem, je dobré váš README přepsat nebo převést do stejného formátu. Na PyPI pak bude váš projekt vypadat lépe.
Při přejmenování na README.rst
dejte pozor na patřičné změny v setup.py
.
Pokud svůj repositář na GitHubu změníte na veřejný, můžete využít službu Read the Docs k hostování dokumentace ve Sphinxu. Dokumentace se sestaví při každém pushnutí na GitHub.
Pokud Read the Docs použijete, nezapomeňte na dokumentaci odkázat
z README.rst
.
{ "data": { "sessionMaterial": { "id": "session-material:2019/mipyt-zima:docs:0", "title": "Dokumentace", "html": "\n \n \n\n <h1>Dokumentace</h1>\n<p>Jednou ze zásadních součástí každého kvalitního Python projektu je dokumentace.\nProtože chceme, abyste vytvářeli kvalitní projekty, podíváme se tedy i na\ndokumentaci.</p>\n<h2>Sphinx</h2>\n<p>Nejpoužívanějším nástrojem na vytváření dokumentace Python projektů je <a href=\"http://www.sphinx-doc.org/\">Sphinx</a>.\nKdyž jste se dívali do dokumentace Flasku, requests, clicku, flexmocku, pytestu,\nbetamaxu či Pythonu samotného, viděli jste dokumentaci vytvořenou ve Sphinxu.</p>\n<p>Pro vytvoření základní kostry dokumentace se používá jednoduchý průvodce,\n<code>sphinx.quickstart</code>.</p>\n<p>Postupujte podle následující ukázky. Jsou v ní zobrazeny jen věci,\nkde nestačí nechat výchozí hodnota; u ostatních otázek stačí výchozí hodnotu\npotvrdit (<kbd>Enter</kbd>).\nK modulům <code>autodoc</code> a <code>doctest</code> se dostaneme později.</p>\n<div class=\"highlight\"><pre><code><span style=\"color: #00aaaa\">$</span> . __venv__/bin/activate\n<span style=\"color: #00aaaa\">(__venv__) $</span> python -m pip install sphinx\n<span style=\"color: #00aaaa\">(__venv__) $</span> mkdir docs\n<span style=\"color: #00aaaa\">(__venv__) $</span> cd docs\n<span style=\"color: #00aaaa\">(__venv__) $</span> python -m sphinx.quickstart\n<span style=\"font-weight: bold\">Welcome to the Sphinx 1.8.1 quickstart utility.</span>\n\nPlease enter values for the following settings (just press Enter to\naccept a default value, if one is given in brackets).\n\n<span style=\"font-weight: bold\">Selected root path: .</span>\n\nYou have two options for placing the build directory for Sphinx output.\nEither, you use a directory "_build" within the root path, or you separate\n"source" and "build" directories within the root path.\n<span style=\"color: #E850A8\">> Separate source and build directories (y/n) [n]: </span>\n\nInside the root directory, two more directories will be created; "_templates"\nfor custom HTML templates and "_static" for custom stylesheets and other static\nfiles. You can enter another prefix (such as ".") to replace the underscore.\n<span style=\"color: #E850A8\">> Name prefix for templates and static dir [_]: </span>\n\nThe project name will occur in several places in the built documentation.\n<span style=\"color: #E850A8\">> Project name: </span>coolthing\n<span style=\"color: #E850A8\">> Author name(s): </span>Pythonista Dokumentarista\n<span style=\"color: #E850A8\">> Project release []: </span> 0.1\n\n...\n\nPlease indicate if you want to use one of the following Sphinx extensions:\n<span style=\"color: #E850A8\">> autodoc: automatically insert docstrings from modules (y/n) [n]: </span>y\n<span style=\"color: #E850A8\">> doctest: automatically test code snippets in doctest blocks (y/n) [n]: </span>y\n<span style=\"color: #E850A8\">> intersphinx: link between Sphinx documentation of different projects (y/n) [n]: </span>y\n\n...\n\n<span style=\"font-weight: bold\">Finished: An initial directory structure has been created.</span></code></pre></div><p>Průvodce vytvoří ve složce <code>docs</code> několik souborů:</p>\n<ul>\n<li><code>conf.py</code> – konfigurační soubor,</li>\n<li><code>index.rst</code> – vlastní text dokumantace,</li>\n<li><code>Makefile</code>, <code>make.bat</code> – spouštěcí soubory,</li>\n<li><code>_static</code> – adresář na obrázky, CSS apod.,</li>\n<li><code>_templates</code> – Adresář na vlastní šablony,</li>\n<li><code>_build</code> – adresář pro výstup, tedy hotovou dokumentaci.</li>\n</ul>\n<p>Do gitu patří všechny nyní vytvořené soubory, kromě složky <code>docs/_build</code>,\nkterá by měla být ignorována.</p>\n<p>Zatím se nebudeme zabývat obsahem těchto souborů, ale zkusíme základní kostru\ndokumentace sestavit do HTML.</p>\n<div class=\"admonition note\"><p>Sphinx umí generovat dokumentaci ve více formátech (LaTeX,\nmanuálové stránky atd.), pro nás bude podstatné především HTML.</p>\n</div><div class=\"highlight\"><pre><span></span><span class=\"gp\">(__venv__) $ </span>make html\n<span class=\"go\">...</span>\n<span class=\"go\">The HTML pages are in _build/html.</span>\n</pre></div><p>Ve zmíněné složce byste měli najít <code>index.html</code>, ten si můžete prohlédnout\nv prohlížeči.</p>\n<h2>Textový obsah v dokumentaci</h2>\n<p>Text dokumentace začíná v souboru <code>index.rst</code> a píše se ve značkovacím formátu\n<a href=\"http://www.sphinx-doc.org/en/stable/rest.html\">reStructuredText</a> neboli rst. Bohužel nelze psát v Markdownu, ačkoli existují\nsložité triky, jak docílit nějaké konverze.</p>\n<p>reStructuredText se od Markdownu liší v syntaxi, která je komplikovanější na\npsaní, ale umožňuje dělat komplexnější věci.</p>\n<p>Pro přehled o tom, co reStructuredText umí a jakou má syntaxi,\nmůžete použít <a href=\"http://www.sphinx-doc.org/en/stable/rest.html\">přehled</a> z dokumentace Sphinxu, případně <a href=\"https://github.com/ralsina/rst-cheatsheet\">tahák</a>.</p>\n<p>V <code>index.rst</code> je seznam kapitol:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"p\">..</span> <span class=\"ow\">toctree</span><span class=\"p\">::</span>\n <span class=\"nc\">:maxdepth:</span> <span class=\"nf\">2</span>\n</pre></div><p>Tam můžete přidat další kapitoly:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"p\">..</span> <span class=\"ow\">toctree</span><span class=\"p\">::</span>\n <span class=\"nc\">:maxdepth:</span> <span class=\"nf\">2</span>\n\n intro\n tutorial/foo\n tutorial/bar\n<span class=\"cp\"> ...</span>\n</pre></div><p>Soubory s kapitolami je třeba vytvořit ve složce <code>docs</code> s příponou <code>.rst</code>\n(např. <code>tutorial/foo.rst</code>).\nText lze pak přidávat samozřejmě do těchto souborů i do\n<code>index.rst</code>.</p>\n<p>Chcete-li odkazovat na některou sekci, označíme si ji pomocí <code>.. _label:</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"p\">..</span> <span class=\"nt\">_my-reference-label:</span>\n\n<span class=\"gh\">Section to cross-reference</span>\n<span class=\"gh\">--------------------------</span>\n\nThis is the text of the section.\n</pre></div><p>Poté na ni lze odkazovat odkudkoli z dokumentace pomocí\n<a href=\"http://www.sphinx-doc.org/en/master/markup/inline.html#role-ref\">konstrukce ref</a>:</p>\n<div class=\"highlight\"><pre><span></span>It refers to the section itself, see <span class=\"na\">:ref:</span><span class=\"nv\">`my-reference-label`</span>.\nIt could refer to a different section as well :)\n</pre></div><h2>Co do dokumentace psát</h2>\n<p>Teď, když víte jak něco napsat, pojďme si povědět <em>co</em> vlastně psát.\nK čemu dokumentace vlastně je?</p>\n<p>Dobrá dokumentace vysvětluje, proč a jak by váš projekt měl někdo používat.\nJak říká Eric Holscher v <a href=\"http://www.writethedocs.org/guide/writing/beginners-guide-to-docs/\">jedné své prezentaci</a>,</p>\n<blockquote><p>Když lidi neví, že váš projekt existuje,<br>\nnebudou ho používat.<br>\nKdyž lidi nepřijdou na to, jak váš projekt nainstalovat,<br>\nnebudou ho používat.<br>\nKdyž lidi nepřijdou na to, jak váš projekt použít,<br>\nnebudou ho používat.<br></p>\n</blockquote>\n<p>Pokud pracujete v malém týmu, teoreticky jde to všechno kolegům prostě říct,\nale potom se musíte spoléhat na to, že to nezapomenete (a neodejdete z týmu).\nMnohem lepší je dokumentaci sepsat co nejdřív, dokud máte všechno čerstvě\nv hlavě.</p>\n<p>Nechce-li se vám nastavovat Sphinx, můžete informace napsat aspoň do malého\nREADME. Ale i tam by měl být stejný druh informací jako ve „velké“ dokumentaci.</p>\n<p>Na první stránce dokumentace (nebo v README) typicky najdeme:</p>\n<ul>\n<li>krátký text o tom, co projekt dělá;</li>\n<li>ukázku – u knihovny příklad kódu, u aplikace screenshot, u webové stránky\nodkaz na běžící instanci;</li>\n<li>návod na instalaci;</li>\n<li>odkazy na zbytek dokumentace;</li>\n<li>odkazy pro přispěvatele – kde je repozitář, kde nahlásit chybu;</li>\n<li>licenci.</li>\n</ul>\n<p>Delší dokumentace knihoven pak většinou obsahuje:</p>\n<ul>\n<li>tutoriál – návod, který uživatele provede použitím a možnostmi knihovny;</li>\n<li>popis architektury, návrhu, použitých konceptů;</li>\n<li>API dokumentaci – popis všech veřejných modulů, tříd, funkcí a podobně;</li>\n<li>podrobný návod jak přispívat.</li>\n</ul>\n<h2>doctest</h2>\n<p><code>doctest</code> je modul ze standardní knihovny, který najde v dokumentaci bloky kódu\na otestuje, jestli odpovídají ukázanému výstupu.</p>\n<p>Pro nás to bude způsob, jak testovat <em>dokumentaci</em> – tedy jestli jsou ukázky\nkódu v ní stále platné.\nDá se sice použít i k testování samotného kódu, ale na to existují\n<a href=\"/2019/mipyt-zima/intro/testing/\">lepší nástroje</a>.</p>\n<p>V kombinaci se Sphinxem se dá použít rozšíření <code>doctest</code>, které jsme v průvodci\naktivovali. Můžete to dělat dvěma způsoby. První je mít v dokumentaci\npříklad vypadající jako interaktivní konzole.\nTakový příklad nemusí být odsazený ani ničím uvozený; stačí <code>>>></code> na začátku.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"o\">>>></span> <span class=\"mi\">1</span> <span class=\"o\">+</span> <span class=\"mi\">1</span>\n<span class=\"mi\">2</span>\n</pre></div><p>Doctest v tomto případě otestuje, že vše funguje, jak má.\nV tomto případě se provede součet a zkontroluje se, zda výsledek je 2.</p>\n<p>Druhý způsob je mít v dokumentaci nejdříve kód:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">'foo'</span><span class=\"p\">)</span>\n</pre></div><p>A dále někde jinde výstup volání:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">foo</span>\n</pre></div><p>K tomu všemu složí několik direktiv:</p>\n<h3>.. testsetup::</h3>\n<p>Direktiva pro potřebný kód, který se musí provést, aby příklad fungoval, ale\nnebude v dokumentaci zobrazen (např. kód pro vytvoření falešného objektu,\nimport...).</p>\n<h3>.. testcleanup::</h3>\n<p>Podobná direktiva jako <code>.. testsetup::</code> provedená po skončení testů.\nV dokumentaci nebude kód zobrazen.</p>\n<h3>.. doctest::</h3>\n<p>Test s interaktivní konzolí. V dokumentaci bude zobrazen, pokud nepoužijete flag\n<code>:hide:</code>.</p>\n<h3>.. testcode::</h3>\n<p>Kód testu bez interaktivní konzole, co chcete kontrolovat, musíte dát na\nstandardní výstup. V dokumentaci bude zobrazen, pokud nepoužijete flag\n<code>:hide:</code>.</p>\n<h3>.. testoutput::</h3>\n<p>Výstup posledního testcode bloku. V dokumentaci bude kód zobrazen, pokud\nnepoužijete flag <code>:hide:</code>.</p>\n<h3>Kompletní příklad</h3>\n<p>Zde můžete vidět výše zmíněné direktivy použité dohromady.\nJedná se o umělý příklad, kdy použitou třídu připravíme v direktivě <code>testsetup</code>.\nV praxi pak doctestem testujeme, jestli naše dokumentace odpovídá chování\nnaší implementace, třídu <code>Parrot</code> bychom tedy odněkud naimportovali.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gh\">The parrot module</span>\n<span class=\"gh\">=================</span>\n\n<span class=\"p\">..</span> <span class=\"ow\">testsetup</span><span class=\"p\">::</span>\n\n class Parrot:\n def voom(self, voltage):\n print('This parrot wouldn\\'t voom if you put {} volts through it!'.format(voltage))\n\n def die(self):\n return 'RIP'\n\n\n parrot = Parrot()\n\nThe parrot module is a module about parrots.\n\nDoctest example:\n\n<span class=\"p\">..</span> <span class=\"ow\">doctest</span><span class=\"p\">::</span>\n\n >>> parrot.voom(3000)\n This parrot wouldn't voom if you put 3000 volts through it!\n\nTest-Output example:\n\n<span class=\"p\">..</span> <span class=\"ow\">testcode</span><span class=\"p\">::</span>\n\n parrot.voom(3000)\n\nThis would output:\n\n<span class=\"p\">..</span> <span class=\"ow\">testoutput</span><span class=\"p\">::</span>\n\n This parrot wouldn't voom if you put 3000 volts through it!\n\nYou can use other values:\n\n<span class=\"p\">..</span> <span class=\"ow\">testcode</span><span class=\"p\">::</span>\n\n parrot.voom(230)\n\n<span class=\"p\">..</span> <span class=\"ow\">testoutput</span><span class=\"p\">::</span>\n <span class=\"nc\">:hide:</span>\n\n This parrot wouldn't voom if you put 230 volts through it!\n\n\n<span class=\"p\">..</span> <span class=\"ow\">testcleanup</span><span class=\"p\">::</span>\n\n parrot.die()\n</pre></div><p>Testy se také dají zařazovat do skupin, více\nv <a href=\"http://www.sphinx-doc.org/en/master/ext/doctest.html\">dokumentaci</a>.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">(__venv__) $ </span>make doctest\n<span class=\"go\">...</span>\n<span class=\"go\">Document: intro</span>\n<span class=\"go\">---------------</span>\n<span class=\"go\">1 items passed all tests:</span>\n<span class=\"go\"> 3 tests in default</span>\n<span class=\"go\">3 tests in 1 items.</span>\n<span class=\"go\">3 passed and 0 failed.</span>\n<span class=\"go\">Test passed.</span>\n<span class=\"go\">1 items passed all tests:</span>\n<span class=\"go\"> 1 tests in default (cleanup code)</span>\n<span class=\"go\">1 tests in 1 items.</span>\n<span class=\"go\">1 passed and 0 failed.</span>\n<span class=\"go\">Test passed.</span>\n\n<span class=\"go\">Doctest summary</span>\n<span class=\"go\">===============</span>\n<span class=\"go\"> 3 tests</span>\n<span class=\"go\"> 0 failures in tests</span>\n<span class=\"go\"> 0 failures in setup code</span>\n<span class=\"go\"> 0 failures in cleanup code</span>\n<span class=\"go\">...</span>\n</pre></div><h3>Import z vlastního kódu</h3>\n<p>Pokud nemáte nainstalovaný vlastní balíček a budete z něj chtít v doctestu\nimportovat, pravděpodobně dostanete <code>ImportError</code>.\nV takovém případě pomůže drobná editace na začátku <code>conf.py</code>.\nMusíte přidat adresář, ze kterého lze váš kód importovat, do <code>sys.path</code>.\nPokud jste postupovali podle návodu výše, máte dokumentaci v adresáři <code>docs</code>,\nje tedy potřeba přidat nadřazený adresář (<code>..</code>):</p>\n<div class=\"highlight\"><pre><span></span><span class=\"c1\"># -- Path setup --------------------------------------------------------------</span>\n\n<span class=\"c1\"># If extensions (or modules to document with autodoc) are in another directory,</span>\n<span class=\"c1\"># add these directories to sys.path here. If the directory is relative to the</span>\n<span class=\"c1\"># documentation root, use os.path.abspath to make it absolute, like shown here.</span>\n<span class=\"c1\">#</span>\n<span class=\"kn\">import</span> <span class=\"nn\">os</span>\n<span class=\"kn\">import</span> <span class=\"nn\">sys</span>\n<span class=\"n\">sys</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">insert</span><span class=\"p\">(</span><span class=\"mi\">0</span><span class=\"p\">,</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">abspath</span><span class=\"p\">(</span><span class=\"s1\">'..'</span><span class=\"p\">))</span>\n</pre></div><h3>Travis CI</h3>\n<p>Neexistuje žádný unifikovaný způsob, jak specifikovat závislosti pro sestavení\ndokumentace. Proto, pokud chcete mít nějaký jednoduchý způsob, jak pouštět\ndoctesty na Travisu, vytvořte například soubor <code>docs/requirements.txt</code>\na do něj dejte závislosti potřebné pro sestavení dokumentace.\nJe na vás, jestli tam budou pouze extra závislosti oproti těm v <code>setup.py</code>\n(většinou pouze <code>sphinx</code>), nebo všechny závislosti, aby šel použít soubor\nsamostatně.</p>\n<p>Poté na Travisu můžete udělat něco jako:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"nt\">language</span><span class=\"p\">:</span> <span class=\"l l-Scalar l-Scalar-Plain\">python</span>\n<span class=\"nt\">python</span><span class=\"p\">:</span>\n<span class=\"p p-Indicator\">-</span> <span class=\"s\">'3.7'</span>\n<span class=\"nt\">install</span><span class=\"p\">:</span>\n<span class=\"p p-Indicator\">-</span> <span class=\"l l-Scalar l-Scalar-Plain\">python setup.py install</span>\n<span class=\"p p-Indicator\">-</span> <span class=\"l l-Scalar l-Scalar-Plain\">pip install -r docs/requirements.txt</span>\n<span class=\"nt\">script</span><span class=\"p\">:</span>\n<span class=\"p p-Indicator\">-</span> <span class=\"l l-Scalar l-Scalar-Plain\">python setup.py test --addopts -v</span>\n<span class=\"p p-Indicator\">-</span> <span class=\"l l-Scalar l-Scalar-Plain\">cd docs && make doctest</span>\n</pre></div><h2>autodoc</h2>\n<p>Pro dokumentaci API lze použít <code>autodoc</code>, rozšíření Sphinxu, které jsme povolili\nv průvodci.</p>\n<div class=\"admonition note\"><p>Nemáte-li toto rozšíření povolené, přidejte jej do <code>conf.py</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">extensions</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n <span class=\"s1\">'sphinx.ext.autodoc'</span><span class=\"p\">,</span>\n <span class=\"s1\">'sphinx.ext.doctest'</span><span class=\"p\">,</span>\n <span class=\"s1\">'sphinx.ext.intersphinx'</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</pre></div></div><p>Rozšíření <code>autodoc</code> se používá takto:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"p\">..</span> <span class=\"ow\">automodule</span><span class=\"p\">::</span> mymodule\n <span class=\"nc\">:members:</span>\n</pre></div><p>Tento příklad na dané místo vygeneruje dokumentaci složenou z dokumentačních\nřetězců jednotlivých funkcí, tříd a metod v modulu <code>mymodule</code>.</p>\n<p>Pokud chcete selektivně vybrat, dokumentaci čeho chcete generovat,\nmůžete použít i\n<a href=\"http://www.sphinx-doc.org/en/master/ext/autodoc.html#directive-automodule\">jiné direktivy</a>.</p>\n<p>Pro vygenerování hezké struktury si můžete pomoci příkazem <code>apidoc</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">(__venv__) $ </span>python -m sphinx.apidoc -o docs mymodule\n</pre></div><p>V dokumentačních řetězcích samozřejmě můžete použít <a href=\"http://www.sphinx-doc.org/en/stable/rest.html\">reStructuredText</a> a je to\ndokonce žádoucí.</p>\n<p>Zde je ukázka z betamaxu (<em>Copyright 2013 Ian Cordasco</em>):</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">class</span> <span class=\"nc\">Betamax</span><span class=\"p\">:</span>\n\n <span class=\"sd\">"""This object contains the main API of the request-vcr library.</span>\n\n<span class=\"sd\"> This object is entirely a context manager so all you have to do is:</span>\n\n<span class=\"sd\"> .. code::</span>\n\n<span class=\"sd\"> s = requests.Session()</span>\n<span class=\"sd\"> with Betamax(s) as vcr:</span>\n<span class=\"sd\"> vcr.use_cassette('example')</span>\n<span class=\"sd\"> r = s.get('https://httpbin.org/get')</span>\n\n<span class=\"sd\"> Or more concisely, you can do:</span>\n\n<span class=\"sd\"> .. code::</span>\n\n<span class=\"sd\"> s = requests.Session()</span>\n<span class=\"sd\"> with Betamax(s).use_cassette('example') as vcr:</span>\n<span class=\"sd\"> r = s.get('https://httpbin.org/get')</span>\n\n<span class=\"sd\"> This object allows for the user to specify the cassette library directory</span>\n<span class=\"sd\"> and default cassette options.</span>\n\n<span class=\"sd\"> .. code::</span>\n\n<span class=\"sd\"> s = requests.Session()</span>\n<span class=\"sd\"> with Betamax(s, cassette_library_dir='tests/cassettes') as vcr:</span>\n<span class=\"sd\"> vcr.use_cassette('example')</span>\n<span class=\"sd\"> r = s.get('https://httpbin.org/get')</span>\n\n<span class=\"sd\"> with Betamax(s, default_cassette_options={</span>\n<span class=\"sd\"> 're_record_interval': 1000</span>\n<span class=\"sd\"> }) as vcr:</span>\n<span class=\"sd\"> vcr.use_cassette('example')</span>\n<span class=\"sd\"> r = s.get('https://httpbin.org/get')</span>\n<span class=\"sd\"> """</span>\n</pre></div><p>Existují různé způsoby, jak dokumentovat argumenty, návratové hodnoty apod.\nZvídavým studentům doporučujeme podívat se na rozšíření <a href=\"http://www.sphinx-doc.org/en/master/ext/napoleon.html\">Napoleon</a>.</p>\n<h2>Odkazy na třídy a moduly</h2>\n<p>Máte-li zdokumentovaný modul, funkci, třídu, metodu apod., je možné na ni\nodkázat pomocí konstrukce <code>:mod:</code>, <code>:func:</code>, <code>:class:</code>, <code>:meth:</code> a dalších\nze Sphinxové <a href=\"http://www.sphinx-doc.org/en/master/domains.html#cross-referencing-python-objects\">domény Python</a>:</p>\n<div class=\"highlight\"><pre><span></span>To test the parrot's electrical resistance, use <span class=\"na\">:meth:</span><span class=\"nv\">`parrot.voom()`</span>.\n</pre></div><p>V této části dokumentace Sphinxu též najdete způsob, jak dokumentovat API\nbez použití <code>autodoc</code>.</p>\n<p>Všechny zdokumentované objekty se automaticky přidávají do rejstříku.\nChcete-li do rejstříku přidat něco navíc, použijte direktivu <a href=\"http://www.sphinx-doc.org/en/master/markup/misc.html#index-generating-markup\">index</a>.</p>\n<h2>README.rst</h2>\n<p>Když už se stejně zabýváme <a href=\"http://www.sphinx-doc.org/en/stable/rest.html\">reStructuredText</a>em, je dobré váš README přepsat\nnebo převést do stejného formátu. Na PyPI pak bude váš projekt vypadat lépe.</p>\n<p>Při přejmenování na <code>README.rst</code> dejte pozor na patřičné změny v <code>setup.py</code>.</p>\n<h2>Read the Docs</h2>\n<p>Pokud svůj repositář na GitHubu změníte na veřejný, můžete využít službu\n<a href=\"https://readthedocs.org/\">Read the Docs</a> k hostování dokumentace ve Sphinxu.\nDokumentace se sestaví při každém pushnutí na GitHub.</p>\n<p>Pokud Read the Docs použijete, nezapomeňte na dokumentaci odkázat\nz <code>README.rst</code>.</p>\n\n\n " } } }