From f86b0ee35b4f95488101e043c200ca6e8c07ea9d Mon Sep 17 00:00:00 2001 From: tell-k Date: Thu, 12 Mar 2015 11:22:44 +0900 Subject: [PATCH 01/19] fixed. Sphinx 1.3 can't load extra theme. --- sphinx/theming.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/theming.py b/sphinx/theming.py index 8f27c010c..6c2d3ad9d 100644 --- a/sphinx/theming.py +++ b/sphinx/theming.py @@ -86,7 +86,7 @@ class Theme(object): if not path.isdir(themedir): continue for theme in os.listdir(themedir): - if theme != 'name': + if theme != name: continue if not path.isfile(path.join(themedir, theme, THEMECONF)): continue From 4e599c13dae7431ee4f5c520877e1894dd509651 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Sat, 14 Mar 2015 16:59:22 +0900 Subject: [PATCH 02/19] fixes #1766: the message "least Python 2.6 to run" is at best misleading. --- CHANGES | 1 + sphinx/__init__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index f3d044167..6324bdad6 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ Bugs fixed * #1769: allows generating quickstart files/dirs for destination dir that doesn't overwrite existent files/dirs. Thanks to WAKAYAMA shirou. * #1773: sphinx-quickstart doesn't accept non-ASCII character as a option argument. +* #1766: the message "least Python 2.6 to run" is at best misleading. Release 1.3 (released Mar 10, 2015) diff --git a/sphinx/__init__.py b/sphinx/__init__.py index 1e1b5bc6f..f5c5ed85d 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -55,7 +55,7 @@ def build_main(argv=sys.argv): """Sphinx build "main" command-line entry.""" if (sys.version_info[:3] < (2, 6, 0) or (3, 0, 0) <= sys.version_info[:3] < (3, 3, 0)): - sys.stderr.write('Error: Sphinx requires at least Python 2.6 to run.\n') + sys.stderr.write('Error: Sphinx requires at least Python 2.6 or 3.3 to run.\n') return 1 try: from sphinx import cmdline From 705639d626f42b2e592d7c06847937ef58bccc5c Mon Sep 17 00:00:00 2001 From: Takayuki Hirai Date: Sat, 14 Mar 2015 17:27:08 +0900 Subject: [PATCH 03/19] Fix #1770: regard empty file as an empty string --- sphinx/directives/code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index 1f7a856a7..5043a31e4 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -219,7 +219,7 @@ class LiteralInclude(Directive): lines = self.read_with_encoding(filename, document, codec_info, encoding) - if not isinstance(lines[0], string_types): + if lines and not isinstance(lines[0], string_types): return lines diffsource = self.options.get('diff') From 70612c610f34a724d35d6ab9be5f09d9d11b2ea4 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Sat, 14 Mar 2015 18:54:20 +0900 Subject: [PATCH 04/19] fix #1772 cross reference in docstrings like ``:param .write:`` breaks building. --- CHANGES | 1 + sphinx/domains/python.py | 16 +++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 6324bdad6..4347daafe 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ Bugs fixed doesn't overwrite existent files/dirs. Thanks to WAKAYAMA shirou. * #1773: sphinx-quickstart doesn't accept non-ASCII character as a option argument. * #1766: the message "least Python 2.6 to run" is at best misleading. +* #1772: cross reference in docstrings like ``:param .write:`` breaks building. Release 1.3 (released Mar 10, 2015) diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index c9a03de2b..b64e797b0 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -90,13 +90,15 @@ class PyXrefMixin(object): result = super(PyXrefMixin, self).make_xref(rolename, domain, target, innernode, contnode) result['refspecific'] = True - if target.startswith('.'): - result['reftarget'] = target[1:] - result[0][0] = nodes.Text(target[1:]) - if target.startswith('~'): - result['reftarget'] = target[1:] - title = target.split('.')[-1] - result[0][0] = nodes.Text(title) + if target.startswith(('.', '~')): + prefix, result['reftarget'] = target[0], target[1:] + if prefix == '.': + text = target[1:] + elif prefix == '~': + text = target.split('.')[-1] + for node in result.traverse(nodes.Text): + node.parent[node.parent.index(node)] = nodes.Text(text) + break return result From f32c5c475e098a7c27c23a196b1c806d48d8a2d0 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Sat, 14 Mar 2015 23:29:16 +0900 Subject: [PATCH 05/19] update CHANGES for PRs. --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 4347daafe..126728b75 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,9 @@ Bugs fixed * #1773: sphinx-quickstart doesn't accept non-ASCII character as a option argument. * #1766: the message "least Python 2.6 to run" is at best misleading. * #1772: cross reference in docstrings like ``:param .write:`` breaks building. +* #1770, #1774: ``literalinclude`` with empty file occurs exception. Thanks to + Takayuki Hirai. +* #1777: Sphinx 1.3 can't load extra theme. Thanks to tell-k. Release 1.3 (released Mar 10, 2015) From 1628eebfb553fe8f117ec28ef0abfabc7ed939a7 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Sun, 15 Mar 2015 00:47:43 +0900 Subject: [PATCH 06/19] refs #1777: add test for loading theme plugins --- tests/roots/test-theming/MANIFEST.in | 2 + tests/roots/test-theming/conf.py | 5 ++ tests/roots/test-theming/index.rst | 5 ++ tests/roots/test-theming/setup.py | 16 ++++++ .../roots/test-theming/test_theme/__init__.py | 5 ++ .../test_theme/test-theme/theme.conf | 2 + tests/test_theming.py | 49 ++++++++++++++++++- 7 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 tests/roots/test-theming/MANIFEST.in create mode 100644 tests/roots/test-theming/conf.py create mode 100644 tests/roots/test-theming/index.rst create mode 100644 tests/roots/test-theming/setup.py create mode 100644 tests/roots/test-theming/test_theme/__init__.py create mode 100644 tests/roots/test-theming/test_theme/test-theme/theme.conf diff --git a/tests/roots/test-theming/MANIFEST.in b/tests/roots/test-theming/MANIFEST.in new file mode 100644 index 000000000..0e977e756 --- /dev/null +++ b/tests/roots/test-theming/MANIFEST.in @@ -0,0 +1,2 @@ +recursive-include test_theme *.conf + diff --git a/tests/roots/test-theming/conf.py b/tests/roots/test-theming/conf.py new file mode 100644 index 000000000..6eecc8343 --- /dev/null +++ b/tests/roots/test-theming/conf.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +html_theme = 'test-theme' +master = 'index' + diff --git a/tests/roots/test-theming/index.rst b/tests/roots/test-theming/index.rst new file mode 100644 index 000000000..18a9a4e2f --- /dev/null +++ b/tests/roots/test-theming/index.rst @@ -0,0 +1,5 @@ +======= +Theming +======= + + diff --git a/tests/roots/test-theming/setup.py b/tests/roots/test-theming/setup.py new file mode 100644 index 000000000..34299647d --- /dev/null +++ b/tests/roots/test-theming/setup.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +# -*- coding: utf-8 -*- +from setuptools import setup, find_packages + +setup( + name='test-theme', + packages=find_packages(), + include_package_data=True, + entry_points=""" + [sphinx_themes] + path = test_theme:get_path + """, +) + + diff --git a/tests/roots/test-theming/test_theme/__init__.py b/tests/roots/test-theming/test_theme/__init__.py new file mode 100644 index 000000000..2d63e888f --- /dev/null +++ b/tests/roots/test-theming/test_theme/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +import os + +def get_path(): + return os.path.dirname(os.path.abspath(__file__)) diff --git a/tests/roots/test-theming/test_theme/test-theme/theme.conf b/tests/roots/test-theming/test_theme/test-theme/theme.conf new file mode 100644 index 000000000..0d8403f0b --- /dev/null +++ b/tests/roots/test-theming/test_theme/test-theme/theme.conf @@ -0,0 +1,2 @@ +[theme] +inherit = classic diff --git a/tests/test_theming.py b/tests/test_theming.py index 77a8b5d8f..4e5476cb4 100644 --- a/tests/test_theming.py +++ b/tests/test_theming.py @@ -11,10 +11,44 @@ import os import zipfile +import sys +import subprocess +from functools import wraps +import tempfile +from path import path from sphinx.theming import Theme, ThemeError +from sphinx.util.osutil import cd -from util import with_app, raises +from util import with_app, raises, TestApp, rootdir + + +def with_theme_setup(root, *args, **kwds): + """ + Run `setup.py build_sphinx` with args and kwargs, + pass it to the test and clean up properly. + """ + def generator(func): + @wraps(func) + def deco(*args2, **kwargs2): + tempdir = path(tempfile.mkdtemp()) + testrootdir = rootdir / 'roots' / ('test-' + root) + pkgdir = tempdir / root + testrootdir.copytree(pkgdir) + with cd(pkgdir): + command = [sys.executable, 'setup.py', 'install'] + command.extend(args) + try: + proc = subprocess.Popen( + command, + env=os.environ, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + func(pkgdir, proc) + finally: + tempdir.rmtree(ignore_errors=True) + return deco + return generator @with_app(confoverrides={'html_theme': 'ziptheme', @@ -79,3 +113,16 @@ def test_js_source(app, status, warning): assert 'Underscore.js {v}'.format(v=v) in underscore_min, msg underscore_src = (app.outdir / '_static' / 'underscore-{v}.js'.format(v=v)).text() assert 'Underscore.js {v}'.format(v=v) in underscore_src, msg + + +@with_theme_setup('theming') +def test_theme_plugin(pkgroot, proc): + out, err = proc.communicate() + print(out) + print(err) + assert proc.returncode == 0, 'expect zero status for setup.py' + app = TestApp(testroot='theming') + try: + assert 'test-theme' in Theme.themes + finally: + app.cleanup() From 6b7a2c8b6ab1b191d3776b33b191ed6a5f313b47 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Sun, 15 Mar 2015 01:13:57 +0900 Subject: [PATCH 07/19] refs #1777: fix testing. first time testing always failed it means testing on travis.ci will never be succeeded. --- tests/roots/test-theming/conf.py | 2 +- tests/test_theming.py | 73 +++++++++++++++----------------- 2 files changed, 34 insertions(+), 41 deletions(-) diff --git a/tests/roots/test-theming/conf.py b/tests/roots/test-theming/conf.py index 6eecc8343..2717087d1 100644 --- a/tests/roots/test-theming/conf.py +++ b/tests/roots/test-theming/conf.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- html_theme = 'test-theme' -master = 'index' +master_doc = 'index' diff --git a/tests/test_theming.py b/tests/test_theming.py index 4e5476cb4..9b94f1c9e 100644 --- a/tests/test_theming.py +++ b/tests/test_theming.py @@ -13,7 +13,6 @@ import os import zipfile import sys import subprocess -from functools import wraps import tempfile from path import path @@ -23,34 +22,6 @@ from sphinx.util.osutil import cd from util import with_app, raises, TestApp, rootdir -def with_theme_setup(root, *args, **kwds): - """ - Run `setup.py build_sphinx` with args and kwargs, - pass it to the test and clean up properly. - """ - def generator(func): - @wraps(func) - def deco(*args2, **kwargs2): - tempdir = path(tempfile.mkdtemp()) - testrootdir = rootdir / 'roots' / ('test-' + root) - pkgdir = tempdir / root - testrootdir.copytree(pkgdir) - with cd(pkgdir): - command = [sys.executable, 'setup.py', 'install'] - command.extend(args) - try: - proc = subprocess.Popen( - command, - env=os.environ, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - func(pkgdir, proc) - finally: - tempdir.rmtree(ignore_errors=True) - return deco - return generator - - @with_app(confoverrides={'html_theme': 'ziptheme', 'html_theme_options.testopt': 'foo'}) def test_theme_api(app, status, warning): @@ -115,14 +86,36 @@ def test_js_source(app, status, warning): assert 'Underscore.js {v}'.format(v=v) in underscore_src, msg -@with_theme_setup('theming') -def test_theme_plugin(pkgroot, proc): - out, err = proc.communicate() - print(out) - print(err) - assert proc.returncode == 0, 'expect zero status for setup.py' - app = TestApp(testroot='theming') - try: - assert 'test-theme' in Theme.themes - finally: - app.cleanup() +def test_theme_plugin(): + tempdir = path(tempfile.mkdtemp()) + testrootdir = rootdir / 'roots' / ('test-theming') + pkgdir = tempdir / 'theming' + testrootdir.copytree(pkgdir) + with cd(pkgdir): + command = [sys.executable, 'setup.py', 'install'] + try: + proc = subprocess.Popen( + command, + env=os.environ, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = proc.communicate() + print(out) + print(err) + assert proc.returncode == 0, 'expect zero status for setup.py' + finally: + pass + + command = ['sphinx-build', '.', '_build/html'] + try: + proc = subprocess.Popen( + command, + env=os.environ, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = proc.communicate() + print(out) + print(err) + assert proc.returncode == 0, 'expect zero status for setup.py' + finally: + tempdir.rmtree(ignore_errors=True) From e8e5bae15f0f3db658fd7c0cc34a5b04dd3ea48e Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Sun, 15 Mar 2015 01:33:59 +0900 Subject: [PATCH 08/19] remove test that is not works correctly on travis.ci (+1 squashed commits) --- tests/test_theming.py | 42 +----------------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/tests/test_theming.py b/tests/test_theming.py index 9b94f1c9e..45229c842 100644 --- a/tests/test_theming.py +++ b/tests/test_theming.py @@ -11,15 +11,10 @@ import os import zipfile -import sys -import subprocess -import tempfile -from path import path from sphinx.theming import Theme, ThemeError -from sphinx.util.osutil import cd -from util import with_app, raises, TestApp, rootdir +from util import with_app, raises, TestApp @with_app(confoverrides={'html_theme': 'ziptheme', @@ -84,38 +79,3 @@ def test_js_source(app, status, warning): assert 'Underscore.js {v}'.format(v=v) in underscore_min, msg underscore_src = (app.outdir / '_static' / 'underscore-{v}.js'.format(v=v)).text() assert 'Underscore.js {v}'.format(v=v) in underscore_src, msg - - -def test_theme_plugin(): - tempdir = path(tempfile.mkdtemp()) - testrootdir = rootdir / 'roots' / ('test-theming') - pkgdir = tempdir / 'theming' - testrootdir.copytree(pkgdir) - with cd(pkgdir): - command = [sys.executable, 'setup.py', 'install'] - try: - proc = subprocess.Popen( - command, - env=os.environ, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out, err = proc.communicate() - print(out) - print(err) - assert proc.returncode == 0, 'expect zero status for setup.py' - finally: - pass - - command = ['sphinx-build', '.', '_build/html'] - try: - proc = subprocess.Popen( - command, - env=os.environ, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - out, err = proc.communicate() - print(out) - print(err) - assert proc.returncode == 0, 'expect zero status for setup.py' - finally: - tempdir.rmtree(ignore_errors=True) From 36d47a2193dbfea8693d2f852414530136f01507 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Mon, 16 Mar 2015 00:20:33 +0900 Subject: [PATCH 09/19] Close #1776: ``source_suffix = ['.rst']`` cause unfriendly error on prior version. --- CHANGES | 1 + sphinx/quickstart.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 126728b75..b23b1cc97 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,7 @@ Bugs fixed * #1770, #1774: ``literalinclude`` with empty file occurs exception. Thanks to Takayuki Hirai. * #1777: Sphinx 1.3 can't load extra theme. Thanks to tell-k. +* #1776: ``source_suffix = ['.rst']`` cause unfriendly error on prior version. Release 1.3 (released Mar 10, 2015) diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index 0548f69c5..f13a5c7cd 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -108,7 +108,9 @@ extensions = [%(extensions)s] templates_path = ['%(dot)stemplates'] # The suffix(es) of source filenames. -source_suffix = ['%(suffix)s'] +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '%(suffix)s' # The encoding of source files. #source_encoding = 'utf-8-sig' From a94c40cbcf0eb0a4af759ccb8302de1f9a65f130 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Mon, 16 Mar 2015 00:27:12 +0900 Subject: [PATCH 10/19] ref #1776: test fixed. --- tests/test_quickstart.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index 51f815049..013700417 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -144,7 +144,7 @@ def test_quickstart_defaults(tempdir): execfile_(conffile, ns) assert ns['extensions'] == [] assert ns['templates_path'] == ['_templates'] - assert ns['source_suffix'] == ['.rst'] + assert ns['source_suffix'] == '.rst' assert ns['master_doc'] == 'index' assert ns['project'] == 'Sphinx Test' assert ns['copyright'] == '%s, Georg Brandl' % time.strftime('%Y') @@ -203,7 +203,7 @@ def test_quickstart_all_answers(tempdir): 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo' ] assert ns['templates_path'] == ['.templates'] - assert ns['source_suffix'] == ['.txt'] + assert ns['source_suffix'] == '.txt' assert ns['master_doc'] == 'contents' assert ns['project'] == u'STASI™' assert ns['copyright'] == u'%s, Wolfgang Schäuble & G\'Beckstein' % \ From ef3a1f7b2e49e8f850e92fe358ee723f4f59dadc Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Mon, 16 Mar 2015 22:03:21 +0900 Subject: [PATCH 11/19] Fixed #1771: automated .mo building doesn't work properly with: * `gettext_compact=True` in conf.py * `sphinx-build -a` to rebuild all files. * `sphinx-build ... ` to specify docnames. --- CHANGES | 1 + sphinx/builders/__init__.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index b23b1cc97..0947b03ce 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,7 @@ Bugs fixed Takayuki Hirai. * #1777: Sphinx 1.3 can't load extra theme. Thanks to tell-k. * #1776: ``source_suffix = ['.rst']`` cause unfriendly error on prior version. +* #1771: automated .mo building doesn't work properly. Release 1.3 (released Mar 10, 2015) diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 60fccf233..4e0a6cfce 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -168,7 +168,7 @@ class Builder(object): def compile_all_catalogs(self): catalogs = i18n.get_catalogs( [path.join(self.srcdir, x) for x in self.config.locale_dirs], - self.config.language, True) + self.config.language, self.config.gettext_compact, True) message = 'all of %d po files' % len(catalogs) self.compile_catalogs(catalogs, message) @@ -181,7 +181,7 @@ class Builder(object): specified_domains = set(map(to_domain, specified_files)) catalogs = i18n.get_catalogs( [path.join(self.srcdir, x) for x in self.config.locale_dirs], - self.config.language, True) + self.config.language, self.config.gettext_compact, True) catalogs = [f for f in catalogs if f.domain in specified_domains] message = 'targets for %d po files that are specified' % len(catalogs) self.compile_catalogs(catalogs, message) @@ -189,7 +189,7 @@ class Builder(object): def compile_update_catalogs(self): catalogs = i18n.get_catalogs( [path.join(self.srcdir, x) for x in self.config.locale_dirs], - self.config.language) + self.config.language, self.config.gettext_compact) message = 'targets for %d po files that are out of date' % len(catalogs) self.compile_catalogs(catalogs, message) From 30d6d72f4741031e905d09700365f1e91d477f8f Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Mon, 16 Mar 2015 23:01:16 +0900 Subject: [PATCH 12/19] Fixed #1771: automated .mo building doesn't work properly with template translation: sphinx-build will load sphinx.mo file to initialize template-bridge before compiling sphinx.po file. --- sphinx/builders/__init__.py | 12 ++++++++---- sphinx/locale/__init__.py | 9 +++++++++ sphinx/util/i18n.py | 12 +++++++++++- tests/test_catalogs.py | 9 ++++++--- tests/test_util_i18n.py | 8 ++++---- 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 4e0a6cfce..4c2a16715 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -168,7 +168,9 @@ class Builder(object): def compile_all_catalogs(self): catalogs = i18n.get_catalogs( [path.join(self.srcdir, x) for x in self.config.locale_dirs], - self.config.language, self.config.gettext_compact, True) + self.config.language, + gettext_compact=self.config.gettext_compact, + force_all=True) message = 'all of %d po files' % len(catalogs) self.compile_catalogs(catalogs, message) @@ -181,15 +183,17 @@ class Builder(object): specified_domains = set(map(to_domain, specified_files)) catalogs = i18n.get_catalogs( [path.join(self.srcdir, x) for x in self.config.locale_dirs], - self.config.language, self.config.gettext_compact, True) - catalogs = [f for f in catalogs if f.domain in specified_domains] + self.config.language, + domains=list(specified_domains), + gettext_compact=self.config.gettext_compact) message = 'targets for %d po files that are specified' % len(catalogs) self.compile_catalogs(catalogs, message) def compile_update_catalogs(self): catalogs = i18n.get_catalogs( [path.join(self.srcdir, x) for x in self.config.locale_dirs], - self.config.language, self.config.gettext_compact) + self.config.language, + gettext_compact=self.config.gettext_compact) message = 'targets for %d po files that are out of date' % len(catalogs) self.compile_catalogs(catalogs, message) diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py index acb71bf28..db8081516 100644 --- a/sphinx/locale/__init__.py +++ b/sphinx/locale/__init__.py @@ -208,6 +208,15 @@ def init(locale_dirs, language, catalog='sphinx'): translator = None # the None entry is the system's default locale path has_translation = True + + # compile mo files if po file is updated + # TODO: remove circular importing + from sphinx.util.i18n import get_catalogs + for catinfo in get_catalogs(locale_dirs, language, domains=[catalog], + force_all=False): + catinfo.write_mo(language) + + # loading for dir_ in locale_dirs: try: trans = gettext.translation(catalog, localedir=dir_, diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py index 7bd0c34ea..e83ba4052 100644 --- a/sphinx/util/i18n.py +++ b/sphinx/util/i18n.py @@ -16,6 +16,7 @@ from babel.messages.pofile import read_po from babel.messages.mofile import write_mo from sphinx.util.osutil import walk +from sphinx.util import SEP LocaleFileInfoBase = namedtuple('CatalogInfo', 'base_dir,domain') @@ -50,13 +51,16 @@ class CatalogInfo(LocaleFileInfoBase): write_mo(mo, read_po(po, locale)) -def get_catalogs(locale_dirs, locale, gettext_compact=False, force_all=False): +def get_catalogs(locale_dirs, locale, domains=None, + gettext_compact=False, force_all=False): """ :param list locale_dirs: list of path as `['locale_dir1', 'locale_dir2', ...]` to find translation catalogs. Each path contains a structure such as `/LC_MESSAGES/domain.po`. :param str locale: a language as `'en'` + :param list domains: list of domain names to get. If empty list or None + is specified, get all domain names. default is None. :param boolean gettext_compact: * False: keep domains directory structure (default). * True: domains in the sub directory will be merged into 1 file. @@ -70,6 +74,9 @@ def get_catalogs(locale_dirs, locale, gettext_compact=False, force_all=False): catalogs = set() for locale_dir in locale_dirs: + if not locale_dir: + continue # skip system locale directory + base_dir = path.join(locale_dir, locale, 'LC_MESSAGES') if not path.exists(base_dir): @@ -82,6 +89,9 @@ def get_catalogs(locale_dirs, locale, gettext_compact=False, force_all=False): domain = path.relpath(path.join(dirpath, base), base_dir) if gettext_compact and path.sep in domain: domain = path.split(domain)[0] + domain = domain.replace(path.sep, SEP) + if domains and domain not in domains: + continue cat = CatalogInfo(base_dir, domain) if force_all or cat.is_outdated(): catalogs.add(cat) diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py index b06e71a57..7b1cc05e0 100644 --- a/tests/test_catalogs.py +++ b/tests/test_catalogs.py @@ -55,10 +55,13 @@ def test_compile_all_catalogs(app, status, warning): @with_app(buildername='html', testroot='intl', confoverrides={'language': 'en', 'locale_dirs': [locale_dir]}) def test_compile_specific_catalogs(app, status, warning): - app.builder.compile_specific_catalogs(['admonitions']) - catalog_dir = locale_dir / app.config.language / 'LC_MESSAGES' - actual = set(find_files(catalog_dir, '.mo')) + def get_actual(): + return set(find_files(catalog_dir, '.mo')) + + actual_on_boot = get_actual() # sphinx.mo might be included + app.builder.compile_specific_catalogs(['admonitions']) + actual = get_actual() - actual_on_boot assert actual == set(['admonitions.mo']) diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py index ba18026ca..d8f0cd012 100644 --- a/tests/test_util_i18n.py +++ b/tests/test_util_i18n.py @@ -77,8 +77,8 @@ def test_get_catalogs_for_xx(dir): assert domains == set([ 'test1', 'test2', - path.normpath('sub/test4'), - path.normpath('sub/test5'), + 'sub/test4', + 'sub/test5', ]) @@ -131,8 +131,8 @@ def test_get_catalogs_for_xx_without_outdated(dir): assert domains == set([ 'test1', 'test2', - path.normpath('sub/test4'), - path.normpath('sub/test5'), + 'sub/test4', + 'sub/test5', ]) From d699b1d3267e421a6661c834092a92e987b196ed Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Mon, 16 Mar 2015 23:06:54 +0900 Subject: [PATCH 13/19] rename function name to avoid ambiguous --- sphinx/builders/__init__.py | 6 +++--- sphinx/locale/__init__.py | 5 ++--- sphinx/util/i18n.py | 4 ++-- tests/test_util_i18n.py | 18 +++++++++--------- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 4c2a16715..8a352d6a1 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -166,7 +166,7 @@ class Builder(object): catalog.write_mo(self.config.language) def compile_all_catalogs(self): - catalogs = i18n.get_catalogs( + catalogs = i18n.find_catalog_source_files( [path.join(self.srcdir, x) for x in self.config.locale_dirs], self.config.language, gettext_compact=self.config.gettext_compact, @@ -181,7 +181,7 @@ class Builder(object): return dom specified_domains = set(map(to_domain, specified_files)) - catalogs = i18n.get_catalogs( + catalogs = i18n.find_catalog_source_files( [path.join(self.srcdir, x) for x in self.config.locale_dirs], self.config.language, domains=list(specified_domains), @@ -190,7 +190,7 @@ class Builder(object): self.compile_catalogs(catalogs, message) def compile_update_catalogs(self): - catalogs = i18n.get_catalogs( + catalogs = i18n.find_catalog_source_files( [path.join(self.srcdir, x) for x in self.config.locale_dirs], self.config.language, gettext_compact=self.config.gettext_compact) diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py index db8081516..4847c0845 100644 --- a/sphinx/locale/__init__.py +++ b/sphinx/locale/__init__.py @@ -211,9 +211,8 @@ def init(locale_dirs, language, catalog='sphinx'): # compile mo files if po file is updated # TODO: remove circular importing - from sphinx.util.i18n import get_catalogs - for catinfo in get_catalogs(locale_dirs, language, domains=[catalog], - force_all=False): + from sphinx.util.i18n import find_catalog_source_files + for catinfo in find_catalog_source_files(locale_dirs, language, domains=[catalog]): catinfo.write_mo(language) # loading diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py index e83ba4052..78830fca7 100644 --- a/sphinx/util/i18n.py +++ b/sphinx/util/i18n.py @@ -51,8 +51,8 @@ class CatalogInfo(LocaleFileInfoBase): write_mo(mo, read_po(po, locale)) -def get_catalogs(locale_dirs, locale, domains=None, - gettext_compact=False, force_all=False): +def find_catalog_source_files(locale_dirs, locale, domains=None, gettext_compact=False, + force_all=False): """ :param list locale_dirs: list of path as `['locale_dir1', 'locale_dir2', ...]` to find diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py index d8f0cd012..c74962fc5 100644 --- a/tests/test_util_i18n.py +++ b/tests/test_util_i18n.py @@ -72,7 +72,7 @@ def test_get_catalogs_for_xx(dir): (dir / 'loc1' / 'xx' / 'LC_ALL').makedirs() (dir / 'loc1' / 'xx' / 'LC_ALL' / 'test7.po').write_text('#') - catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=False) + catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', force_all=False) domains = set(c.domain for c in catalogs) assert domains == set([ 'test1', @@ -89,22 +89,22 @@ def test_get_catalogs_for_en(dir): (dir / 'loc1' / 'en' / 'LC_MESSAGES').makedirs() (dir / 'loc1' / 'en' / 'LC_MESSAGES' / 'en_dom.po').write_text('#') - catalogs = i18n.get_catalogs([dir / 'loc1'], 'en', force_all=False) + catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'en', force_all=False) domains = set(c.domain for c in catalogs) assert domains == set(['en_dom']) @with_tempdir def test_get_catalogs_with_non_existent_locale(dir): - catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx') + catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx') assert not catalogs - catalogs = i18n.get_catalogs([dir / 'loc1'], None) + catalogs = i18n.find_catalog_source_files([dir / 'loc1'], None) assert not catalogs def test_get_catalogs_with_non_existent_locale_dirs(): - catalogs = i18n.get_catalogs(['dummy'], 'xx') + catalogs = i18n.find_catalog_source_files(['dummy'], 'xx') assert not catalogs @@ -123,10 +123,10 @@ def test_get_catalogs_for_xx_without_outdated(dir): (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.po').write_text('#') (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test5.mo').write_text('#') - catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=False) + catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', force_all=False) assert not catalogs - catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', force_all=True) + catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', force_all=True) domains = set(c.domain for c in catalogs) assert domains == set([ 'test1', @@ -144,7 +144,7 @@ def test_get_catalogs_from_multiple_locale_dirs(dir): (dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test1.po').write_text('#') (dir / 'loc2' / 'xx' / 'LC_MESSAGES' / 'test2.po').write_text('#') - catalogs = i18n.get_catalogs([dir / 'loc1', dir / 'loc2'], 'xx') + catalogs = i18n.find_catalog_source_files([dir / 'loc1', dir / 'loc2'], 'xx') domains = sorted(c.domain for c in catalogs) assert domains == ['test1', 'test1', 'test2'] @@ -158,6 +158,6 @@ def test_get_catalogs_with_compact(dir): (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test3.po').write_text('#') (dir / 'loc1' / 'xx' / 'LC_MESSAGES' / 'sub' / 'test4.po').write_text('#') - catalogs = i18n.get_catalogs([dir / 'loc1'], 'xx', gettext_compact=True) + catalogs = i18n.find_catalog_source_files([dir / 'loc1'], 'xx', gettext_compact=True) domains = set(c.domain for c in catalogs) assert domains == set(['test1', 'test2', 'sub']) From dbfc72a4510b0c88951b706248d92b1fcaf52e3c Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Mon, 16 Mar 2015 23:11:23 +0900 Subject: [PATCH 14/19] refactoring: move i18n related function from osutil into i18n --- sphinx/builders/__init__.py | 3 ++- sphinx/builders/gettext.py | 3 ++- sphinx/environment.py | 3 ++- sphinx/transforms.py | 3 ++- sphinx/util/i18n.py | 22 +++++++++++++++++++++- sphinx/util/osutil.py | 21 --------------------- 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 8a352d6a1..38cde6123 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -21,7 +21,8 @@ except ImportError: from docutils import nodes from sphinx.util import i18n, path_stabilize -from sphinx.util.osutil import SEP, relative_uri, find_catalog +from sphinx.util.osutil import SEP, relative_uri +from sphinx.util.i18n import find_catalog from sphinx.util.console import bold, darkgreen from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \ parallel_available diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index c23675d36..ec6a18805 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -23,7 +23,8 @@ from six import iteritems from sphinx.builders import Builder from sphinx.util import split_index_msg from sphinx.util.nodes import extract_messages, traverse_translatable_index -from sphinx.util.osutil import safe_relpath, ensuredir, find_catalog, SEP +from sphinx.util.osutil import safe_relpath, ensuredir, SEP +from sphinx.util.i18n import find_catalog from sphinx.util.console import darkgreen, purple, bold from sphinx.locale import pairindextypes diff --git a/sphinx/environment.py b/sphinx/environment.py index 79212e96b..11f395b43 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -40,7 +40,8 @@ from sphinx import addnodes from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \ FilenameUniqDict, get_figtype, import_object from sphinx.util.nodes import clean_astext, make_refnode, WarningStream, is_translatable -from sphinx.util.osutil import SEP, find_catalog_files, getcwd, fs_encoding +from sphinx.util.osutil import SEP, getcwd, fs_encoding +from sphinx.util.i18n import find_catalog_files from sphinx.util.console import bold, purple from sphinx.util.matching import compile_matchers from sphinx.util.parallel import ParallelTasks, parallel_available, make_chunks diff --git a/sphinx/transforms.py b/sphinx/transforms.py index 789bf5d39..681b50e05 100644 --- a/sphinx/transforms.py +++ b/sphinx/transforms.py @@ -23,7 +23,8 @@ from sphinx.util import split_index_msg from sphinx.util.nodes import ( traverse_translatable_index, extract_messages, LITERAL_TYPE_NODES, IMAGE_TYPE_NODES, ) -from sphinx.util.osutil import ustrftime, find_catalog +from sphinx.util.osutil import ustrftime +from sphinx.util.i18n import find_catalog from sphinx.util.pycompat import indent from sphinx.domains.std import ( make_term_from_paragraph_node, diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py index 78830fca7..efdc31828 100644 --- a/sphinx/util/i18n.py +++ b/sphinx/util/i18n.py @@ -8,7 +8,7 @@ :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ - +import gettext from os import path from collections import namedtuple @@ -51,6 +51,26 @@ class CatalogInfo(LocaleFileInfoBase): write_mo(mo, read_po(po, locale)) +def find_catalog(docname, compaction): + if compaction: + ret = docname.split(SEP, 1)[0] + else: + ret = docname + + return ret + + +def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction): + if not(lang and locale_dirs): + return [] + + domain = find_catalog(docname, compaction) + files = [gettext.find(domain, path.join(srcdir, dir_), [lang]) + for dir_ in locale_dirs] + files = [path.relpath(f, srcdir) for f in files if f] + return files + + def find_catalog_source_files(locale_dirs, locale, domains=None, gettext_compact=False, force_all=False): """ diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py index 46f908292..20c6a90cc 100644 --- a/sphinx/util/osutil.py +++ b/sphinx/util/osutil.py @@ -17,7 +17,6 @@ import time import errno import locale import shutil -import gettext from os import path import contextlib @@ -170,26 +169,6 @@ def safe_relpath(path, start=None): return path -def find_catalog(docname, compaction): - if compaction: - ret = docname.split(SEP, 1)[0] - else: - ret = docname - - return ret - - -def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction): - if not(lang and locale_dirs): - return [] - - domain = find_catalog(docname, compaction) - files = [gettext.find(domain, path.join(srcdir, dir_), [lang]) - for dir_ in locale_dirs] - files = [path.relpath(f, srcdir) for f in files if f] - return files - - fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() From efd1fefc0b546059ab49ae160556e4430e4b1525 Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Mon, 16 Mar 2015 19:34:55 +0000 Subject: [PATCH 15/19] Autodoc: Python2 Allow unicode string in __all__ --- sphinx/ext/autodoc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index bf0ad5fa9..ff6a30ecc 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -17,7 +17,7 @@ import inspect import traceback from types import FunctionType, BuiltinFunctionType, MethodType -from six import iteritems, itervalues, text_type, class_types +from six import iteritems, itervalues, text_type, class_types, string_types from docutils import nodes from docutils.utils import assemble_option_dict from docutils.statemachine import ViewList @@ -888,7 +888,7 @@ class ModuleDocumenter(Documenter): memberlist = self.object.__all__ # Sometimes __all__ is broken... if not isinstance(memberlist, (list, tuple)) or not \ - all(isinstance(entry, str) for entry in memberlist): + all(isinstance(entry, string_types) for entry in memberlist): self.directive.warn( '__all__ should be a list of strings, not %r ' '(in module %s) -- ignoring __all__' % From bd22185cf965be81e6b8f102fbc8481844a9ad54 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Tue, 17 Mar 2015 07:31:58 +0900 Subject: [PATCH 16/19] update CHANGES refs #1783 --- CHANGES | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 0947b03ce..321469059 100644 --- a/CHANGES +++ b/CHANGES @@ -14,7 +14,8 @@ Bugs fixed * #1777: Sphinx 1.3 can't load extra theme. Thanks to tell-k. * #1776: ``source_suffix = ['.rst']`` cause unfriendly error on prior version. * #1771: automated .mo building doesn't work properly. - +* #1783: Autodoc: Python2 Allow unicode string in __all__. + Thanks to Jens Hedegaard Nielsen. Release 1.3 (released Mar 10, 2015) =================================== From 8fb65162566bde63f0cd902e5adbf3ee80e5bb93 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Tue, 17 Mar 2015 00:27:40 +0900 Subject: [PATCH 17/19] fix typo. --- doc/markup/misc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/markup/misc.rst b/doc/markup/misc.rst index fd31480a6..2855f1fad 100644 --- a/doc/markup/misc.rst +++ b/doc/markup/misc.rst @@ -263,5 +263,5 @@ following directive exists: format and the builder name. Note that the current builder tag is not available in ``conf.py``, it is - only available after the builder is intialized. + only available after the builder is initialized. From 085bcfa5189ea135f91efa8d88b266be12c9b587 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Tue, 17 Mar 2015 07:34:26 +0900 Subject: [PATCH 18/19] refs #1781: Setting `html_domain_indices` to a list raises a type check warnings. --- CHANGES | 1 + sphinx/config.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGES b/CHANGES index 321469059..3accf942a 100644 --- a/CHANGES +++ b/CHANGES @@ -16,6 +16,7 @@ Bugs fixed * #1771: automated .mo building doesn't work properly. * #1783: Autodoc: Python2 Allow unicode string in __all__. Thanks to Jens Hedegaard Nielsen. +* #1781: Setting `html_domain_indices` to a list raises a type check warnings. Release 1.3 (released Mar 10, 2015) =================================== diff --git a/sphinx/config.py b/sphinx/config.py index ac3358dda..090875a79 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -28,6 +28,10 @@ if PY3: CONFIG_EXIT_ERROR = "The configuration file (or one of the modules it imports) " \ "called sys.exit()" +IGNORE_CONFIG_TYPE_CHECKS = ( + 'html_domain_indices', 'latex_domain_indices', 'texinfo_domain_indices' +) + class Config(object): """ @@ -288,6 +292,8 @@ class Config(object): # NB. since config values might use l_() we have to wait with calling # this method until i18n is initialized for name in self._raw_config: + if name in IGNORE_CONFIG_TYPE_CHECKS: + continue # for a while, ignore multiple types config value. see #1781 if name not in Config.config_values: continue # we don't know a default value default, dummy_rebuild = Config.config_values[name] From a4083dde29022eecf26281cf23f54ea586520ec9 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Tue, 17 Mar 2015 14:30:11 +0900 Subject: [PATCH 19/19] Bump to 1.3.1 final --- CHANGES | 4 ++-- sphinx/__init__.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 3accf942a..666944a98 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ -Release 1.3.1 (in development) -=============================== +Release 1.3.1 (released Mar 17, 2015) +===================================== Bugs fixed ---------- diff --git a/sphinx/__init__.py b/sphinx/__init__.py index f5c5ed85d..705aeabe9 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -15,13 +15,13 @@ import sys from os import path -__version__ = '1.3+' -__released__ = '1.3+' # used when Sphinx builds its own docs +__version__ = '1.3.1' +__released__ = '1.3.1' # used when Sphinx builds its own docs # version info for better programmatic use # possible values for 3rd element: 'alpha', 'beta', 'rc', 'final' # 'final' has 0 as the last element -version_info = (1, 3, 1, 'beta', 1) +version_info = (1, 3, 1, 'final', 0) package_dir = path.abspath(path.dirname(__file__))