diff --git a/tests/roots/test-config/conf.py b/tests/roots/test-config/conf.py index 4c2ea9fc5..0027d87f2 100644 --- a/tests/roots/test-config/conf.py +++ b/tests/roots/test-config/conf.py @@ -1,54 +1,3 @@ -from sphinx.config import string_classes, ENUM - -value1 = 123 # wrong type -value2 = 123 # lambda with wrong type -value3 = [] # lambda with correct type -value4 = True # child type -value5 = 3 # parent type -value6 = () # other sequence type, also raises -value7 = ['foo'] # explicitly permitted - - -class A(object): - pass - - -class B(A): - pass - - -class C(A): - pass - - -value8 = C() # sibling type - -# both have no default or permissible types -value9 = 'foo' -value10 = 123 -value11 = u'bar' -value12 = u'bar' -value13 = 'bar' -value14 = u'bar' -value15 = 'bar' -value16 = u'bar' - - -def setup(app): - app.add_config_value('value1', 'string', False) - app.add_config_value('value2', lambda conf: [], False) - app.add_config_value('value3', [], False) - app.add_config_value('value4', 100, False) - app.add_config_value('value5', False, False) - app.add_config_value('value6', [], False) - app.add_config_value('value7', 'string', False, [list]) - app.add_config_value('value8', B(), False) - app.add_config_value('value9', None, False) - app.add_config_value('value10', None, False) - app.add_config_value('value11', None, False, [str]) - app.add_config_value('value12', 'string', False) - app.add_config_value('value13', None, False, string_classes) - app.add_config_value('value14', None, False, string_classes) - app.add_config_value('value15', u'unicode', False) - app.add_config_value('value16', u'unicode', False) - app.add_config_value('value17', 'default', False, ENUM('default', 'one', 'two')) +project = 'Sphinx ' +release = '0.6alpha1' +templates_path = ['_templates'] diff --git a/tests/test_config.py b/tests/test_config.py index 4775421d5..c3600ddca 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -11,15 +11,15 @@ """ import mock import pytest -from six import PY3, iteritems +from six import PY3 import sphinx -from sphinx.config import Config +from sphinx.config import Config, ENUM, string_classes from sphinx.errors import ExtensionError, ConfigError, VersionRequirementError from sphinx.testing.path import path -@pytest.mark.sphinx(confoverrides={ +@pytest.mark.sphinx(testroot='config', confoverrides={ 'master_doc': 'master', 'nonexisting_value': 'True', 'latex_elements.docclass': 'scrartcl', @@ -91,6 +91,30 @@ def test_extension_values(app, status, warning): assert 'already present' in str(excinfo.value) +def test_overrides(): + config = Config({'value1': '1', 'value2': 2, 'value6': {'default': 6}}, + {'value2': 999, 'value3': '999', 'value5.attr1': 999, 'value6.attr1': 999, + 'value7': 'abc,def,ghi', 'value8': 'abc,def,ghi'}) + config.add('value1', None, 'env', ()) + config.add('value2', None, 'env', ()) + config.add('value3', 0, 'env', ()) + config.add('value4', 0, 'env', ()) + config.add('value5', {'default': 0}, 'env', ()) + config.add('value6', {'default': 0}, 'env', ()) + config.add('value7', None, 'env', ()) + config.add('value8', [], 'env', ()) + config.init_values() + + assert config.value1 == '1' + assert config.value2 == 999 + assert config.value3 == 999 + assert config.value4 == 0 + assert config.value5 == {'attr1': 999} + assert config.value6 == {'default': 6, 'attr1': 999} + assert config.value7 == 'abc,def,ghi' + assert config.value8 == ['abc', 'def', 'ghi'] + + @mock.patch("sphinx.config.logger") def test_errors_warnings(logger, tempdir): # test the error for syntax errors in the config file @@ -195,60 +219,81 @@ def test_builtin_conf(app, status, warning): 'warning') -# See roots/test-config/conf.py. -TYPECHECK_WARNINGS = { - 'value1': True, - 'value2': True, - 'value3': False, - 'value4': True, - 'value5': False, - 'value6': True, - 'value7': False, - 'value8': False, - 'value9': False, - 'value10': False, - 'value11': False if PY3 else True, - 'value12': False, - 'value13': False, - 'value14': False, - 'value15': False, - 'value16': False, -} +# example classes for type checking +class A(object): + pass -@pytest.mark.parametrize("key,should", iteritems(TYPECHECK_WARNINGS)) -@pytest.mark.sphinx(testroot='config') -def test_check_types(warning, key, should): - warn = warning.getvalue() - if should: - assert key in warn, ( - 'override on "%s" should raise a type warning' % key - ) - else: - assert key not in warn, ( - 'override on "%s" should NOT raise a type warning' % key - ) +class B(A): + pass -@pytest.mark.sphinx(testroot='config') -def test_check_enum(app, status, warning): - assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \ - not in warning.getvalue() +class C(A): + pass -@pytest.mark.sphinx(testroot='config', confoverrides={'value17': 'invalid'}) -def test_check_enum_failed(app, status, warning): - assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \ - "but `invalid` is given." in warning.getvalue() +# name, default, annotation, actual, warned +TYPECHECK_WARNINGS = [ + ('value1', 'string', None, 123, True), # wrong type + ('value2', lambda _: [], None, 123, True), # lambda with wrong type + ('value3', lambda _: [], None, [], False), # lambda with correct type + ('value4', 100, None, True, True), # child type + ('value5', False, None, True, False), # parent type + ('value6', [], None, (), True), # other sequence type + ('value7', 'string', [list], ['foo'], False), # explicit type annotation + ('value8', B(), None, C(), False), # sibling type + ('value9', None, None, 'foo', False), # no default or no annotations + ('value10', None, None, 123, False), # no default or no annotations + ('value11', None, [str], u'bar', False if PY3 else True), # str vs unicode + ('value12', 'string', None, u'bar', False), # str vs unicode + ('value13', None, string_classes, 'bar', False), # string_classes + ('value14', None, string_classes, u'bar', False), # string_classes + ('value15', u'unicode', None, 'bar', False), # str vs unicode + ('value16', u'unicode', None, u'bar', False), # str vs unicode +] -@pytest.mark.sphinx(testroot='config', confoverrides={'value17': ['one', 'two']}) -def test_check_enum_for_list(app, status, warning): - assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \ - not in warning.getvalue() +@mock.patch("sphinx.config.logger") +@pytest.mark.parametrize("name,default,annotation,actual,warned", TYPECHECK_WARNINGS) +def test_check_types(logger, name, default, annotation, actual, warned): + config = Config({name: actual}) + config.add(name, default, 'env', annotation or ()) + config.init_values() + config.check_types() + assert logger.warning.called == warned -@pytest.mark.sphinx(testroot='config', confoverrides={'value17': ['one', 'two', 'invalid']}) -def test_check_enum_for_list_failed(app, status, warning): - assert "The config value `value17` has to be a one of ('default', 'one', 'two'), " \ - "but `['one', 'two', 'invalid']` is given." in warning.getvalue() +@mock.patch("sphinx.config.logger") +def test_check_enum(logger): + config = Config() + config.add('value', 'default', False, ENUM('default', 'one', 'two')) + config.init_values() + config.check_types() + logger.warning.assert_not_called() # not warned + + +@mock.patch("sphinx.config.logger") +def test_check_enum_failed(logger): + config = Config({'value': 'invalid'}) + config.add('value', 'default', False, ENUM('default', 'one', 'two')) + config.init_values() + config.check_types() + logger.warning.assert_called() + + +@mock.patch("sphinx.config.logger") +def test_check_enum_for_list(logger): + config = Config({'value': ['one', 'two']}) + config.add('value', 'default', False, ENUM('default', 'one', 'two')) + config.init_values() + config.check_types() + logger.warning.assert_not_called() # not warned + + +@mock.patch("sphinx.config.logger") +def test_check_enum_for_list_failed(logger): + config = Config({'value': ['one', 'two', 'invalid']}) + config.add('value', 'default', False, ENUM('default', 'one', 'two')) + config.init_values() + config.check_types() + logger.warning.assert_called()