diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index 16a487ef8..5e035ece1 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -125,6 +125,14 @@ def read_inventory_v2(f, uri, join, bufsize=16*1024): return invdata +def read_inventory(f, uri, join, bufsize=16*1024): + line = f.readline().rstrip().decode('utf-8') + if line == '# Sphinx inventory version 1': + return read_inventory_v1(f, uri, join) + elif line == '# Sphinx inventory version 2': + return read_inventory_v2(f, uri, join, bufsize=bufsize) + + def _strip_basic_auth(url): """Returns *url* with basic auth credentials removed. Also returns the basic auth username and password if they're present in *url*. @@ -227,7 +235,6 @@ def fetch_inventory(app, uri, inv): if not localuri: # case: inv URI points to remote resource; strip any existing auth uri, _, _ = _strip_basic_auth(uri) - join = localuri and path.join or posixpath.join try: if '://' in inv: f = _read_from_url(inv) @@ -245,18 +252,12 @@ def fetch_inventory(app, uri, inv): if uri in (inv, path.dirname(inv), path.dirname(inv) + '/'): uri = path.dirname(newinv) - line = f.readline().rstrip().decode('utf-8') - try: - if line == '# Sphinx inventory version 1': - invdata = read_inventory_v1(f, uri, join) - elif line == '# Sphinx inventory version 2': - invdata = read_inventory_v2(f, uri, join) - else: - raise ValueError - f.close() - except ValueError: - f.close() - raise ValueError('unknown or unsupported inventory version') + with f: + try: + join = localuri and path.join or posixpath.join + invdata = read_inventory(f, uri, join) + except ValueError: + raise ValueError('unknown or unsupported inventory version') except Exception as err: app.warn('intersphinx inventory %r not readable due to ' '%s: %s' % (inv, err.__class__.__name__, err)) diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py index 334d53971..ebbf76fca 100644 --- a/tests/test_ext_intersphinx.py +++ b/tests/test_ext_intersphinx.py @@ -17,7 +17,7 @@ from six import BytesIO from docutils import nodes from sphinx import addnodes -from sphinx.ext.intersphinx import read_inventory_v1, read_inventory_v2, \ +from sphinx.ext.intersphinx import read_inventory, \ load_mappings, missing_reference, _strip_basic_auth, _read_from_url, \ _get_safe_url, fetch_inventory, INVENTORY_FILENAME @@ -49,8 +49,7 @@ a term including:colon std:term -1 glossary.html#term-a-term-including-colon - def test_read_inventory_v1(): f = BytesIO(inventory_v1) - f.readline() - invdata = read_inventory_v1(f, '/util', posixpath.join) + invdata = read_inventory(f, '/util', posixpath.join) assert invdata['py:module']['module'] == \ ('foo', '1.0', '/util/foo.html#module-module', '-') assert invdata['py:class']['module.cls'] == \ @@ -59,13 +58,11 @@ def test_read_inventory_v1(): def test_read_inventory_v2(): f = BytesIO(inventory_v2) - f.readline() - invdata1 = read_inventory_v2(f, '/util', posixpath.join) + invdata1 = read_inventory(f, '/util', posixpath.join) # try again with a small buffer size to test the chunking algorithm f = BytesIO(inventory_v2) - f.readline() - invdata2 = read_inventory_v2(f, '/util', posixpath.join, bufsize=5) + invdata2 = read_inventory(f, '/util', posixpath.join, bufsize=5) assert invdata1 == invdata2