Merged in knzm/sphinx-fix-docfields-fork (pull request #96)

This commit is contained in:
Nozomu Kaneko
2013-02-04 05:59:15 +09:00
59 changed files with 1408 additions and 198 deletions

29
CHANGES
View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -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 &#8220;in action&#8221; 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 %}

View File

@@ -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

View File

@@ -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>&nbsp;|&nbsp;</li>
<li><a href="{{ pathto('contents') }}">Documentation</a>
&raquo;</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
View 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>&nbsp;|</li>
<li><a href="{{ pathto('contents') }}">Documentation</a> &raquo;</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

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

BIN
doc/_themes/sphinx13/static/footerbg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

BIN
doc/_themes/sphinx13/static/headerbg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

BIN
doc/_themes/sphinx13/static/listitem.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

BIN
doc/_themes/sphinx13/static/relbg.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

396
doc/_themes/sphinx13/static/sphinx13.css vendored Normal file
View 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

4
doc/_themes/sphinx13/theme.conf vendored Normal file
View File

@@ -0,0 +1,4 @@
[theme]
inherit = basic
stylesheet = sphinx13.css
pygments_style = trac

View File

@@ -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
View 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/

View File

@@ -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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -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

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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'))

View File

@@ -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,

View File

@@ -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),

View File

@@ -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

View File

@@ -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

View File

@@ -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(

View File

@@ -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

View File

@@ -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

View File

@@ -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'),
}

View File

@@ -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):

View File

@@ -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,
)

View File

@@ -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];

View File

@@ -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):

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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__)

View File

@@ -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))

View File

@@ -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)

View File

@@ -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']

View File

@@ -8,7 +8,10 @@
external_links
refs_inconsistency
literalblock
seealso
definition_terms
figure_caption
index_entries
glossary_terms
glossary_terms_inconsistency
docfields

View 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`."

View 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`.

View 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`."

View File

@@ -0,0 +1,6 @@
:tocdepth: 2
i18n with glossary terms inconsistency
======================================
1. link to :term:`Some term` and :term:`Some other term`.

View 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"

View 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

View File

@@ -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)

View File

@@ -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."""

View File

@@ -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):

View File

@@ -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'])

View File

@@ -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