diff --git a/sphinx/config.py b/sphinx/config.py index 0c0cad1fc..daa81f17e 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -395,8 +395,8 @@ def convert_source_suffix(app, config): # if dict, convert it to OrderedDict config.source_suffix = OrderedDict(config.source_suffix) # type: ignore else: - logger.warning(__("The config value `source_suffix' expected to " - "a string, list of strings or dictionary. " + logger.warning(__("The config value `source_suffix' expects " + "a string, list of strings, or dictionary. " "But `%r' is given." % source_suffix)) @@ -463,11 +463,16 @@ def check_confval_types(app, config): continue # at least we share a non-trivial base class if annotations: - msg = __("The config value `{name}' has type `{current.__name__}', " - "expected to {permitted}.") + msg = __("The config value `{name}' has type `{current.__name__}'; " + "expected {permitted}.") + wrapped_annotations = ["`{}'".format(c.__name__) for c in annotations] + if len(wrapped_annotations) > 2: + permitted = ", ".join(wrapped_annotations[:-1]) + ", or " + wrapped_annotations[-1] + else: + permitted = " or ".join(wrapped_annotations) logger.warning(msg.format(name=confval.name, current=type(confval.value), - permitted=str([c.__name__ for c in annotations]))) + permitted=permitted)) else: msg = __("The config value `{name}' has type `{current.__name__}', " "defaults to `{default.__name__}'.") diff --git a/tests/test_config.py b/tests/test_config.py index bf69c40e5..f8df52863 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -247,6 +247,27 @@ def test_check_types(logger, name, default, annotation, actual, warned): assert logger.warning.called == warned +TYPECHECK_WARNING_MESSAGES = [ + ('value1', 'string', [str], ['foo', 'bar'], + "The config value `value1' has type `list'; expected `str'."), + ('value1', 'string', [str, int], ['foo', 'bar'], + "The config value `value1' has type `list'; expected `str' or `int'."), + ('value1', 'string', [str, int, tuple], ['foo', 'bar'], + "The config value `value1' has type `list'; expected `str', `int', or `tuple'."), +] + + +@mock.patch("sphinx.config.logger") +@pytest.mark.parametrize("name,default,annotation,actual,message", TYPECHECK_WARNING_MESSAGES) +def test_conf_warning_message(logger, name, default, annotation, actual, message): + config = Config({name: actual}) + config.add(name, default, False, annotation or ()) + config.init_values() + check_confval_types(None, config) + logger.warning.assert_called() + assert logger.warning.call_args[0][0] == message + + @mock.patch("sphinx.config.logger") def test_check_enum(logger): config = Config()