From 556f599e6ec343e2594b39f55d72d651a64e2458 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 4 Nov 2018 20:22:50 +0900 Subject: [PATCH] intersphinx: Normalize mapping on config-inited --- sphinx/ext/intersphinx.py | 51 +++++++++++++++++++---------------- tests/test_ext_intersphinx.py | 11 +++++++- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index 81c4da726..fc2a525f7 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -204,28 +204,7 @@ def load_mappings(app): cache_time = now - app.config.intersphinx_cache_limit * 86400 inventories = InventoryAdapter(app.builder.env) update = False - for key, value in app.config.intersphinx_mapping.items(): - name = None # type: str - uri = None # type: str - inv = None # type: Union[str, Tuple[str, ...]] - - if isinstance(value, (list, tuple)): - # new format - name, (uri, inv) = key, value - if not isinstance(name, str): - logger.warning(__('intersphinx identifier %r is not string. Ignored'), name) - continue - else: - # old format, no name - name, uri, inv = None, key, value - # we can safely assume that the uri<->inv mapping is not changed - # during partial rebuilds since a changed intersphinx_mapping - # setting will cause a full environment reread - if not isinstance(inv, tuple): - invs = (inv, ) - else: - invs = inv # type: ignore - + for key, (name, (uri, invs)) in app.config.intersphinx_mapping.items(): failures = [] for inv in invs: if not inv: @@ -358,13 +337,39 @@ def missing_reference(app, env, node, contnode): return None +def normalize_intersphinx_mapping(app, config): + # type: (Sphinx, Config) -> None + for key, value in config.intersphinx_mapping.copy().items(): + try: + if isinstance(value, (list, tuple)): + # new format + name, (uri, inv) = key, value + if not isinstance(name, str): + logger.warning(__('intersphinx identifier %r is not string. Ignored'), + name) + config.intersphinx_mapping.pop(key) + continue + else: + # old format, no name + name, uri, inv = None, key, value + + if not isinstance(inv, tuple): + config.intersphinx_mapping[key] = (name, (uri, (inv,))) + else: + config.intersphinx_mapping[key] = (name, (uri, inv)) + except Exception as exc: + logger.warning(__('Fail to read intersphinx_mapping[%s], Ignored: %r'), key, exc) + config.intersphinx_mapping.pop(key) + + def setup(app): # type: (Sphinx) -> Dict[str, Any] app.add_config_value('intersphinx_mapping', {}, True) app.add_config_value('intersphinx_cache_limit', 5, False) app.add_config_value('intersphinx_timeout', None, False) - app.connect('missing-reference', missing_reference) + app.connect('config-inited', normalize_intersphinx_mapping) app.connect('builder-inited', load_mappings) + app.connect('missing-reference', missing_reference) return { 'version': sphinx.__display_version__, 'env_version': 1, diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py index b1f4d03af..e81101300 100644 --- a/tests/test_ext_intersphinx.py +++ b/tests/test_ext_intersphinx.py @@ -20,7 +20,7 @@ from test_util_inventory import inventory_v2, inventory_v2_not_having_version from sphinx import addnodes from sphinx.ext.intersphinx import ( - load_mappings, missing_reference, _strip_basic_auth, + load_mappings, missing_reference, normalize_intersphinx_mapping, _strip_basic_auth, _get_safe_url, fetch_inventory, INVENTORY_FILENAME, inspect_main ) from sphinx.ext.intersphinx import setup as intersphinx_setup @@ -99,6 +99,7 @@ def test_missing_reference(tempdir, app, status, warning): app.config.intersphinx_cache_limit = 0 # load the inventory and check if it's done correctly + normalize_intersphinx_mapping(app, app.config) load_mappings(app) inv = app.env.intersphinx_inventory @@ -174,6 +175,7 @@ def test_missing_reference_pydomain(tempdir, app, status, warning): app.config.intersphinx_cache_limit = 0 # load the inventory and check if it's done correctly + normalize_intersphinx_mapping(app, app.config) load_mappings(app) # no context data @@ -198,6 +200,7 @@ def test_missing_reference_stddomain(tempdir, app, status, warning): app.config.intersphinx_cache_limit = 0 # load the inventory and check if it's done correctly + normalize_intersphinx_mapping(app, app.config) load_mappings(app) # no context data @@ -229,6 +232,7 @@ def test_missing_reference_cppdomain(tempdir, app, status, warning): app.config.intersphinx_cache_limit = 0 # load the inventory and check if it's done correctly + normalize_intersphinx_mapping(app, app.config) load_mappings(app) app.build() @@ -255,6 +259,7 @@ def test_missing_reference_jsdomain(tempdir, app, status, warning): app.config.intersphinx_cache_limit = 0 # load the inventory and check if it's done correctly + normalize_intersphinx_mapping(app, app.config) load_mappings(app) # no context data @@ -280,6 +285,7 @@ def test_inventory_not_having_version(tempdir, app, status, warning): app.config.intersphinx_cache_limit = 0 # load the inventory and check if it's done correctly + normalize_intersphinx_mapping(app, app.config) load_mappings(app) rn = reference_check(app, 'py', 'mod', 'module1', 'foo') @@ -307,6 +313,7 @@ def test_load_mappings_warnings(tempdir, app, status, warning): app.config.intersphinx_cache_limit = 0 # load the inventory and check if it's done correctly + normalize_intersphinx_mapping(app, app.config) load_mappings(app) assert warning.getvalue().count('\n') == 1 @@ -320,6 +327,7 @@ def test_load_mappings_fallback(tempdir, app, status, warning): app.config.intersphinx_mapping = { 'fallback': ('https://docs.python.org/py3k/', '/invalid/inventory/path'), } + normalize_intersphinx_mapping(app, app.config) load_mappings(app) assert "failed to reach any of the inventories" in warning.getvalue() @@ -335,6 +343,7 @@ def test_load_mappings_fallback(tempdir, app, status, warning): 'fallback': ('https://docs.python.org/py3k/', ('/invalid/inventory/path', inv_file)), } + normalize_intersphinx_mapping(app, app.config) load_mappings(app) assert "encountered some issues with some of the inventories" in status.getvalue() assert "" == warning.getvalue()