Merged in knzm/sphinx-fix-docfields-fork (pull request #96)
29
CHANGES
@@ -1,6 +1,35 @@
|
||||
Release 1.2 (in development)
|
||||
============================
|
||||
|
||||
* #1062: sphinx.ext.autodoc use __init__ method signature for class signature.
|
||||
|
||||
* PR#111: Respect add_autodoc_attrgetter() even when inherited-members is set.
|
||||
Thanks to A. Jesse Jiryu Davis.
|
||||
|
||||
* #1090: Fix gettext does not extract glossary terms.
|
||||
|
||||
* #1070: Avoid un-pickling issues when running Python 3 and the saved
|
||||
environment was created under Python 2.
|
||||
|
||||
* #1069: Fixed error caused when autodoc would try to format signatures of
|
||||
"partial" functions without keyword arguments (patch by Artur Gaspar).
|
||||
|
||||
* The :confval:`latex_documents`, :confval:`texinfo_documents`, and
|
||||
:confval:`man_pages` configuration values will be set to default values based
|
||||
on the :confval:`master_doc` if not explicitly set in :file:`conf.py`.
|
||||
Previously, if these values were not set, no output would be genereted by
|
||||
their respective builders.
|
||||
|
||||
* The :rst:dir:`toctree` directive and the ``toctree()`` template function now
|
||||
have an ``includehidden`` option that includes hidden toctree entries (bugs
|
||||
#790 and #1047). A bug in the ``maxdepth`` option for the ``toctree()``
|
||||
template function has been fixed (bug #1046).
|
||||
|
||||
* PR#99: Strip down seealso directives to normal admonitions. This removes
|
||||
their unusual CSS classes (admonition-see-also), inconsistent LaTeX
|
||||
admonition title ("See Also" instead of "See also"), and spurious indentation
|
||||
in the text builder.
|
||||
|
||||
* sphinx-build now has a verbose option :option:`-v` which can be
|
||||
repeated for greater effect. A single occurrance provides a
|
||||
slightly more verbose output than normal. Two or more occurrences
|
||||
|
||||
BIN
doc/_static/pocoo.png
vendored
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.1 KiB |
26
doc/_templates/index.html
vendored
@@ -17,25 +17,23 @@
|
||||
documentation of Python projects, but C/C++ is already supported as well,
|
||||
and it is planned to add special support for other languages as well. Of
|
||||
course, this site is also created from reStructuredText sources using
|
||||
Sphinx!
|
||||
</p>
|
||||
<p>
|
||||
Sphinx is under constant development. The following features are present,
|
||||
work fine and can be seen “in action” in the Python docs:
|
||||
Sphinx! The following features should be highlighted:
|
||||
</p>
|
||||
<ul>
|
||||
<li><b>Output formats:</b> HTML (including Windows HTML Help), LaTeX (for
|
||||
printable PDF versions), manual pages, plain text</li>
|
||||
printable PDF versions), Texinfo, manual pages, plain text</li>
|
||||
<li><b>Extensive cross-references:</b> semantic markup and automatic links
|
||||
for functions, classes, citations, glossary terms and similar pieces of
|
||||
information</li>
|
||||
<li><b>Hierarchical structure:</b> easy definition of a document tree, with
|
||||
automatic links to siblings, parents and children</li>
|
||||
<li><b>Automatic indices:</b> general index as well as a module index</li>
|
||||
<li><b>Automatic indices:</b> general index as well as a language-specific
|
||||
module indices</li>
|
||||
<li><b>Code handling:</b> automatic highlighting using the <a
|
||||
href="http://pygments.org">Pygments</a> highlighter</li>
|
||||
<li><b>Extensions:</b> automatic testing of code snippets, inclusion of
|
||||
docstrings from Python modules (API docs), and more</li>
|
||||
docstrings from Python modules (API docs), and
|
||||
<a href="{{ pathto('ext') }}">more</a></li>
|
||||
</ul>
|
||||
<p>
|
||||
Sphinx uses <a href="http://docutils.sf.net/rst.html">reStructuredText</a>
|
||||
@@ -44,7 +42,7 @@
|
||||
suite, the <a href="http://docutils.sf.net/">Docutils</a>.
|
||||
</p>
|
||||
|
||||
<h2>Documentation</h2>
|
||||
<h2 style="margin-bottom: 0">Documentation</h2>
|
||||
|
||||
<table class="contentstable" align="center" style="margin-left: 30px"><tr>
|
||||
<td width="50%">
|
||||
@@ -86,14 +84,4 @@
|
||||
<p>There is a <a href="http://sphinx-users.jp/doc10/">Japanese translation</a>
|
||||
of this documentation, thanks to Yoshiki Shibukawa.</p>
|
||||
|
||||
<h2>Get Sphinx</h2>
|
||||
<p>
|
||||
Sphinx is available as an <a
|
||||
href="http://peak.telecommunity.com/DevCenter/EasyInstall">easy-install</a>able
|
||||
package on the <a href="http://pypi.python.org/pypi/Sphinx">Python Package
|
||||
Index</a>.
|
||||
</p>
|
||||
<p>The code can be found in a Mercurial repository, at
|
||||
<tt>http://bitbucket.org/birkenfeld/sphinx/</tt>.</p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
11
doc/_templates/indexsidebar.html
vendored
@@ -1,5 +1,5 @@
|
||||
<p class="logo"><a href="http://pocoo.org/">
|
||||
<img src="{{ pathto("_static/pocoo.png", 1) }}" /></a></p>
|
||||
<p class="logo">A <a href="http://pocoo.org/">
|
||||
<img src="{{ pathto("_static/pocoo.png", 1) }}" /></a> project</a></p>
|
||||
|
||||
<h3>Download</h3>
|
||||
{% if version.endswith('(hg)') %}
|
||||
@@ -22,9 +22,10 @@ are also available.</p>
|
||||
|
||||
<p>Join the <a href="http://groups.google.com/group/sphinx-users">Google group</a>:</p>
|
||||
<form action="http://groups.google.com/group/sphinx-users/boxsubscribe"
|
||||
style="padding-left: 1em">
|
||||
<input type="text" name="email" value="your@email"/>
|
||||
<input type="submit" name="sub" value="Subscribe" />
|
||||
style="padding-left: 0.5em">
|
||||
<input type="text" name="email" value="your@email" style="font-size: 90%; width: 120px"
|
||||
onfocus="$(this).val('');"/>
|
||||
<input type="submit" name="sub" value="Subscribe" style="font-size: 90%; width: 70px"/>
|
||||
</form>
|
||||
<p>or come to the <tt>#pocoo</tt> channel on FreeNode.</p>
|
||||
<p>You can also open an issue at the
|
||||
|
||||
23
doc/_templates/layout.html
vendored
@@ -1,23 +0,0 @@
|
||||
{% extends "!layout.html" %}
|
||||
|
||||
{% block extrahead %}
|
||||
{{ super() }}
|
||||
{%- if not embedded %}
|
||||
<style type="text/css">
|
||||
table.right { float: right; margin-left: 20px; }
|
||||
table.right td { border: 1px solid #ccc; }
|
||||
</style>
|
||||
{%- endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block rootrellink %}
|
||||
<li><a href="{{ pathto('index') }}">Sphinx home</a> | </li>
|
||||
<li><a href="{{ pathto('contents') }}">Documentation</a>
|
||||
»</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
<div style="background-color: white; text-align: left; padding: 10px 10px 15px 15px">
|
||||
<img src="{{ pathto("_static/sphinx.png", 1) }}" alt="Sphinx logo" />
|
||||
</div>
|
||||
{% endblock %}
|
||||
78
doc/_themes/sphinx13/layout.html
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
{#
|
||||
sphinxdoc/layout.html
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sphinx layout template for the sphinxdoc theme.
|
||||
|
||||
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
#}
|
||||
{%- extends "basic/layout.html" %}
|
||||
|
||||
{# put the sidebar before the body #}
|
||||
{% block sidebar1 %}{{ sidebar() }}{% endblock %}
|
||||
{% block sidebar2 %}{% endblock %}
|
||||
|
||||
{% block extrahead %}
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400,700'
|
||||
rel='stylesheet' type='text/css'>
|
||||
{{ super() }}
|
||||
{%- if not embedded %}
|
||||
<style type="text/css">
|
||||
table.right { float: right; margin-left: 20px; }
|
||||
table.right td { border: 1px solid #ccc; }
|
||||
{% if pagename == 'index' %}
|
||||
.related { display: none; }
|
||||
{% endif %}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
// intelligent scrolling of the sidebar content
|
||||
$(window).scroll(function() {
|
||||
var sb = $('.sphinxsidebarwrapper');
|
||||
var win = $(window);
|
||||
var sbh = sb.height();
|
||||
var offset = $('.sphinxsidebar').position()['top'];
|
||||
var wintop = win.scrollTop();
|
||||
var winbot = wintop + win.innerHeight();
|
||||
var curtop = sb.position()['top'];
|
||||
var curbot = curtop + sbh;
|
||||
// does sidebar fit in window?
|
||||
if (sbh < win.innerHeight()) {
|
||||
// yes: easy case -- always keep at the top
|
||||
sb.css('top', $u.min([$u.max([0, wintop - offset - 10]),
|
||||
$(document).height() - sbh - 200]));
|
||||
} else {
|
||||
// no: only scroll if top/bottom edge of sidebar is at
|
||||
// top/bottom edge of window
|
||||
if (curtop > wintop && curbot > winbot) {
|
||||
sb.css('top', $u.max([wintop - offset - 10, 0]));
|
||||
} else if (curtop < wintop && curbot < winbot) {
|
||||
sb.css('top', $u.min([winbot - sbh - offset - 20,
|
||||
$(document).height() - sbh - 200]));
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{%- endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block rootrellink %}
|
||||
<li><a href="{{ pathto('index') }}">Sphinx home</a> |</li>
|
||||
<li><a href="{{ pathto('contents') }}">Documentation</a> »</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
<div class="pageheader">
|
||||
<ul>
|
||||
<li><a href="{{ pathto('index') }}">Home</a></li>
|
||||
<li><a href="{{ pathto('install') }}">Get it</a></li>
|
||||
<li><a href="{{ pathto('contents') }}">Docs</a></li>
|
||||
<li><a href="{{ pathto('develop') }}">Extend/Develop</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<a href="{{ pathto('index') }}">
|
||||
<img src="{{ pathto('_static/sphinxheader.png', 1) }}" alt="SPHINX" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
BIN
doc/_themes/sphinx13/static/bodybg.png
vendored
Normal file
|
After Width: | Height: | Size: 602 B |
BIN
doc/_themes/sphinx13/static/footerbg.png
vendored
Normal file
|
After Width: | Height: | Size: 313 B |
BIN
doc/_themes/sphinx13/static/headerbg.png
vendored
Normal file
|
After Width: | Height: | Size: 344 B |
BIN
doc/_themes/sphinx13/static/listitem.png
vendored
Normal file
|
After Width: | Height: | Size: 207 B |
BIN
doc/_themes/sphinx13/static/relbg.png
vendored
Normal file
|
After Width: | Height: | Size: 332 B |
396
doc/_themes/sphinx13/static/sphinx13.css
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* sphinx13.css
|
||||
* ~~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- sphinx13 theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
||||
'Verdana', sans-serif;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
background-image: url(bodybg.png);
|
||||
color: black;
|
||||
padding: 0;
|
||||
border-right: 1px solid #0a507a;
|
||||
border-left: 1px solid #0a507a;
|
||||
|
||||
margin: 0 auto;
|
||||
min-width: 780px;
|
||||
max-width: 1080px;
|
||||
}
|
||||
|
||||
.pageheader {
|
||||
background-image: url(headerbg.png);
|
||||
text-align: left;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.pageheader ul {
|
||||
float: right;
|
||||
color: white;
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
margin-top: 30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.pageheader li {
|
||||
float: left;
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
|
||||
.pageheader li a {
|
||||
border-radius: 1px;
|
||||
padding: 8px 12px;
|
||||
color: #f9f9f0;
|
||||
text-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.pageheader li a:hover {
|
||||
background-color: #f9f9f0;
|
||||
color: #0a507a;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
div.document {
|
||||
background-color: white;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 240px 0 0;
|
||||
border-right: 1px solid #0a507a;
|
||||
}
|
||||
|
||||
div.body {
|
||||
margin: 0;
|
||||
padding: 0.5em 20px 20px 20px;
|
||||
}
|
||||
|
||||
div.related {
|
||||
font-size: 1em;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
background-image: url(relbg.png);
|
||||
height: 1.9em;
|
||||
border-top: 1px solid #002e50;
|
||||
border-bottom: 1px solid #002e50;
|
||||
}
|
||||
|
||||
div.related ul li {
|
||||
margin: 0 5px 0 0;
|
||||
padding: 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.related ul li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
div.related ul li a {
|
||||
margin: 0;
|
||||
padding: 0 5px 0 5px;
|
||||
line-height: 1.75em;
|
||||
color: #f9f9f0;
|
||||
text-shadow: 0px 0px 1px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
div.related ul li a:hover {
|
||||
color: white;
|
||||
/*text-decoration: underline;*/
|
||||
text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
position: relative;
|
||||
top: 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
margin: 0;
|
||||
padding: 0 15px 15px 0;
|
||||
width: 210px;
|
||||
float: right;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.sphinxsidebar .logo {
|
||||
font-size: 1.8em;
|
||||
color: #0A507A;
|
||||
font-weight: 300;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.sphinxsidebar .logo img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #aaa;
|
||||
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
||||
'Verdana', sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 {
|
||||
font-size: 1.5em;
|
||||
border-top: 1px solid #0a507a;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-size: 1.2em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3, div.sphinxsidebar h4 {
|
||||
margin-right: -15px;
|
||||
margin-left: -15px;
|
||||
padding-right: 14px;
|
||||
padding-left: 14px;
|
||||
color: #333;
|
||||
font-weight: 300;
|
||||
/*text-shadow: 0px 0px 0.5px rgba(0, 0, 0, 0.4);*/
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper > h3:first-child {
|
||||
margin-top: 0.5em;
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
color: #444;
|
||||
margin-top: 7px;
|
||||
padding: 0;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-left: 20px;
|
||||
list-style-image: url(listitem.png);
|
||||
}
|
||||
|
||||
div.footer {
|
||||
background-image: url(footerbg.png);
|
||||
color: #ccc;
|
||||
text-shadow: 0 0 .2px rgba(255, 255, 255, 0.8);
|
||||
padding: 3px 8px 3px 0;
|
||||
clear: both;
|
||||
font-size: 0.8em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* no need to make a visible link to Sphinx on the Sphinx page */
|
||||
div.footer a {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
p {
|
||||
margin: 0.8em 0 0.5em 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #A2881D;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #E1C13F;
|
||||
}
|
||||
|
||||
div.body a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 10px 0 0 0;
|
||||
font-size: 2.4em;
|
||||
color: #0A507A;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 1.em 0 0.2em 0;
|
||||
font-size: 1.5em;
|
||||
font-weight: 300;
|
||||
padding: 0;
|
||||
color: #174967;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 1em 0 -0.3em 0;
|
||||
font-size: 1.3em;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div.body h1 a tt, div.body h2 a tt, div.body h3 a tt, div.body h4 a tt, div.body h5 a tt, div.body h6 a tt {
|
||||
color: #0A507A !important;
|
||||
font-size: inherit !important;
|
||||
}
|
||||
|
||||
a.headerlink {
|
||||
color: #0A507A !important;
|
||||
font-size: 12px;
|
||||
margin-left: 6px;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none !important;
|
||||
float: right;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #ccc;
|
||||
color: white!important;
|
||||
}
|
||||
|
||||
cite, code, tt {
|
||||
font-family: 'Consolas', 'DejaVu Sans Mono',
|
||||
'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 14px;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #f2f2f2;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 2px;
|
||||
color: #333;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
tt.descname, tt.descclassname, tt.xref {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #abc;
|
||||
margin: 2em;
|
||||
}
|
||||
|
||||
a tt {
|
||||
border: 0;
|
||||
color: #a2881d;
|
||||
}
|
||||
|
||||
a tt:hover {
|
||||
color: #e1c13f;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: 'Consolas', 'DejaVu Sans Mono',
|
||||
'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 13px;
|
||||
letter-spacing: 0.015em;
|
||||
line-height: 120%;
|
||||
padding: 0.5em;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
pre a {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
div.quotebar {
|
||||
background-color: #f8f8f8;
|
||||
max-width: 250px;
|
||||
float: right;
|
||||
padding: 0px 7px;
|
||||
border: 1px solid #ccc;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin: 0 -0.5em 0 -0.5em;
|
||||
}
|
||||
|
||||
table td, table th {
|
||||
padding: 0.2em 0.5em 0.2em 0.5em;
|
||||
}
|
||||
|
||||
div.admonition, div.warning {
|
||||
font-size: 0.9em;
|
||||
margin: 1em 0 1em 0;
|
||||
border: 1px solid #86989B;
|
||||
border-radius: 2px;
|
||||
background-color: #f7f7f7;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.admonition p, div.warning p {
|
||||
margin: 0.5em 1em 0.5em 1em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.admonition pre, div.warning pre {
|
||||
margin: 0.4em 1em 0.4em 1em;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title,
|
||||
div.warning p.admonition-title {
|
||||
margin-top: 1em;
|
||||
padding-top: 0.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
border: 1px solid #940000;
|
||||
/* background-color: #FFCCCF;*/
|
||||
}
|
||||
|
||||
div.warning p.admonition-title {
|
||||
}
|
||||
|
||||
div.admonition ul, div.admonition ol,
|
||||
div.warning ul, div.warning ol {
|
||||
margin: 0.1em 0.5em 0.5em 3em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
||||
'Verdana', sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
background-color: #f4debf;
|
||||
border-top: 1px solid #ac9;
|
||||
border-bottom: 1px solid #ac9;
|
||||
}
|
||||
BIN
doc/_themes/sphinx13/static/sphinxheader.png
vendored
Normal file
|
After Width: | Height: | Size: 16 KiB |
4
doc/_themes/sphinx13/theme.conf
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = sphinx13.css
|
||||
pygments_style = trac
|
||||
@@ -18,7 +18,8 @@ version = sphinx.__released__
|
||||
release = version
|
||||
show_authors = True
|
||||
|
||||
html_theme = 'sphinxdoc'
|
||||
html_theme = 'sphinx13'
|
||||
html_theme_path = ['_themes']
|
||||
modindex_common_prefix = ['sphinx.']
|
||||
html_static_path = ['_static']
|
||||
html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']}
|
||||
|
||||
103
doc/develop.rst
Normal file
@@ -0,0 +1,103 @@
|
||||
:orphan:
|
||||
|
||||
Sphinx development
|
||||
==================
|
||||
|
||||
Sphinx is a maintained by a group of volunteers. We value every contribution!
|
||||
|
||||
* The code can be found in a Mercurial repository, at
|
||||
http://bitbucket.org/birkenfeld/sphinx/.
|
||||
* Issues and feature requests should be raised in the `tracker
|
||||
<http://bitbucket.org/birkenfeld/sphinx/issues/>`_.
|
||||
* The mailing list for development is at `Google Groups
|
||||
<http://groups.google.com/group/sphinx-dev/>`_.
|
||||
|
||||
For more about our development process and methods, see the :doc:`devguide`.
|
||||
|
||||
Extensions
|
||||
==========
|
||||
|
||||
The `sphinx-contrib <http://bitbucket.org/birkenfeld/sphinx-contrib/>`_
|
||||
repository contains many contributed extensions. Some of them have their own
|
||||
releases on PyPI, others you can install from a checkout.
|
||||
|
||||
This is the current list of contributed extensions in that repository:
|
||||
|
||||
- aafig: render embeded ASCII art as nice images using aafigure_.
|
||||
- actdiag: embed activity diagrams by using actdiag_
|
||||
- adadomain: an extension for Ada support (Sphinx 1.0 needed)
|
||||
- ansi: parse ANSI color sequences inside documents
|
||||
- autorun: Execute code in a runblock directive.
|
||||
- blockdiag: embed block diagrams by using blockdiag_
|
||||
- cheeseshop: easily link to PyPI packages
|
||||
- clearquest: create tables from ClearQuest_ queries.
|
||||
- coffeedomain: a domain for (auto)documenting CoffeeScript source code.
|
||||
- context: a builder for ConTeXt.
|
||||
- doxylink: Link to external Doxygen-generated HTML documentation
|
||||
- email: obfuscate email addresses
|
||||
- erlangdomain: an extension for Erlang support (Sphinx 1.0 needed)
|
||||
- exceltable: embed Excel spreadsheets into documents using exceltable_
|
||||
- feed: an extension for creating syndication feeds and time-based overviews
|
||||
from your site content
|
||||
- gnuplot: produces images using gnuplot_ language.
|
||||
- googleanalytics: track html visitors statistics
|
||||
- googlechart: embed charts by using `Google Chart`_
|
||||
- googlemaps: embed maps by using `Google Maps`_
|
||||
- httpdomain: a domain for documenting RESTful HTTP APIs.
|
||||
- hyphenator: client-side hyphenation of HTML using hyphenator_
|
||||
- lilypond: an extension inserting music scripts from Lilypond_ in PNG format.
|
||||
- mscgen: embed mscgen-formatted MSC (Message Sequence Chart)s.
|
||||
- nicoviceo: embed videos from nicovideo
|
||||
- nwdiag: embed network diagrams by using nwdiag_
|
||||
- omegat: support tools to collaborate with OmegaT_ (Sphinx 1.1 needed)
|
||||
- osaka: convert standard Japanese doc to Osaka dialect (it is joke extension)
|
||||
- paverutils: an alternate integration of Sphinx with Paver_.
|
||||
- phpdomain: an extension for PHP support
|
||||
- plantuml: embed UML diagram by using PlantUML_
|
||||
- rawfiles: copy raw files, like a CNAME.
|
||||
- requirements: declare requirements wherever you need (e.g. in test
|
||||
docstrings), mark statuses and collect them in a single list
|
||||
- rubydomain: an extension for Ruby support (Sphinx 1.0 needed)
|
||||
- sadisplay: display SqlAlchemy model sadisplay_
|
||||
- sdedit: an extension inserting sequence diagram by using Quick Sequence.
|
||||
Diagram Editor (sdedit_)
|
||||
- seqdiag: embed sequence diagrams by using seqdiag_
|
||||
- slide: embed presentation slides on slideshare_ and other sites.
|
||||
- swf: embed flash files
|
||||
- sword: an extension inserting Bible verses from Sword_.
|
||||
- tikz: draw pictures with the `TikZ/PGF LaTeX package`_.
|
||||
- traclinks: create TracLinks_ to a Trac_ instance from within Sphinx
|
||||
- whooshindex: whoosh indexer extension
|
||||
- youtube: embed videos from YouTube_
|
||||
- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_.
|
||||
|
||||
|
||||
See the :ref:`extension tutorial <exttut>` on getting started with writing your
|
||||
own extensions.
|
||||
|
||||
|
||||
.. _aafigure: https://launchpad.net/aafigure
|
||||
.. _gnuplot: http://www.gnuplot.info/
|
||||
.. _paver: http://www.blueskyonmars.com/projects/paver/
|
||||
.. _Sword: http://www.crosswire.org/sword/
|
||||
.. _Lilypond: http://lilypond.org/web/
|
||||
.. _sdedit: http://sdedit.sourceforge.net/
|
||||
.. _Trac: http://trac.edgewall.org
|
||||
.. _TracLinks: http://trac.edgewall.org/wiki/TracLinks
|
||||
.. _OmegaT: http://www.omegat.org/
|
||||
.. _PlantUML: http://plantuml.sourceforge.net/
|
||||
.. _PyEnchant: http://www.rfk.id.au/software/pyenchant/
|
||||
.. _sadisplay: http://bitbucket.org/estin/sadisplay/wiki/Home
|
||||
.. _blockdiag: http://blockdiag.com/
|
||||
.. _seqdiag: http://blockdiag.com/
|
||||
.. _actdiag: http://blockdiag.com/
|
||||
.. _nwdiag: http://blockdiag.com/
|
||||
.. _Google Chart: http://code.google.com/intl/ja/apis/chart/
|
||||
.. _Google Maps: http://maps.google.com/
|
||||
.. _hyphenator: http://code.google.com/p/hyphenator/
|
||||
.. _exceltable: http://packages.python.org/sphinxcontrib-exceltable/
|
||||
.. _YouTube: http://www.youtube.com/
|
||||
.. _ClearQuest: http://www-01.ibm.com/software/awdtools/clearquest/
|
||||
.. _Zope interfaces: http://docs.zope.org/zope.interface/README.html
|
||||
.. _slideshare: http://www.slideshare.net/
|
||||
.. _TikZ/PGF LaTeX package: http://sourceforge.net/projects/pgf/
|
||||
@@ -36,6 +36,13 @@ How do I...
|
||||
still need to mark up classes and such, but the headings and code examples
|
||||
come through cleanly.
|
||||
|
||||
... create HTML slides from Sphinx documents?
|
||||
See the "Hieroglyph" package at http://github.com/nyergler/hieroglyph.
|
||||
|
||||
For many more extensions and other contributed stuff, see the sphinx-contrib_
|
||||
repository.
|
||||
|
||||
.. _sphinx-contrib: https://bitbucket.org/birkenfeld/sphinx-contrib/
|
||||
|
||||
.. _usingwith:
|
||||
|
||||
|
||||
166
doc/install.rst
Normal file
@@ -0,0 +1,166 @@
|
||||
:orphan:
|
||||
|
||||
Installing Sphinx
|
||||
==================
|
||||
|
||||
Sphinx is written by Python, you need to install Python and Sphinx.
|
||||
|
||||
Sphinx package is available as a package on the `Python Package Index
|
||||
<http://pypi.python.org/pypi/Sphinx>`_.
|
||||
|
||||
You can also download a snapshot from the Mercurial development repository:
|
||||
|
||||
* as a `.tar.bz2 <https://bitbucket.org/birkenfeld/sphinx/get/default.tar.bz2>`_
|
||||
file or
|
||||
* as a `.zip <https://bitbucket.org/birkenfeld/sphinx/get/default.zip>`_ file
|
||||
|
||||
There is introductions for each environments:
|
||||
|
||||
.. contents::
|
||||
:depth: 1
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
|
||||
Install by your own
|
||||
--------------------
|
||||
|
||||
If you use system installed Python or build your own Python, you can
|
||||
use that python to install Sphinx. The actual command list is same as
|
||||
these install.
|
||||
|
||||
* `Install easy_install command`_
|
||||
* `Install Sphinx`_
|
||||
|
||||
|
||||
Debian/Ubuntu: Install Sphinx using packaging system
|
||||
-----------------------------------------------------
|
||||
|
||||
You may install using this command if you use Debian/Ubuntu.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ aptitude install python-sphinx
|
||||
|
||||
|
||||
Mac OS X: Install Sphinx using MacPorts
|
||||
----------------------------------------
|
||||
|
||||
If you use Mac OS X `MacPorts <http://www.macports.org/>`_ , use this
|
||||
command to install all software.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ sudo port install py27-sphinx
|
||||
|
||||
However, the execution path is not added, use select command to use
|
||||
Python2.7 as default.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ sudo port select --set python python27
|
||||
$ sudo port select --set sphinx py27-sphinx
|
||||
|
||||
Type :command:`which sphinx-quickstart` to check the installation.
|
||||
|
||||
|
||||
Windows: Install Python and Sphinx
|
||||
-----------------------------------
|
||||
|
||||
Intall Python
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Almost every Windows user do not have Python, we begin Python
|
||||
installation. If you already install python, please skip this section.
|
||||
|
||||
Go to http://python.org . This site is a headquarter of the
|
||||
Python. Look at Left sidebar and "Quick Links", Click "Windows
|
||||
Installer" to download.
|
||||
|
||||
.. image:: pythonorg.jpg
|
||||
|
||||
.. note::
|
||||
|
||||
Currently, Python has two version, 2.X and 3.X. Sphinx-1.2 can
|
||||
run under Python-2.5, 2.6, 2.7, 3.1, 3.2, 3.3.
|
||||
You may get some advice from ML or other places.
|
||||
|
||||
This chapter assumes Python-2.7.
|
||||
|
||||
|
||||
Follow the normal Windows installer, the Python install will be completed.
|
||||
|
||||
.. image:: installpython.jpg
|
||||
|
||||
After installation, you have better to add PATH to the Environment
|
||||
Variable in order to run Python from Command Prompt.
|
||||
|
||||
* Right-Click the My Computer Icon and open Property Dialog
|
||||
* Click Environment Variable button under detail tab
|
||||
* Edit and add the path to the system variables PATH
|
||||
|
||||
Add these variables. This is for Python-2.7. If you use another version
|
||||
of Python, change the "27" number. Add these pathes separeted by ";".
|
||||
|
||||
.. list-table:: Adding PATH
|
||||
:widths: 10 40
|
||||
:header-rows: 1
|
||||
|
||||
* - PATH
|
||||
- description
|
||||
* - C:\\Python27
|
||||
- Folder which includes Python Command
|
||||
* - C:\\Python27\\Scripts
|
||||
- Folder which includes easy_install (described later) or sphinx commands
|
||||
|
||||
Run **Command Prompt** or enter ``cmd`` to the "search program and
|
||||
files" text box. After command prompt window appear, type
|
||||
``python[Enter]``. If you can get installed python version and prompt
|
||||
about ``>>>``, the Python installation is succeeded. Enter ``Ctrl+Z``
|
||||
key to quit.
|
||||
|
||||
|
||||
Install easy_install command
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Python has very useful :command:`easy_install` command which install 3rd
|
||||
party library.
|
||||
|
||||
* http://pypi.python.org/pypi/distribute
|
||||
|
||||
easy_install downloads and install software which you want to need by only
|
||||
one command.
|
||||
|
||||
|
||||
Save http://distribute.org/distribute_setup.py link by Right-click.
|
||||
Some browsers can download just open the URL.
|
||||
If you can read the file iteslf, calm down, Right-click and choose "Save".
|
||||
|
||||
After download, invoke command prompt, go to the distribute_setup.py saved
|
||||
directory and run this command:
|
||||
|
||||
.. code-block:: bat
|
||||
|
||||
C:\> python distribute_setup.py
|
||||
|
||||
Now :command:`easy_insall` command is installed. OK, Let's go to the Sphinx
|
||||
install!
|
||||
|
||||
|
||||
Install Sphinx
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
If you finshed easy_install install, for the rest is just a moment.
|
||||
Type this line.
|
||||
|
||||
.. code-block:: bat
|
||||
|
||||
C:\> easy_install sphinx
|
||||
|
||||
After installation, type :command:`sphinx-quickstart` on the command
|
||||
prompt. If you get interactive messages which starts with
|
||||
``Welcome to the Sphinx <version> quickstart utility.``,
|
||||
installation is succeeded. Quit by hitting ``Ctrl+C``.
|
||||
|
||||
That it. Install is over. Let's go to :doc:`tutorial` to make Sphinx project.
|
||||
|
||||
BIN
doc/installpython.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
@@ -138,6 +138,13 @@ The :program:`sphinx-build` script has several options:
|
||||
Do not emit colored output. (On Windows, colored output is disabled in any
|
||||
case.)
|
||||
|
||||
.. option:: -v
|
||||
|
||||
Increase verbosity. This option can be given up to three times to get more
|
||||
debug output. It implies :option:`-T`.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
.. option:: -q
|
||||
|
||||
Do not output anything on standard output, only write warnings and errors to
|
||||
@@ -157,11 +164,24 @@ The :program:`sphinx-build` script has several options:
|
||||
Turn warnings into errors. This means that the build stops at the first
|
||||
warning and ``sphinx-build`` exits with exit status 1.
|
||||
|
||||
.. option:: -T
|
||||
|
||||
Display the full traceback when an unhandled exception occurs. Otherwise,
|
||||
only a summary is displayed and the traceback information is saved to a file
|
||||
for further analysis.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
.. option:: -P
|
||||
|
||||
(Useful for debugging only.) Run the Python debugger, :mod:`pdb`, if an
|
||||
unhandled exception occurs while building.
|
||||
|
||||
.. option:: -h, --help, --version
|
||||
|
||||
Display usage summary or Sphinx version.
|
||||
|
||||
.. versionadded:: 1.2
|
||||
|
||||
You can also give one or more filenames on the command line after the source and
|
||||
build directories. Sphinx will then try to build only these output files (and
|
||||
|
||||
@@ -126,6 +126,18 @@ tables of contents. The ``toctree`` directive is the central element.
|
||||
intend to insert these links yourself, in a different style, or in the HTML
|
||||
sidebar.
|
||||
|
||||
In cases where you want to have only one top-level toctree and hide all other
|
||||
lower level toctrees you can add the "includehidden" option to the top-level
|
||||
toctree entry::
|
||||
|
||||
.. toctree::
|
||||
:includehidden:
|
||||
|
||||
doc_1
|
||||
doc_2
|
||||
|
||||
All other toctree entries can then be eliminated by the "hidden" option.
|
||||
|
||||
In the end, all documents in the :term:`source directory` (or subdirectories)
|
||||
must occur in some ``toctree`` directive; Sphinx will emit a warning if it
|
||||
finds a file that is not included, because that means that this file will not
|
||||
@@ -150,6 +162,8 @@ tables of contents. The ``toctree`` directive is the central element.
|
||||
.. versionchanged:: 1.1
|
||||
Added numeric argument to "numbered".
|
||||
|
||||
.. versionchanged:: 1.2
|
||||
Added "includehidden" option.
|
||||
|
||||
Special names
|
||||
-------------
|
||||
|
||||
BIN
doc/pythonorg.jpg
Normal file
|
After Width: | Height: | Size: 183 KiB |
@@ -13,10 +13,10 @@ the described task.
|
||||
Setting up the documentation sources
|
||||
------------------------------------
|
||||
|
||||
The root directory of a documentation collection is called the :term:`source
|
||||
directory`. This directory also contains the Sphinx configuration file
|
||||
:file:`conf.py`, where you can configure all aspects of how Sphinx reads your
|
||||
sources and builds your documentation. [#]_
|
||||
The root directory of a Sphinx collection of reStructuredText document sources
|
||||
is called the :term:`source directory`. This directory also contains the Sphinx
|
||||
configuration file :file:`conf.py`, where you can configure all aspects of how
|
||||
Sphinx reads your sources and builds your documentation. [#]_
|
||||
|
||||
Sphinx comes with a script called :program:`sphinx-quickstart` that sets up a
|
||||
source directory and creates a default :file:`conf.py` with the most useful
|
||||
|
||||
@@ -35,7 +35,7 @@ from sphinx.environment import BuildEnvironment, SphinxStandaloneReader
|
||||
from sphinx.util import pycompat # imported for side-effects
|
||||
from sphinx.util.tags import Tags
|
||||
from sphinx.util.osutil import ENOENT
|
||||
from sphinx.util.console import bold
|
||||
from sphinx.util.console import bold, lightgray, darkgray
|
||||
|
||||
|
||||
# List of all known core events. Maps name to arguments description.
|
||||
@@ -196,6 +196,8 @@ class Sphinx(object):
|
||||
self.builder = builderclass(self)
|
||||
self.emit('builder-inited')
|
||||
|
||||
# ---- main "build" method -------------------------------------------------
|
||||
|
||||
def build(self, force_all=False, filenames=None):
|
||||
try:
|
||||
if force_all:
|
||||
@@ -215,6 +217,8 @@ class Sphinx(object):
|
||||
self.emit('build-finished', None)
|
||||
self.builder.cleanup()
|
||||
|
||||
# ---- logging handling ----------------------------------------------------
|
||||
|
||||
def _log(self, message, wfile, nonl=False):
|
||||
try:
|
||||
wfile.write(message)
|
||||
@@ -248,20 +252,27 @@ class Sphinx(object):
|
||||
return
|
||||
if args or kwargs:
|
||||
message = message % (args or kwargs)
|
||||
self._log(message, self._warning)
|
||||
self._log(message, self._status)
|
||||
|
||||
def debug(self, message, *args, **kwargs):
|
||||
if self.verbosity < 2:
|
||||
return
|
||||
if args or kwargs:
|
||||
message = message % (args or kwargs)
|
||||
self._log(message, self._warning)
|
||||
self._log(darkgray(message), self._status)
|
||||
|
||||
# general extensibility interface
|
||||
def debug2(self, message, *args, **kwargs):
|
||||
if self.verbosity < 3:
|
||||
return
|
||||
if args or kwargs:
|
||||
message = message % (args or kwargs)
|
||||
self._log(lightgray(message), self._status)
|
||||
|
||||
# ---- general extensibility interface -------------------------------------
|
||||
|
||||
def setup_extension(self, extension):
|
||||
"""Import and setup a Sphinx extension module. No-op if called twice."""
|
||||
self.debug('setting up extension: %r', extension)
|
||||
self.debug('[app] setting up extension: %r', extension)
|
||||
if extension in self._extensions:
|
||||
return
|
||||
try:
|
||||
@@ -322,16 +333,17 @@ class Sphinx(object):
|
||||
else:
|
||||
self._listeners[event][listener_id] = callback
|
||||
self.next_listener_id += 1
|
||||
self.debug('connecting event %r: %r [id=%s]',
|
||||
self.debug('[app] connecting event %r: %r [id=%s]',
|
||||
event, callback, listener_id)
|
||||
return listener_id
|
||||
|
||||
def disconnect(self, listener_id):
|
||||
self.debug('disconnecting event: [id=%s]', listener_id)
|
||||
self.debug('[app] disconnecting event: [id=%s]', listener_id)
|
||||
for event in self._listeners.itervalues():
|
||||
event.pop(listener_id, None)
|
||||
|
||||
def emit(self, event, *args):
|
||||
self.debug2('[app] emitting event: %r%s', event, repr(args)[:100])
|
||||
results = []
|
||||
if event in self._listeners:
|
||||
for _, callback in self._listeners[event].iteritems():
|
||||
@@ -347,7 +359,7 @@ class Sphinx(object):
|
||||
# registering addon parts
|
||||
|
||||
def add_builder(self, builder):
|
||||
self.debug('adding builder: %r', builder)
|
||||
self.debug('[app] adding builder: %r', builder)
|
||||
if not hasattr(builder, 'name'):
|
||||
raise ExtensionError('Builder class %s has no "name" attribute'
|
||||
% builder)
|
||||
@@ -362,7 +374,7 @@ class Sphinx(object):
|
||||
self.builderclasses[builder.name] = builder
|
||||
|
||||
def add_config_value(self, name, default, rebuild):
|
||||
self.debug('adding config value: %r', (name, default, rebuild))
|
||||
self.debug('[app] adding config value: %r', (name, default, rebuild))
|
||||
if name in self.config.values:
|
||||
raise ExtensionError('Config value %r already present' % name)
|
||||
if rebuild in (False, True):
|
||||
@@ -370,13 +382,13 @@ class Sphinx(object):
|
||||
self.config.values[name] = (default, rebuild)
|
||||
|
||||
def add_event(self, name):
|
||||
self.debug('adding event: %r', name)
|
||||
self.debug('[app] adding event: %r', name)
|
||||
if name in self._events:
|
||||
raise ExtensionError('Event %r already present' % name)
|
||||
self._events[name] = ''
|
||||
|
||||
def add_node(self, node, **kwds):
|
||||
self.debug('adding node: %r', (node, kwds))
|
||||
self.debug('[app] adding node: %r', (node, kwds))
|
||||
nodes._add_node_class_names([node.__name__])
|
||||
for key, val in kwds.iteritems():
|
||||
try:
|
||||
@@ -416,30 +428,30 @@ class Sphinx(object):
|
||||
return obj
|
||||
|
||||
def add_directive(self, name, obj, content=None, arguments=None, **options):
|
||||
self.debug('adding directive: %r',
|
||||
self.debug('[app] adding directive: %r',
|
||||
(name, obj, content, arguments, options))
|
||||
directives.register_directive(
|
||||
name, self._directive_helper(obj, content, arguments, **options))
|
||||
|
||||
def add_role(self, name, role):
|
||||
self.debug('adding role: %r', (name, role))
|
||||
self.debug('[app] adding role: %r', (name, role))
|
||||
roles.register_local_role(name, role)
|
||||
|
||||
def add_generic_role(self, name, nodeclass):
|
||||
# don't use roles.register_generic_role because it uses
|
||||
# register_canonical_role
|
||||
self.debug('adding generic role: %r', (name, nodeclass))
|
||||
self.debug('[app] adding generic role: %r', (name, nodeclass))
|
||||
role = roles.GenericRole(name, nodeclass)
|
||||
roles.register_local_role(name, role)
|
||||
|
||||
def add_domain(self, domain):
|
||||
self.debug('adding domain: %r', domain)
|
||||
self.debug('[app] adding domain: %r', domain)
|
||||
if domain.name in self.domains:
|
||||
raise ExtensionError('domain %s already registered' % domain.name)
|
||||
self.domains[domain.name] = domain
|
||||
|
||||
def override_domain(self, domain):
|
||||
self.debug('overriding domain: %r', domain)
|
||||
self.debug('[app] overriding domain: %r', domain)
|
||||
if domain.name not in self.domains:
|
||||
raise ExtensionError('domain %s not yet registered' % domain.name)
|
||||
if not issubclass(domain, self.domains[domain.name]):
|
||||
@@ -449,7 +461,7 @@ class Sphinx(object):
|
||||
|
||||
def add_directive_to_domain(self, domain, name, obj,
|
||||
content=None, arguments=None, **options):
|
||||
self.debug('adding directive to domain: %r',
|
||||
self.debug('[app] adding directive to domain: %r',
|
||||
(domain, name, obj, content, arguments, options))
|
||||
if domain not in self.domains:
|
||||
raise ExtensionError('domain %s not yet registered' % domain)
|
||||
@@ -457,13 +469,13 @@ class Sphinx(object):
|
||||
self._directive_helper(obj, content, arguments, **options)
|
||||
|
||||
def add_role_to_domain(self, domain, name, role):
|
||||
self.debug('adding role to domain: %r', (domain, name, role))
|
||||
self.debug('[app] adding role to domain: %r', (domain, name, role))
|
||||
if domain not in self.domains:
|
||||
raise ExtensionError('domain %s not yet registered' % domain)
|
||||
self.domains[domain].roles[name] = role
|
||||
|
||||
def add_index_to_domain(self, domain, index):
|
||||
self.debug('adding index to domain: %r', (domain, index))
|
||||
self.debug('[app] adding index to domain: %r', (domain, index))
|
||||
if domain not in self.domains:
|
||||
raise ExtensionError('domain %s not yet registered' % domain)
|
||||
self.domains[domain].indices.append(index)
|
||||
@@ -471,7 +483,7 @@ class Sphinx(object):
|
||||
def add_object_type(self, directivename, rolename, indextemplate='',
|
||||
parse_node=None, ref_nodeclass=None, objname='',
|
||||
doc_field_types=[]):
|
||||
self.debug('adding object type: %r',
|
||||
self.debug('[app] adding object type: %r',
|
||||
(directivename, rolename, indextemplate, parse_node,
|
||||
ref_nodeclass, objname, doc_field_types))
|
||||
StandardDomain.object_types[directivename] = \
|
||||
@@ -490,7 +502,7 @@ class Sphinx(object):
|
||||
|
||||
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
||||
ref_nodeclass=None, objname=''):
|
||||
self.debug('adding crossref type: %r',
|
||||
self.debug('[app] adding crossref type: %r',
|
||||
(directivename, rolename, indextemplate, ref_nodeclass,
|
||||
objname))
|
||||
StandardDomain.object_types[directivename] = \
|
||||
@@ -503,11 +515,11 @@ class Sphinx(object):
|
||||
StandardDomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass)
|
||||
|
||||
def add_transform(self, transform):
|
||||
self.debug('adding transform: %r', transform)
|
||||
self.debug('[app] adding transform: %r', transform)
|
||||
SphinxStandaloneReader.transforms.append(transform)
|
||||
|
||||
def add_javascript(self, filename):
|
||||
self.debug('adding javascript: %r', filename)
|
||||
self.debug('[app] adding javascript: %r', filename)
|
||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||
if '://' in filename:
|
||||
StandaloneHTMLBuilder.script_files.append(filename)
|
||||
@@ -516,7 +528,7 @@ class Sphinx(object):
|
||||
posixpath.join('_static', filename))
|
||||
|
||||
def add_stylesheet(self, filename):
|
||||
self.debug('adding stylesheet: %r', filename)
|
||||
self.debug('[app] adding stylesheet: %r', filename)
|
||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||
if '://' in filename:
|
||||
StandaloneHTMLBuilder.css_files.append(filename)
|
||||
@@ -525,25 +537,25 @@ class Sphinx(object):
|
||||
posixpath.join('_static', filename))
|
||||
|
||||
def add_lexer(self, alias, lexer):
|
||||
self.debug('adding lexer: %r', (alias, lexer))
|
||||
self.debug('[app] adding lexer: %r', (alias, lexer))
|
||||
from sphinx.highlighting import lexers
|
||||
if lexers is None:
|
||||
return
|
||||
lexers[alias] = lexer
|
||||
|
||||
def add_autodocumenter(self, cls):
|
||||
self.debug('adding autodocumenter: %r', cls)
|
||||
self.debug('[app] adding autodocumenter: %r', cls)
|
||||
from sphinx.ext import autodoc
|
||||
autodoc.add_documenter(cls)
|
||||
self.add_directive('auto' + cls.objtype, autodoc.AutoDirective)
|
||||
|
||||
def add_autodoc_attrgetter(self, type, getter):
|
||||
self.debug('adding autodoc attrgetter: %r', (type, getter))
|
||||
self.debug('[app] adding autodoc attrgetter: %r', (type, getter))
|
||||
from sphinx.ext import autodoc
|
||||
autodoc.AutoDirective._special_attrgetters[type] = getter
|
||||
|
||||
def add_search_language(self, cls):
|
||||
self.debug('adding search language: %r', cls)
|
||||
self.debug('[app] adding search language: %r', cls)
|
||||
from sphinx.search import languages, SearchLanguage
|
||||
assert isinstance(cls, SearchLanguage)
|
||||
languages[cls.lang] = cls
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import re
|
||||
from os import path
|
||||
|
||||
@@ -30,7 +30,7 @@ from docutils import nodes
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||
from sphinx.util.osutil import ensuredir, EEXIST
|
||||
from sphinx.util.osutil import ensuredir, copyfile, EEXIST
|
||||
from sphinx.util.smartypants import sphinx_smarty_pants as ssp
|
||||
from sphinx.util.console import brown
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ from collections import defaultdict
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.util import split_index_msg
|
||||
from sphinx.util.nodes import extract_messages, traverse_translatable_index
|
||||
from sphinx.util.osutil import SEP, safe_relpath, ensuredir, find_catalog
|
||||
from sphinx.util.osutil import safe_relpath, ensuredir, find_catalog
|
||||
from sphinx.util.console import darkgreen
|
||||
from sphinx.locale import pairindextypes
|
||||
|
||||
|
||||
@@ -53,6 +53,23 @@ INVENTORY_FILENAME = 'objects.inv'
|
||||
LAST_BUILD_FILENAME = 'last_build'
|
||||
|
||||
|
||||
def get_object_hash(obj):
|
||||
"""
|
||||
In python3.3, unicode(dict_instance) retun another string per process.
|
||||
get_object_hash(dict_instance) return same hash for same dict_instance.
|
||||
"""
|
||||
if isinstance(obj, dict):
|
||||
return get_object_hash(list(obj.items()))
|
||||
|
||||
elif isinstance(obj, (list, tuple)):
|
||||
obj = sorted(get_object_hash(o) for o in obj)
|
||||
|
||||
else: # int or other objects
|
||||
pass
|
||||
|
||||
return md5(unicode(obj).encode('utf8')).hexdigest()
|
||||
|
||||
|
||||
class StandaloneHTMLBuilder(Builder):
|
||||
"""
|
||||
Builds standalone HTML docs.
|
||||
@@ -156,9 +173,8 @@ class StandaloneHTMLBuilder(Builder):
|
||||
cfgdict = dict((name, self.config[name])
|
||||
for (name, desc) in self.config.values.iteritems()
|
||||
if desc[1] == 'html')
|
||||
self.config_hash = md5(unicode(cfgdict).encode('utf-8')).hexdigest()
|
||||
self.tags_hash = md5(unicode(sorted(self.tags)).encode('utf-8')) \
|
||||
.hexdigest()
|
||||
self.config_hash = get_object_hash(cfgdict)
|
||||
self.tags_hash = get_object_hash(sorted(self.tags))
|
||||
old_config_hash = old_tags_hash = ''
|
||||
try:
|
||||
fp = open(path.join(self.outdir, '.buildinfo'))
|
||||
|
||||
@@ -40,33 +40,47 @@ def usage(argv, msg=None):
|
||||
print >>sys.stderr, """\
|
||||
Sphinx v%s
|
||||
Usage: %s [options] sourcedir outdir [filenames...]
|
||||
Options: -b <builder> -- builder to use; default is html
|
||||
-a -- write all files; default is to only write \
|
||||
new and changed files
|
||||
-E -- don't use a saved environment, always read all files
|
||||
-t <tag> -- include "only" blocks with <tag>
|
||||
-d <path> -- path for the cached environment and doctree files
|
||||
|
||||
General options
|
||||
^^^^^^^^^^^^^^^
|
||||
-b <builder> builder to use; default is html
|
||||
-a write all files; default is to only write new and changed files
|
||||
-E don't use a saved environment, always read all files
|
||||
-d <path> path for the cached environment and doctree files
|
||||
(default: outdir/.doctrees)
|
||||
-c <path> -- path where configuration file (conf.py) is located
|
||||
|
||||
Build configuration options
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
-c <path> path where configuration file (conf.py) is located
|
||||
(default: same as sourcedir)
|
||||
-C -- use no config file at all, only -D options
|
||||
-D <setting=value> -- override a setting in configuration
|
||||
-A <name=value> -- pass a value into the templates, for HTML builder
|
||||
-n -- nit-picky mode, warn about all missing references
|
||||
-N -- do not do colored output
|
||||
-q -- no output on stdout, just warnings on stderr
|
||||
-Q -- no output at all, not even warnings
|
||||
-w <file> -- write warnings (and errors) to given file
|
||||
-W -- turn warnings into errors
|
||||
-P -- run Pdb on exception
|
||||
-T -- show full traceback on exception
|
||||
-v -- increase verbosity (can be repeated)
|
||||
--help -- show this help and exit
|
||||
--version -- show version information and exit
|
||||
Modi:
|
||||
-C use no config file at all, only -D options
|
||||
-D <setting=value> override a setting in configuration file
|
||||
-t <tag> define tag: include "only" blocks with <tag>
|
||||
-A <name=value> pass a value into the templates, for HTML builder
|
||||
-n nit-picky mode, warn about all missing references
|
||||
|
||||
Console output options
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
-v increase verbosity (can be repeated)
|
||||
-q no output on stdout, just warnings on stderr
|
||||
-Q no output at all, not even warnings
|
||||
-w <file> write warnings (and errors) to given file
|
||||
-W turn warnings into errors
|
||||
-T show full traceback on exception
|
||||
-N do not emit colored output
|
||||
-P run Pdb on exception
|
||||
|
||||
Filename arguments
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
* without -a and without filenames, write new and changed files.
|
||||
* with -a, write all files.
|
||||
* with filenames, write these.""" % (__version__, argv[0])
|
||||
* with filenames, write these.
|
||||
|
||||
Standard options
|
||||
^^^^^^^^^^^^^^^^
|
||||
-h, --help show this help and exit
|
||||
--version show version information and exit
|
||||
""" % (__version__, argv[0])
|
||||
|
||||
|
||||
def main(argv):
|
||||
@@ -75,11 +89,14 @@ def main(argv):
|
||||
nocolor()
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(argv[1:], 'ab:t:d:c:CD:A:ng:NEqQWw:PThv',
|
||||
opts, args = getopt.getopt(argv[1:], 'ab:t:d:c:CD:A:nNEqQWw:PThv',
|
||||
['help', 'version'])
|
||||
allopts = set(opt[0] for opt in opts)
|
||||
if '-h' in allopts or '--help' in allopts:
|
||||
usage(argv)
|
||||
print >>sys.stderr
|
||||
print >>sys.stderr, 'For more information, see '\
|
||||
'<http://sphinx-doc.org/>.'
|
||||
return 0
|
||||
if '--version' in allopts:
|
||||
print 'Sphinx (sphinx-build) %s' % __version__
|
||||
@@ -95,9 +112,6 @@ def main(argv):
|
||||
'contain conf.py file.')
|
||||
return 1
|
||||
outdir = abspath(args[1])
|
||||
if not path.isdir(outdir):
|
||||
print >>sys.stderr, 'Making output directory...'
|
||||
os.makedirs(outdir)
|
||||
except getopt.error, err:
|
||||
usage(argv, 'Error: %s' % err)
|
||||
return 1
|
||||
@@ -212,6 +226,11 @@ def main(argv):
|
||||
warning = Tee(warning, warnfp)
|
||||
error = warning
|
||||
|
||||
if not path.isdir(outdir):
|
||||
if status:
|
||||
print >>status, 'Making output directory...'
|
||||
os.makedirs(outdir)
|
||||
|
||||
try:
|
||||
app = Sphinx(srcdir, confdir, outdir, doctreedir, buildername,
|
||||
confoverrides, status, warning, freshenv,
|
||||
|
||||
@@ -144,7 +144,11 @@ class Config(object):
|
||||
epub_max_image_width = (0, 'env'),
|
||||
|
||||
# LaTeX options
|
||||
latex_documents = ([], None),
|
||||
latex_documents = (lambda self: [(self.master_doc,
|
||||
make_filename(self.project) + '.tex',
|
||||
self.project,
|
||||
'', 'manual')],
|
||||
None),
|
||||
latex_logo = (None, None),
|
||||
latex_appendices = ([], None),
|
||||
latex_use_parts = (False, None),
|
||||
@@ -167,11 +171,22 @@ class Config(object):
|
||||
text_newlines = ('unix', 'env'),
|
||||
|
||||
# manpage options
|
||||
man_pages = ([], None),
|
||||
man_pages = (lambda self: [(self.master_doc,
|
||||
make_filename(self.project).lower(),
|
||||
'%s %s' % (self.project, self.release),
|
||||
[], 1)],
|
||||
None),
|
||||
man_show_urls = (False, None),
|
||||
|
||||
# Texinfo options
|
||||
texinfo_documents = ([], None),
|
||||
texinfo_documents = (lambda self: [(self.master_doc,
|
||||
make_filename(self.project).lower(),
|
||||
self.project, '',
|
||||
make_filename(self.project),
|
||||
'The %s reference manual.' %
|
||||
make_filename(self.project),
|
||||
'Python')],
|
||||
None),
|
||||
texinfo_appendices = ([], None),
|
||||
texinfo_elements = ({}, None),
|
||||
texinfo_domain_indices = (True, None),
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive, directives
|
||||
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
|
||||
from docutils.parsers.rst.directives.misc import Class
|
||||
from docutils.parsers.rst.directives.misc import Include as BaseInclude
|
||||
|
||||
@@ -19,7 +18,6 @@ from sphinx.locale import _
|
||||
from sphinx.util import url_re, docname_join
|
||||
from sphinx.util.nodes import explicit_title_re, set_source_info, \
|
||||
process_index_entry
|
||||
from sphinx.util.compat import make_admonition
|
||||
from sphinx.util.matching import patfilter
|
||||
|
||||
|
||||
@@ -42,6 +40,7 @@ class TocTree(Directive):
|
||||
'maxdepth': int,
|
||||
'glob': directives.flag,
|
||||
'hidden': directives.flag,
|
||||
'includehidden': directives.flag,
|
||||
'numbered': int_or_nothing,
|
||||
'titlesonly': directives.flag,
|
||||
}
|
||||
@@ -107,6 +106,7 @@ class TocTree(Directive):
|
||||
subnode['maxdepth'] = self.options.get('maxdepth', -1)
|
||||
subnode['glob'] = glob
|
||||
subnode['hidden'] = 'hidden' in self.options
|
||||
subnode['includehidden'] = 'includehidden' in self.options
|
||||
subnode['numbered'] = self.options.get('numbered', 0)
|
||||
subnode['titlesonly'] = 'titlesonly' in self.options
|
||||
set_source_info(self, subnode)
|
||||
@@ -205,29 +205,11 @@ class VersionChange(Directive):
|
||||
return ret
|
||||
|
||||
|
||||
class SeeAlso(Directive):
|
||||
class SeeAlso(BaseAdmonition):
|
||||
"""
|
||||
An admonition mentioning things to look at as reference.
|
||||
"""
|
||||
has_content = True
|
||||
required_arguments = 0
|
||||
optional_arguments = 1
|
||||
final_argument_whitespace = True
|
||||
option_spec = {}
|
||||
|
||||
def run(self):
|
||||
ret = make_admonition(
|
||||
addnodes.seealso, self.name, [_('See also')], self.options,
|
||||
self.content, self.lineno, self.content_offset, self.block_text,
|
||||
self.state, self.state_machine)
|
||||
if self.arguments:
|
||||
argnodes, msgs = self.state.inline_text(self.arguments[0],
|
||||
self.lineno)
|
||||
para = nodes.paragraph()
|
||||
para += argnodes
|
||||
para += msgs
|
||||
ret[0].insert(1, para)
|
||||
return ret
|
||||
node_class = addnodes.seealso
|
||||
|
||||
|
||||
class TabularColumns(Directive):
|
||||
@@ -347,7 +329,7 @@ class Only(Directive):
|
||||
self.state.memo.title_styles = []
|
||||
self.state.memo.section_level = 0
|
||||
try:
|
||||
result = self.state.nested_parse(self.content, self.content_offset,
|
||||
self.state.nested_parse(self.content, self.content_offset,
|
||||
node, match_titles=1)
|
||||
title_styles = self.state.memo.title_styles
|
||||
if (not surrounding_title_styles
|
||||
|
||||
@@ -307,12 +307,18 @@ class Glossary(Directive):
|
||||
# add an index entry too
|
||||
indexnode = addnodes.index()
|
||||
indexnode['entries'] = [('single', termtext, new_id, 'main')]
|
||||
termnodes.append(indexnode)
|
||||
termnodes.extend(res[0])
|
||||
termnodes.append(addnodes.termsep())
|
||||
_termnodes = []
|
||||
_termnodes.append(indexnode)
|
||||
_termnodes.extend(res[0])
|
||||
_termnodes.append(addnodes.termsep())
|
||||
for termnode in _termnodes:
|
||||
termnode.source, termnode.line = source, lineno
|
||||
termnodes.extend(_termnodes)
|
||||
# make a single "term" node with all the terms, separated by termsep
|
||||
# nodes (remove the dangling trailing separator)
|
||||
term = nodes.term('', '', *termnodes[:-1])
|
||||
term.source, term.line = termnodes[0].source, termnodes[0].line
|
||||
term.rawsource = term.astext()
|
||||
term['ids'].extend(ids)
|
||||
term['names'].extend(ids)
|
||||
term += system_messages
|
||||
|
||||
@@ -41,8 +41,7 @@ from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \
|
||||
split_index_msg, FilenameUniqDict
|
||||
from sphinx.util.nodes import clean_astext, make_refnode, extract_messages, \
|
||||
traverse_translatable_index, WarningStream
|
||||
from sphinx.util.osutil import movefile, SEP, ustrftime, find_catalog, \
|
||||
fs_encoding
|
||||
from sphinx.util.osutil import SEP, ustrftime, find_catalog, fs_encoding
|
||||
from sphinx.util.matching import compile_matchers
|
||||
from sphinx.util.pycompat import all, class_types
|
||||
from sphinx.util.websupport import is_commentable
|
||||
@@ -71,7 +70,7 @@ default_settings = {
|
||||
|
||||
# This is increased every time an environment attribute is added
|
||||
# or changed to properly invalidate pickle files.
|
||||
ENV_VERSION = 42
|
||||
ENV_VERSION = 42 + (sys.version_info[0] - 2)
|
||||
|
||||
|
||||
default_substitutions = set([
|
||||
@@ -298,6 +297,16 @@ class Locale(Transform):
|
||||
if refname in refname_ids_map:
|
||||
new["ids"] = refname_ids_map[refname]
|
||||
|
||||
# Original pending_xref['reftarget'] contain not-translated
|
||||
# target name, new pending_xref must use original one.
|
||||
old_refs = node.traverse(addnodes.pending_xref)
|
||||
new_refs = patch.traverse(addnodes.pending_xref)
|
||||
if len(old_refs) != len(new_refs):
|
||||
env.warn_node('inconsistent term references in '
|
||||
'translated message', node)
|
||||
for old, new in zip(old_refs, new_refs):
|
||||
new['reftarget'] = old['reftarget']
|
||||
|
||||
# update leaves
|
||||
for child in patch.children:
|
||||
child.parent = node
|
||||
@@ -1533,6 +1542,8 @@ class BuildEnvironment:
|
||||
maxdepth = maxdepth or toctree.get('maxdepth', -1)
|
||||
if not titles_only and toctree.get('titlesonly', False):
|
||||
titles_only = True
|
||||
if not includehidden and toctree.get('includehidden', False):
|
||||
includehidden = True
|
||||
|
||||
# NOTE: previously, this was separate=True, but that leads to artificial
|
||||
# separation when two or more toctree entries form a logical unit, so
|
||||
@@ -1594,8 +1605,16 @@ class BuildEnvironment:
|
||||
elif typ == 'citation':
|
||||
docname, labelid = self.citations.get(target, ('', ''))
|
||||
if docname:
|
||||
newnode = make_refnode(builder, fromdocname, docname,
|
||||
labelid, contnode)
|
||||
try:
|
||||
newnode = make_refnode(builder, fromdocname,
|
||||
docname, labelid, contnode)
|
||||
except NoUri:
|
||||
# remove the ids we added in the CitationReferences
|
||||
# transform since they can't be transfered to
|
||||
# the contnode (if it's a Text node)
|
||||
if not isinstance(contnode, nodes.Element):
|
||||
del node['ids'][:]
|
||||
raise
|
||||
# no new node found? try the missing-reference event
|
||||
if newnode is None:
|
||||
newnode = builder.app.emit_firstresult(
|
||||
|
||||
@@ -317,27 +317,28 @@ class Documenter(object):
|
||||
|
||||
Returns True if successful, False if an error occurred.
|
||||
"""
|
||||
dbg = self.env.app.debug
|
||||
if self.objpath:
|
||||
self.env.app.debug('autodoc: from %s import %s',
|
||||
dbg('[autodoc] from %s import %s',
|
||||
self.modname, '.'.join(self.objpath))
|
||||
try:
|
||||
self.env.app.debug('autodoc: import %s', self.modname)
|
||||
dbg('[autodoc] import %s', self.modname)
|
||||
__import__(self.modname)
|
||||
parent = None
|
||||
obj = self.module = sys.modules[self.modname]
|
||||
self.env.app.debug('autodoc: => %r', obj)
|
||||
dbg('[autodoc] => %r', obj)
|
||||
for part in self.objpath:
|
||||
parent = obj
|
||||
self.env.app.debug('autodoc: getattr(_, %r)', part)
|
||||
dbg('[autodoc] getattr(_, %r)', part)
|
||||
obj = self.get_attr(obj, part)
|
||||
self.env.app.debug('autodoc: => %r', obj)
|
||||
dbg('[autodoc] => %r', obj)
|
||||
self.object_name = part
|
||||
self.parent = parent
|
||||
self.object = obj
|
||||
return True
|
||||
# this used to only catch SyntaxError, ImportError and AttributeError,
|
||||
# but importing modules with side effects can raise all kinds of errors
|
||||
except Exception, err:
|
||||
except Exception:
|
||||
if self.objpath:
|
||||
errmsg = 'autodoc: failed to import %s %r from module %r' % \
|
||||
(self.objtype, '.'.join(self.objpath), self.modname)
|
||||
@@ -346,7 +347,7 @@ class Documenter(object):
|
||||
(self.objtype, self.fullname)
|
||||
errmsg += '; the following exception was raised:\n%s' % \
|
||||
traceback.format_exc()
|
||||
self.env.app.debug(errmsg)
|
||||
dbg(errmsg)
|
||||
self.directive.warn(errmsg)
|
||||
self.env.note_reread()
|
||||
return False
|
||||
@@ -522,7 +523,7 @@ class Documenter(object):
|
||||
elif self.options.inherited_members:
|
||||
# safe_getmembers() uses dir() which pulls in members from all
|
||||
# base classes
|
||||
members = safe_getmembers(self.object)
|
||||
members = safe_getmembers(self.object, attr_getter=self.get_attr)
|
||||
else:
|
||||
# __dict__ contains only the members directly defined in
|
||||
# the class (but get them via getattr anyway, to e.g. get
|
||||
@@ -591,6 +592,7 @@ class Documenter(object):
|
||||
membername != '__doc__':
|
||||
keep = has_doc or self.options.undoc_members
|
||||
elif self.options.special_members and \
|
||||
self.options.special_members is not ALL and \
|
||||
membername in self.options.special_members:
|
||||
keep = has_doc or self.options.undoc_members
|
||||
elif want_all and membername.startswith('_'):
|
||||
@@ -716,7 +718,8 @@ class Documenter(object):
|
||||
# parse right now, to get PycodeErrors on parsing (results will
|
||||
# be cached anyway)
|
||||
self.analyzer.find_attr_docs()
|
||||
except PycodeError:
|
||||
except PycodeError, err:
|
||||
self.env.app.debug('[autodoc] module analyzer failed: %s', err)
|
||||
# no source file -- e.g. for builtin and C modules
|
||||
self.analyzer = None
|
||||
# at least add the module.__file__ as a dependency
|
||||
@@ -1009,6 +1012,18 @@ class ClassDocumenter(ModuleLevelDocumenter):
|
||||
def format_signature(self):
|
||||
if self.doc_as_attr:
|
||||
return ''
|
||||
|
||||
# get __init__ method signature from __init__.__doc__
|
||||
if self.env.config.autodoc_docstring_signature:
|
||||
# only act if the feature is enabled
|
||||
init_doc = MethodDocumenter(self.directive, '__init__')
|
||||
init_doc.object = self.get_attr(self.object, '__init__', None)
|
||||
init_doc.objpath = ['__init__']
|
||||
result = init_doc._find_signature()
|
||||
if result is not None:
|
||||
# use args only for Class signature
|
||||
return '(%s)' % result[0]
|
||||
|
||||
return ModuleLevelDocumenter.format_signature(self)
|
||||
|
||||
def add_directive_header(self, sig):
|
||||
@@ -1190,7 +1205,7 @@ class AttributeDocumenter(ClassLevelDocumenter):
|
||||
def can_document_member(cls, member, membername, isattr, parent):
|
||||
isdatadesc = isdescriptor(member) and not \
|
||||
isinstance(member, cls.method_types) and not \
|
||||
type(member).__name__ == "method_descriptor"
|
||||
type(member).__name__ in ("type", "method_descriptor")
|
||||
return isdatadesc or (not isinstance(parent, ModuleDocumenter)
|
||||
and not inspect.isroutine(member)
|
||||
and not isinstance(member, class_types))
|
||||
@@ -1309,7 +1324,7 @@ class AutoDirective(Directive):
|
||||
source, lineno = self.reporter.get_source_and_line(self.lineno)
|
||||
except AttributeError:
|
||||
source = lineno = None
|
||||
self.env.app.debug('%s:%s: <input>\n%s',
|
||||
self.env.app.debug('[autodoc] %s:%s: input:\n%s',
|
||||
source, lineno, self.block_text)
|
||||
|
||||
# find out what documenter to call
|
||||
@@ -1332,8 +1347,7 @@ class AutoDirective(Directive):
|
||||
if not self.result:
|
||||
return self.warnings
|
||||
|
||||
if self.env.app.verbosity >= 2:
|
||||
self.env.app.debug('autodoc: <output>\n%s', '\n'.join(self.result))
|
||||
self.env.app.debug2('[autodoc] output:\n%s', '\n'.join(self.result))
|
||||
|
||||
# record all filenames as dependencies -- this will at least
|
||||
# partially make automatic invalidation possible
|
||||
|
||||
@@ -14,7 +14,6 @@ import re
|
||||
import codecs
|
||||
import posixpath
|
||||
from os import path
|
||||
from math import ceil
|
||||
from subprocess import Popen, PIPE
|
||||
try:
|
||||
from hashlib import sha1 as sha
|
||||
|
||||
@@ -159,7 +159,7 @@ admonitionlabels = {
|
||||
'hint': l_('Hint'),
|
||||
'important': l_('Important'),
|
||||
'note': l_('Note'),
|
||||
'seealso': l_('See Also'),
|
||||
'seealso': l_('See also'),
|
||||
'tip': l_('Tip'),
|
||||
'warning': l_('Warning'),
|
||||
}
|
||||
|
||||
@@ -881,14 +881,13 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
# remove Unicode literal prefixes
|
||||
_unicode_string_re = re.compile(r"[uU]('.*?')")
|
||||
def _convert_python_source(source):
|
||||
return _unicode_string_re.sub('\\1', source)
|
||||
def _convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
|
||||
return rex.sub('\\1', source)
|
||||
|
||||
for f in ['QUICKSTART_CONF', 'EPUB_CONFIG', 'INTERSPHINX_CONFIG']:
|
||||
globals()[f] = _convert_python_source(globals()[f])
|
||||
|
||||
del _unicode_string_re, _convert_python_source
|
||||
del _convert_python_source
|
||||
|
||||
|
||||
def ask_user(d):
|
||||
|
||||
@@ -311,6 +311,7 @@ class IndexBuilder(object):
|
||||
def context_for_searchtool(self):
|
||||
return dict(
|
||||
search_language_stemming_code = self.lang.js_stemmer_code,
|
||||
search_language_stop_words = jsdump.dumps(sorted(self.lang.stopwords)),
|
||||
search_language_stop_words =
|
||||
jsdump.dumps(sorted(self.lang.stopwords)),
|
||||
search_scorer_tool = self.js_scorer_code,
|
||||
)
|
||||
|
||||
@@ -363,7 +363,7 @@ var Search = {
|
||||
for (i = 0; i < searchterms.length; i++) {
|
||||
var word = searchterms[i];
|
||||
// no match but word was a required one
|
||||
if ((files = terms[word]) === null)
|
||||
if (!(files = terms[word]))
|
||||
break;
|
||||
if (files.length === undefined) {
|
||||
files = [files];
|
||||
|
||||
@@ -27,13 +27,18 @@ if sys.version_info >= (2, 5):
|
||||
func = func.im_func
|
||||
parts = 0, ()
|
||||
if type(func) is partial:
|
||||
parts = len(func.args), func.keywords.keys()
|
||||
keywords = func.keywords
|
||||
if keywords is None:
|
||||
keywords = {}
|
||||
parts = len(func.args), keywords.keys()
|
||||
func = func.func
|
||||
if not inspect.isfunction(func):
|
||||
raise TypeError('%r is not a Python function' % func)
|
||||
args, varargs, varkw = inspect.getargs(func.func_code)
|
||||
func_defaults = func.func_defaults
|
||||
if func_defaults:
|
||||
if func_defaults is None:
|
||||
func_defaults = []
|
||||
else:
|
||||
func_defaults = list(func_defaults)
|
||||
if parts[0]:
|
||||
args = args[parts[0]:]
|
||||
@@ -73,12 +78,12 @@ def safe_getattr(obj, name, *defargs):
|
||||
raise AttributeError(name)
|
||||
|
||||
|
||||
def safe_getmembers(object, predicate=None):
|
||||
def safe_getmembers(object, predicate=None, attr_getter=safe_getattr):
|
||||
"""A version of inspect.getmembers() that uses safe_getattr()."""
|
||||
results = []
|
||||
for key in dir(object):
|
||||
try:
|
||||
value = safe_getattr(object, key, None)
|
||||
value = attr_getter(object, key, None)
|
||||
except AttributeError:
|
||||
continue
|
||||
if not predicate or predicate(value):
|
||||
|
||||
@@ -54,10 +54,10 @@ def extract_messages(doctree):
|
||||
rawsource.split("\n", 2)[0]
|
||||
# workaround: nodes.caption doesn't have source, line.
|
||||
# this issue was filed to Docutils tracker:
|
||||
# https://sourceforge.net/tracker/?func=detail&aid=3599485&group_id=38414&atid=422032
|
||||
# sf.net/tracker/?func=detail&aid=3599485&group_id=38414&atid=422032
|
||||
if isinstance(node, nodes.caption) and not node.source:
|
||||
node.source = node.parent.source
|
||||
node.line = '' #need fix docutils to get `node.line`
|
||||
node.line = 0 #need fix docutils to get `node.line`
|
||||
|
||||
if not node.source:
|
||||
continue # built-in message
|
||||
@@ -233,3 +233,17 @@ def _new_copy(self):
|
||||
return self.__class__(self.rawsource, **self.attributes)
|
||||
|
||||
nodes.Element.copy = _new_copy
|
||||
|
||||
# monkey-patch Element.__repr__ to return str if include unicode.
|
||||
# sf.net/tracker/?func=detail&aid=3601607&group_id=38414&atid=422030
|
||||
import sys
|
||||
if sys.version_info < (3,):
|
||||
_element_repr_orig = nodes.Element.__repr__
|
||||
|
||||
def _repr(self):
|
||||
s = _element_repr_orig(self)
|
||||
if isinstance(s, unicode):
|
||||
return s.encode('utf-8')
|
||||
return s
|
||||
|
||||
nodes.Element.__repr__ = _repr
|
||||
|
||||
@@ -134,7 +134,7 @@ else:
|
||||
|
||||
rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
|
||||
if not rel_list:
|
||||
return curdir
|
||||
return start
|
||||
return join(*rel_list)
|
||||
del curdir
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ class HTMLTranslator(BaseTranslator):
|
||||
def visit_admonition(self, node, name=''):
|
||||
self.body.append(self.starttag(
|
||||
node, 'div', CLASS=('admonition ' + name)))
|
||||
if name and name != 'seealso':
|
||||
if name:
|
||||
node.insert(0, nodes.title(name, admonitionlabels[name]))
|
||||
self.set_first_last(node)
|
||||
|
||||
|
||||
@@ -340,5 +340,13 @@ class ManualPageTranslator(BaseTranslator):
|
||||
self.body.append(node.astext())
|
||||
raise nodes.SkipNode
|
||||
|
||||
def visit_meta(self, node):
|
||||
raise nodes.SkipNode
|
||||
|
||||
def visit_inline(self, node):
|
||||
pass
|
||||
def depart_inline(self, node):
|
||||
pass
|
||||
|
||||
def unknown_visit(self, node):
|
||||
raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
|
||||
|
||||
@@ -1179,7 +1179,7 @@ class TexinfoTranslator(nodes.NodeVisitor):
|
||||
for id in production.get('ids'):
|
||||
self.add_anchor(id, production)
|
||||
s = production['tokenname'].ljust(maxlen) + ' ::='
|
||||
lastname = production['tokenname']
|
||||
##lastname = production['tokenname']
|
||||
else:
|
||||
s = '%s ' % (' '*maxlen)
|
||||
self.body.append(self.escape(s))
|
||||
|
||||
@@ -271,11 +271,6 @@ class TextTranslator(nodes.NodeVisitor):
|
||||
self.end_state(wrap=False)
|
||||
raise nodes.SkipNode
|
||||
|
||||
def visit_seealso(self, node):
|
||||
self.new_state()
|
||||
def depart_seealso(self, node):
|
||||
self.end_state(first='')
|
||||
|
||||
def visit_footnote(self, node):
|
||||
self._footnote = node.children[0].astext().strip()
|
||||
self.new_state(len(self._footnote) + 3)
|
||||
@@ -578,6 +573,8 @@ class TextTranslator(nodes.NodeVisitor):
|
||||
depart_tip = _make_depart_admonition('tip')
|
||||
visit_warning = _visit_admonition
|
||||
depart_warning = _make_depart_admonition('warning')
|
||||
visit_seealso = _visit_admonition
|
||||
depart_seealso = _make_depart_admonition('seealso')
|
||||
|
||||
def visit_versionmodified(self, node):
|
||||
self.new_state(0)
|
||||
|
||||
@@ -55,6 +55,11 @@ texinfo_documents = [
|
||||
'Georg Brandl \\and someone else', 'Sphinx Testing', 'Miscellaneous'),
|
||||
]
|
||||
|
||||
man_pages = [
|
||||
('contents', 'SphinxTests', 'Sphinx Tests Documentation',
|
||||
'Georg Brandl and someone else', 1),
|
||||
]
|
||||
|
||||
value_from_conf_py = 84
|
||||
|
||||
coverage_c_path = ['special/*.h']
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
external_links
|
||||
refs_inconsistency
|
||||
literalblock
|
||||
seealso
|
||||
definition_terms
|
||||
figure_caption
|
||||
index_entries
|
||||
glossary_terms
|
||||
glossary_terms_inconsistency
|
||||
docfields
|
||||
|
||||
35
tests/roots/test-intl/glossary_terms.po
Normal file
@@ -0,0 +1,35 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2012, foof
|
||||
# This file is distributed under the same license as the foo package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sphinx 1.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-01-29 14:10\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
msgid "i18n with glossary terms"
|
||||
msgstr "I18N WITH GLOSSARY TERMS"
|
||||
|
||||
msgid "Some term"
|
||||
msgstr "SOME NEW TERM"
|
||||
|
||||
msgid "The corresponding glossary"
|
||||
msgstr "THE CORRESPONDING GLOSSARY"
|
||||
|
||||
msgid "Some other term"
|
||||
msgstr "SOME OTHER NEW TERM"
|
||||
|
||||
msgid "The corresponding glossary #2"
|
||||
msgstr "THE CORRESPONDING GLOSSARY #2"
|
||||
|
||||
msgid "link to :term:`Some term`."
|
||||
msgstr "LINK TO :term:`SOME NEW TERM`."
|
||||
14
tests/roots/test-intl/glossary_terms.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
:tocdepth: 2
|
||||
|
||||
i18n with glossary terms
|
||||
========================
|
||||
|
||||
.. glossary::
|
||||
|
||||
Some term
|
||||
The corresponding glossary
|
||||
|
||||
Some other term
|
||||
The corresponding glossary #2
|
||||
|
||||
link to :term:`Some term`.
|
||||
23
tests/roots/test-intl/glossary_terms_inconsistency.po
Normal file
@@ -0,0 +1,23 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2012, foof
|
||||
# This file is distributed under the same license as the foo package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sphinx 1.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-01-29 14:10\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
msgid "i18n with glossary terms inconsistency"
|
||||
msgstr "I18N WITH GLOSSARY TERMS INCONSISTENCY"
|
||||
|
||||
msgid "link to :term:`Some term` and :term:`Some other term`."
|
||||
msgstr "LINK TO :term:`SOME NEW TERM`."
|
||||
6
tests/roots/test-intl/glossary_terms_inconsistency.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
:tocdepth: 2
|
||||
|
||||
i18n with glossary terms inconsistency
|
||||
======================================
|
||||
|
||||
1. link to :term:`Some term` and :term:`Some other term`.
|
||||
33
tests/roots/test-intl/seealso.po
Normal file
@@ -0,0 +1,33 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2010, Georg Brandl & Team
|
||||
# This file is distributed under the same license as the Sphinx <Tests> package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Sphinx <Tests> 0.6\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2012-12-16 06:06\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
msgid "i18n with seealso"
|
||||
msgstr "I18N WITH SEEALSO"
|
||||
|
||||
msgid "short text 1"
|
||||
msgstr "SHORT TEXT 1"
|
||||
|
||||
msgid "long text 1"
|
||||
msgstr "LONG TEXT 1"
|
||||
|
||||
msgid "short text 2"
|
||||
msgstr "SHORT TEXT 2"
|
||||
|
||||
msgid "long text 2"
|
||||
msgstr "LONG TEXT 2"
|
||||
|
||||
15
tests/roots/test-intl/seealso.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
:tocdepth: 2
|
||||
|
||||
i18n with seealso
|
||||
============================
|
||||
.. #960 directive-seelaso-ignored-in-the-gettext
|
||||
|
||||
.. seealso:: short text 1
|
||||
|
||||
.. seealso::
|
||||
|
||||
long text 1
|
||||
|
||||
.. seealso:: short text 2
|
||||
|
||||
long text 2
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
from StringIO import StringIO
|
||||
|
||||
from docutils import nodes
|
||||
from sphinx.application import ExtensionError
|
||||
from sphinx.domains import Domain
|
||||
|
||||
@@ -41,6 +42,12 @@ def test_events(app):
|
||||
"Callback called when disconnected"
|
||||
|
||||
|
||||
@with_app()
|
||||
def test_emit_with_multibyte_name_node(app):
|
||||
node = nodes.section(names=[u'\u65e5\u672c\u8a9e'])
|
||||
app.emit('my_event', node)
|
||||
|
||||
|
||||
def test_output():
|
||||
status, warnings = StringIO(), StringIO()
|
||||
app = TestApp(status=status, warning=warnings)
|
||||
|
||||
@@ -14,6 +14,7 @@ import sys
|
||||
from StringIO import StringIO
|
||||
|
||||
from util import *
|
||||
from nose.tools import with_setup
|
||||
|
||||
from docutils.statemachine import ViewList
|
||||
|
||||
@@ -22,8 +23,7 @@ from sphinx.ext.autodoc import AutoDirective, add_documenter, \
|
||||
|
||||
|
||||
def setup_module():
|
||||
global app, lid, options, directive
|
||||
|
||||
global app
|
||||
app = TestApp()
|
||||
app.builder.env.app = app
|
||||
app.builder.env.temp_data['docname'] = 'dummy'
|
||||
@@ -31,6 +31,15 @@ def setup_module():
|
||||
app.connect('autodoc-process-signature', process_signature)
|
||||
app.connect('autodoc-skip-member', skip_member)
|
||||
|
||||
|
||||
def teardown_module():
|
||||
app.cleanup()
|
||||
|
||||
|
||||
def setup_test():
|
||||
global options, directive
|
||||
global processed_docstrings, processed_signatures, _warnings
|
||||
|
||||
options = Struct(
|
||||
inherited_members = False,
|
||||
undoc_members = False,
|
||||
@@ -54,8 +63,9 @@ def setup_module():
|
||||
filename_set = set(),
|
||||
)
|
||||
|
||||
def teardown_module():
|
||||
app.cleanup()
|
||||
processed_docstrings = []
|
||||
processed_signatures = []
|
||||
_warnings = []
|
||||
|
||||
|
||||
_warnings = []
|
||||
@@ -80,12 +90,15 @@ def process_signature(app, what, name, obj, options, args, retann):
|
||||
|
||||
|
||||
def skip_member(app, what, name, obj, skip, options):
|
||||
if name in ('__special1__', '__special2__'):
|
||||
return skip
|
||||
if name.startswith('_'):
|
||||
return True
|
||||
if name == 'skipmeth':
|
||||
return True
|
||||
|
||||
|
||||
@with_setup(setup_test)
|
||||
def test_parse_name():
|
||||
def verify(objtype, name, result):
|
||||
inst = AutoDirective._registry[objtype](directive, name)
|
||||
@@ -127,6 +140,7 @@ def test_parse_name():
|
||||
del directive.env.temp_data['autodoc:class']
|
||||
|
||||
|
||||
@with_setup(setup_test)
|
||||
def test_format_signature():
|
||||
def formatsig(objtype, name, obj, args, retann):
|
||||
inst = AutoDirective._registry[objtype](directive, name)
|
||||
@@ -165,6 +179,20 @@ def test_format_signature():
|
||||
assert formatsig('class', 'C', C, None, None) == '(a, b=None)'
|
||||
assert formatsig('class', 'C', D, 'a, b', 'X') == '(a, b) -> X'
|
||||
|
||||
#__init__ have signature at first line of docstring
|
||||
class F2:
|
||||
'''some docstring for F2.'''
|
||||
def __init__(self, *args, **kw):
|
||||
'''
|
||||
__init__(a1, a2, kw1=True, kw2=False)
|
||||
|
||||
some docstring for __init__.
|
||||
'''
|
||||
class G2(F2, object):
|
||||
pass
|
||||
for C in (F2, G2):
|
||||
assert formatsig('class', 'C', C, None, None) == '(a1, a2, kw1=True, kw2=False)'
|
||||
|
||||
# test for methods
|
||||
class H:
|
||||
def foo1(self, b, *c):
|
||||
@@ -182,7 +210,23 @@ def test_format_signature():
|
||||
# test processing by event handler
|
||||
assert formatsig('method', 'bar', H.foo1, None, None) == '42'
|
||||
|
||||
# test functions created via functools.partial
|
||||
from functools import partial
|
||||
curried1 = partial(lambda a, b, c: None, 'A')
|
||||
assert formatsig('function', 'curried1', curried1, None, None) == \
|
||||
'(b, c)'
|
||||
curried2 = partial(lambda a, b, c=42: None, 'A')
|
||||
assert formatsig('function', 'curried2', curried2, None, None) == \
|
||||
'(b, c=42)'
|
||||
curried3 = partial(lambda a, b, *c: None, 'A')
|
||||
assert formatsig('function', 'curried3', curried3, None, None) == \
|
||||
'(b, *c)'
|
||||
curried4 = partial(lambda a, b, c=42, *d, **e: None, 'A')
|
||||
assert formatsig('function', 'curried4', curried4, None, None) == \
|
||||
'(b, c=42, *d, **e)'
|
||||
|
||||
|
||||
@with_setup(setup_test)
|
||||
def test_get_doc():
|
||||
def getdocl(objtype, obj, encoding=None):
|
||||
inst = AutoDirective._registry[objtype](directive, 'tmp')
|
||||
@@ -251,6 +295,7 @@ def test_get_doc():
|
||||
'', 'Other', ' lines']
|
||||
|
||||
|
||||
@with_setup(setup_test)
|
||||
def test_docstring_processing():
|
||||
def process(objtype, name, obj):
|
||||
inst = AutoDirective._registry[objtype](directive, name)
|
||||
@@ -301,6 +346,8 @@ def test_docstring_processing():
|
||||
assert process('function', 'h', h) == ['first line', 'third line', '']
|
||||
app.disconnect(lid)
|
||||
|
||||
|
||||
@with_setup(setup_test)
|
||||
def test_new_documenter():
|
||||
class MyDocumenter(ModuleLevelDocumenter):
|
||||
objtype = 'integer'
|
||||
@@ -328,6 +375,40 @@ def test_new_documenter():
|
||||
assert_result_contains('.. py:data:: integer', 'module', 'test_autodoc')
|
||||
|
||||
|
||||
@with_setup(setup_test, AutoDirective._special_attrgetters.clear)
|
||||
def test_attrgetter_using():
|
||||
def assert_getter_works(objtype, name, obj, attrs=[], **kw):
|
||||
getattr_spy = []
|
||||
def special_getattr(obj, name, *defargs):
|
||||
if name in attrs:
|
||||
getattr_spy.append((obj, name))
|
||||
return None
|
||||
return getattr(obj, name, *defargs)
|
||||
AutoDirective._special_attrgetters[type] = special_getattr
|
||||
|
||||
del getattr_spy[:]
|
||||
inst = AutoDirective._registry[objtype](directive, name)
|
||||
inst.generate(**kw)
|
||||
|
||||
hooked_members = [s[1] for s in getattr_spy]
|
||||
documented_members = [s[1] for s in processed_signatures]
|
||||
for attr in attrs:
|
||||
fullname = '.'.join((name, attr))
|
||||
assert attr in hooked_members
|
||||
assert fullname not in documented_members, \
|
||||
'%r was not hooked by special_attrgetter function' % fullname
|
||||
|
||||
options.members = ALL
|
||||
options.inherited_members = False
|
||||
assert_getter_works('class', 'test_autodoc.Class', Class,
|
||||
['meth'])
|
||||
|
||||
options.inherited_members = True
|
||||
assert_getter_works('class', 'test_autodoc.Class', Class,
|
||||
['meth', 'inheritedmeth'])
|
||||
|
||||
|
||||
@with_setup(setup_test)
|
||||
def test_generate():
|
||||
def assert_warns(warn_str, objtype, name, **kw):
|
||||
inst = AutoDirective._registry[objtype](directive, name)
|
||||
@@ -440,6 +521,15 @@ def test_generate():
|
||||
should.append(('method', 'test_autodoc.Class.inheritedmeth'))
|
||||
assert_processes(should, 'class', 'Class')
|
||||
|
||||
# test special members
|
||||
options.special_members = ['__special1__']
|
||||
should.append(('method', 'test_autodoc.Class.__special1__'))
|
||||
assert_processes(should, 'class', 'Class')
|
||||
options.special_members = ALL
|
||||
should.append(('method', 'test_autodoc.Class.__special2__'))
|
||||
assert_processes(should, 'class', 'Class')
|
||||
options.special_members = False
|
||||
|
||||
options.members = []
|
||||
# test module flags
|
||||
assert_result_contains('.. py:module:: test_autodoc',
|
||||
@@ -567,6 +657,13 @@ def test_generate():
|
||||
del directive.env.temp_data['autodoc:module']
|
||||
del directive.env.temp_data['py:module']
|
||||
|
||||
# test descriptor class documentation
|
||||
options.members = ['CustomDataDescriptor']
|
||||
assert_result_contains('.. py:class:: CustomDataDescriptor(doc)',
|
||||
'module', 'test_autodoc')
|
||||
assert_result_contains(' .. py:method:: CustomDataDescriptor.meth()',
|
||||
'module', 'test_autodoc')
|
||||
|
||||
# --- generate fodder ------------
|
||||
|
||||
__all__ = ['Class']
|
||||
@@ -591,6 +688,10 @@ class CustomDataDescriptor(object):
|
||||
return self
|
||||
return 42
|
||||
|
||||
def meth(self):
|
||||
"""Function."""
|
||||
return "The Answer"
|
||||
|
||||
def _funky_classmethod(name, b, c, d, docstring=None):
|
||||
"""Generates a classmethod for a class from a template by filling out
|
||||
some arguments."""
|
||||
@@ -660,6 +761,13 @@ class Class(Base):
|
||||
self.inst_attr_string = None
|
||||
"""a documented instance attribute"""
|
||||
|
||||
def __special1__(self):
|
||||
"""documented special method"""
|
||||
|
||||
def __special2__(self):
|
||||
# undocumented special method
|
||||
pass
|
||||
|
||||
|
||||
class CustomDict(dict):
|
||||
"""Docstring."""
|
||||
|
||||
@@ -58,6 +58,7 @@ else:
|
||||
@with_app(buildername='man')
|
||||
def test_man(app):
|
||||
app.builder.build_all()
|
||||
assert (app.outdir / 'SphinxTests.1').exists()
|
||||
|
||||
@with_app(buildername='singlehtml', cleanenv=True)
|
||||
def test_singlehtml(app):
|
||||
|
||||
@@ -39,6 +39,14 @@ def test_build(app):
|
||||
assert (app.outdir / 'subdir.pot').isfile()
|
||||
|
||||
|
||||
@with_app(buildername='gettext')
|
||||
def test_seealso(app):
|
||||
# regression test for issue #960
|
||||
app.builder.build(['markup'])
|
||||
catalog = (app.outdir / 'markup.pot').text(encoding='utf-8')
|
||||
assert 'msgid "something, something else, something more"' in catalog
|
||||
|
||||
|
||||
@with_app(buildername='gettext')
|
||||
def test_gettext(app):
|
||||
app.builder.build(['markup'])
|
||||
|
||||
@@ -62,7 +62,8 @@ def setup_module():
|
||||
if p.returncode != 0:
|
||||
print stdout
|
||||
print stderr
|
||||
assert False, 'msgfmt exited with return code %s' % p.returncode
|
||||
assert False, \
|
||||
'msgfmt exited with return code %s' % p.returncode
|
||||
assert mo.isfile(), 'msgfmt failed'
|
||||
|
||||
|
||||
@@ -158,13 +159,17 @@ def test_i18n_link_to_undefined_reference(app):
|
||||
app.builder.build(['refs_inconsistency'])
|
||||
result = (app.outdir / 'refs_inconsistency.html').text(encoding='utf-8')
|
||||
|
||||
expected_expr = """<a class="reference external" href="http://www.example.com">reference</a>"""
|
||||
expected_expr = ('<a class="reference external" '
|
||||
'href="http://www.example.com">reference</a>')
|
||||
assert len(re.findall(expected_expr, result)) == 2
|
||||
|
||||
expected_expr = """<a class="reference internal" href="#reference">reference</a>"""
|
||||
expected_expr = ('<a class="reference internal" '
|
||||
'href="#reference">reference</a>')
|
||||
assert len(re.findall(expected_expr, result)) == 0
|
||||
|
||||
expected_expr = """<a class="reference internal" href="#i18n-with-refs-inconsistency">I18N WITH REFS INCONSISTENCY</a>"""
|
||||
expected_expr = ('<a class="reference internal" '
|
||||
'href="#i18n-with-refs-inconsistency">I18N WITH '
|
||||
'REFS INCONSISTENCY</a>')
|
||||
assert len(re.findall(expected_expr, result)) == 1
|
||||
|
||||
|
||||
@@ -175,7 +180,8 @@ def test_i18n_keep_external_links(app):
|
||||
result = (app.outdir / 'external_links.html').text(encoding='utf-8')
|
||||
|
||||
# external link check
|
||||
expect_line = u"""<li>EXTERNAL LINK TO <a class="reference external" href="http://python.org">Python</a>.</li>"""
|
||||
expect_line = (u'<li>EXTERNAL LINK TO <a class="reference external" '
|
||||
u'href="http://python.org">Python</a>.</li>')
|
||||
matched = re.search('^<li>EXTERNAL LINK TO .*$', result, re.M)
|
||||
matched_line = ''
|
||||
if matched:
|
||||
@@ -183,7 +189,9 @@ def test_i18n_keep_external_links(app):
|
||||
assert expect_line == matched_line
|
||||
|
||||
# internal link check
|
||||
expect_line = u"""<li><a class="reference internal" href="#i18n-with-external-links">EXTERNAL LINKS</a> IS INTERNAL LINK.</li>"""
|
||||
expect_line = (u'<li><a class="reference internal" '
|
||||
u'href="#i18n-with-external-links">EXTERNAL '
|
||||
u'LINKS</a> IS INTERNAL LINK.</li>')
|
||||
matched = re.search('^<li><a .* IS INTERNAL LINK.</li>$', result, re.M)
|
||||
matched_line = ''
|
||||
if matched:
|
||||
@@ -191,7 +199,8 @@ def test_i18n_keep_external_links(app):
|
||||
assert expect_line == matched_line
|
||||
|
||||
# inline link check
|
||||
expect_line = u"""<li>INLINE LINK BY <a class="reference external" href="http://sphinx-doc.org">SPHINX</a>.</li>"""
|
||||
expect_line = (u'<li>INLINE LINK BY <a class="reference external" '
|
||||
u'href="http://sphinx-doc.org">SPHINX</a>.</li>')
|
||||
matched = re.search('^<li>INLINE LINK BY .*$', result, re.M)
|
||||
matched_line = ''
|
||||
if matched:
|
||||
@@ -199,7 +208,8 @@ def test_i18n_keep_external_links(app):
|
||||
assert expect_line == matched_line
|
||||
|
||||
# unnamed link check
|
||||
expect_line = u"""<li>UNNAMED <a class="reference external" href="http://google.com">LINK</a>.</li>"""
|
||||
expect_line = (u'<li>UNNAMED <a class="reference external" '
|
||||
u'href="http://google.com">LINK</a>.</li>')
|
||||
matched = re.search('^<li>UNNAMED .*$', result, re.M)
|
||||
matched_line = ''
|
||||
if matched:
|
||||
@@ -242,6 +252,57 @@ def test_i18n_definition_terms(app):
|
||||
assert result == expect
|
||||
|
||||
|
||||
@with_intl_app(buildername='text', warning=warnfile)
|
||||
def test_i18n_glossary_terms(app):
|
||||
# regression test for #1090
|
||||
app.builddir.rmtree(True) #for warnings acceleration
|
||||
app.builder.build(['glossary_terms'])
|
||||
result = (app.outdir / 'glossary_terms.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH GLOSSARY TERMS"
|
||||
u"\n************************\n"
|
||||
u"\nSOME NEW TERM"
|
||||
u"\n THE CORRESPONDING GLOSSARY\n"
|
||||
u"\nSOME OTHER NEW TERM"
|
||||
u"\n THE CORRESPONDING GLOSSARY #2\n"
|
||||
u"\nLINK TO *SOME NEW TERM*.\n")
|
||||
assert result == expect
|
||||
|
||||
warnings = warnfile.getvalue().replace(os.sep, '/')
|
||||
assert 'term not in glossary' not in warnings
|
||||
|
||||
|
||||
@with_intl_app(buildername='text', warning=warnfile)
|
||||
def test_i18n_glossary_terms_inconsistency(app):
|
||||
# regression test for #1090
|
||||
app.builddir.rmtree(True) #for warnings acceleration
|
||||
app.builder.build(['glossary_terms_inconsistency'])
|
||||
result = (app.outdir / 'glossary_terms_inconsistency.txt'
|
||||
).text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH GLOSSARY TERMS INCONSISTENCY"
|
||||
u"\n**************************************\n"
|
||||
u"\n1. LINK TO *SOME NEW TERM*.\n")
|
||||
assert result == expect
|
||||
|
||||
warnings = warnfile.getvalue().replace(os.sep, '/')
|
||||
expected_warning_expr = (
|
||||
u'.*/glossary_terms_inconsistency.txt:\\d+: '
|
||||
u'WARNING: inconsistent term references in translated message\n')
|
||||
assert re.search(expected_warning_expr, warnings)
|
||||
|
||||
|
||||
@with_intl_app(buildername='text')
|
||||
def test_seealso(app):
|
||||
app.builder.build(['seealso'])
|
||||
result = (app.outdir / 'seealso.txt').text(encoding='utf-8')
|
||||
expect = (u"\nI18N WITH SEEALSO"
|
||||
u"\n*****************\n"
|
||||
u"\nSee also: SHORT TEXT 1\n"
|
||||
u"\nSee also: LONG TEXT 1\n"
|
||||
u"\nSee also: SHORT TEXT 2\n"
|
||||
u"\n LONG TEXT 2\n")
|
||||
assert result == expect
|
||||
|
||||
|
||||
@with_intl_app(buildername='text')
|
||||
def test_i18n_figure_caption(app):
|
||||
# regression test for #940
|
||||
|
||||