diff options
author | Takayuki Shimizukawa <shimizukawa+bitbucket@gmail.com> | 2012-12-07 17:24:46 +0900 |
---|---|---|
committer | Takayuki Shimizukawa <shimizukawa+bitbucket@gmail.com> | 2012-12-07 17:24:46 +0900 |
commit | 97df679847d6a4959fefc64ad333a5ae64193fbd (patch) | |
tree | 873c0ba96fd3475eef05569f002ac1cec9ddb2ac | |
parent | 68c8e824d8b0dd5a4efe3de445f431f3389891dd (diff) | |
parent | 4ba1b19953223c6b4ac0f4e82b6116ee5849ef47 (diff) | |
download | sphinx-97df679847d6a4959fefc64ad333a5ae64193fbd.tar.gz |
Merged in shimizukawa/sphinx-fix-i18n-fork/#955 (pull request #86)
-rw-r--r-- | CHANGES | 24 | ||||
-rw-r--r-- | doc/Makefile | 13 | ||||
-rw-r--r-- | doc/builders.rst | 23 | ||||
-rw-r--r-- | doc/config.rst | 10 | ||||
-rw-r--r-- | doc/contents.rst | 1 | ||||
-rw-r--r-- | doc/devguide.rst | 214 | ||||
-rw-r--r-- | sphinx/builders/__init__.py | 2 | ||||
-rw-r--r-- | sphinx/builders/xml.py | 85 | ||||
-rw-r--r-- | sphinx/config.py | 3 | ||||
-rw-r--r-- | sphinx/domains/cpp.py | 12 | ||||
-rw-r--r-- | sphinx/quickstart.py | 34 | ||||
-rw-r--r-- | sphinx/writers/xml.py | 58 | ||||
-rw-r--r-- | tests/test_build.py | 8 | ||||
-rw-r--r-- | tests/test_cpp_domain.py | 12 | ||||
-rw-r--r-- | tests/test_quickstart.py | 19 |
15 files changed, 510 insertions, 8 deletions
@@ -36,6 +36,30 @@ Release 1.2 (in development) * #1010: Make pngmath images transparent by default; IE7+ should handle it. +* #440: Fix coarse timestamp resolution in some filesystem generate wrong outdated file-list. + +* #1008: Fix test failures with Python 3.3. + +* #1029: Fix intersphinx_mapping values are not stable if mapping have plural key/value set with Python 3.3. + +* #920: Rescue PIL packaging issue that allow import Image without PIL namespace. Thanks to Marc Schlaich. + +* #1024: Improve Makefile/make.bat error message if Sphinx is not found. Thanks to anatoly techtonik. + +* #1037: Fix typos in Polish translation. Thanks to Jakub Wilk. + +* #1038: Fix cpp domain parser fails to parse C+11 "static constexpr" declarations. Thanks to Jakub Wilk. + +* #1043: Fix sphinx-quickstart asks again and again Y|N because input() return value with extra '\r' on Python-3.2.0 + Windows. Thanks to Régis Décamps. + +* #1041: Fix cpp domain parser fails to parse a const type with a modifier. + +* PR#88: Added the "Sphinx Developer's Guide" (:file:`doc/devguide.rst`) + which outlines the basic development process of the Sphinx project. + +* Added the Docutils-native XML and pseudo-XML builders. See + :class:`XMLBuilder` and :class:`PseudoXMLBuilder`. + Release 1.1.3 (Mar 10, 2012) ============================ diff --git a/doc/Makefile b/doc/Makefile index 47951316..a46b0227 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -13,7 +13,8 @@ ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) \ I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) . .PHONY: help clean html dirhtml singlehtml text man pickle json htmlhelp \ - qthelp devhelp epub latex latexpdf changes linkcheck doctest + qthelp devhelp epub latex latexpdf changes linkcheck doctest xml \ + pseudoxml help: @echo "Please use \`make <target>' where <target> is one of" @@ -147,3 +148,13 @@ info: @echo "Running Texinfo files through makeinfo..." make -C _build/texinfo info @echo "makeinfo finished; the Info files are in _build/texinfo." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) _build/xml + @echo + @echo "Build finished. The XML files are in _build/XML." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) _build/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in _build/pseudoxml." diff --git a/doc/builders.rst b/doc/builders.rst index 6600807d..0075ad81 100644 --- a/doc/builders.rst +++ b/doc/builders.rst @@ -272,6 +272,29 @@ Note that a direct PDF builder using ReportLab is available in `rst2pdf Its name is ``linkcheck``. +.. module:: sphinx.builders.xml +.. class:: XMLBuilder + + This builder produces Docutils-native XML files. The output can be + transformed with standard XML tools such as XSLT processors into arbitrary + final forms. + + Its name is ``xml``. + + .. versionadded:: 1.2 + +.. class:: PseudoXMLBuilder + + This builder is used for debugging the Sphinx/Docutils "Reader to Transform + to Writer" pipeline. It produces compact pretty-printed "pseudo-XML", files + where nesting is indicated by indentation (no end-tags). External + attributes for all elements are output, and internal attributes for any + leftover "pending" elements are also given. + + Its name is ``pseudoxml``. + + .. versionadded:: 1.2 + Built-in Sphinx extensions that offer more builders are: diff --git a/doc/config.rst b/doc/config.rst index df5a208c..0ff6d405 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -1342,6 +1342,16 @@ Options for the linkcheck builder .. versionadded:: 1.2 +Options for the XML builder +--------------------------- + +.. confval:: xml_pretty + + If True, pretty-print the XML. Default is ``True``. + + .. versionadded:: 1.2 + + .. rubric:: Footnotes .. [1] A note on available globbing syntax: you can use the standard shell diff --git a/doc/contents.rst b/doc/contents.rst index 3bbc2835..5e0ae6c1 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -22,6 +22,7 @@ Sphinx documentation contents faq glossary + devguide changes examples diff --git a/doc/devguide.rst b/doc/devguide.rst new file mode 100644 index 00000000..ab4bc740 --- /dev/null +++ b/doc/devguide.rst @@ -0,0 +1,214 @@ +Sphinx Developer's Guide +======================== + +.. topic:: Abstract + + This document describes the development process of Sphinx, a documentation + system used by developers to document systems used by other developers to + develop other systems that may also be documented using Sphinx. + +The Sphinx source code is managed using `Mercurial`_ and is hosted on +`BitBucket`_. + + hg clone https://bitbucket.org/birkenfeld/sphinx + +.. rubric:: Community + +sphinx-users <sphinx-users@googlegroups.com> + Mailing list for user support. + +sphinx-dev <sphinx-dev@googlegroups.com> + Mailing list for development related discussions. + +#pocoo on irc.freenode.net + IRC channel for development questions and user support. + + This channel is shared with other Pocoo projects. Archived logs are + available `here <http://dev.pocoo.org/irclogs/>`_. + +.. _`BitBucket`: http://bitbucket.org +.. _`Mercurial`: http://mercurial.selenic.com/ + + +Bug Reports and Feature Requests +-------------------------------- + +If you have encountered a problem with Sphinx or have an idea for a new +feature, please submit it to the `issue tracker`_ on BitBucket or discuss it +on the sphinx-dev mailing list. + +For bug reports, please include the output produced during the build process +and also the log file Sphinx creates after it encounters an un-handled +exception. The location of this file should be shown towards the end of the +error message. + +Including or providing a link to the source files involved may help us fix the +issue. If possible, try to create a minimal project that produces the error +and post that instead. + +.. _`issue tracker`: http://bitbucket.org/birkenfeld/sphinx/issues + + +Contributing to Sphinx +---------------------- + +The recommended way for new contributors to submit code to Sphinx is to fork +the Mercurial repository on BitBucket and then submit a pull request after +committing the changes. The pull request will then need to be approved by one +of the core developers before it is merged into the main repository. + + +Getting Started +~~~~~~~~~~~~~~~ + +These are the basic steps needed to start developing on Sphinx. + +#. Create an account on BitBucket. + +#. Fork the main Sphinx repository (`birkenfeld/sphinx + <https://bitbucket.org/birkenfeld/sphinx>`_) using the BitBucket interface. + +#. Clone the forked repository to your machine. :: + + hg clone https://bitbucket.org/USERNAME/sphinx-fork + cd sphinx-fork + +#. Checkout the appropriate branch. + + For changes that should be included in the next minor release (namely bug + fixes), use the ``stable`` branch. :: + + hg checkout stable + + For new features or other substantial changes that should wait until the + next major release, use the ``default`` branch. + +#. Setup your Python environment. :: + + virtualenv ~/sphinxenv + . ~/sphinxenv/bin/activate + pip install -e . + +#. Hack, hack, hack. + + For tips on working with the code, see the `Coding Guide`_. + +#. Test, test, test. + + Run the unit tests:: + + pip install nose + make test + + Build the documentation and check the output for different builders:: + + cd docs + make clean html text man info latexpdf + + Run the unit tests under different Python environments using + :program:`tox`:: + + pip install tox + tox -v + + Add a new unit test in the ``tests`` directory if you can. + + For bug fixes, first add a test that fails without your changes and passes + after they are applied. + +#. Commit your changes. :: + + hg commit -m 'Add useful new feature that does this.' + + BitBucket recognizes `certain phrases`__ that can be used to automatically + update the issue tracker. + + For example:: + + hg commit -m 'Closes #42: Fix invalid markup in docstring of Foo.bar.' + + would close issue #42. + + __ https://confluence.atlassian.com/display/BITBUCKET/Automatically+Resolving+Issues+when+Users+Push+Code + +#. Push changes to your forked repository on BitBucket. :: + + hg push + +#. Submit a pull request from your repository to ``birkenfeld/sphinx`` using + the BitBucket interface. + +#. Wait for a core developer to review your changes. + + +Core Developers +~~~~~~~~~~~~~~~ + +The core developers of Sphinx have write access to the main repository. They +can commit changes, accept/reject pull requests, and manage items on the issue +tracker. + +You do not need to be a core developer or have write access to be involved in +the development of Sphinx. You can submit patches or create pull requests +from forked repositories and have a core developer add the changes for you. + +The following are some general guidelines for core developers: + +* Questionable or extensive changes should be submitted as a pull request + instead of being committed directly to the main repository. The pull + request should be reviewed by another core developer before it is merged. + +* Trivial changes can be committed directly but be sure to keep the repository + in a good working state and that all tests pass before pushing your changes. + +* When committing code written by someone else, please attribute the original + author in the commit message and any relevant :file:`CHANGES` entry. + +* Using Mercurial named branches other than ``default`` and ``stable`` is not + encouraged. + + +Coding Guide +------------ + +* Try to use the same code style as used in the rest of the project. See the + `Pocoo Styleguide`__ for more information. + + __ http://flask.pocoo.org/docs/styleguide/ + +* For non-trivial changes, please update the :file:`CHANGES` file. If your + changes alter existing behavior, please document this. + +* New features should be documented. Include examples and use cases where + appropriate. If possible, include a sample that is displayed in the + generated output. + +* When adding a new configuration variable, be sure to document it and update + :file:`sphinx/quickstart.py`. + +* Use the included :program:`utils/check_sources.py` script to check for + common formatting issues (trailing whitespace, lengthy lines, etc). + +* Add appropriate unit tests. + + +Debugging Tips +~~~~~~~~~~~~~~ + +* Delete the build cache before building documents if you make changes in the + code by running the command ``make clean`` or using the + :option:`sphinx-build -E` option. + +* Use the :option:`sphinx-build -P` option to run Pdb on exceptions. + +* Use ``node.pformat()`` and ``node.asdom().toxml()`` to generate a printable + representation of the document structure. + +* Set the configuration variable :confval:`keep_warnings` to True so warnings + will be displayed in the generated output. + +* Set the configuration variable :confval:`nitpicky` to True so that Sphinx + will complain about references without a known target. + +* Set the debugging options in the `Docutils configuration file + <http://docutils.sourceforge.net/docs/user/config.html>`_. diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 5240a1c7..4355b801 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -334,4 +334,6 @@ BUILTIN_BUILDERS = { 'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'), 'websupport': ('websupport', 'WebSupportBuilder'), 'gettext': ('gettext', 'MessageCatalogBuilder'), + 'xml': ('xml', 'XMLBuilder'), + 'pseudoxml': ('xml', 'PseudoXMLBuilder'), } diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py new file mode 100644 index 00000000..74c1fc06 --- /dev/null +++ b/sphinx/builders/xml.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +""" + sphinx.builders.xml + ~~~~~~~~~~~~~~~~~~~ + + Docutils-native XML and pseudo-XML builders. + + :copyright: Copyright 2007-2012 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import codecs +from os import path + +from docutils.io import StringOutput + +from sphinx.builders import Builder +from sphinx.util.osutil import ensuredir, os_path +from sphinx.writers.xml import XMLWriter, PseudoXMLWriter + +class XMLBuilder(Builder): + """ + Builds Docutils-native XML. + """ + name = 'xml' + format = 'xml' + out_suffix = '.xml' + + _writer_class = XMLWriter + + def init(self): + pass + + def get_outdated_docs(self): + for docname in self.env.found_docs: + if docname not in self.env.all_docs: + yield docname + continue + targetname = self.env.doc2path(docname, self.outdir, + self.out_suffix) + try: + targetmtime = path.getmtime(targetname) + except Exception: + targetmtime = 0 + try: + srcmtime = path.getmtime(self.env.doc2path(docname)) + if srcmtime > targetmtime: + yield docname + except EnvironmentError: + # source doesn't exist anymore + pass + + def get_target_uri(self, docname, typ=None): + return '' + + def prepare_writing(self, docnames): + self.writer = self._writer_class(self) + + def write_doc(self, docname, doctree): + destination = StringOutput(encoding='utf-8') + self.writer.write(doctree, destination) + outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix) + ensuredir(path.dirname(outfilename)) + try: + f = codecs.open(outfilename, 'w', 'utf-8') + try: + f.write(self.writer.output) + finally: + f.close() + except (IOError, OSError), err: + self.warn("error writing file %s: %s" % (outfilename, err)) + + def finish(self): + pass + + +class PseudoXMLBuilder(XMLBuilder): + """ + Builds pseudo-XML for display purposes. + """ + name = 'pseudoxml' + format = 'pseudoxml' + out_suffix = '.pseudoxml' + + _writer_class = PseudoXMLWriter diff --git a/sphinx/config.py b/sphinx/config.py index 2012634e..eef8d31c 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -184,6 +184,9 @@ class Config(object): # gettext options gettext_compact = (True, 'gettext'), + + # XML options + xml_pretty = (True, 'env'), ) def __init__(self, dirname, filename, overrides, tags): diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 31daa1f6..e4204aab 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -672,8 +672,9 @@ class DefinitionParser(object): except ValueError: return False - def _parse_builtin(self, modifier): - path = [modifier] + def _parse_builtin(self, modifiers): + modifier = modifiers[-1] + path = modifiers following = self._modifiers[modifier] while 1: self.skip_ws() @@ -730,9 +731,10 @@ class DefinitionParser(object): # impossible for a template to follow, so what # we do is go to a different function that just # eats types - if following is not None: - return self._parse_builtin(modifier) modifiers.append(modifier) + if following is not None: + return self._parse_builtin(modifiers) + self.skip_ws() else: self.backout() break @@ -852,7 +854,7 @@ class DefinitionParser(object): visibility = 'public' if self.match(_visibility_re): visibility = self.matched_text - static = self.skip_word('static') + static = self.skip_word_and_ws('static') return visibility, static def parse_type(self): diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index 2bba4459..dd2df0df 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -387,7 +387,7 @@ to the full path of the 'sphinx-build' executable. Alternatively you may add the Sphinx directory to PATH. If you don't have Sphinx installed, grab it from -http://sphinx-doc.org/ +http://sphinx-doc.org/ endef $(error $(MSG)) endif @@ -423,6 +423,8 @@ help: \t@echo " info to make Texinfo files and run them through makeinfo" \t@echo " gettext to make PO message catalogs" \t@echo " changes to make an overview of all changed/added/deprecated items" +\t@echo " xml to make Docutils-native XML files" +\t@echo " pseudoxml to make pseudoxml-XML files for display purposes" \t@echo " linkcheck to check all external links for integrity" \t@echo " doctest to run all doctests embedded in the documentation \ (if enabled)" @@ -547,6 +549,16 @@ doctest: \t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest \t@echo "Testing of doctests in the sources finished, look at the " \\ \t "results in $(BUILDDIR)/doctest/output.txt." + +xml: +\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml +\t@echo +\t@echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: +\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml +\t@echo +\t@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." ''' BATCHFILE = '''\ @@ -585,6 +597,8 @@ if "%%1" == "help" ( \techo. texinfo to make Texinfo files \techo. gettext to make PO message catalogs \techo. changes to make an overview over all changed/added/deprecated items +\techo. xml to make Docutils-native XML files +\techo. pseudoxml to make pseudoxml-XML files for display purposes \techo. linkcheck to check all external links for integrity \techo. doctest to run all doctests embedded in the documentation if enabled \tgoto end @@ -773,6 +787,22 @@ results in %%BUILDDIR%%/doctest/output.txt. \tgoto end ) +if "%%1" == "xml" ( +\t%%SPHINXBUILD%% -b xml %%ALLSPHINXOPTS%% %%BUILDDIR%%/xml +\tif errorlevel 1 exit /b 1 +\techo. +\techo.Build finished. The XML files are in %%BUILDDIR%%/xml. +\tgoto end +) + +if "%%1" == "pseudoxml" ( +\t%%SPHINXBUILD%% -b pseudoxml %%ALLSPHINXOPTS%% %%BUILDDIR%%/pseudoxml +\tif errorlevel 1 exit /b 1 +\techo. +\techo.Build finished. The pseudo-XML files are in %%BUILDDIR%%/pseudoxml. +\tgoto end +) + :end ''' @@ -824,7 +854,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty): prompt = purple(PROMPT_PREFIX + '%s [%s]: ' % (text, default)) else: prompt = purple(PROMPT_PREFIX + text + ': ') - x = term_input(prompt) + x = term_input(prompt).strip() if default and not x: x = default if not isinstance(x, unicode): diff --git a/sphinx/writers/xml.py b/sphinx/writers/xml.py new file mode 100644 index 00000000..02becb73 --- /dev/null +++ b/sphinx/writers/xml.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +""" + sphinx.writers.xml + ~~~~~~~~~~~~~~~~~~ + + Docutils-native XML and pseudo-XML writers. + + :copyright: Copyright 2007-2012 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from docutils import writers +from docutils.writers.docutils_xml import Writer as BaseXMLWriter +from docutils.writers.docutils_xml import XMLTranslator as BaseXMLTranslator + + +class XMLWriter(BaseXMLWriter): + + def __init__(self, builder): + BaseXMLWriter.__init__(self) + self.builder = builder + + def translate(self, *args, **kwargs): + self.document.settings.newlines = \ + self.document.settings.indents = \ + self.builder.env.config.xml_pretty + self.document.settings.xml_declaration = True + self.document.settings.doctype_declaration = True + return BaseXMLWriter.translate(self) + + +class XMLTranslator(BaseXMLTranslator): + def __init__(self, builder, doc): + BaseXMLTranslator.__init__(self, doc) + self.builder = builder + + +class PseudoXMLWriter(writers.Writer): + + supported = ('pprint', 'pformat', 'pseudoxml') + """Formats this writer supports.""" + + config_section = 'pseudoxml writer' + config_section_dependencies = ('writers',) + + output = None + """Final translated form of `document`.""" + + def __init__(self, builder): + writers.Writer.__init__(self) + self.builder = builder + + def translate(self): + self.output = self.document.pformat() + + def supports(self, format): + """This writer supports all format-specific elements.""" + return True diff --git a/tests/test_build.py b/tests/test_build.py index 5f24f89a..87f5a14c 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -61,3 +61,11 @@ else: @with_app(buildername='singlehtml', cleanenv=True) def test_singlehtml(app): app.builder.build_all() + +@with_app(buildername='xml') +def test_xml(app): + app.builder.build_all() + +@with_app(buildername='pseudoxml') +def test_pseudoxml(app): + app.builder.build_all() diff --git a/tests/test_cpp_domain.py b/tests/test_cpp_domain.py index bd8aafa7..c8466e37 100644 --- a/tests/test_cpp_domain.py +++ b/tests/test_cpp_domain.py @@ -43,6 +43,15 @@ def test_type_definitions(): x = 'int printf(const char* fmt, ...)' assert unicode(parse('function', x)) == x + x = 'int foo(const unsigned int j)' + assert unicode(parse('function', x)) == x + + x = 'int foo(const unsigned int const j)' + assert unicode(parse('function', x)) == x + + x = 'int foo(const int* const ptr)' + assert unicode(parse('function', x)) == x + x = 'std::vector<std::pair<std::string, long long>> module::blah' assert unicode(parse('type_object', x)) == x @@ -60,6 +69,9 @@ def test_type_definitions(): x = 'constexpr int get_value()' assert unicode(parse('function', x)) == x + x = 'static constexpr int get_value()' + assert unicode(parse('function', x)) == x + x = 'int get_value() const noexcept' assert unicode(parse('function', x)) == x diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index dba888dd..c054f858 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -46,6 +46,25 @@ def teardown_module(): coloron() +def test_quickstart_inputstrip(): + d = {} + answers = { + 'Q1': 'Y\r', # input() return with '\r' on Python-3.2.0 for Windows + 'Q2': ' Yes \r', + 'Q3': 'N', + 'Q4': 'N ', + } + qs.term_input = mock_raw_input(answers) + qs.do_prompt(d, 'k1', 'Q1') + assert d['k1'] == 'Y' + qs.do_prompt(d, 'k2', 'Q2') + assert d['k2'] == 'Yes' + qs.do_prompt(d, 'k3', 'Q3') + assert d['k3'] == 'N' + qs.do_prompt(d, 'k4', 'Q4') + assert d['k4'] == 'N' + + def test_do_prompt(): d = {} answers = { |