Add InventoryFile.dump()

This commit is contained in:
Takeshi KOMIYA 2017-03-02 23:48:05 +09:00
parent 29254c15f1
commit c1a70397e1
3 changed files with 67 additions and 26 deletions

View File

@ -31,6 +31,7 @@ from docutils.readers.doctree import Reader as DoctreeReader
from sphinx import package_dir, __display_version__ from sphinx import package_dir, __display_version__
from sphinx.util import jsonimpl, logging, status_iterator from sphinx.util import jsonimpl, logging, status_iterator
from sphinx.util.i18n import format_date from sphinx.util.i18n import format_date
from sphinx.util.inventory import InventoryFile
from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \ from sphinx.util.osutil import SEP, os_path, relative_uri, ensuredir, \
movefile, copyfile movefile, copyfile
from sphinx.util.nodes import inline_all_toctrees from sphinx.util.nodes import inline_all_toctrees
@ -896,33 +897,8 @@ class StandaloneHTMLBuilder(Builder):
def dump_inventory(self): def dump_inventory(self):
# type: () -> None # type: () -> None
def safe_name(string):
return re.sub("\s+", " ", string)
logger.info(bold('dumping object inventory... '), nonl=True) logger.info(bold('dumping object inventory... '), nonl=True)
with open(path.join(self.outdir, INVENTORY_FILENAME), 'wb') as f: InventoryFile.dump(path.join(self.outdir, INVENTORY_FILENAME), self.env, self)
f.write((u'# Sphinx inventory version 2\n'
u'# Project: %s\n'
u'# Version: %s\n'
u'# The remainder of this file is compressed using zlib.\n'
% (safe_name(self.config.project),
safe_name(self.config.version))).encode('utf-8'))
compressor = zlib.compressobj(9)
for domainname, domain in sorted(self.env.domains.items()):
for name, dispname, type, docname, anchor, prio in \
sorted(domain.get_objects()):
if anchor.endswith(name):
# this can shorten the inventory by as much as 25%
anchor = anchor[:-len(name)] + '$'
uri = self.get_target_uri(docname)
if anchor:
uri += '#' + anchor
if dispname == name:
dispname = u'-'
f.write(compressor.compress(
(u'%s %s:%s %s %s %s\n' % (name, domainname, type,
prio, uri, dispname)).encode('utf-8')))
f.write(compressor.flush())
logger.info('done') logger.info('done')
def dump_search_index(self): def dump_search_index(self):

View File

@ -9,11 +9,14 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
import re import re
import os
import zlib import zlib
import codecs import codecs
from six import PY3 from six import PY3
from sphinx.util import logging
if False: if False:
# For type annotation # For type annotation
from typing import Callable, Dict, IO, Iterator, Tuple # NOQA from typing import Callable, Dict, IO, Iterator, Tuple # NOQA
@ -27,6 +30,8 @@ if False:
BUFSIZE = 16 * 1024 BUFSIZE = 16 * 1024
UTF8StreamReader = codecs.lookup('utf-8')[2] UTF8StreamReader = codecs.lookup('utf-8')[2]
logger = logging.getLogger(__name__)
class ZlibReader(object): class ZlibReader(object):
"""Compressed file reader.""" """Compressed file reader."""
@ -121,3 +126,35 @@ class InventoryFile(object):
invdata.setdefault(type, {})[name] = (projname, version, invdata.setdefault(type, {})[name] = (projname, version,
location, dispname) location, dispname)
return invdata return invdata
@classmethod
def dump(cls, filename, env, builder):
# type: (unicode, BuildEnvironment, Builder) -> None
def escape(string):
# type: (unicode) -> unicode
return re.sub("\s+", " ", string).encode('utf-8')
with open(os.path.join(filename), 'wb') as f:
# header
f.write('# Sphinx inventory version 2\n')
f.write('# Project: %s\n' % escape(env.config.project))
f.write('# Version: %s\n' % escape(env.config.version))
f.write('# The remainder of this file is compressed using zlib.\n')
# body
compressor = zlib.compressobj(9)
for domainname, domain in sorted(env.domains.items()):
for name, dispname, typ, docname, anchor, prio in \
sorted(domain.get_objects()):
if anchor.endswith(name):
# this can shorten the inventory by as much as 25%
anchor = anchor[:-len(name)] + '$'
uri = builder.get_target_uri(docname)
if anchor:
uri += '#' + anchor
if dispname == name:
dispname = u'-'
entry = (u'%s %s:%s %s %s %s\n' %
(name, domainname, typ, prio, uri, dispname))
f.write(compressor.compress(entry.encode('utf-8')))
f.write(compressor.flush())

View File

@ -16,6 +16,8 @@ from itertools import cycle, chain
from six import PY3 from six import PY3
from sphinx import __display_version__ from sphinx import __display_version__
from sphinx.util.inventory import InventoryFile
from util import remove_unicode_literals, strip_escseq from util import remove_unicode_literals, strip_escseq
import xml.etree.cElementTree as ElementTree import xml.etree.cElementTree as ElementTree
from html5lib import getTreeBuilder, HTMLParser from html5lib import getTreeBuilder, HTMLParser
@ -1149,3 +1151,29 @@ def test_html_entity(app):
content = (app.outdir / 'index.html').text() content = (app.outdir / 'index.html').text()
for entity in re.findall(r'&([a-z]+);', content, re.M): for entity in re.findall(r'&([a-z]+);', content, re.M):
assert entity not in valid_entities assert entity not in valid_entities
@pytest.mark.sphinx('html', testroot='basic')
def test_html_inventory(app):
app.builder.build_all()
with open(app.outdir / 'objects.inv') as f:
invdata = InventoryFile.load(f, 'http://example.com', os.path.join)
assert invdata.keys() == ['std:label', 'std:doc']
assert invdata['std:label'].keys() == ['modindex', 'genindex', 'search']
assert invdata['std:label']['modindex'] == ('Python',
'',
'http://example.com/py-modindex.html',
'Module Index')
assert invdata['std:label']['genindex'] == ('Python',
'',
'http://example.com/genindex.html',
'Index')
assert invdata['std:label']['search'] == ('Python',
'',
'http://example.com/search.html',
'Search Page')
assert invdata['std:doc'].keys() == ['index']
assert invdata['std:doc']['index'] == ('Python',
'',
'http://example.com/index.html',
'The basic Sphinx documentation for testing')