diff --git a/CHANGES b/CHANGES index 4f86c7691..880e868dd 100644 --- a/CHANGES +++ b/CHANGES @@ -96,11 +96,28 @@ Features added - #221: Added Swedish locale. - #526: Added Iranian locale. + - #694: Added Latvian locale. Release 1.0.8 (in development) ============================== +* #657: viewcode now works correctly with source files that have + non-ASCII encoding. + +* #669: Respect the ``noindex`` flag option in py:module directives. + +* #675: Fix IndexErrors when including nonexisting lines with + :rst:dir:`literalinclude`. + +* #676: Respect custom function/method parameter separator strings. + +* #682: Fix JS incompatibility with jQuery >= 1.5. + +* #693: Fix double encoding done when writing HTMLHelp .hhk files. + +* #647: Do not apply SmartyPants in parsed-literal blocks. + Release 1.0.7 (Jan 15, 2011) ============================ diff --git a/doc/config.rst b/doc/config.rst index 649490cd2..55db63635 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -379,6 +379,7 @@ documentation on :ref:`intl` for details. * ``it`` -- Italian * ``ja`` -- Japanese * ``lt`` -- Lithuanian + * ``lv`` -- Latvian * ``nl`` -- Dutch * ``pl`` -- Polish * ``pt_BR`` -- Brazilian Portuguese @@ -1187,9 +1188,10 @@ These options influence Texinfo output. * *targetname*: file name (no extension) of the Texinfo file in the output directory. * *title*: Texinfo document title. Can be empty to use the title of the - *startdoc*. - * *author*: Author for the Texinfo document. Use ``\and`` to separate - multiple authors, as in: ``'John \and Sarah'``. + *startdoc*. Inserted as Texinfo markup, so special characters like @ and + {} will need to be escaped to be inserted literally. + * *author*: Author for the Texinfo document. Inserted as Texinfo markup. + Use ``@*`` to separate multiple authors, as in: ``'John@*Sarah'``. * *dir_entry*: The name that will appear in the top-level ``DIR`` menu file. * *description*: Descriptive text to appear in the top-level ``DIR`` menu file. @@ -1203,13 +1205,32 @@ These options influence Texinfo output. .. versionadded:: 1.1 - .. confval:: texinfo_appendices A list of document names to append as an appendix to all manuals. .. versionadded:: 1.1 +.. confval:: texinfo_domain_indices + + If true, generate domain-specific indices in addition to the general index. + For e.g. the Python domain, this is the global module index. Default is + ``True``. + + This value can be a bool or a list of index names that should be generated, + like for :confval:`html_domain_indices`. + + .. versionadded:: 1.1 + +.. confval:: texinfo_show_urls + + Control how to display URL addresses. + + * ``'footnote'`` -- display URLs in footnotes (default) + * ``'no'`` -- do not display URLs + * ``'inline'`` -- display URLs inline in parentheses + + .. versionadded:: 1.1 .. confval:: texinfo_elements @@ -1227,12 +1248,23 @@ These options influence Texinfo output. default ``4``. Specify ``0`` for no indentation. ``'preamble'`` - Text inserted as is near the beginning of the file. + Texinfo markup inserted near the beginning of the file. + + ``'copying'`` + Texinfo markup inserted within the ``@copying`` block and displayed + after the title. The default value consists of a simple title page + identifying the project. * Keys that are set by other options and therefore should not be overridden are: + ``'author'`` + ``'body'`` + ``'date'`` + ``'direntry'`` ``'filename'`` + ``'project'`` + ``'release'`` ``'title'`` ``'direntry'`` diff --git a/doc/ext/math.rst b/doc/ext/math.rst index 1c7332d6d..e6e1826b0 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -191,13 +191,17 @@ MathJax_ is then loaded and transforms the LaTeX markup to readable math live in the browser. Because MathJax (and the necessary fonts) is very large, it is not included in -Sphinx. You must install it yourself, and give Sphinx its path in this config -value: +Sphinx. .. confval:: mathjax_path The path to the JavaScript file to include in the HTML files in order to load - JSMath. There is no default. + JSMath. + + The default is the ``http://`` URL that loads the JS files from the `MathJax + CDN `_. If you want MathJax to + be available offline, you have to donwload it and set this value to a + different path. The path can be absolute or relative; if it is relative, it is relative to the ``_static`` directory of the built docs. @@ -207,11 +211,7 @@ value: documentation set on one server, it is advisable to install MathJax in a shared location. - You can also give a full ``http://`` URL. Kevin Dunn maintains a MathJax - installation on a public server, which he offers for use by development and - production servers:: - - mathjax_path = 'http://mathjax.connectmv.com/MathJax.js' + You can also give a full ``http://`` URL different from the CDN URL. :mod:`sphinx.ext.jsmath` -- Render math via JavaScript diff --git a/doc/faq.rst b/doc/faq.rst index 334a3a4d4..965a19869 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -42,6 +42,13 @@ How do I... Using Sphinx with... -------------------- +Read the Docs + http://readthedocs.org is a documentation hosting service based around Sphinx. + They will host sphinx documentation, along with supporting a number of other + features including version support, PDF generation, and more. The `Getting + Started `_ + guide is a good place to start. + Epydoc There's a third-party extension providing an `api role`_ which refers to Epydoc's API docs for a given identifier. @@ -215,7 +222,7 @@ Info files, try adding the following Emacs Lisp code to your start-up file, (widen) (goto-char (point-min)) (when (re-search-forward "^Generated by \\(Sphinx\\|Docutils\\)" - (save-excursion (search-forward "^_" nil t)) t) + (save-excursion (search-forward "\x1f" nil t)) t) (set (make-local-variable 'Info-hide-note-references) 'hide))))) @@ -227,9 +234,8 @@ The following notes may be helpful if you want to create Texinfo files: - Each section corresponds to a different ``node`` in the Info file. -- Some characters cannot be properly escaped in menu entries and xrefs. The - following characters are replaced by spaces in these contexts: ``@``, ``{``, - ``}``, ``.``, ``,``, and ``:``. +- Colons (``:``) cannot be properly escaped in menu entries and xrefs. + They will be replaced with semicolons (``;``). - In the HTML and Tex output, the word ``see`` is automatically inserted before all xrefs. diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst index 30f824e8c..b7212a84b 100644 --- a/doc/man/sphinx-build.rst +++ b/doc/man/sphinx-build.rst @@ -47,6 +47,10 @@ latex man Generates manual pages. +texinfo + Generates Texinfo output that can be processed by :program:`makeinfo` to + generate an Info document. + text Generates a plain-text version of the documentation. diff --git a/doc/templating.rst b/doc/templating.rst index 193a90bd9..05a1346c0 100644 --- a/doc/templating.rst +++ b/doc/templating.rst @@ -198,7 +198,11 @@ Overriding works like this:: Add additional script files here, like this:: - {% set script_files = script_files + [pathto("_static/myscript.js", 1)] %} + {% set script_files = script_files + ["_static/myscript.js"] %} + +.. data:: css_files + + Similar to :data:`script_files`, for CSS files. Helper Functions diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py index 86ed04d06..af4043336 100644 --- a/sphinx/apidoc.py +++ b/sphinx/apidoc.py @@ -7,7 +7,10 @@ ReST files appropriately to create code documentation with Sphinx. It also creates a modules index (named modules.). - :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + This is derived from the "sphinx-autopackage" script, which is: + Copyright 2008 Société des arts technologiques (SAT), http://www.sat.qc.ca/. + + :copyright: 2007-2011 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import os @@ -134,9 +137,12 @@ def recurse_tree(rootpath, excludes, opts): Look for every file in the directory tree and create the corresponding ReST files. """ + # use absolute path for root, as relative paths like '../../foo' cause + # 'if "/." in root ...' to filter out *all* modules otherwise + rootpath = os.path.abspath(rootpath) # check if the base directory is a package and get is name if INITPY in os.listdir(rootpath): - package_name = path.abspath(rootpath).split(path.sep)[-1] + package_name = rootpath.split(path.sep)[-1] else: package_name = None diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index 1ff92360f..f030750e4 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -67,7 +67,12 @@ class I18nBuilder(Builder): catalog = self.catalogs[docname.split(SEP, 1)[0]] for node, msg in extract_messages(doctree): - catalog.setdefault(node.uid, msg) + if not msg in catalog: + catalog[msg] = [] + if node.source and node.line: + position = {"source": node.source, + "line": node.line} + catalog[msg].append(position) class MessageCatalogBuilder(I18nBuilder): @@ -93,11 +98,14 @@ class MessageCatalogBuilder(I18nBuilder): pofile = open(pofn, 'w', encoding='utf-8') try: pofile.write(POHEADER % data) - for uid, message in messages.iteritems(): + for message, positions in messages.iteritems(): # message contains *one* line of text ready for translation message = message.replace(u'\\', ur'\\'). \ replace(u'"', ur'\"') - pomsg = u'#%s\nmsgid "%s"\nmsgstr ""\n\n' % (uid, message) - pofile.write(pomsg) + for position in positions: + source = path.relpath(position["source"], self.outdir) + line = position["line"] + pofile.write(u'#: %s:%d\n' % (source, line)) + pofile.write(u'msgid "%s"\nmsgstr ""\n\n' % message) finally: pofile.close() diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py index 9227a6e62..143f6df9e 100644 --- a/sphinx/builders/htmlhelp.py +++ b/sphinx/builders/htmlhelp.py @@ -132,6 +132,7 @@ chm_locales = { 'fr': (0x40c, 'iso8859_1'), 'it': (0x410, 'iso8859_1'), 'ja': (0x411, 'cp932'), + 'lv': (0x426, 'cp1257'), 'nl': (0x413, 'iso8859_1'), 'pl': (0x415, 'iso8859_2'), 'pt_BR': (0x416, 'iso8859_1'), @@ -258,8 +259,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder): def write_index(title, refs, subitems): def write_param(name, value): item = ' \n' % (name, value) - f.write(item.encode(self.encoding, 'xmlcharrefreplace') - .decode(self.encoding)) + f.write(item) title = cgi.escape(title) f.write('
  • \n') write_param('Keyword', title) diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py index 52e32362a..535c527e0 100644 --- a/sphinx/builders/texinfo.py +++ b/sphinx/builders/texinfo.py @@ -86,8 +86,8 @@ class TexinfoBuilder(Builder): """ name = 'texinfo' format = 'texinfo' - supported_image_types = ['application/pdf', 'image/png', - 'image/gif', 'image/jpeg'] + supported_image_types = ['image/png', 'image/jpeg', + 'image/gif',] def init(self): self.docnames = [] @@ -143,18 +143,6 @@ class TexinfoBuilder(Builder): doctree = self.assemble_doctree(docname, toctree_only, appendices=(self.config.texinfo_appendices or [])) self.info("writing... ", nonl=1) - - # Add an Index section - if self.config.texinfo_domain_indices: - doctree.append( - nodes.section('', - nodes.title(_("Index"), - nodes.Text(_('Index'), - _('Index'))), - nodes.raw('@printindex ge\n', - nodes.Text('@printindex ge\n', - '@printindex ge\n'), - format="texinfo"))) self.post_process_images(doctree) docwriter = TexinfoWriter(self) settings = OptionParser( diff --git a/sphinx/config.py b/sphinx/config.py index 37b2dcbd5..9421330eb 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -172,6 +172,7 @@ class Config(object): texinfo_appendices = ([], None), texinfo_elements = ({}, None), texinfo_domain_indices = (True, None), + texinfo_show_urls = ('footnote', None), # linkcheck options linkcheck_ignore = ([], None), diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index 99fb3502a..8cedab190 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -138,7 +138,13 @@ class LiteralInclude(Directive): linelist = parselinenos(linespec, len(lines)) except ValueError, err: return [document.reporter.warning(str(err), line=self.lineno)] - lines = [lines[i] for i in linelist] + # just ignore nonexisting lines + nlines = len(lines) + lines = [lines[i] for i in linelist if i < nlines] + if not lines: + return [document.reporter.warning( + 'Line spec %r: no lines pulled from include file %r' % + (linespec, filename), line=self.lineno)] startafter = self.options.get('start-after') endbefore = self.options.get('end-before') diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index 246d64036..7647e7386 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -347,6 +347,10 @@ class Include(BaseInclude): def run(self): env = self.state.document.settings.env + if self.arguments[0].startswith('<') and \ + self.arguments[0].endswith('>'): + # docutils "standard" includes, do not do path processing + return BaseInclude.run(self) rel_filename, filename = env.relfn2path(self.arguments[0]) self.arguments[0] = filename return BaseInclude.run(self) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 5465c91fb..2a4117402 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -712,6 +712,13 @@ class DefinitionParser(object): self.fail('expected comma between arguments') self.skip_ws() + if self.skip_string('...'): + args.append(ArgumentDefExpr(None, '...', None)) + if self.skip_string(')'): + break + else: + self.fail('expected closing parenthesis after ellipses') + argtype = self._parse_type() argname = default = None self.skip_ws() diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index 021aaaaa7..4004599cb 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -418,18 +418,19 @@ class PyModule(Directive): modname = self.arguments[0].strip() noindex = 'noindex' in self.options env.temp_data['py:module'] = modname - env.domaindata['py']['modules'][modname] = \ - (env.docname, self.options.get('synopsis', ''), - self.options.get('platform', ''), 'deprecated' in self.options) - # make a duplicate entry in 'objects' to facilitate searching for the - # module in PythonDomain.find_obj() - env.domaindata['py']['objects'][modname] = (env.docname, 'module') - targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True) - self.state.document.note_explicit_target(targetnode) - ret = [targetnode] - # the platform and synopsis aren't printed; in fact, they are only used - # in the modindex currently + ret = [] if not noindex: + env.domaindata['py']['modules'][modname] = \ + (env.docname, self.options.get('synopsis', ''), + self.options.get('platform', ''), 'deprecated' in self.options) + # make a duplicate entry in 'objects' to facilitate searching for the + # module in PythonDomain.find_obj() + env.domaindata['py']['objects'][modname] = (env.docname, 'module') + targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True) + self.state.document.note_explicit_target(targetnode) + # the platform and synopsis aren't printed; in fact, they are only used + # in the modindex currently + ret.append(targetnode) indextext = _('%s (module)') % modname inode = addnodes.index(entries=[('single', indextext, 'module-' + modname, '')]) diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index e00f6fd2c..55ac820d1 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -555,28 +555,33 @@ class Documenter(object): # if isattr is True, the member is documented as an attribute isattr = False + doc = self.get_attr(member, '__doc__', None) + # if the member __doc__ is the same as self's __doc__, it's just + # inherited and therefore not the member's doc + cls = self.get_attr(member, '__class__', None) + if cls: + cls_doc = self.get_attr(cls, '__doc__', None) + if cls_doc == doc: + doc = None + has_doc = bool(doc) + + keep = False if want_all and membername.startswith('__') and \ membername.endswith('__') and len(membername) > 4: # special __methods__ - skip = not self.options.special_members + if self.options.special_members and membername != '__doc__': + keep = has_doc or self.options.undoc_members elif want_all and membername.startswith('_'): # ignore members whose name starts with _ by default - skip = not self.options.private_members + keep = self.options.private_members and \ + (has_doc or self.options.undoc_members) elif (namespace, membername) in attr_docs: # keep documented attributes - skip = False + keep = True isattr = True else: # ignore undocumented members if :undoc-members: is not given - doc = self.get_attr(member, '__doc__', None) - # if the member __doc__ is the same as self's __doc__, it's just - # inherited and therefore not the member's doc - cls = self.get_attr(member, '__class__', None) - if cls: - cls_doc = self.get_attr(cls, '__doc__', None) - if cls_doc == doc: - doc = None - skip = not self.options.undoc_members and not doc + keep = has_doc or self.options.undoc_members # give the user a chance to decide whether this member # should be skipped @@ -584,13 +589,12 @@ class Documenter(object): # let extensions preprocess docstrings skip_user = self.env.app.emit_firstresult( 'autodoc-skip-member', self.objtype, membername, member, - skip, self.options) + not keep, self.options) if skip_user is not None: - skip = skip_user - if skip: - continue + keep = not skip_user - ret.append((membername, member, isattr)) + if keep: + ret.append((membername, member, isattr)) return ret @@ -1348,3 +1352,13 @@ def setup(app): app.add_event('autodoc-process-docstring') app.add_event('autodoc-process-signature') app.add_event('autodoc-skip-member') + + +class testcls: + """test doc string""" + + def __getattr__(self, x): + return x + + def __setattr__(self, x, y): + """Attr setter.""" diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py index e3e3a65eb..5ff81d704 100644 --- a/sphinx/ext/coverage.py +++ b/sphinx/ext/coverage.py @@ -228,7 +228,7 @@ class CoverageBuilder(Builder): op.write('\n') if undoc['classes']: op.write('Classes:\n') - for name, methods in undoc['classes'].iteritems(): + for name, methods in sorted(undoc['classes'].iteritems()): if not methods: op.write(' * %s\n' % name) else: diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 57a08375d..90874f0b2 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -299,10 +299,30 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'): def latex_visit_graphviz(self, node): render_dot_latex(self, node, node['code'], node['options']) + +def render_dot_texinfo(self, node, code, options, prefix='graphviz'): + try: + fname, outfn = render_dot(self, code, options, 'png', prefix) + except GraphvizError, exc: + self.builder.warn('dot code %r: ' % code + str(exc)) + raise nodes.SkipNode + if fname is not None: + self.body.append('\n\n@float\n') + if node.get('caption'): + self.body.append('@caption{%s}\n' % self.escape_arg(caption)) + self.body.append('@image{%s,,,[graphviz],png}\n' + '@end float\n\n' % fname[:-4]) + raise nodes.SkipNode + +def texinfo_visit_graphviz(self, node): + render_dot_texinfo(self, node, node['code'], node['options']) + + def setup(app): app.add_node(graphviz, html=(html_visit_graphviz, None), - latex=(latex_visit_graphviz, None)) + latex=(latex_visit_graphviz, None), + texinfo=(texinfo_visit_graphviz, None)) app.add_directive('graphviz', Graphviz) app.add_directive('graph', GraphvizSimple) app.add_directive('digraph', GraphvizSimple) diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index fba083bf4..a2490486a 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -47,7 +47,8 @@ except ImportError: from docutils import nodes from docutils.parsers.rst import directives -from sphinx.ext.graphviz import render_dot_html, render_dot_latex +from sphinx.ext.graphviz import render_dot_html, render_dot_latex, \ + render_dot_texinfo from sphinx.util.compat import Directive @@ -354,6 +355,21 @@ def latex_visit_inheritance_diagram(self, node): raise nodes.SkipNode +def texinfo_visit_inheritance_diagram(self, node): + """ + Output the graph for Texinfo. This will insert a PNG. + """ + graph = node['graph'] + + graph_hash = get_graph_hash(node) + name = 'inheritance%s' % graph_hash + + dotcode = graph.generate_dot(name, env=self.builder.env, + graph_attrs={'size': '"6.0,6.0"'}) + render_dot_texinfo(self, node, dotcode, [], 'inheritance') + raise nodes.SkipNode + + def skip(self, node): raise nodes.SkipNode @@ -366,7 +382,7 @@ def setup(app): html=(html_visit_inheritance_diagram, None), text=(skip, None), man=(skip, None), - texinfo=(skip, None)) + texinfo=(texinfo_visit_inheritance_diagram, None)) app.add_directive('inheritance-diagram', InheritanceDiagram) app.add_config_value('inheritance_graph_attrs', {}, False), app.add_config_value('inheritance_node_attrs', {}, False), diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index d021c60bd..b5473449e 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -12,7 +12,6 @@ from docutils import nodes, utils from docutils.parsers.rst import directives -from sphinx.writers import texinfo from sphinx.util.compat import Directive @@ -127,16 +126,20 @@ def man_visit_eqref(self, node): def texinfo_visit_math(self, node): - self.body.append('@math{' + texinfo.escape_arg(node['latex']) + '}') + self.body.append('@math{' + self.escape_arg(node['latex']) + '}') raise nodes.SkipNode def texinfo_visit_displaymath(self, node): - self.visit_paragraph(node) + if node.get('label'): + self.add_anchor(node['label'], node) + self.body.append('\n\n@example\n%s\n@end example\n\n' % + self.escape_arg(node['latex'])) def texinfo_depart_displaymath(self, node): - self.depart_paragraph(node) + pass def texinfo_visit_eqref(self, node): - self.body.append(node['target']) + self.add_xref(node['docname'] + ':' + node['target'], + node['target'], node) raise nodes.SkipNode diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py index e8d2d4851..7a5523643 100644 --- a/sphinx/ext/mathjax.py +++ b/sphinx/ext/mathjax.py @@ -60,8 +60,9 @@ def builder_inited(app): def setup(app): mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None)) - app.add_config_value('mathjax_path', '', False) + app.add_config_value('mathjax_path', + 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?' + 'config=TeX-AMS-MML_HTMLorMML', False) app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html') app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html') app.connect('builder-inited', builder_inited) - diff --git a/sphinx/locale/ja/LC_MESSAGES/sphinx.mo b/sphinx/locale/ja/LC_MESSAGES/sphinx.mo index c60fd6dbb..09535b7a4 100644 Binary files a/sphinx/locale/ja/LC_MESSAGES/sphinx.mo and b/sphinx/locale/ja/LC_MESSAGES/sphinx.mo differ diff --git a/sphinx/locale/ja/LC_MESSAGES/sphinx.po b/sphinx/locale/ja/LC_MESSAGES/sphinx.po index e8f84f418..9d5488ec8 100644 --- a/sphinx/locale/ja/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/ja/LC_MESSAGES/sphinx.po @@ -2,20 +2,19 @@ # Copyright (C) 2008 ORGANIZATION # This file is distributed under the same license as the Sphinx project. # Yasushi Masuda , 2008. +# Kouhei Sutou \n" -"Language-Team: ja \n" +"PO-Revision-Date: 2011-05-15 21:25+0900\n" +"Last-Translator: Kouhei Sutou \n" +"Language-Team: Japanese\n" "Plural-Forms: nplurals=1; plural=0\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Generated-By: Babel 0.9.5\n" #: sphinx/environment.py:120 sphinx/writers/latex.py:189 #: sphinx/writers/manpage.py:67 @@ -26,12 +25,12 @@ msgstr "%Y 年 %m 月 %d 日" #: sphinx/environment.py:1624 #, python-format msgid "see %s" -msgstr "" +msgstr "%sを参照" #: sphinx/environment.py:1627 #, python-format msgid "see also %s" -msgstr "" +msgstr "%sも参照" #: sphinx/roles.py:175 #, python-format @@ -91,9 +90,8 @@ msgid "Module author: " msgstr "モジュールの作者: " #: sphinx/directives/other.py:140 -#, fuzzy msgid "Code author: " -msgstr "モジュールの作者: " +msgstr "コードの作者: " #: sphinx/directives/other.py:142 msgid "Author: " @@ -164,12 +162,11 @@ msgid "type" msgstr "のデータ型" #: sphinx/domains/c.py:208 -#, fuzzy msgid "variable" msgstr "変数" #: sphinx/domains/cpp.py:897 -#, fuzzy, python-format +#, python-format msgid "%s (C++ class)" msgstr "%s (C++ のクラス)" @@ -204,9 +201,9 @@ msgid "%s() (%s method)" msgstr "%s() (%s のメソッド)" #: sphinx/domains/javascript.py:109 -#, fuzzy, python-format +#, python-format msgid "%s() (class)" -msgstr "%s() (のクラス)" +msgstr "%s() (クラス)" #: sphinx/domains/javascript.py:111 #, python-format @@ -219,9 +216,8 @@ msgid "%s (%s attribute)" msgstr "%s (%s の属性)" #: sphinx/domains/javascript.py:122 -#, fuzzy msgid "Arguments" -msgstr "パラメタ" +msgstr "引数" #: sphinx/domains/javascript.py:125 msgid "Throws" @@ -236,7 +232,6 @@ msgid "attribute" msgstr "の属性" #: sphinx/domains/python.py:100 -#, fuzzy msgid "Variables" msgstr "変数" @@ -286,14 +281,14 @@ msgid "%s() (%s static method)" msgstr "%s() (%s の静的メソッド)" #: sphinx/domains/python.py:341 -#, fuzzy, python-format +#, python-format msgid "%s() (%s.%s class method)" -msgstr "%s() (%s.%s のメソッド)" +msgstr "%s() (%s.%s のクラスメソッド)" #: sphinx/domains/python.py:344 -#, fuzzy, python-format +#, python-format msgid "%s() (%s class method)" -msgstr "%s() (%s のメソッド)" +msgstr "%s() (%s のクラスメソッド)" #: sphinx/domains/python.py:354 #, python-format @@ -306,9 +301,8 @@ msgid "%s (module)" msgstr "%s (モジュール)" #: sphinx/domains/python.py:490 -#, fuzzy msgid "Python Module Index" -msgstr "モジュール索引" +msgstr "Pythonモジュール索引" #: sphinx/domains/python.py:491 msgid "modules" @@ -328,7 +322,7 @@ msgstr "メソッド" #: sphinx/domains/python.py:563 msgid "class method" -msgstr "" +msgstr "クラスメソッド" #: sphinx/domains/python.py:564 msgid "static method" @@ -350,7 +344,7 @@ msgstr "%s (ディレクティブ)" #: sphinx/domains/rst.py:57 #, python-format msgid "%s (role)" -msgstr "" +msgstr "%s (ロール)" #: sphinx/domains/rst.py:106 msgid "directive" @@ -358,7 +352,7 @@ msgstr "ディレクティブ" #: sphinx/domains/rst.py:107 msgid "role" -msgstr "" +msgstr "ロール" #: sphinx/domains/std.py:70 sphinx/domains/std.py:86 #, python-format @@ -430,7 +424,6 @@ msgid "[docs]" msgstr "[ドキュメント]" #: sphinx/ext/viewcode.py:131 -#, fuzzy msgid "Module code" msgstr "モジュールコード" diff --git a/sphinx/locale/lv/LC_MESSAGES/sphinx.js b/sphinx/locale/lv/LC_MESSAGES/sphinx.js new file mode 100644 index 000000000..434a99e34 --- /dev/null +++ b/sphinx/locale/lv/LC_MESSAGES/sphinx.js @@ -0,0 +1 @@ +Documentation.addTranslations({"locale": "lv", "plural_expr": "(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)", "messages": {"Search Results": "Atlases rezult\u0101ti", "Preparing search...": "Sagatavojam atlasi...", "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories.": "J\u016bsu atlases rindai neatbilst neviens dokuments. L\u016bdzu, p\u0101rbaudiet, vai visi v\u0101rdi ir uzrakst\u012bti pareizi, un vai ir izv\u0113l\u0113tas pareiz\u0101s kategorijas.", "Search finished, found %s page(s) matching the search query.": "Atlase pabeigta, atrastas lapas: %s", ", in ": ", iek\u0161 ", "Expand sidebar": "Izplest s\u0101njoslu", "Permalink to this headline": "Past\u0101v\u012bga nor\u0101de \u0161o virsrakstu", "Searching": "Mekl\u0113jam", "Collapse sidebar": "Sav\u0113rst s\u0101njoslu", "Permalink to this definition": "Past\u0101v\u012bga nor\u0101de uz \u0161o defin\u012bciju", "Hide Search Matches": "Pasl\u0113pt atlases v\u0101rdus"}}); \ No newline at end of file diff --git a/sphinx/locale/lv/LC_MESSAGES/sphinx.mo b/sphinx/locale/lv/LC_MESSAGES/sphinx.mo new file mode 100644 index 000000000..497ce4d0d Binary files /dev/null and b/sphinx/locale/lv/LC_MESSAGES/sphinx.mo differ diff --git a/sphinx/locale/lv/LC_MESSAGES/sphinx.po b/sphinx/locale/lv/LC_MESSAGES/sphinx.po new file mode 100644 index 000000000..e8409c5aa --- /dev/null +++ b/sphinx/locale/lv/LC_MESSAGES/sphinx.po @@ -0,0 +1,770 @@ +# Latvian translations for Sphinx. +# This file is distributed under the same license as the Sphinx project. +# +msgid "" +msgstr "" +"Project-Id-Version: Sphinx 1.0.7\n" +"POT-Creation-Date: 2010-05-24 23:53+0200\n" +"PO-Revision-Date: 2011-05-10 16:40+0200\n" +"Last-Translator: alexander smishlajev \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"(n%100<10 || n%100>=20) ? 1 : 2)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: sphinx/environment.py:106 sphinx/writers/latex.py:184 +#: sphinx/writers/manpage.py:67 +#, python-format +msgid "%B %d, %Y" +msgstr "%d.%m.%Y" + +#: sphinx/roles.py:174 +#, python-format +msgid "Python Enhancement Proposals!PEP %s" +msgstr "" + +#: sphinx/builders/changes.py:72 +msgid "Builtins" +msgstr "Iebūvētie" + +#: sphinx/builders/changes.py:74 +msgid "Module level" +msgstr "Moduļu līmenis" + +#: sphinx/builders/html.py:266 +#, python-format +msgid "%b %d, %Y" +msgstr "%d.%m.%Y" + +#: sphinx/builders/html.py:285 sphinx/themes/basic/defindex.html:30 +msgid "General Index" +msgstr "Vispārējs indekss" + +#: sphinx/builders/html.py:285 +msgid "index" +msgstr "indekss" + +#: sphinx/builders/html.py:345 +msgid "next" +msgstr "nākošais" + +#: sphinx/builders/html.py:354 +msgid "previous" +msgstr "iepriekšējs" + +#: sphinx/builders/latex.py:151 +msgid " (in " +msgstr " (iekš " + +#: sphinx/directives/other.py:127 +msgid "Section author: " +msgstr "Sekcijas autors: " + +#: sphinx/directives/other.py:129 +msgid "Module author: " +msgstr "Moduļa autors: " + +#: sphinx/directives/other.py:131 +msgid "Code author: " +msgstr "Koda autors: " + +#: sphinx/directives/other.py:133 +msgid "Author: " +msgstr "Autors: " + +#: sphinx/directives/other.py:238 +msgid "See also" +msgstr "Skat.arī" + +#: sphinx/domains/__init__.py:253 +#, python-format +msgid "%s %s" +msgstr "%s %s" + +#: sphinx/domains/c.py:51 sphinx/domains/python.py:49 +msgid "Parameters" +msgstr "Parametri" + +#: sphinx/domains/c.py:54 sphinx/domains/javascript.py:137 +#: sphinx/domains/python.py:59 +msgid "Returns" +msgstr "Atgriež" + +#: sphinx/domains/c.py:56 sphinx/domains/python.py:61 +msgid "Return type" +msgstr "Atgriežamais tips" + +#: sphinx/domains/c.py:133 +#, python-format +msgid "%s (C function)" +msgstr "%s (C funkcija)" + +#: sphinx/domains/c.py:135 +#, python-format +msgid "%s (C member)" +msgstr "%s (C loceklis)" + +#: sphinx/domains/c.py:137 +#, python-format +msgid "%s (C macro)" +msgstr "%s (C makross)" + +#: sphinx/domains/c.py:139 +#, python-format +msgid "%s (C type)" +msgstr "%s (C tips)" + +#: sphinx/domains/c.py:141 +#, python-format +msgid "%s (C variable)" +msgstr "%s (C mainīgais)" + +#: sphinx/domains/c.py:171 sphinx/domains/cpp.py:1031 +#: sphinx/domains/javascript.py:166 sphinx/domains/python.py:497 +msgid "function" +msgstr "funkcija" + +#: sphinx/domains/c.py:172 sphinx/domains/cpp.py:1032 +msgid "member" +msgstr "loceklis" + +#: sphinx/domains/c.py:173 +msgid "macro" +msgstr "makross" + +#: sphinx/domains/c.py:174 sphinx/domains/cpp.py:1033 +msgid "type" +msgstr "tips" + +#: sphinx/domains/c.py:175 +msgid "variable" +msgstr "mainīgais" + +#: sphinx/domains/cpp.py:876 +#, python-format +msgid "%s (C++ class)" +msgstr "%s (C++ klase)" + +#: sphinx/domains/cpp.py:891 +#, python-format +msgid "%s (C++ type)" +msgstr "%s (C++ tips)" + +#: sphinx/domains/cpp.py:910 +#, python-format +msgid "%s (C++ member)" +msgstr "%s (C++ loceklis)" + +#: sphinx/domains/cpp.py:962 +#, python-format +msgid "%s (C++ function)" +msgstr "%s (C++ funkcija)" + +#: sphinx/domains/cpp.py:1030 sphinx/domains/python.py:499 +msgid "class" +msgstr "klase" + +#: sphinx/domains/javascript.py:117 sphinx/domains/python.py:221 +#, python-format +msgid "%s() (built-in function)" +msgstr "%s() (iebūvēta funkcija)" + +#: sphinx/domains/javascript.py:118 sphinx/domains/python.py:285 +#, python-format +msgid "%s() (%s method)" +msgstr "%s() (%s metods)" + +#: sphinx/domains/javascript.py:120 +#, python-format +msgid "%s (global variable or constant)" +msgstr "%s (globālais mainīgais vai konstanta)" + +#: sphinx/domains/javascript.py:122 sphinx/domains/python.py:323 +#, python-format +msgid "%s (%s attribute)" +msgstr "%s (%s atributs)" + +#: sphinx/domains/javascript.py:131 +msgid "Arguments" +msgstr "Argumenti" + +#: sphinx/domains/javascript.py:134 +msgid "Throws" +msgstr "Izmet" + +#: sphinx/domains/javascript.py:167 sphinx/domains/python.py:498 +msgid "data" +msgstr "dati" + +#: sphinx/domains/javascript.py:168 sphinx/domains/python.py:504 +msgid "attribute" +msgstr "atributs" + +#: sphinx/domains/python.py:53 +msgid "Variables" +msgstr "Mainīgie" + +#: sphinx/domains/python.py:56 +msgid "Raises" +msgstr "Ceļ" + +#: sphinx/domains/python.py:222 sphinx/domains/python.py:279 +#: sphinx/domains/python.py:291 sphinx/domains/python.py:304 +#, python-format +msgid "%s() (in module %s)" +msgstr "%s() (moduļī %s)" + +#: sphinx/domains/python.py:225 +#, python-format +msgid "%s (built-in variable)" +msgstr "%s (iebūvētais mainīgais)" + +#: sphinx/domains/python.py:226 sphinx/domains/python.py:317 +#, python-format +msgid "%s (in module %s)" +msgstr "%s (moduļī %s)" + +#: sphinx/domains/python.py:242 +#, python-format +msgid "%s (built-in class)" +msgstr "%s (iebūvēta klase)" + +#: sphinx/domains/python.py:243 +#, python-format +msgid "%s (class in %s)" +msgstr "%s (klase iekš %s)" + +#: sphinx/domains/python.py:283 +#, python-format +msgid "%s() (%s.%s method)" +msgstr "%s() (%s.%s metods)" + +#: sphinx/domains/python.py:295 +#, python-format +msgid "%s() (%s.%s static method)" +msgstr "%s() (%s.%s statiskais metods)" + +#: sphinx/domains/python.py:298 +#, python-format +msgid "%s() (%s static method)" +msgstr "%s() (%s statiskais metods)" + +#: sphinx/domains/python.py:308 +#, python-format +msgid "%s() (%s.%s class method)" +msgstr "%s() (%s.%s klases metods)" + +#: sphinx/domains/python.py:311 +#, python-format +msgid "%s() (%s class method)" +msgstr "%s() (%s klases metods)" + +#: sphinx/domains/python.py:321 +#, python-format +msgid "%s (%s.%s attribute)" +msgstr "%s (%s.%s atributs)" + +#: sphinx/domains/python.py:366 +msgid "Platforms: " +msgstr "Platformas: " + +#: sphinx/domains/python.py:372 +#, python-format +msgid "%s (module)" +msgstr "%s (modulis)" + +#: sphinx/domains/python.py:429 +msgid "Python Module Index" +msgstr "" + +#: sphinx/domains/python.py:430 +msgid "modules" +msgstr "moduļi" + +#: sphinx/domains/python.py:475 +msgid "Deprecated" +msgstr "Nav ieteicams" + +#: sphinx/domains/python.py:500 sphinx/locale/__init__.py:162 +msgid "exception" +msgstr "izņēmums" + +#: sphinx/domains/python.py:501 +msgid "method" +msgstr "metods" + +#: sphinx/domains/python.py:502 +msgid "class method" +msgstr "klases metods" + +#: sphinx/domains/python.py:503 +msgid "static method" +msgstr "statiskais metods" + +#: sphinx/domains/python.py:505 sphinx/locale/__init__.py:158 +msgid "module" +msgstr "modulis" + +#: sphinx/domains/rst.py:53 +#, python-format +msgid "%s (directive)" +msgstr "%s (direktīva)" + +#: sphinx/domains/rst.py:55 +#, python-format +msgid "%s (role)" +msgstr "%s (role)" + +#: sphinx/domains/rst.py:103 +msgid "directive" +msgstr "direktīva" + +#: sphinx/domains/rst.py:104 +msgid "role" +msgstr "role" + +#: sphinx/domains/std.py:68 sphinx/domains/std.py:84 +#, python-format +msgid "environment variable; %s" +msgstr "apkārtnes mainīgais; %s" + +#: sphinx/domains/std.py:160 +#, python-format +msgid "%scommand line option; %s" +msgstr "%skomandrindas opcija; %s" + +#: sphinx/domains/std.py:328 +msgid "glossary term" +msgstr "glosārija termins" + +#: sphinx/domains/std.py:329 +msgid "grammar token" +msgstr "gramatiskais marķieris" + +#: sphinx/domains/std.py:330 +msgid "reference label" +msgstr "atsauces virsraksts" + +#: sphinx/domains/std.py:331 +msgid "environment variable" +msgstr "apkārtnes mainīgais" + +#: sphinx/domains/std.py:332 +msgid "program option" +msgstr "programmas opcija" + +#: sphinx/domains/std.py:360 sphinx/themes/basic/genindex-single.html:11 +#: sphinx/themes/basic/genindex-split.html:11 +#: sphinx/themes/basic/genindex-split.html:14 +#: sphinx/themes/basic/genindex.html:11 sphinx/themes/basic/genindex.html:14 +#: sphinx/themes/basic/genindex.html:50 sphinx/themes/basic/layout.html:125 +#: sphinx/writers/latex.py:173 +msgid "Index" +msgstr "Indekss" + +#: sphinx/domains/std.py:361 +msgid "Module Index" +msgstr "Moduļu indekss" + +#: sphinx/domains/std.py:362 sphinx/themes/basic/defindex.html:25 +msgid "Search Page" +msgstr "Atlases lapa" + +#: sphinx/ext/autodoc.py:917 +#, python-format +msgid " Bases: %s" +msgstr " Bāzes: %s" + +#: sphinx/ext/autodoc.py:950 +#, python-format +msgid "alias of :class:`%s`" +msgstr "aizstājvārds klasei :class:`%s`" + +#: sphinx/ext/todo.py:41 +msgid "Todo" +msgstr "Jāizdara" + +#: sphinx/ext/todo.py:109 +#, python-format +msgid "(The <> is located in %s, line %d.)" +msgstr "(<> atrodas iekš %s, rinda %d.)" + +#: sphinx/ext/todo.py:117 +msgid "original entry" +msgstr "sākotnējs ieraksts" + +#: sphinx/ext/viewcode.py:66 +msgid "[source]" +msgstr "[kods]" + +#: sphinx/ext/viewcode.py:109 +msgid "[docs]" +msgstr "[dokumenti]" + +#: sphinx/ext/viewcode.py:123 +msgid "Module code" +msgstr "Moduļa teksts" + +#: sphinx/ext/viewcode.py:129 +#, python-format +msgid "

    Source code for %s

    " +msgstr "

    %s izejas teksts

    " + +#: sphinx/ext/viewcode.py:156 +msgid "Overview: module code" +msgstr "Apskats: moduļa teksts" + +#: sphinx/ext/viewcode.py:157 +msgid "

    All modules for which code is available

    " +msgstr "

    Visi moduļi, kuriem ir izejas teksti

    " + +#: sphinx/locale/__init__.py:139 +msgid "Attention" +msgstr "Uzmanību" + +#: sphinx/locale/__init__.py:140 +msgid "Caution" +msgstr "Uzmanies" + +#: sphinx/locale/__init__.py:141 +msgid "Danger" +msgstr "Bīstami" + +#: sphinx/locale/__init__.py:142 +msgid "Error" +msgstr "Kļūda" + +#: sphinx/locale/__init__.py:143 +msgid "Hint" +msgstr "Mājiens" + +#: sphinx/locale/__init__.py:144 +msgid "Important" +msgstr "Svarīgi" + +#: sphinx/locale/__init__.py:145 +msgid "Note" +msgstr "Piezīme" + +#: sphinx/locale/__init__.py:146 +msgid "See Also" +msgstr "Skat.arī" + +#: sphinx/locale/__init__.py:147 +msgid "Tip" +msgstr "Padoms" + +#: sphinx/locale/__init__.py:148 +msgid "Warning" +msgstr "Brīdinājums" + +#: sphinx/locale/__init__.py:152 +#, python-format +msgid "New in version %s" +msgstr "Jauns versijā %s" + +#: sphinx/locale/__init__.py:153 +#, python-format +msgid "Changed in version %s" +msgstr "Mainīts versijā %s" + +#: sphinx/locale/__init__.py:154 +#, python-format +msgid "Deprecated since version %s" +msgstr "Neieteicams no versijas %s" + +#: sphinx/locale/__init__.py:159 +msgid "keyword" +msgstr "atslēgas vārds" + +#: sphinx/locale/__init__.py:160 +msgid "operator" +msgstr "operators" + +#: sphinx/locale/__init__.py:161 +msgid "object" +msgstr "objekts" + +#: sphinx/locale/__init__.py:163 +msgid "statement" +msgstr "priekšraksts" + +#: sphinx/locale/__init__.py:164 +msgid "built-in function" +msgstr "iebūvēta funkcija" + +#: sphinx/themes/agogo/layout.html:45 sphinx/themes/basic/globaltoc.html:10 +#: sphinx/themes/basic/localtoc.html:11 +msgid "Table Of Contents" +msgstr "Saturs" + +#: sphinx/themes/agogo/layout.html:49 sphinx/themes/basic/layout.html:128 +#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:14 +msgid "Search" +msgstr "Meklēt" + +#: sphinx/themes/agogo/layout.html:52 sphinx/themes/basic/searchbox.html:15 +msgid "Go" +msgstr "Izpildīt" + +#: sphinx/themes/agogo/layout.html:57 sphinx/themes/basic/searchbox.html:20 +msgid "Enter search terms or a module, class or function name." +msgstr "Ievadiet meklējamus terminus vai moduļa, klases vai funkcijas vārdu." + +#: sphinx/themes/agogo/layout.html:78 sphinx/themes/basic/sourcelink.html:14 +msgid "Show Source" +msgstr "Rādīt izejas tekstu" + +#: sphinx/themes/basic/defindex.html:11 +msgid "Overview" +msgstr "Apskats" + +#: sphinx/themes/basic/defindex.html:20 +msgid "Indices and tables:" +msgstr "Indeksi un tabulas:" + +#: sphinx/themes/basic/defindex.html:23 +msgid "Complete Table of Contents" +msgstr "Pilns saturs" + +#: sphinx/themes/basic/defindex.html:24 +msgid "lists all sections and subsections" +msgstr "rāda visas sekcijas un apakšsekcijas" + +#: sphinx/themes/basic/defindex.html:26 +msgid "search this documentation" +msgstr "meklēt šajā dokumentācijā" + +#: sphinx/themes/basic/defindex.html:28 +msgid "Global Module Index" +msgstr "Vispārējs moduļu indekss" + +#: sphinx/themes/basic/defindex.html:29 +msgid "quick access to all modules" +msgstr "ātra piekļuve visiem moduliem" + +#: sphinx/themes/basic/defindex.html:31 +msgid "all functions, classes, terms" +msgstr "visas funkcijas, klases un termini" + +#: sphinx/themes/basic/genindex-single.html:14 +#, python-format +msgid "Index – %(key)s" +msgstr "Indekss – %(key)s" + +#: sphinx/themes/basic/genindex-single.html:46 +#: sphinx/themes/basic/genindex-split.html:24 +#: sphinx/themes/basic/genindex-split.html:38 +#: sphinx/themes/basic/genindex.html:56 +msgid "Full index on one page" +msgstr "Pilns indekss vienā lappusē" + +#: sphinx/themes/basic/genindex-split.html:16 +msgid "Index pages by letter" +msgstr "Lappušu indekss pēc burtiem" + +#: sphinx/themes/basic/genindex-split.html:25 +msgid "can be huge" +msgstr "var būt milzīgs" + +#: sphinx/themes/basic/layout.html:23 +msgid "Navigation" +msgstr "Navigācija" + +#: sphinx/themes/basic/layout.html:113 +#, python-format +msgid "Search within %(docstitle)s" +msgstr "Meklēt iekš %(docstitle)s" + +#: sphinx/themes/basic/layout.html:122 +msgid "About these documents" +msgstr "Par šiem dokumentiem" + +#: sphinx/themes/basic/layout.html:131 +msgid "Copyright" +msgstr "Copyright" + +#: sphinx/themes/basic/layout.html:180 +#, python-format +msgid "© Copyright %(copyright)s." +msgstr "© Copyright %(copyright)s." + +#: sphinx/themes/basic/layout.html:182 +#, python-format +msgid "© Copyright %(copyright)s." +msgstr "© Copyright %(copyright)s." + +#: sphinx/themes/basic/layout.html:186 +#, python-format +msgid "Last updated on %(last_updated)s." +msgstr "Pēdējas izmaiņas %(last_updated)s." + +#: sphinx/themes/basic/layout.html:189 +#, python-format +msgid "" +"Created using Sphinx " +"%(sphinx_version)s." +msgstr "" +"Sagatavots izmantojot Sphinx " +"%(sphinx_version)s." + +#: sphinx/themes/basic/opensearch.xml:4 +#, python-format +msgid "Search %(docstitle)s" +msgstr "%(docstitle)s meklēšana" + +#: sphinx/themes/basic/relations.html:11 +msgid "Previous topic" +msgstr "iepriekšēja tēma" + +#: sphinx/themes/basic/relations.html:13 +msgid "previous chapter" +msgstr "iepriekšēja sadaļa" + +#: sphinx/themes/basic/relations.html:16 +msgid "Next topic" +msgstr "nākoša tēma" + +#: sphinx/themes/basic/relations.html:18 +msgid "next chapter" +msgstr "nākoša sadaļa" + +#: sphinx/themes/basic/search.html:18 +msgid "" +"Please activate JavaScript to enable the search\n" +" functionality." +msgstr "" +"Lai iespējotu meklēšanu, lūdzu aktivizēt JavaScript." + +#: sphinx/themes/basic/search.html:23 +msgid "" +"From here you can search these documents. Enter your search\n" +" words into the box below and click \"search\". Note that the search\n" +" function will automatically search for all of the words. Pages\n" +" containing fewer words won't appear in the result list." +msgstr "" +"Šeit Jūs varat meklēt šajos dokumentos. Norādiet meklējamus vārdus\n" +" ievada lauka un uzklikšķiniet pogu \"meklēt\". Lūdzu ievērojiet,\n" +" ka meklēšanas programma atradīs tikai tos dokumentus, kuros ir\n" +" visi ievadītie vārdi. Dokumenti, kuros ir tikai daļa no ievadītiem\n" +" vārdiem, netiks atlasīti." + +#: sphinx/themes/basic/search.html:30 +msgid "search" +msgstr "meklēt" + +#: sphinx/themes/basic/search.html:34 +#: sphinx/themes/basic/static/searchtools.js:489 +msgid "Search Results" +msgstr "Atlases rezultāti" + +#: sphinx/themes/basic/search.html:36 +msgid "Your search did not match any results." +msgstr "Nav rezultātu, atbilstošu Jūsu atlasei." + +#: sphinx/themes/basic/searchbox.html:12 +msgid "Quick search" +msgstr "Ātra meklēšana" + +#: sphinx/themes/basic/sourcelink.html:11 +msgid "This Page" +msgstr "Šī lappuse" + +#: sphinx/themes/basic/changes/frameset.html:5 +#: sphinx/themes/basic/changes/versionchanges.html:12 +#, python-format +msgid "Changes in Version %(version)s — %(docstitle)s" +msgstr "Izmaiņas versijā %(version)s — %(docstitle)s" + +#: sphinx/themes/basic/changes/rstsource.html:5 +#, python-format +msgid "%(filename)s — %(docstitle)s" +msgstr "%(filename)s — %(docstitle)s" + +#: sphinx/themes/basic/changes/versionchanges.html:17 +#, python-format +msgid "Automatically generated list of changes in version %(version)s" +msgstr "Automātiski sagatavots izmaiņu saraksts versijai %(version)s" + +#: sphinx/themes/basic/changes/versionchanges.html:18 +msgid "Library changes" +msgstr "Bibliotēkas izmaiņas" + +#: sphinx/themes/basic/changes/versionchanges.html:23 +msgid "C API changes" +msgstr "Izmaiņas iekš C API" + +#: sphinx/themes/basic/changes/versionchanges.html:25 +msgid "Other changes" +msgstr "Citas izmaiņas" + +#: sphinx/themes/basic/static/doctools.js:154 sphinx/writers/html.py:482 +#: sphinx/writers/html.py:487 +msgid "Permalink to this headline" +msgstr "Pastāvīga norāde šo virsrakstu" + +#: sphinx/themes/basic/static/doctools.js:160 sphinx/writers/html.py:87 +msgid "Permalink to this definition" +msgstr "Pastāvīga norāde uz šo definīciju" + +#: sphinx/themes/basic/static/doctools.js:189 +msgid "Hide Search Matches" +msgstr "Paslēpt atlases vārdus" + +#: sphinx/themes/basic/static/searchtools.js:285 +msgid "Searching" +msgstr "Meklējam" + +#: sphinx/themes/basic/static/searchtools.js:290 +msgid "Preparing search..." +msgstr "Sagatavojam atlasi..." + +#: sphinx/themes/basic/static/searchtools.js:364 +msgid ", in " +msgstr ", iekš " + +#: sphinx/themes/basic/static/searchtools.js:491 +msgid "" +"Your search did not match any documents. Please make sure that all words " +"are spelled correctly and that you've selected enough categories." +msgstr "Jūsu atlases rindai neatbilst neviens dokuments. Lūdzu, pārbaudiet, vai visi vārdi ir uzrakstīti pareizi, un vai ir izvēlētas pareizās kategorijas." + +#: sphinx/themes/basic/static/searchtools.js:493 +#, python-format +msgid "Search finished, found %s page(s) matching the search query." +msgstr "Atlase pabeigta, atrastas lapas: %s" + +#: sphinx/themes/default/static/sidebar.js:66 +msgid "Expand sidebar" +msgstr "Izplest sānjoslu" + +#: sphinx/themes/default/static/sidebar.js:79 +#: sphinx/themes/default/static/sidebar.js:106 +msgid "Collapse sidebar" +msgstr "Savērst sānjoslu" + +#: sphinx/themes/haiku/layout.html:26 +msgid "Contents" +msgstr "Saturs" + +#: sphinx/writers/latex.py:171 +msgid "Release" +msgstr "Izlaidums" + +#: sphinx/writers/latex.py:572 sphinx/writers/manpage.py:178 +msgid "Footnotes" +msgstr "Vēres" + +#: sphinx/writers/latex.py:641 +msgid "continued from previous page" +msgstr "turpinājums no iepriekšējās lappuses" + +#: sphinx/writers/latex.py:646 +msgid "Continued on next page" +msgstr "Turpnājums nākošā lappusē" + +#: sphinx/writers/text.py:422 +msgid "[image]" +msgstr "[attēls]" + diff --git a/sphinx/locale/tr/LC_MESSAGES/sphinx.mo b/sphinx/locale/tr/LC_MESSAGES/sphinx.mo index 742eff993..cbe9b2528 100644 Binary files a/sphinx/locale/tr/LC_MESSAGES/sphinx.mo and b/sphinx/locale/tr/LC_MESSAGES/sphinx.mo differ diff --git a/sphinx/locale/tr/LC_MESSAGES/sphinx.po b/sphinx/locale/tr/LC_MESSAGES/sphinx.po index 9b99a4b6d..2fe3043a9 100644 --- a/sphinx/locale/tr/LC_MESSAGES/sphinx.po +++ b/sphinx/locale/tr/LC_MESSAGES/sphinx.po @@ -1,23 +1,23 @@ -# Turkish translations for Sphinx. -# Copyright (C) 2009 ORGANIZATION +# Translations template for Sphinx. +# Copyright (C) 2011 ORGANIZATION # This file is distributed under the same license as the Sphinx project. -# FIRST AUTHOR , 2009. +# FIRST AUTHOR , 2011. # msgid "" msgstr "" -"Project-Id-Version: Sphinx 0.6.2+/6b02a19ccf31\n" +"Project-Id-Version: Sphinx 1.1pre/339c7a794c1a\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2009-08-06 22:48+0200\n" -"PO-Revision-Date: 2011-01-22 14:41+0100\n" +"POT-Creation-Date: 2011-01-22 14:40+0100\n" +"PO-Revision-Date: 2011-04-04 00:42+0200\n" "Last-Translator: Firat Ozgul \n" -"Language-Team: Turkish \n" -"Plural-Forms: nplurals=1; plural=0\n" +"Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 0.9.5\n" -#: sphinx/environment.py:120 sphinx/writers/latex.py:189 +#: sphinx/environment.py:120 +#: sphinx/writers/latex.py:189 #: sphinx/writers/manpage.py:67 #, python-format msgid "%B %d, %Y" @@ -26,12 +26,12 @@ msgstr "%d %B %Y" #: sphinx/environment.py:1624 #, python-format msgid "see %s" -msgstr "" +msgstr "bkz. %s" #: sphinx/environment.py:1627 #, python-format msgid "see also %s" -msgstr "" +msgstr "ayrıca bkz. %s" #: sphinx/roles.py:175 #, python-format @@ -51,7 +51,8 @@ msgstr "Modül düzeyi" msgid "%b %d, %Y" msgstr "%d %b %Y" -#: sphinx/builders/html.py:293 sphinx/themes/basic/defindex.html:30 +#: sphinx/builders/html.py:293 +#: sphinx/themes/basic/defindex.html:30 msgid "General Index" msgstr "Genel Dizin" @@ -67,17 +68,22 @@ msgstr "sonraki" msgid "previous" msgstr "önceki" -#: sphinx/builders/latex.py:141 sphinx/builders/texinfo.py:208 +#: sphinx/builders/latex.py:141 +#: sphinx/builders/texinfo.py:208 msgid " (in " msgstr " (şunun içinde: " -#: sphinx/builders/texinfo.py:151 sphinx/builders/texinfo.py:152 -#: sphinx/builders/texinfo.py:153 sphinx/domains/std.py:427 +#: sphinx/builders/texinfo.py:151 +#: sphinx/builders/texinfo.py:152 +#: sphinx/builders/texinfo.py:153 +#: sphinx/domains/std.py:427 #: sphinx/themes/basic/genindex-single.html:32 #: sphinx/themes/basic/genindex-split.html:11 #: sphinx/themes/basic/genindex-split.html:14 -#: sphinx/themes/basic/genindex.html:32 sphinx/themes/basic/genindex.html:35 -#: sphinx/themes/basic/genindex.html:68 sphinx/themes/basic/layout.html:134 +#: sphinx/themes/basic/genindex.html:32 +#: sphinx/themes/basic/genindex.html:35 +#: sphinx/themes/basic/genindex.html:68 +#: sphinx/themes/basic/layout.html:134 #: sphinx/writers/latex.py:178 msgid "Index" msgstr "Dizin" @@ -107,16 +113,19 @@ msgstr "Ayrıca bkz." msgid "%s %s" msgstr "%s %s" -#: sphinx/domains/c.py:51 sphinx/domains/python.py:95 +#: sphinx/domains/c.py:51 +#: sphinx/domains/python.py:95 msgid "Parameters" msgstr "Parametreler" -#: sphinx/domains/c.py:54 sphinx/domains/javascript.py:128 +#: sphinx/domains/c.py:54 +#: sphinx/domains/javascript.py:128 #: sphinx/domains/python.py:107 msgid "Returns" -msgstr "Şunu döndürür:" +msgstr "Dönüş değeri:" -#: sphinx/domains/c.py:56 sphinx/domains/python.py:109 +#: sphinx/domains/c.py:56 +#: sphinx/domains/python.py:109 msgid "Return type" msgstr "Dönüş tipi" @@ -145,12 +154,15 @@ msgstr "%s (C tipi)" msgid "%s (C variable)" msgstr "%s (C değişkeni)" -#: sphinx/domains/c.py:204 sphinx/domains/cpp.py:1053 -#: sphinx/domains/javascript.py:162 sphinx/domains/python.py:558 +#: sphinx/domains/c.py:204 +#: sphinx/domains/cpp.py:1053 +#: sphinx/domains/javascript.py:162 +#: sphinx/domains/python.py:558 msgid "function" msgstr "fonksiyonu" -#: sphinx/domains/c.py:205 sphinx/domains/cpp.py:1054 +#: sphinx/domains/c.py:205 +#: sphinx/domains/cpp.py:1054 msgid "member" msgstr "öğesi" @@ -158,7 +170,8 @@ msgstr "öğesi" msgid "macro" msgstr "makrosu" -#: sphinx/domains/c.py:207 sphinx/domains/cpp.py:1055 +#: sphinx/domains/c.py:207 +#: sphinx/domains/cpp.py:1055 msgid "type" msgstr "tipi" @@ -186,17 +199,20 @@ msgstr "%s (C++ öğesi)" msgid "%s (C++ function)" msgstr "%s (C++ fonksiyonu)" -#: sphinx/domains/cpp.py:1052 sphinx/domains/javascript.py:163 +#: sphinx/domains/cpp.py:1052 +#: sphinx/domains/javascript.py:163 #: sphinx/domains/python.py:560 msgid "class" msgstr "sınıfı" -#: sphinx/domains/javascript.py:106 sphinx/domains/python.py:254 +#: sphinx/domains/javascript.py:106 +#: sphinx/domains/python.py:254 #, python-format msgid "%s() (built-in function)" msgstr "%s() (gömülü fonksiyon)" -#: sphinx/domains/javascript.py:107 sphinx/domains/python.py:318 +#: sphinx/domains/javascript.py:107 +#: sphinx/domains/python.py:318 #, python-format msgid "%s() (%s method)" msgstr "%s() (%s metodu)" @@ -211,7 +227,8 @@ msgstr "%s() (sınıfı)" msgid "%s (global variable or constant)" msgstr "%s (global değişken veya sabit)" -#: sphinx/domains/javascript.py:113 sphinx/domains/python.py:356 +#: sphinx/domains/javascript.py:113 +#: sphinx/domains/python.py:356 #, python-format msgid "%s (%s attribute)" msgstr "%s (%s niteliği)" @@ -224,11 +241,13 @@ msgstr "Argümanlar" msgid "Throws" msgstr "Şunu verir: " -#: sphinx/domains/javascript.py:164 sphinx/domains/python.py:559 +#: sphinx/domains/javascript.py:164 +#: sphinx/domains/python.py:559 msgid "data" msgstr "verisi" -#: sphinx/domains/javascript.py:165 sphinx/domains/python.py:565 +#: sphinx/domains/javascript.py:165 +#: sphinx/domains/python.py:565 msgid "attribute" msgstr "niteliği" @@ -240,8 +259,10 @@ msgstr "Değişkenler" msgid "Raises" msgstr "Şunu üretir:" -#: sphinx/domains/python.py:255 sphinx/domains/python.py:312 -#: sphinx/domains/python.py:324 sphinx/domains/python.py:337 +#: sphinx/domains/python.py:255 +#: sphinx/domains/python.py:312 +#: sphinx/domains/python.py:324 +#: sphinx/domains/python.py:337 #, python-format msgid "%s() (in module %s)" msgstr "%s() (%s modülü içinde)" @@ -251,7 +272,8 @@ msgstr "%s() (%s modülü içinde)" msgid "%s (built-in variable)" msgstr "%s (gömülü değişken)" -#: sphinx/domains/python.py:259 sphinx/domains/python.py:350 +#: sphinx/domains/python.py:259 +#: sphinx/domains/python.py:350 #, python-format msgid "%s (in module %s)" msgstr "%s (%s modülü içinde)" @@ -313,7 +335,8 @@ msgstr "modüller" msgid "Deprecated" msgstr "Önerilmiyor" -#: sphinx/domains/python.py:561 sphinx/locale/__init__.py:179 +#: sphinx/domains/python.py:561 +#: sphinx/locale/__init__.py:179 msgid "exception" msgstr "istisnası" @@ -329,7 +352,8 @@ msgstr "sınıf metodu" msgid "static method" msgstr "statik metodu" -#: sphinx/domains/python.py:566 sphinx/locale/__init__.py:175 +#: sphinx/domains/python.py:566 +#: sphinx/locale/__init__.py:175 msgid "module" msgstr "modülü" @@ -355,7 +379,8 @@ msgstr "yönergesi" msgid "role" msgstr "rolü" -#: sphinx/domains/std.py:70 sphinx/domains/std.py:86 +#: sphinx/domains/std.py:70 +#: sphinx/domains/std.py:86 #, python-format msgid "environment variable; %s" msgstr "çevre değişkeni; %s" @@ -389,7 +414,8 @@ msgstr "program seçeneği" msgid "Module Index" msgstr "Modül Dizini" -#: sphinx/domains/std.py:429 sphinx/themes/basic/defindex.html:25 +#: sphinx/domains/std.py:429 +#: sphinx/themes/basic/defindex.html:25 msgid "Search Page" msgstr "Arama Sayfası" @@ -498,7 +524,7 @@ msgstr "%s sürümünden beri önerilmiyor" #: sphinx/locale/__init__.py:176 msgid "keyword" -msgstr "anahtar kelime" +msgstr "anahtar sözcük" #: sphinx/locale/__init__.py:177 msgid "operator" @@ -516,25 +542,31 @@ msgstr "deyim" msgid "built-in function" msgstr "gömülü fonksiyon" -#: sphinx/themes/agogo/layout.html:45 sphinx/themes/basic/globaltoc.html:10 +#: sphinx/themes/agogo/layout.html:45 +#: sphinx/themes/basic/globaltoc.html:10 #: sphinx/themes/basic/localtoc.html:11 msgid "Table Of Contents" msgstr "İçindekiler Tablosu" -#: sphinx/themes/agogo/layout.html:49 sphinx/themes/basic/layout.html:137 -#: sphinx/themes/basic/search.html:11 sphinx/themes/basic/search.html:20 +#: sphinx/themes/agogo/layout.html:49 +#: sphinx/themes/basic/layout.html:137 +#: sphinx/themes/basic/search.html:11 +#: sphinx/themes/basic/search.html:20 msgid "Search" msgstr "Ara" -#: sphinx/themes/agogo/layout.html:52 sphinx/themes/basic/searchbox.html:15 +#: sphinx/themes/agogo/layout.html:52 +#: sphinx/themes/basic/searchbox.html:15 msgid "Go" msgstr "Git" -#: sphinx/themes/agogo/layout.html:57 sphinx/themes/basic/searchbox.html:20 +#: sphinx/themes/agogo/layout.html:57 +#: sphinx/themes/basic/searchbox.html:20 msgid "Enter search terms or a module, class or function name." msgstr "Aranacak terimleri veya modül, sınıf ya da fonksiyon adını yazınız" -#: sphinx/themes/agogo/layout.html:78 sphinx/themes/basic/sourcelink.html:14 +#: sphinx/themes/agogo/layout.html:78 +#: sphinx/themes/basic/sourcelink.html:14 msgid "Show Source" msgstr "Kaynağı Göster" @@ -624,12 +656,8 @@ msgstr "Son güncelleme: %(last_updated)s." #: sphinx/themes/basic/layout.html:198 #, python-format -msgid "" -"Created using Sphinx " -"%(sphinx_version)s." -msgstr "" -"Sphinx %(sphinx_version)s ile " -"oluşturulmuştur." +msgid "Created using Sphinx %(sphinx_version)s." +msgstr "Sphinx %(sphinx_version)s ile oluşturulmuştur." #: sphinx/themes/basic/opensearch.xml:4 #, python-format @@ -720,12 +748,14 @@ msgstr "C API'sindeki değişiklikler" msgid "Other changes" msgstr "Diğer değişiklikler" -#: sphinx/themes/basic/static/doctools.js:154 sphinx/writers/html.py:505 +#: sphinx/themes/basic/static/doctools.js:154 +#: sphinx/writers/html.py:505 #: sphinx/writers/html.py:511 msgid "Permalink to this headline" msgstr "Bu başlığın kalıcı bağlantısı" -#: sphinx/themes/basic/static/doctools.js:160 sphinx/writers/html.py:92 +#: sphinx/themes/basic/static/doctools.js:160 +#: sphinx/writers/html.py:92 msgid "Permalink to this definition" msgstr "Bu tanımın kalıcı bağlantısı" @@ -750,7 +780,8 @@ msgstr "İçindekiler" msgid "Release" msgstr "Sürüm" -#: sphinx/writers/latex.py:590 sphinx/writers/manpage.py:182 +#: sphinx/writers/latex.py:590 +#: sphinx/writers/manpage.py:182 msgid "Footnotes" msgstr "Dipnotları" @@ -766,28 +797,3 @@ msgstr "Devamı sonraki sayfada" msgid "[image]" msgstr "[resim]" -#~ msgid "Platforms: " -#~ msgstr "Platformlar:" - -#~ msgid "Searching" -#~ msgstr "Arıyor" - -#~ msgid "Preparing search..." -#~ msgstr "Aramaya hazırlanıyor..." - -#~ msgid ", in " -#~ msgstr ", şunun içinde: " - -#~ msgid "" -#~ "Your search did not match any " -#~ "documents. Please make sure that all " -#~ "words are spelled correctly and that " -#~ "you've selected enough categories." -#~ msgstr "" -#~ "Arama sonucunda hiçbir belge bulunamadı. " -#~ "Bütün kelimeleri doğru yazdığınızdan ve " -#~ "gereken kategorileri seçtiğinizden emin olun." - -#~ msgid "Search finished, found %s page(s) matching the search query." -#~ msgstr "Arama sonuçlandı, aramayla eşleşen %s sayfa bulundu." - diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py index e15e42bf2..bf51e7408 100644 --- a/sphinx/pycode/__init__.py +++ b/sphinx/pycode/__init__.py @@ -17,7 +17,7 @@ from cStringIO import StringIO from sphinx.errors import PycodeError from sphinx.pycode import nodes from sphinx.pycode.pgen2 import driver, token, tokenize, parse, literals -from sphinx.util import get_module_source +from sphinx.util import get_module_source, detect_encoding from sphinx.util.pycompat import next from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc @@ -38,10 +38,6 @@ for k, v in token.tok_name.iteritems(): number2name = pygrammar.number2symbol.copy() number2name.update(token.tok_name) - -# a regex to recognize coding cookies -_coding_re = re.compile(r'coding[:=]\s*([-\w.]+)') - _eq = nodes.Leaf(token.EQUAL, '=') @@ -217,11 +213,10 @@ class ModuleAnalyzer(object): self.srcname = srcname # file-like object yielding source lines self.source = source - # will be changed when found by parse() - self.encoding = sys.getdefaultencoding() # cache the source code as well pos = self.source.tell() + self.encoding = detect_encoding(self.source.readline) self.code = self.source.read() self.source.seek(pos) @@ -251,13 +246,6 @@ class ModuleAnalyzer(object): self.parsetree = pydriver.parse_tokens(self.tokens) except parse.ParseError, err: raise PycodeError('parsing failed', err) - # find the source code encoding, if present - comments = self.parsetree.get_prefix() - for line in comments.splitlines()[:2]: - match = _coding_re.search(line) - if match is not None: - self.encoding = match.group(1) - break def find_attr_docs(self, scope=''): """Find class and module-level attributes and their documentation.""" diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index d606e7ad0..dcc6a855d 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -258,6 +258,7 @@ man_pages = [ # If true, show URL addresses after external links. #man_show_urls = False + # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples @@ -269,7 +270,13 @@ texinfo_documents = [ ] # Documents to append as an appendix to all manuals. -texinfo_appendices = [] +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' ''' EPUB_CONFIG = ''' diff --git a/sphinx/themes/basic/static/searchtools.js_t b/sphinx/themes/basic/static/searchtools.js_t index 6be7489fb..0aa291cba 100644 --- a/sphinx/themes/basic/static/searchtools.js_t +++ b/sphinx/themes/basic/static/searchtools.js_t @@ -127,8 +127,12 @@ var Search = { var excluded = []; var hlterms = []; var tmp = query.split(/\s+/); - var object = (tmp.length == 1) ? tmp[0].toLowerCase() : null; + var objectterms = []; for (var i = 0; i < tmp.length; i++) { + if (tmp[i] != "") { + objectterms.push(tmp[i].toLowerCase()); + } + if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/) || tmp[i] == "") { // skip this "word" @@ -159,9 +163,6 @@ var Search = { var filenames = this._index.filenames; var titles = this._index.titles; var terms = this._index.terms; - var objects = this._index.objects; - var objtypes = this._index.objtypes; - var objnames = this._index.objnames; var fileMap = {}; var files = null; // different result priorities @@ -172,40 +173,19 @@ var Search = { $('#search-progress').empty(); // lookup as object - if (object != null) { - for (var prefix in objects) { - for (var name in objects[prefix]) { - var fullname = (prefix ? prefix + '.' : '') + name; - if (fullname.toLowerCase().indexOf(object) > -1) { - match = objects[prefix][name]; - descr = objnames[match[1]] + _(', in ') + titles[match[0]]; - // XXX the generated anchors are not generally correct - // XXX there may be custom prefixes - result = [filenames[match[0]], fullname, '#'+fullname, descr]; - switch (match[2]) { - case 1: objectResults.push(result); break; - case 0: importantResults.push(result); break; - case 2: unimportantResults.push(result); break; - } - } - } - } + for (var i = 0; i < objectterms.length; i++) { + var others = Array.concat(objectterms.slice(0,i), + objectterms.slice(i+1, objectterms.length)) + var results = this.performObjectSearch(objectterms[i], others); + // Assume first word is most likely to be the object, + // other words more likely to be in description. + // Therefore put matches for earlier words first. + // (Results are eventually used in reverse order). + objectResults = results[0].concat(objectResults); + importantResults = results[1].concat(importantResults); + unimportantResults = results[2].concat(unimportantResults); } - // sort results descending - objectResults.sort(function(a, b) { - return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); - }); - - importantResults.sort(function(a, b) { - return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); - }); - - unimportantResults.sort(function(a, b) { - return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); - }); - - // perform the search on the required terms for (var i = 0; i < searchterms.length; i++) { var word = searchterms[i]; @@ -304,7 +284,7 @@ var Search = { listItem.slideDown(5, function() { displayNextItem(); }); - }); + }, "text"); } else { // no source available, just display title Search.output.append(listItem); @@ -325,6 +305,67 @@ var Search = { } } displayNextItem(); + }, + + performObjectSearch : function(object, otherterms) { + var filenames = this._index.filenames; + var objects = this._index.objects; + var objnames = this._index.objnames; + var titles = this._index.titles; + + var importantResults = []; + var objectResults = []; + var unimportantResults = []; + + for (var prefix in objects) { + for (var name in objects[prefix]) { + var fullname = (prefix ? prefix + '.' : '') + name; + if (fullname.toLowerCase().indexOf(object) > -1) { + var match = objects[prefix][name]; + var objname = objnames[match[1]]; + var title = titles[match[0]]; + // If more than one term searched for, we require other words to be + // found in the name/title/description + if (otherterms.length > 0) { + var haystack = (prefix + ' ' + name + ' ' + objname + ' ' + title).toLowerCase(); + var allfound = true; + for (var i = 0; i < otherterms.length; i++) { + if (haystack.indexOf(otherterms[i]) == -1) { + allfound = false; + break; + } + } + if (!allfound) { + continue; + } + } + var descr = objname + _(', in ') + title; + // XXX the generated anchors are not generally correct + // XXX there may be custom prefixes + result = [filenames[match[0]], fullname, '#'+fullname, descr]; + switch (match[2]) { + case 1: objectResults.push(result); break; + case 0: importantResults.push(result); break; + case 2: unimportantResults.push(result); break; + } + } + } + } + + // sort results descending + objectResults.sort(function(a, b) { + return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); + }); + + importantResults.sort(function(a, b) { + return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); + }); + + unimportantResults.sort(function(a, b) { + return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0); + }); + + return [importantResults, objectResults, unimportantResults] } } diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 8218c04a9..b1a3a0d7d 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -18,7 +18,7 @@ import tempfile import posixpath import traceback from os import path -from codecs import open +from codecs import open, BOM_UTF8 from collections import deque import docutils @@ -216,6 +216,59 @@ def get_module_source(modname): return 'file', filename +# a regex to recognize coding cookies +_coding_re = re.compile(r'coding[:=]\s*([-\w.]+)') + +def detect_encoding(readline): + """Like tokenize.detect_encoding() from Py3k, but a bit simplified.""" + + def read_or_stop(): + try: + return readline() + except StopIteration: + return None + + def get_normal_name(orig_enc): + """Imitates get_normal_name in tokenizer.c.""" + # Only care about the first 12 characters. + enc = orig_enc[:12].lower().replace('_', '-') + if enc == 'utf-8' or enc.startswith('utf-8-'): + return 'utf-8' + if enc in ('latin-1', 'iso-8859-1', 'iso-latin-1') or \ + enc.startswith(('latin-1-', 'iso-8859-1-', 'iso-latin-1-')): + return 'iso-8859-1' + return orig_enc + + def find_cookie(line): + try: + line_string = line.decode('ascii') + except UnicodeDecodeError: + return None + + matches = _coding_re.findall(line_string) + if not matches: + return None + return get_normal_name(matches[0]) + + default = sys.getdefaultencoding() + first = read_or_stop() + if first and first.startswith(BOM_UTF8): + first = first[3:] + default = 'utf-8-sig' + if not first: + return default + encoding = find_cookie(first) + if encoding: + return encoding + second = read_or_stop() + if not second: + return default + encoding = find_cookie(second) + if encoding: + return encoding + return default + + # Low-level utility functions and classes. class Tee(object): diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index eb5c76fa9..99d621c6f 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -116,12 +116,13 @@ class HTMLTranslator(BaseTranslator): def visit_desc_parameterlist(self, node): self.body.append('(') self.first_param = 1 + self.param_separator = node.child_text_separator def depart_desc_parameterlist(self, node): self.body.append(')') def visit_desc_parameter(self, node): if not self.first_param: - self.body.append(', ') + self.body.append(self.param_separator) else: self.first_param = 0 if not node.hasattr('noemph'): @@ -566,8 +567,15 @@ class SmartyPantsHTMLTranslator(HTMLTranslator): self.no_smarty += 1 try: HTMLTranslator.visit_literal_block(self, node) - finally: + except nodes.SkipNode: + # HTMLTranslator raises SkipNode for simple literal blocks, + # but not for parsed literal blocks self.no_smarty -= 1 + raise + + def depart_literal_block(self, node): + HTMLTranslator.depart_literal_block(self, node) + self.no_smarty -= 1 def visit_literal_emphasis(self, node): self.no_smarty += 1 diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index c5c3aabe2..7eb63c842 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -11,21 +11,34 @@ import re from os import path +import textwrap from docutils import nodes, writers -from sphinx import addnodes -from sphinx.locale import versionlabels +from sphinx import addnodes, __version__ +from sphinx.locale import versionlabels, _ +from sphinx.util import ustrftime +from sphinx.writers.latex import collected_footnote +COPYING = """\ +@quotation +%(project)s %(release)s, %(date)s + +%(author)s + +Copyright @copyright{} %(copyright)s +@end quotation +""" + TEMPLATE = """\ \\input texinfo @c -*-texinfo-*- @c %%**start of header @setfilename %(filename)s @documentencoding UTF-8 -@copying -Generated by Sphinx -@end copying +@ifinfo +@*Generated by Sphinx """ + __version__ + """.@* +@end ifinfo @settitle %(title)s @defindex ge @paragraphindent %(paragraphindent)s @@ -34,9 +47,13 @@ Generated by Sphinx %(direntry)s @c %%**end of header +@copying +%(copying)s +@end copying + @titlepage @title %(title)s -@author %(author)s +@insertcopying @end titlepage @contents @@ -47,6 +64,7 @@ Generated by Sphinx @ifnottex @node Top @top %(title)s +@insertcopying @end ifnottex @c %%**start of body @@ -67,70 +85,19 @@ def find_subsections(section): return result -## Escaping -# Which characters to escape depends on the context. In some cases, -# namely menus and node names, it's not possible to escape certain -# characters. - -def escape(s): - """Return a string with Texinfo command characters escaped.""" - s = s.replace('@', '@@') - s = s.replace('{', '@{') - s = s.replace('}', '@}') - # Prevent "--" from being converted to an "em dash" - # s = s.replace('-', '@w{-}') - return s - -def escape_arg(s): - """Return an escaped string suitable for use as an argument - to a Texinfo command.""" - s = escape(s) - # Commas are the argument delimeters - s = s.replace(',', '@comma{}') - # Normalize white space - s = ' '.join(s.split()).strip() - return s - -def escape_id(s): - """Return an escaped string suitable for node names, menu entries, - and xrefs anchors.""" - bad_chars = ',:.()@{}' - for bc in bad_chars: - s = s.replace(bc, ' ') - s = ' '.join(s.split()).strip() - return s - class TexinfoWriter(writers.Writer): """Texinfo writer for generating Texinfo documents.""" supported = ('texinfo', 'texi') settings_spec = ( - 'Texinfo Specific Options', - None, - ( - ("Name of the resulting Info file to be created by 'makeinfo'. " - "Should probably end with '.info'.", - ['--texinfo-filename'], - {'default': '', 'metavar': ''}), - - ('Specify the Info dir entry category.', - ['--texinfo-dir-category'], - {'default': 'Miscellaneous', 'metavar': ''}), - - ('The name to use for the Info dir entry. ' - 'If not provided, no entry will be created.', - ['--texinfo-dir-entry'], - {'default': '', 'metavar': ''}), - - ('A brief description (one or two lines) to use for the ' - 'Info dir entry.', - ['--texinfo-dir-description'], - {'default': '', 'metavar': ''}), - ) - ) + 'Texinfo Specific Options', None, ( + ("Name of the Info file", ['--texinfo-filename'], {'default': ''}), + ('Dir entry', ['--texinfo-dir-entry'], {'default': ''}), + ('Description', ['--texinfo-dir-description'], {'default': ''}), + ('Category', ['--texinfo-dir-category'], {'default': + 'Miscellaneous'}))) settings_defaults = {} - settings_default_overrides = {'docinfo_xform': 0} output = None @@ -153,13 +120,18 @@ class TexinfoTranslator(nodes.NodeVisitor): ignore_missing_images = False default_elements = { - 'filename': '', - 'title': '', - 'paragraphindent': 2, - 'exampleindent': 4, - 'direntry': '', - 'preamble': '', + 'author': '', 'body': '', + 'copying': '', + 'date': '', + 'direntry': '', + 'exampleindent': 4, + 'filename': '', + 'paragraphindent': 2, + 'preamble': '', + 'project': '', + 'release': '', + 'title': '', } def __init__(self, document, builder): @@ -170,37 +142,47 @@ class TexinfoTranslator(nodes.NodeVisitor): self.written_ids = set() # node names and anchors in output self.referenced_ids = set() # node names and anchors that should # be in output + self.indices = [] # (node name, content) + self.short_ids = {} # anchors --> short ids self.node_names = {} # node name --> node's name to display self.node_menus = {} # node name --> node's menu entries self.rellinks = {} # node name --> (next, previous, up) + self.collect_indices() self.collect_node_names() self.collect_node_menus() self.collect_rellinks() - self.short_ids = {} self.body = [] self.context = [] self.previous_section = None self.section_level = 0 self.seen_title = False - self.next_section_targets = [] + self.next_section_ids = set() self.escape_newlines = 0 self.curfilestack = [] + self.footnotestack = [] + self.in_footnote = 0 + self.handled_abbrs = set() def finish(self): + if self.previous_section is None: + self.add_menu('Top') + for index in self.indices: + name, content = index + pointers = tuple([name] + self.rellinks[name]) + self.body.append('\n@node %s,%s,%s,%s\n' % pointers) + self.body.append('@unnumbered %s\n\n%s\n' % (name, content)) + while self.referenced_ids: - # Handle xrefs with missing anchors + # handle xrefs with missing anchors r = self.referenced_ids.pop() if r not in self.written_ids: - self.document.reporter.info( - "Unknown cross-reference target: `%s'" % r) - self.add_text('@anchor{%s}@w{%s}\n' % (r, ' ' * 30)) + self.body.append('@anchor{%s}@w{%s}\n' % (r, ' ' * 30)) self.fragment = ''.join(self.body).strip() + '\n' self.elements['body'] = self.fragment self.output = TEMPLATE % self.elements - ## Helper routines def init_settings(self): @@ -209,32 +191,40 @@ class TexinfoTranslator(nodes.NodeVisitor): elements.update({ # if empty, the title is set to the first section title 'title': settings.title, - 'author': escape_arg(settings.author), + 'author': settings.author, # if empty, use basename of input file 'filename': settings.texinfo_filename, + 'release': self.escape(self.builder.config.release), + 'project': self.escape(self.builder.config.project), + 'copyright': self.escape(self.builder.config.copyright), + 'date': self.escape(self.builder.config.today or + ustrftime(self.builder.config.today_fmt + or _('%B %d, %Y'))) }) - # Title + # title title = elements['title'] if not title: title = self.document.next_node(nodes.title) title = (title and title.astext()) or '' - elements['title'] = escape_id(title) or '' - # Filename + elements['title'] = self.escape_id(title) or '' + # filename if not elements['filename']: elements['filename'] = self.document.get('source') or 'untitled' if elements['filename'][-4:] in ('.txt', '.rst'): elements['filename'] = elements['filename'][:-4] elements['filename'] += '.info' - # Direntry + # direntry if settings.texinfo_dir_entry: + entry = self.format_menu_entry( + self.escape_menu(settings.texinfo_dir_entry), + '(%s)' % elements['filename'], + self.escape_arg(settings.texinfo_dir_description)) elements['direntry'] = ('@dircategory %s\n' '@direntry\n' - '* %s: (%s). %s\n' + '%s' '@end direntry\n') % ( - escape_id(settings.texinfo_dir_category), - escape_id(settings.texinfo_dir_entry), - elements['filename'], - escape_arg(settings.texinfo_dir_description)) + self.escape_id(settings.texinfo_dir_category), entry) + elements['copying'] = COPYING % elements # allow the user to override them all elements.update(settings.texinfo_elements) @@ -242,26 +232,30 @@ class TexinfoTranslator(nodes.NodeVisitor): """Generates a unique id for each section. Assigns the attribute ``node_name`` to each section.""" + # must have a "Top" node self.document['node_name'] = 'Top' self.node_names['Top'] = 'Top' self.written_ids.update(('Top', 'top')) - + # each index is a node + for name, content in self.indices: + self.node_names[name] = name + self.written_ids.add(name) + # each section is also a node for section in self.document.traverse(nodes.section): title = section.next_node(nodes.Titular) name = (title and title.astext()) or '' - node_id = name = escape_id(name) or '' + node_id = self.escape_id(name) or '' assert node_id and name nth, suffix = 1, '' - while (node_id + suffix).lower() in self.written_ids: + while node_id + suffix in self.written_ids: nth += 1 suffix = '<%s>' % nth node_id += suffix assert node_id not in self.node_names assert node_id not in self.written_ids - assert node_id.lower() not in self.written_ids section['node_name'] = node_id self.node_names[node_id] = name - self.written_ids.update((node_id, node_id.lower())) + self.written_ids.add(node_id) def collect_node_menus(self): """Collect the menu entries for each "node" section.""" @@ -269,10 +263,9 @@ class TexinfoTranslator(nodes.NodeVisitor): for node in ([self.document] + self.document.traverse(nodes.section)): assert 'node_name' in node and node['node_name'] - entries = tuple(s['node_name'] - for s in find_subsections(node)) + entries = [s['node_name'] for s in find_subsections(node)] node_menus[node['node_name']] = entries - # Try to find a suitable "Top" node + # try to find a suitable "Top" node title = self.document.next_node(nodes.title) top = (title and title.parent) or self.document if not isinstance(top, (nodes.document, nodes.section)): @@ -283,6 +276,10 @@ class TexinfoTranslator(nodes.NodeVisitor): node_menus['Top'] = entries del node_menus[top['node_name']] top['node_name'] = 'Top' + # handle the indices + for name, content in self.indices: + node_menus[name] = () + node_menus['Top'].append(name) def collect_rellinks(self): """Collect the relative links (next, previous, up) for each "node".""" @@ -290,11 +287,11 @@ class TexinfoTranslator(nodes.NodeVisitor): node_menus = self.node_menus for id, entries in node_menus.items(): rellinks[id] = ['', '', ''] - # Up's + # up's for id, entries in node_menus.items(): for e in entries: rellinks[e][2] = id - # Next's and prev's + # next's and prev's for id, entries in node_menus.items(): for i, id in enumerate(entries): # First child's prev is empty @@ -303,7 +300,7 @@ class TexinfoTranslator(nodes.NodeVisitor): # Last child's next is empty if i != len(entries) - 1: rellinks[id][0] = entries[i+1] - # Top's next is its first child + # top's next is its first child try: first = node_menus['Top'][0] except IndexError: @@ -312,57 +309,95 @@ class TexinfoTranslator(nodes.NodeVisitor): rellinks['Top'][0] = first rellinks[first][1] = 'Top' - def add_text(self, text, fresh=False): - """Add some text to the output. + ## Escaping + # Which characters to escape depends on the context. In some cases, + # namely menus and node names, it's not possible to escape certain + # characters. - Optional argument ``fresh`` means to insert a newline before - the text if the last character out was not a newline.""" - if fresh: - if self.body and not self.body[-1].endswith('\n'): - self.body.append('\n') - self.body.append(text) + def escape(self, s): + """Return a string with Texinfo command characters escaped.""" + s = s.replace('@', '@@') + s = s.replace('{', '@{') + s = s.replace('}', '@}') + # prevent "--" from being converted to an "em dash" + # s = s.replace('-', '@w{-}') + return s - def rstrip(self): - """Strip trailing whitespace from the current output.""" - while self.body and not self.body[-1].strip(): - del self.body[-1] - if not self.body: - return - self.body[-1] = self.body[-1].rstrip() + def escape_arg(self, s): + """Return an escaped string suitable for use as an argument + to a Texinfo command.""" + s = self.escape(s) + # commas are the argument delimeters + s = s.replace(',', '@comma{}') + # normalize white space + s = ' '.join(s.split()).strip() + return s - def add_menu_entries(self, entries): + def escape_id(self, s): + """Return an escaped string suitable for node names and anchors.""" + bad_chars = ',:.()' + for bc in bad_chars: + s = s.replace(bc, ' ') + s = ' '.join(s.split()).strip() + return self.escape(s) + + def escape_menu(self, s): + """Return an escaped string suitable for menu entries.""" + s = self.escape_arg(s) + s = s.replace(':', ';') + s = ' '.join(s.split()).strip() + return s + + def format_menu_entry(self, name, node_name, desc): + if name == node_name: + s = '* %s:: ' % (name,) + else: + s = '* %s: %s. ' % (name, node_name) + offset = max((24, (len(name) + 4) % 78)) + wdesc = '\n'.join(' ' * offset + l for l in + textwrap.wrap(desc, width=78-offset)) + return s + wdesc.strip() + '\n' + + def add_menu_entries(self, entries, reg=re.compile(r'\s+---?\s+')): for entry in entries: name = self.node_names[entry] - if name == entry: - self.add_text('* %s::\n' % name, fresh=1) + # special formatting for entries that are divided by an em-dash + parts = reg.split(name, 1) + if len(parts) == 2: + name, desc = parts else: - self.add_text('* %s: %s.\n' % (name, entry), fresh=1) + desc = '' + name = self.escape_menu(name) + desc = self.escape(desc) + self.body.append(self.format_menu_entry(name, entry, desc)) - def add_menu(self, section, master=False): - entries = self.node_menus[section['node_name']] + def add_menu(self, node_name): + entries = self.node_menus[node_name] if not entries: return - self.add_text('\n@menu\n') + self.body.append('\n@menu\n') self.add_menu_entries(entries) - if master: - # Write the "detailed menu" - started_detail = False - for entry in entries: - subentries = self.node_menus[entry] - if not subentries: - continue - if not started_detail: - started_detail = True - self.add_text('\n@detailmenu\n' - ' --- The Detailed Node Listing ---\n') - self.add_text('\n%s\n\n' % self.node_names[entry]) - self.add_menu_entries(subentries) - if started_detail: - self.rstrip() - self.add_text('\n@end detailmenu\n') - self.rstrip() - self.add_text('\n@end menu\n\n') + if not self.node_menus[entries[0]]: + self.body.append('\n@end menu\n') + return + def _add_detailed_menu(name): + entries = self.node_menus[name] + if not entries: + return + self.body.append('\n%s\n\n' % (self.escape(self.node_names[name],))) + self.add_menu_entries(entries) + for subentry in entries: + _add_detailed_menu(subentry) + + if node_name == 'Top': + self.body.append('\n@detailmenu\n' + ' --- The Detailed Node Listing ---\n') + for entry in entries: + _add_detailed_menu(entry) + if node_name == 'Top': + self.body.append('\n@end detailmenu') + self.body.append('\n@end menu\n\n') def tex_image_length(self, width_str): match = re.match('(\d*\.?\d*)\s*(\S*)', width_str) @@ -379,6 +414,57 @@ class TexinfoTranslator(nodes.NodeVisitor): res = "%d.0pt" % (float(amount) * 4.1825368) return res + def collect_indices(self): + def generate(content, collapsed): + ret = ['\n@menu\n'] + for letter, entries in content: + for entry in entries: + if not entry[3]: + continue + name = self.escape_menu(entry[0]) + sid = self.get_short_id('%s:%s' % (entry[2], entry[3])) + desc = self.escape_arg(entry[6]) + me = self.format_menu_entry(name, sid, desc) + ret.append(me) + ret.append('@end menu\n') + return ''.join(ret) + + indices_config = self.builder.config.texinfo_domain_indices + if indices_config: + for domain in self.builder.env.domains.itervalues(): + for indexcls in domain.indices: + indexname = '%s-%s' % (domain.name, indexcls.name) + if isinstance(indices_config, list): + if indexname not in indices_config: + continue + content, collapsed = indexcls(domain).generate( + self.builder.docnames) + if not content: + continue + node_name = self.escape_id(indexcls.localname) + self.indices.append((node_name, + generate(content, collapsed))) + self.indices.append((_('Index'), '\n@printindex ge\n')) + + # this is copied from the latex writer + # TODO: move this to sphinx.util + + def collect_footnotes(self, node): + fnotes = {} + def footnotes_under(n): + if isinstance(n, nodes.footnote): + yield n + else: + for c in n.children: + if isinstance(c, addnodes.start_of_file): + continue + for k in footnotes_under(c): + yield k + for fn in footnotes_under(node): + num = fn.children[0].astext().strip() + fnotes[num] = [collected_footnote(*fn.children), False] + return fnotes + ## xref handling def get_short_id(self, id): @@ -392,58 +478,59 @@ class TexinfoTranslator(nodes.NodeVisitor): self.short_ids[id] = sid return sid - def add_anchor(self, id, msg_node=None): - # Anchors can be referenced by their original id - # or by the generated shortened id - id = escape_id(id).lower() - ids = (self.get_short_id(id), id) - for id in ids: + def add_anchor(self, id, node): + if id.startswith('index-'): + return + id = self.curfilestack[-1] + ':' + id + eid = self.escape_id(id) + sid = self.get_short_id(id) + for id in (eid, sid): if id not in self.written_ids: - self.add_text('@anchor{%s}' % id) + self.body.append('@anchor{%s}' % id) self.written_ids.add(id) - def add_xref(self, ref, name, node): - ref = self.get_short_id(escape_id(ref).lower()) - name = ' '.join(name.split()).strip() - if not name or ref == name: - self.add_text('@pxref{%s}' % ref) - else: - self.add_text('@pxref{%s,,%s}' % (ref, name)) - self.referenced_ids.add(ref) + def add_xref(self, id, name, node): + name = self.escape_menu(name) + sid = self.get_short_id(id) + self.body.append('@pxref{%s,,%s}' % (sid, name)) + self.referenced_ids.add(sid) + self.referenced_ids.add(self.escape_id(id)) ## Visiting def visit_document(self, node): - pass + self.footnotestack.append(self.collect_footnotes(node)) + self.curfilestack.append(node.get('docname', '')) + if 'docname' in node: + self.add_anchor(':doc', node) def depart_document(self, node): - pass + self.footnotestack.pop() + self.curfilestack.pop() def visit_Text(self, node): - s = escape(node.astext()) + s = self.escape(node.astext()) if self.escape_newlines: s = s.replace('\n', ' ') - self.add_text(s) + self.body.append(s) def depart_Text(self, node): pass def visit_section(self, node): - self.next_section_targets.extend(node.get('ids', [])) + self.next_section_ids.update(node.get('ids', [])) if not self.seen_title: return if self.previous_section: - self.add_menu(self.previous_section) + self.add_menu(self.previous_section['node_name']) else: - self.add_menu(self.document, master=True) + self.add_menu('Top') node_name = node['node_name'] pointers = tuple([node_name] + self.rellinks[node_name]) - self.add_text('\n@node %s,%s,%s,%s\n' % pointers) - if node_name != node_name.lower(): - self.add_text('@anchor{%s}' % node_name.lower()) - for id in self.next_section_targets: + self.body.append('\n@node %s,%s,%s,%s\n' % pointers) + for id in self.next_section_ids: self.add_anchor(id, node) - self.next_section_targets = [] + self.next_section_ids.clear() self.previous_section = node self.section_level += 1 @@ -471,110 +558,129 @@ class TexinfoTranslator(nodes.NodeVisitor): parent = node.parent if isinstance(parent, nodes.table): return - if isinstance(parent, nodes.Admonition): - raise nodes.SkipNode - elif isinstance(parent, nodes.sidebar): - self.visit_rubric(node) - elif isinstance(parent, nodes.topic): + if isinstance(parent, (nodes.Admonition, nodes.sidebar, nodes.topic)): raise nodes.SkipNode elif not isinstance(parent, nodes.section): - self.document.reporter.warning( + self.builder.warn( 'encountered title node not in section, topic, table, ' - 'admonition or sidebar', base_node=node) + 'admonition or sidebar', (self.curfilestack[-1], node.line)) self.visit_rubric(node) else: try: heading = self.headings[self.section_level] except IndexError: heading = self.headings[-1] - self.add_text('%s ' % heading, fresh=1) + self.body.append('\n%s ' % heading) def depart_title(self, node): - self.add_text('', fresh=1) + self.body.append('\n\n') def visit_rubric(self, node): + if len(node.children) == 1 and node.children[0].astext() in \ + ('Footnotes', _('Footnotes')): + raise nodes.SkipNode try: rubric = self.rubrics[self.section_level] except IndexError: rubric = self.rubrics[-1] - self.add_text('%s ' % rubric, fresh=1) + self.body.append('\n%s ' % rubric) def depart_rubric(self, node): - self.add_text('', fresh=1) + self.body.append('\n\n') def visit_subtitle(self, node): - self.add_text('\n\n@noindent\n') + self.body.append('\n\n@noindent\n') def depart_subtitle(self, node): - self.add_text('\n\n') + self.body.append('\n\n') ## References def visit_target(self, node): - if node.get('ids'): - self.add_anchor(node['ids'][0], node) - elif node.get('refid'): - # Section targets need to go after the start of the section. - next = node.next_node(ascend=1, siblings=1) - while isinstance(next, nodes.target): - next = next.next_node(ascend=1, siblings=1) + # postpone the labels until after the sectioning command + parindex = node.parent.index(node) + try: + try: + next = node.parent[parindex+1] + except IndexError: + # last node in parent, look at next after parent + # (for section of equal level) + next = node.parent.parent[node.parent.parent.index(node.parent)] if isinstance(next, nodes.section): - self.next_section_targets.append(node['refid']) + if node.get('refid'): + self.next_section_ids.add(node['refid']) + self.next_section_ids.update(node['ids']) return - self.add_anchor(node['refid'], node) - elif node.get('refuri'): + except IndexError: pass - else: - self.document.reporter.error("Unknown target type: %r" % node) + if 'refuri' in node: + return + if node.get('refid'): + self.add_anchor(node['refid'], node) + for id in node['ids']: + self.add_anchor(id, node) + def depart_target(self, node): + pass def visit_reference(self, node): - if isinstance(node.parent, nodes.title): + # an xref's target is displayed in Info so we ignore a few + # cases for the sake of appearance + if isinstance(node.parent, (nodes.title, addnodes.desc_type,)): return if isinstance(node[0], nodes.image): return - if isinstance(node.parent, addnodes.desc_type): - return name = node.get('name', node.astext()).strip() - if node.get('refid'): - self.add_xref(escape_id(node['refid']), - escape_id(name), node) - raise nodes.SkipNode - if not node.get('refuri'): - self.document.reporter.error("Unknown reference type: %s" % node) + uri = node.get('refuri', '') + if not uri and node.get('refid'): + uri = '%' + self.curfilestack[-1] + '#' + node['refid'] + if not uri: return - uri = node['refuri'] - if uri.startswith('#'): - self.add_xref(escape_id(uri[1:]), escape_id(name), node) - elif uri.startswith('%'): - id = uri[1:] - if '#' in id: - src, id = uri[1:].split('#', 1) - assert '#' not in id - self.add_xref(escape_id(id), escape_id(name), node) - elif uri.startswith('mailto:'): - uri = escape_arg(uri[7:]) - name = escape_arg(name) + if uri.startswith('mailto:'): + uri = self.escape_arg(uri[7:]) + name = self.escape_arg(name) if not name or name == uri: - self.add_text('@email{%s}' % uri) + self.body.append('@email{%s}' % uri) else: - self.add_text('@email{%s,%s}' % (uri, name)) + self.body.append('@email{%s,%s}' % (uri, name)) + elif uri.startswith('#'): + # references to labels in the same document + id = self.curfilestack[-1] + ':' + uri[1:] + self.add_xref(id, name, node) + elif uri.startswith('%'): + # references to documents or labels inside documents + hashindex = uri.find('#') + if hashindex == -1: + # reference to the document + id = uri[1:] + '::doc' + else: + # reference to a label + id = uri[1:].replace('#', ':') + self.add_xref(id, name, node) elif uri.startswith('info:'): + # references to an external Info file uri = uri[5:].replace('_', ' ') - uri = escape_arg(uri) + uri = self.escape_arg(uri) id = 'Top' if '#' in uri: uri, id = uri.split('#', 1) - id = escape_id(id) - name = escape_id(name) + id = self.escape_id(id) + name = self.escape_menu(name) if name == id: - self.add_text('@pxref{%s,,,%s}' % (id, uri)) + self.body.append('@pxref{%s,,,%s}' % (id, uri)) else: - self.add_text('@pxref{%s,,%s,%s}' % (id, name, uri)) + self.body.append('@pxref{%s,,%s,%s}' % (id, name, uri)) else: - uri = escape_arg(uri) - name = escape_arg(name) + uri = self.escape_arg(uri) + name = self.escape_arg(name) + show_urls = self.builder.config.texinfo_show_urls + if self.in_footnote: + show_urls = 'inline' if not name or uri == name: - self.add_text('@indicateurl{%s}' % uri) + self.body.append('@indicateurl{%s}' % uri) + elif show_urls == 'inline': + self.body.append('@uref{%s,%s}' % (uri, name)) + elif show_urls == 'no': + self.body.append('@uref{%s,,%s}' % (uri, name)) else: - self.add_text('@uref{%s,%s}' % (uri, name)) + self.body.append('%s@footnote{%s}' % (name, uri)) raise nodes.SkipNode def depart_reference(self, node): @@ -582,133 +688,137 @@ class TexinfoTranslator(nodes.NodeVisitor): def visit_title_reference(self, node): text = node.astext() - self.add_text('@cite{%s}' % escape_arg(text)) + self.body.append('@cite{%s}' % self.escape_arg(text)) raise nodes.SkipNode - def depart_title_reference(self, node): - pass ## Blocks def visit_paragraph(self, node): if 'continued' in node or isinstance(node.parent, nodes.compound): - self.add_text('@noindent\n', fresh=1) + self.body.append('\n@noindent') + self.body.append('\n') def depart_paragraph(self, node): - self.add_text('\n\n') + self.body.append('\n') def visit_block_quote(self, node): - self.rstrip() - self.add_text('\n\n@quotation\n') + self.body.append('\n@quotation\n') def depart_block_quote(self, node): - self.rstrip() - self.add_text('\n@end quotation\n\n') + self.body.append('\n@end quotation\n\n') def visit_literal_block(self, node): - self.rstrip() - self.add_text('\n\n@example\n') + self.body.append('\n@example\n') def depart_literal_block(self, node): - self.rstrip() - self.add_text('\n@end example\n\n' - '@noindent\n') + self.body.append('\n@end example\n\n' + '@noindent\n') visit_doctest_block = visit_literal_block depart_doctest_block = depart_literal_block def visit_line_block(self, node): - self.add_text('@display\n', fresh=1) + if not isinstance(node.parent, nodes.line_block): + self.body.append('\n\n') + self.body.append('@display\n') def depart_line_block(self, node): - self.add_text('@end display\n', fresh=1) + self.body.append('@end display\n') + if not isinstance(node.parent, nodes.line_block): + self.body.append('\n\n') def visit_line(self, node): - self.rstrip() - self.add_text('\n') self.escape_newlines += 1 def depart_line(self, node): - self.add_text('@w{ }\n') + self.body.append('@w{ }\n') self.escape_newlines -= 1 ## Inline def visit_strong(self, node): - self.add_text('@strong{') + self.body.append('@strong{') def depart_strong(self, node): - self.add_text('}') + self.body.append('}') def visit_emphasis(self, node): - self.add_text('@emph{') + self.body.append('@emph{') def depart_emphasis(self, node): - self.add_text('}') + self.body.append('}') def visit_literal(self, node): - self.add_text('@code{') + self.body.append('@code{') def depart_literal(self, node): - self.add_text('}') + self.body.append('}') def visit_superscript(self, node): - self.add_text('@w{^') + self.body.append('@w{^') def depart_superscript(self, node): - self.add_text('}') + self.body.append('}') def visit_subscript(self, node): - self.add_text('@w{[') + self.body.append('@w{[') def depart_subscript(self, node): - self.add_text(']}') + self.body.append(']}') ## Footnotes def visit_footnote(self, node): - self.visit_block_quote(node) - def depart_footnote(self, node): - self.depart_block_quote(node) + raise nodes.SkipNode + + def visit_collected_footnote(self, node): + self.in_footnote += 1 + self.body.append('@footnote{') + def depart_collected_footnote(self, node): + self.body.append('}') + self.in_footnote -= 1 def visit_footnote_reference(self, node): - self.add_text('@w{(') - def depart_footnote_reference(self, node): - self.add_text(')}') + num = node.astext().strip() + try: + footnode, used = self.footnotestack[-1][num] + except (KeyError, IndexError): + raise nodes.SkipNode + # footnotes are repeated for each reference + footnode.walkabout(self) + raise nodes.SkipChildren - visit_citation = visit_footnote - depart_citation = depart_footnote + def visit_citation(self, node): + for id in node.get('ids'): + self.add_anchor(id, node) + def depart_citation(self, node): + pass def visit_citation_reference(self, node): - self.add_text('@w{[') + self.body.append('@w{[') def depart_citation_reference(self, node): - self.add_text(']}') + self.body.append(']}') ## Lists def visit_bullet_list(self, node): bullet = node.get('bullet', '*') - self.rstrip() - self.add_text('\n\n@itemize %s\n' % bullet) + self.body.append('\n\n@itemize %s\n' % bullet) def depart_bullet_list(self, node): - self.rstrip() - self.add_text('\n@end itemize\n\n') + self.body.append('\n@end itemize\n\n') def visit_enumerated_list(self, node): - # Doesn't support Roman numerals + # doesn't support Roman numerals enum = node.get('enumtype', 'arabic') starters = {'arabic': '', 'loweralpha': 'a', 'upperalpha': 'A',} start = node.get('start', starters.get(enum, '')) - self.rstrip() - self.add_text('\n\n@enumerate %s\n' % start) + self.body.append('\n\n@enumerate %s\n' % start) def depart_enumerated_list(self, node): - self.rstrip() - self.add_text('\n@end enumerate\n\n') + self.body.append('\n@end enumerate\n\n') def visit_list_item(self, node): - self.rstrip() - self.add_text('\n@item\n') + self.body.append('\n@item\n') def depart_list_item(self, node): pass ## Option List def visit_option_list(self, node): - self.add_text('\n@table @option\n') + self.body.append('\n\n@table @option\n') def depart_option_list(self, node): - self.rstrip() - self.add_text('\n@end table\n\n') + self.body.append('\n@end table\n\n') def visit_option_list_item(self, node): pass @@ -721,7 +831,7 @@ class TexinfoTranslator(nodes.NodeVisitor): pass def visit_option(self, node): - self.add_text(self.at_item_x + ' ', fresh=1) + self.body.append('\n%s ' % self.at_item_x) self.at_item_x = '@itemx' def depart_option(self, node): pass @@ -732,22 +842,21 @@ class TexinfoTranslator(nodes.NodeVisitor): pass def visit_option_argument(self, node): - self.add_text(node.get('delimiter', ' ')) + self.body.append(node.get('delimiter', ' ')) def depart_option_argument(self, node): pass def visit_description(self, node): - self.add_text('', fresh=1) + self.body.append('\n') def depart_description(self, node): pass ## Definitions def visit_definition_list(self, node): - self.add_text('\n@table @asis\n') + self.body.append('\n\n@table @asis\n') def depart_definition_list(self, node): - self.rstrip() - self.add_text('\n@end table\n\n') + self.body.append('\n@end table\n\n') def visit_definition_list_item(self, node): self.at_item_x = '@item' @@ -755,23 +864,30 @@ class TexinfoTranslator(nodes.NodeVisitor): pass def visit_term(self, node): - if node.get('ids') and node['ids'][0]: - self.add_anchor(node['ids'][0], node) - self.add_text(self.at_item_x + ' ', fresh=1) + for id in node.get('ids'): + self.add_anchor(id, node) + # anchors and indexes need to go in front + for n in node[::]: + if isinstance(n, (addnodes.index, nodes.target)): + n.walkabout(self) + node.remove(n) + self.body.append('\n%s ' % self.at_item_x) self.at_item_x = '@itemx' def depart_term(self, node): pass def visit_termsep(self, node): - self.add_text(self.at_item_x + ' ', fresh=1) + self.body.append('\n%s ' % self.at_item_x) + def depart_termsep(self, node): + pass def visit_classifier(self, node): - self.add_text(' : ') + self.body.append(' : ') def depart_classifier(self, node): pass def visit_definition(self, node): - self.add_text('', fresh=1) + self.body.append('\n') def depart_definition(self, node): pass @@ -780,8 +896,7 @@ class TexinfoTranslator(nodes.NodeVisitor): def visit_table(self, node): self.entry_sep = '@item' def depart_table(self, node): - self.rstrip() - self.add_text('\n@end multitable\n\n') + self.body.append('\n@end multitable\n\n') def visit_tabular_col_spec(self, node): pass @@ -792,9 +907,9 @@ class TexinfoTranslator(nodes.NodeVisitor): self.colwidths.append(node['colwidth']) if len(self.colwidths) != self.n_cols: return - self.add_text('@multitable ', fresh=1) + self.body.append('\n\n@multitable ') for i, n in enumerate(self.colwidths): - self.add_text('{%s} ' %('x' * (n+2))) + self.body.append('{%s} ' %('x' * (n+2))) def depart_colspec(self, node): pass @@ -820,135 +935,136 @@ class TexinfoTranslator(nodes.NodeVisitor): self.entry_sep = '@item' def visit_entry(self, node): - self.rstrip() - self.add_text('\n%s ' % self.entry_sep) + self.body.append('\n%s\n' % self.entry_sep) self.entry_sep = '@tab' def depart_entry(self, node): for i in xrange(node.get('morecols', 0)): - self.add_text('@tab\n', fresh=1) - self.add_text('', fresh=1) + self.body.append('\n@tab\n') ## Field Lists def visit_field_list(self, node): - self.add_text('\n@itemize @w\n') + self.body.append('\n\n@itemize @w\n') def depart_field_list(self, node): - self.rstrip() - self.add_text('\n@end itemize\n\n') + self.body.append('\n@end itemize\n\n') def visit_field(self, node): if not isinstance(node.parent, nodes.field_list): - self.visit_field_list(None) + self.visit_field_list(node) def depart_field(self, node): if not isinstance(node.parent, nodes.field_list): - self.depart_field_list(None) + self.depart_field_list(node) def visit_field_name(self, node): - self.add_text('@item ', fresh=1) + self.body.append('\n@item ') def depart_field_name(self, node): - self.add_text(':') + self.body.append(': ') def visit_field_body(self, node): - self.add_text('', fresh=1) + pass def depart_field_body(self, node): pass ## Admonitions - def visit_admonition(self, node): - title = escape(node[0].astext()) - self.add_text('\n@cartouche\n' - '@quotation %s\n' % title) + def visit_admonition(self, node, name=''): + if not name: + name = self.escape(node[0].astext()) + self.body.append('\n@cartouche\n' + '@quotation %s\n' % name) def depart_admonition(self, node): - self.rstrip() - self.add_text('\n@end quotation\n' - '@end cartouche\n\n') + self.body.append('\n@end quotation\n' + '@end cartouche\n\n') def _make_visit_admonition(typ): def visit(self, node): - title = escape(typ) - self.add_text('\n@cartouche\n' - '@quotation %s\n' % title) + self.body.append('\n@cartouche\n' + '@quotation %s\n' % self.escape(_(typ))) return visit visit_attention = _make_visit_admonition('Attention') - visit_caution = _make_visit_admonition('Caution') - visit_danger = _make_visit_admonition('Danger') - visit_error = _make_visit_admonition('Error') - visit_important = _make_visit_admonition('Important') - visit_note = _make_visit_admonition('Note') - visit_tip = _make_visit_admonition('Tip') - visit_hint = _make_visit_admonition('Hint') - visit_warning = _make_visit_admonition('Warning') - depart_attention = depart_admonition - depart_caution = depart_admonition - depart_danger = depart_admonition - depart_error = depart_admonition + visit_caution = _make_visit_admonition('Caution') + depart_caution = depart_admonition + visit_danger = _make_visit_admonition('Danger') + depart_danger = depart_admonition + visit_error = _make_visit_admonition('Error') + depart_error = depart_admonition + visit_important = _make_visit_admonition('Important') depart_important = depart_admonition - depart_note = depart_admonition - depart_tip = depart_admonition - depart_hint = depart_admonition - depart_warning = depart_admonition + visit_note = _make_visit_admonition('Note') + depart_note = depart_admonition + visit_tip = _make_visit_admonition('Tip') + depart_tip = depart_admonition + visit_hint = _make_visit_admonition('Hint') + depart_hint = depart_admonition + visit_warning = _make_visit_admonition('Warning') + depart_warning = depart_admonition ## Misc def visit_docinfo(self, node): - # No 'docinfo_xform' raise nodes.SkipNode + def visit_generated(self, node): + raise nodes.SkipNode + + def visit_header(self, node): + raise nodes.SkipNode + + def visit_footer(self, node): + raise nodes.SkipNode + + def visit_container(self, node): + pass + def depart_container(self, node): + pass + + def visit_decoration(self, node): + pass + def depart_decoration(self, node): + pass + def visit_topic(self, node): - # Ignore TOC's since we have to have a "menu" anyway + # ignore TOC's since we have to have a "menu" anyway if 'contents' in node.get('classes', []): raise nodes.SkipNode title = node[0] self.visit_rubric(title) - self.add_text('%s\n' % escape(title.astext())) - self.visit_block_quote(node) + self.body.append('%s\n' % self.escape(title.astext())) def depart_topic(self, node): - self.depart_block_quote(node) - - def visit_generated(self, node): - raise nodes.SkipNode - def depart_generated(self, node): pass def visit_transition(self, node): - self.add_text('\n\n@noindent\n' - '@exdent @w{%s}\n\n' - '@noindent\n' % ('_' * 70)) + self.body.append('\n\n@exdent @w{ %s}\n\n' % ('* ' * 30)) def depart_transition(self, node): pass def visit_attribution(self, node): - self.add_text('@flushright\n', fresh=1) + self.body.append('\n\n@center --- ') def depart_attribution(self, node): - self.add_text('@end flushright\n', fresh=1) + self.body.append('\n\n') def visit_raw(self, node): format = node.get('format', '').split() if 'texinfo' in format or 'texi' in format: - self.add_text(node.astext()) + self.body.append(node.astext()) raise nodes.SkipNode - def depart_raw(self, node): - pass def visit_figure(self, node): - self.add_text('\n@float Figure\n') + self.body.append('\n\n@float Figure\n') def depart_figure(self, node): - self.rstrip() - self.add_text('\n@end float\n\n') + self.body.append('\n@end float\n\n') def visit_caption(self, node): if not isinstance(node.parent, nodes.figure): - self.document.reporter.warning('Caption not inside a figure.', - base_node=node) + self.builder.warn('caption not inside a figure.', + (self.curfilestack[-1], node.line)) return - self.add_text('@caption{', fresh=1) + self.body.append('\n@caption{') def depart_caption(self, node): if isinstance(node.parent, nodes.figure): - self.rstrip() - self.add_text('}\n') + self.body.append('}\n') def visit_image(self, node): if node['uri'] in self.builder.images: @@ -963,12 +1079,12 @@ class TexinfoTranslator(nodes.NodeVisitor): return name, ext = path.splitext(uri) attrs = node.attributes - # ignored in non-tex output + # width and height ignored in non-tex output width = self.tex_image_length(attrs.get('width', '')) height = self.tex_image_length(attrs.get('height', '')) - alt = escape_arg(attrs.get('alt', '')) - self.add_text('\n\n@image{%s,%s,%s,%s,%s}\n\n' % - (name, width, height, alt, ext[1:])) + alt = self.escape_arg(attrs.get('alt', '')) + self.body.append('\n\n@image{%s,%s,%s,%s,%s}\n\n' % + (name, width, height, alt, ext[1:])) def depart_image(self, node): pass @@ -978,14 +1094,14 @@ class TexinfoTranslator(nodes.NodeVisitor): pass def visit_sidebar(self, node): - pass + self.visit_topic(node) def depart_sidebar(self, node): - pass + self.depart_topic(node) def visit_label(self, node): - self.add_text('@w{(') + self.body.append('@w{(') def depart_label(self, node): - self.add_text(')} ') + self.body.append(')} ') def visit_legend(self, node): pass @@ -999,34 +1115,34 @@ class TexinfoTranslator(nodes.NodeVisitor): def visit_substitution_definition(self, node): raise nodes.SkipNode - def depart_substitution_definition(self, node): - pass def visit_system_message(self, node): - self.add_text('\n@format\n' - '---------- SYSTEM MESSAGE -----------\n') + self.body.append('\n@w{----------- System Message: %s/%s -----------} ' + '(%s, line %s)\n' % ( + node.get('type', '?'), + node.get('level', '?'), + self.escape(node.get('source', '?')), + node.get('line', '?'))) def depart_system_message(self, node): - self.rstrip() - self.add_text('\n------------------------------------\n' - '@end format\n') + pass def visit_comment(self, node): for line in node.astext().splitlines(): - self.add_text('@c %s\n' % line, fresh=1) + self.body.append('\n@c %s\n' % line) raise nodes.SkipNode def visit_problematic(self, node): - self.add_text('>') + self.body.append('>') def depart_problematic(self, node): - self.add_text('<') + self.body.append('<') def unimplemented_visit(self, node): - self.document.reporter.error("Unimplemented node type: `%s'" - % node.__class__.__name__, base_node=node) + self.builder.warn("unimplemented node type: %r" % node, + (self.curfilestack[-1], node.line)) def unknown_visit(self, node): - self.document.reporter.error("Unknown node type: `%s'" - % node.__class__.__name__, base_node=node) + self.builder.warn("unknown node type: %r" % node, + (self.curfilestack[-1], node.line)) def unknown_departure(self, node): pass @@ -1040,52 +1156,37 @@ class TexinfoTranslator(nodes.NodeVisitor): maxlen = max(len(name) for name in names) for production in node: if production['tokenname']: + for id in production.get('ids'): + self.add_anchor(id, production) s = production['tokenname'].ljust(maxlen) + ' ::=' lastname = production['tokenname'] else: - s = '%s ' % (' '*len(lastname)) - self.add_text(escape(s)) - self.add_text(escape(production.astext() + '\n')) + s = '%s ' % (' '*maxlen) + self.body.append(self.escape(s)) + self.body.append(self.escape(production.astext() + '\n')) self.depart_literal_block(None) raise nodes.SkipNode - def depart_productionlist(self, node): + + def visit_production(self, node): + pass + def depart_production(self, node): pass def visit_literal_emphasis(self, node): - self.add_text('@code{') + self.body.append('@code{') def depart_literal_emphasis(self, node): - self.add_text('}') - - def visit_module(self, node): - modname = escape_id(node['modname']) - self.add_anchor(modname, node) + self.body.append('}') def visit_index(self, node): - # Throws off table alignment - if isinstance(node.parent, nodes.term): - return for entry in node['entries']: typ, text, tid, text2 = entry - text = text.replace('!', ' ').replace(';', ' ') - text = escape_id(text) - self.add_text('@geindex %s\n' % text, fresh=1) - - def visit_autosummary_table(self, node): - pass - def depart_autosummary_table(self, node): - pass - - def visit_todo_node(self, node): - self.visit_transition(node) - self.visit_admonition(node) - def depart_todo_node(self, node): - self.depart_admonition(node) - self.visit_transition(node) + text = self.escape_menu(text) + self.body.append('@geindex %s\n' % text) def visit_refcount(self, node): - self.add_text('\n') + self.body.append('\n') def depart_refcount(self, node): - self.add_text('\n\n') + self.body.append('\n\n') def visit_versionmodified(self, node): intro = versionlabels[node['type']] % node['version'] @@ -1093,34 +1194,31 @@ class TexinfoTranslator(nodes.NodeVisitor): intro += ': ' else: intro += '.' - self.add_text('%s' % escape(intro), fresh=1) + self.body.append('\n\n%s' % self.escape(intro)) def depart_versionmodified(self, node): - self.rstrip() - self.add_text('\n\n', fresh=1) + self.body.append('\n\n') def visit_start_of_file(self, node): - self.curfilestack.append(node.get('docname', '')) - if node.get('docname'): - self.next_section_targets.append(node['docname']) + # add a document target + self.next_section_ids.add(':doc') + self.curfilestack.append(node['docname']) + self.footnotestack.append(self.collect_footnotes(node)) def depart_start_of_file(self, node): self.curfilestack.pop() + self.footnotestack.pop() def visit_centered(self, node): - txt = escape_arg(node.astext()) - self.add_text('@center %s\n' % txt, fresh=1) + txt = self.escape_arg(node.astext()) + self.body.append('\n\n@center %s\n\n' % txt) raise nodes.SkipNode - def depart_centered(self, node): - pass def visit_seealso(self, node): - pass + self.visit_topic(node) def depart_seealso(self, node): - pass + self.depart_topic(node) def visit_meta(self, node): raise nodes.SkipNode - def depart_meta(self, node): - pass def visit_glossary(self, node): pass @@ -1128,9 +1226,11 @@ class TexinfoTranslator(nodes.NodeVisitor): pass def visit_acks(self, node): - pass - def depart_acks(self, node): - pass + self.body.append('\n\n') + self.body.append(', '.join(n.astext() + for n in node.children[0].children) + '.') + self.body.append('\n\n') + raise nodes.SkipNode def visit_highlightlang(self, node): pass @@ -1140,38 +1240,35 @@ class TexinfoTranslator(nodes.NodeVisitor): ## Desc desc_map = { - 'function' : 'Function', - 'class': 'Class', - 'method': 'Method', - 'classmethod': 'Class Method', + 'cfunction': 'C Function', + 'classmethod': 'Class Method', + 'cmacro': 'C Macro', + 'cmdoption': 'Command Option', + 'cmember': 'C Member', + 'confval': 'Configuration Value', + 'ctype': 'C Type', + 'cvar': 'C Variable', + 'describe': 'Description', + 'envvar': 'Environment Variable', 'staticmethod': 'Static Method', - 'exception': 'Exception', - 'data': 'Data', - 'attribute': 'Attribute', - 'opcode': 'Opcode', - 'cfunction': 'C Function', - 'cmember': 'C Member', - 'cmacro': 'C Macro', - 'ctype': 'C Type', - 'cvar': 'C Variable', - 'cmdoption': 'Option', - 'describe': 'Description', + 'var': 'Variable', } def visit_desc(self, node): self.at_deffnx = '@deffn' def depart_desc(self, node): - self.rstrip() - self.add_text('@end deffn\n\n', fresh=1) + self.body.append('\n@end deffn\n\n') def visit_desc_signature(self, node): self.desctype = node.parent['desctype'].strip() - if self.desctype != 'describe' and node['ids']: - self.add_anchor(node['ids'][0], node) - typ = self.desc_map.get(self.desctype, self.desctype) - self.add_text('%s {%s} ' % (self.at_deffnx, escape_arg(typ)), fresh=1) + if self.desctype != 'describe': + for id in node.get('ids'): + self.add_anchor(id, node) + typ = _(self.desc_map.get(self.desctype, + self.desctype.capitalize())) + self.body.append('\n%s {%s} ' % (self.at_deffnx, self.escape_arg(typ))) self.at_deffnx = '@deffnx' def depart_desc_signature(self, node): - self.add_text("", fresh=1) + self.body.append("\n") def visit_desc_name(self, node): pass @@ -1189,51 +1286,48 @@ class TexinfoTranslator(nodes.NodeVisitor): pass def visit_desc_returns(self, node): - self.add_text(' -> ') + self.body.append(' -> ') def depart_desc_returns(self, node): pass def visit_desc_parameterlist(self, node): - self.add_text(' (') + self.body.append(' (') self.first_param = 1 def depart_desc_parameterlist(self, node): - self.add_text(')') + self.body.append(')') def visit_desc_parameter(self, node): if not self.first_param: - self.add_text(', ') + self.body.append(', ') else: self.first_param = 0 - self.add_text(escape(node.astext())) + self.body.append(self.escape(node.astext())) raise nodes.SkipNode - def depart_desc_parameter(self, node): - pass def visit_desc_optional(self, node): - self.add_text('[') + self.body.append('[') def depart_desc_optional(self, node): - self.add_text(']') + self.body.append(']') def visit_desc_annotation(self, node): raise nodes.SkipNode - def depart_desc_annotation(self, node): - pass def visit_desc_content(self, node): - self.add_text("", fresh=1) + self.body.append("\n") def depart_desc_content(self, node): pass def visit_inline(self, node): - # stub pass def depart_inline(self, node): pass def visit_abbreviation(self, node): - self.add_text('@abbr{') - if node.hasattr('explanation'): - self.context.append(', %s}' % escape_arg(node['explanation'])) + abbr = node.astext() + self.body.append('@abbr{') + if node.hasattr('explanation') and abbr not in self.handled_abbrs: + self.context.append(',%s}' % self.escape_arg(node['explanation'])) + self.handled_abbrs.add(abbr) else: self.context.append('}') def depart_abbreviation(self, node): @@ -1245,7 +1339,6 @@ class TexinfoTranslator(nodes.NodeVisitor): pass def visit_hlist(self, node): - # stub self.visit_bullet_list(node) def depart_hlist(self, node): self.depart_bullet_list(node) @@ -1254,3 +1347,8 @@ class TexinfoTranslator(nodes.NodeVisitor): pass def depart_hlistcol(self, node): pass + + def visit_pending_xref(self, node): + pass + def depart_pending_xref(self, node): + pass diff --git a/tests/run.py b/tests/run.py index 40c4fbed8..7d51c0718 100755 --- a/tests/run.py +++ b/tests/run.py @@ -29,8 +29,20 @@ sys.path.insert(0, path.join(path.dirname(__file__), path.pardir)) try: import nose except ImportError: - print("The nose package is needed to run the Sphinx test suite.") + print('The nose package is needed to run the Sphinx test suite.') sys.exit(1) -print("Running Sphinx test suite...") +try: + import docutils +except ImportError: + print('Sphinx requires the docutils package to be installed.') + sys.exit(1) + +try: + import jinja2 +except ImportError: + print('Sphinx requires the jinja2 package to be installed.') + sys.exit(1) + +print('Running Sphinx test suite...') nose.main() diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 7e68f8dbb..f544403de 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -11,8 +11,8 @@ import os import re -import htmlentitydefs import sys +import htmlentitydefs from StringIO import StringIO try: diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py index ce689a696..eedfd1fc7 100644 --- a/tests/test_build_texinfo.py +++ b/tests/test_build_texinfo.py @@ -29,6 +29,7 @@ texinfo_warnfile = StringIO() TEXINFO_WARNINGS = ENV_WARNINGS + """\ None:None: WARNING: no matching candidate for image URI u'foo.\\*' +None:None: WARNING: no matching candidate for image URI u'svgimg.\\*' """ if sys.version_info >= (3, 0): diff --git a/tests/test_cpp_domain.py b/tests/test_cpp_domain.py index 296de1c87..84649fd1b 100644 --- a/tests/test_cpp_domain.py +++ b/tests/test_cpp_domain.py @@ -37,6 +37,9 @@ def test_type_definitions(): x = 'explicit module::myclass::foo::foo()' assert unicode(parse('function', x)) == x + x = 'int printf(const char* fmt, ...)' + assert unicode(parse('function', x)) == x + x = 'std::vector> module::blah' assert unicode(parse('type_object', x)) == x diff --git a/tests/test_intl.py b/tests/test_intl.py index 9459a1b76..d1e28002f 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -25,6 +25,11 @@ def setup_module(): test_root / 'xx' / 'LC_MESSAGES' / '%s.mo' % catalog], stdout=PIPE, stderr=PIPE) except OSError: + # The test will fail the second time it's run if we don't + # tear down here. Not sure if there's a more idiomatic way + # of ensuring that teardown gets run in the event of an + # exception from the setup function. + teardown_module() raise SkipTest # most likely msgfmt was not found else: stdout, stderr = p.communicate() diff --git a/tests/util.py b/tests/util.py index 3711de724..bd50bec05 100644 --- a/tests/util.py +++ b/tests/util.py @@ -193,8 +193,8 @@ def with_app(*args, **kwargs): def gen_with_app(*args, **kwargs): """ - Make a TestApp with args and kwargs, pass it to the test and clean up - properly. + Decorate a test generator to pass a TestApp as the first argument to the + test generator when it's executed. """ def generator(func): @wraps(func) @@ -224,7 +224,7 @@ def write_file(name, contents, encoding=None): contents = contents.encode('ascii') else: mode = 'w' - f = open(str(name), 'wb', encoding=encoding) + f = open(str(name), mode, encoding=encoding) f.write(contents) f.close()