From 39916e6ed3e298bfbec167e6cd982e3cb76e8cb0 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Fri, 27 May 2022 23:42:00 +0100 Subject: [PATCH 1/9] Resolve issue 10474 --- sphinx/config.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sphinx/config.py b/sphinx/config.py index 5f92479d38..7afb65eb3b 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -163,6 +163,12 @@ def read(cls, confdir: str, overrides: Dict = None, tags: Tags = None) -> "Confi raise ConfigError(__("config directory doesn't contain a conf.py file (%s)") % confdir) namespace = eval_config_file(filename, tags) + + # Resolve https://github.com/sphinx-doc/sphinx/issues/10474 where conf.py + # explicitly sets language to None, by coercing it to English. + if namespace["language"] is None: + namespace["language"] = "en" + return cls(namespace, overrides or {}) def convert_overrides(self, name: str, value: Any) -> Any: From 20a1775c833a4ff355b7401bfab3f0ce02f0babb Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Fri, 27 May 2022 23:50:07 +0100 Subject: [PATCH 2/9] Add test --- tests/test_config.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_config.py b/tests/test_config.py index 3d72a6b0f0..dea7418207 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -381,3 +381,17 @@ def test_nitpick_ignore_regex_fullmatch(app, status, warning): assert len(warning) == len(nitpick_warnings) for actual, expected in zip(warning, nitpick_warnings): assert expected in actual + + +def test_conf_py_language_none(tempdir): + """Regression test for #10474.""" + + # Given a conf.py file with language = None + (tempdir / 'conf.py').write_text("language = None", encoding='utf-8') + + # When we load conf.py into a Config object + cfg = Config.read(tempdir, {}, None) + cfg.init_values() + + # Then the language is coerced to English + assert cfg.language == "en" From 57e4a2f4cc42a3bb31b4d900dea06a78c660bb45 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sat, 28 May 2022 00:06:29 +0100 Subject: [PATCH 3/9] Fix case where language isn't set --- sphinx/config.py | 2 +- tests/test_config.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/sphinx/config.py b/sphinx/config.py index 7afb65eb3b..9e05bc1b3d 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -166,7 +166,7 @@ def read(cls, confdir: str, overrides: Dict = None, tags: Tags = None) -> "Confi # Resolve https://github.com/sphinx-doc/sphinx/issues/10474 where conf.py # explicitly sets language to None, by coercing it to English. - if namespace["language"] is None: + if namespace.get("language", ...) is None: namespace["language"] = "en" return cls(namespace, overrides or {}) diff --git a/tests/test_config.py b/tests/test_config.py index dea7418207..804772d467 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -395,3 +395,17 @@ def test_conf_py_language_none(tempdir): # Then the language is coerced to English assert cfg.language == "en" + + +def test_conf_py_no_language(tempdir): + """Regression test for #10474.""" + + # Given a conf.py file with no language attribute + (tempdir / 'conf.py').write_text("", encoding='utf-8') + + # When we load conf.py into a Config object + cfg = Config.read(tempdir, {}, None) + cfg.init_values() + + # Then the language is coerced to English + assert cfg.language == "en" From a3d09835522e6487cf93dcc871179db8d69e4180 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sat, 28 May 2022 19:06:48 +0100 Subject: [PATCH 4/9] Add warning --- sphinx/config.py | 4 ++++ tests/test_config.py | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/sphinx/config.py b/sphinx/config.py index 9e05bc1b3d..27653f307a 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -3,6 +3,7 @@ import re import traceback import types +import warnings from collections import OrderedDict from os import getenv, path from typing import (TYPE_CHECKING, Any, Callable, Dict, Generator, Iterator, List, NamedTuple, @@ -168,6 +169,9 @@ def read(cls, confdir: str, overrides: Dict = None, tags: Tags = None) -> "Confi # explicitly sets language to None, by coercing it to English. if namespace.get("language", ...) is None: namespace["language"] = "en" + warnings.warn("'None' is not a valid value for 'language', coercing to 'en'. " + "Update 'conf.py' to a valid language code to silence this " + "warning.", RuntimeWarning, stacklevel=4) return cls(namespace, overrides or {}) diff --git a/tests/test_config.py b/tests/test_config.py index 804772d467..8d707ae252 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -397,6 +397,22 @@ def test_conf_py_language_none(tempdir): assert cfg.language == "en" +def test_conf_py_language_none_warning(tempdir): + """Regression test for #10474.""" + + # Given a conf.py file with language = None + (tempdir / 'conf.py').write_text("language = None", encoding='utf-8') + + # Then a warning is raised + with pytest.warns( + RuntimeWarning, + match="'None' is not a valid value for 'language', coercing to 'en'. " + "Update 'conf.py' to a valid language code to silence this " + "warning."): + # When we load conf.py into a Config object + Config.read(tempdir, {}, None) + + def test_conf_py_no_language(tempdir): """Regression test for #10474.""" From 8e353e3103b5bbeacfe447304f3b4dabfaaf5da2 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 29 May 2022 02:53:23 +0900 Subject: [PATCH 5/9] Emit a warning if "language = None" setting found (refs: #10474) --- sphinx/config.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sphinx/config.py b/sphinx/config.py index 27653f307a..9b32d7f95e 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -168,6 +168,9 @@ def read(cls, confdir: str, overrides: Dict = None, tags: Tags = None) -> "Confi # Resolve https://github.com/sphinx-doc/sphinx/issues/10474 where conf.py # explicitly sets language to None, by coercing it to English. if namespace.get("language", ...) is None: + logging.warning(__("Invalid configuration found: 'language = None'. " + "Now it takes only a string. Please update your configuration. " + "Fallback to 'en' (English).")) namespace["language"] = "en" warnings.warn("'None' is not a valid value for 'language', coercing to 'en'. " "Update 'conf.py' to a valid language code to silence this " From 68252c646a4343a5142f5c44d8d0544f2af69374 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 29 May 2022 02:54:16 +0900 Subject: [PATCH 6/9] doc: The default setting of "language" has been changed since v5.0 --- CHANGES | 3 +++ doc/usage/configuration.rst | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index b56b22d643..a7b565e79b 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,9 @@ Dependencies Incompatible changes -------------------- +* #10474: :confval:`language` does not accept ``None`` as it value. The default + value of ``language`` becomes to ``'en'`` now. + Deprecated ---------- diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index 677eb39271..f297e5c5cb 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -725,7 +725,7 @@ documentation on :ref:`intl` for details. (e.g. the German version of ``myfigure.png`` will be ``myfigure.de.png`` by default setting) and substitute them for original figures. In the LaTeX builder, a suitable language will be selected as an option for the *Babel* - package. Default is ``None``, which means that no translation will be done. + package. Default is ``'en'``. .. versionadded:: 0.5 @@ -733,6 +733,8 @@ documentation on :ref:`intl` for details. Support figure substitution + .. versionchanged:: 5.0 + Currently supported languages by Sphinx are: * ``ar`` -- Arabic @@ -745,7 +747,7 @@ documentation on :ref:`intl` for details. * ``da`` -- Danish * ``de`` -- German * ``el`` -- Greek - * ``en`` -- English + * ``en`` -- English (default) * ``eo`` -- Esperanto * ``es`` -- Spanish * ``et`` -- Estonian From fb6db30c1024ce5838dcf330f275cdf2adbd94b6 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 29 May 2022 03:01:42 +0900 Subject: [PATCH 7/9] Update comment --- sphinx/config.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sphinx/config.py b/sphinx/config.py index 9b32d7f95e..0233cbbd13 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -165,8 +165,10 @@ def read(cls, confdir: str, overrides: Dict = None, tags: Tags = None) -> "Confi confdir) namespace = eval_config_file(filename, tags) - # Resolve https://github.com/sphinx-doc/sphinx/issues/10474 where conf.py - # explicitly sets language to None, by coercing it to English. + # Note: Old sphinx projects has been configured as "langugae = None" because + # sphinx-quickstart had generated the configuration by default formerly. + # To keep compatibility, they should be fallback to 'en' for a while + # (At least 2 years or more since v5.0 release). if namespace.get("language", ...) is None: logging.warning(__("Invalid configuration found: 'language = None'. " "Now it takes only a string. Please update your configuration. " From 479e48266c025c99025787a8004a82b2afda8e6c Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sat, 28 May 2022 19:17:46 +0100 Subject: [PATCH 8/9] Update warning, revert my original warning patch --- sphinx/config.py | 15 ++++++--------- tests/test_config.py | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/sphinx/config.py b/sphinx/config.py index 0233cbbd13..1cd0632ed9 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -165,18 +165,15 @@ def read(cls, confdir: str, overrides: Dict = None, tags: Tags = None) -> "Confi confdir) namespace = eval_config_file(filename, tags) - # Note: Old sphinx projects has been configured as "langugae = None" because - # sphinx-quickstart had generated the configuration by default formerly. + # Note: Old sphinx projects have been configured as "langugae = None" because + # sphinx-quickstart previously generated this by default. # To keep compatibility, they should be fallback to 'en' for a while - # (At least 2 years or more since v5.0 release). + # (This conversion should not be removed before 2025-01-01). if namespace.get("language", ...) is None: - logging.warning(__("Invalid configuration found: 'language = None'. " - "Now it takes only a string. Please update your configuration. " - "Fallback to 'en' (English).")) + logger.warning(__("Invalid configuration value found: 'language = None'. " + "Update your configuration to a valid langauge code. " + "Falling back to 'en' (English).")) namespace["language"] = "en" - warnings.warn("'None' is not a valid value for 'language', coercing to 'en'. " - "Update 'conf.py' to a valid language code to silence this " - "warning.", RuntimeWarning, stacklevel=4) return cls(namespace, overrides or {}) diff --git a/tests/test_config.py b/tests/test_config.py index 8d707ae252..ec8194af11 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -397,20 +397,22 @@ def test_conf_py_language_none(tempdir): assert cfg.language == "en" -def test_conf_py_language_none_warning(tempdir): +def test_conf_py_language_none_warning(tempdir, caplog): """Regression test for #10474.""" # Given a conf.py file with language = None (tempdir / 'conf.py').write_text("language = None", encoding='utf-8') + # When we load conf.py into a Config object + Config.read(tempdir, {}, None) + # Then a warning is raised - with pytest.warns( - RuntimeWarning, - match="'None' is not a valid value for 'language', coercing to 'en'. " - "Update 'conf.py' to a valid language code to silence this " - "warning."): - # When we load conf.py into a Config object - Config.read(tempdir, {}, None) + assert len(caplog.messages) == 1 + assert caplog.messages[0] == ( + "Invalid configuration value found: 'language = None'. " + "Update your configuration to a valid langauge code. " + "Falling back to 'en' (English).") + assert caplog.records[0].levelname == "WARNING" def test_conf_py_no_language(tempdir): From 200414982c768c213ca66f41fa331a5b4d129d94 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sat, 28 May 2022 19:26:13 +0100 Subject: [PATCH 9/9] Update test --- sphinx/config.py | 1 - tests/test_config.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sphinx/config.py b/sphinx/config.py index 1cd0632ed9..15337e924d 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -3,7 +3,6 @@ import re import traceback import types -import warnings from collections import OrderedDict from os import getenv, path from typing import (TYPE_CHECKING, Any, Callable, Dict, Generator, Iterator, List, NamedTuple, diff --git a/tests/test_config.py b/tests/test_config.py index ec8194af11..c0b8864e00 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -397,7 +397,8 @@ def test_conf_py_language_none(tempdir): assert cfg.language == "en" -def test_conf_py_language_none_warning(tempdir, caplog): +@mock.patch("sphinx.config.logger") +def test_conf_py_language_none_warning(logger, tempdir): """Regression test for #10474.""" # Given a conf.py file with language = None @@ -407,12 +408,11 @@ def test_conf_py_language_none_warning(tempdir, caplog): Config.read(tempdir, {}, None) # Then a warning is raised - assert len(caplog.messages) == 1 - assert caplog.messages[0] == ( + assert logger.warning.called + assert logger.warning.call_args[0][0] == ( "Invalid configuration value found: 'language = None'. " "Update your configuration to a valid langauge code. " "Falling back to 'en' (English).") - assert caplog.records[0].levelname == "WARNING" def test_conf_py_no_language(tempdir):