def on_doctree_read(app, document):
literal_blocks = uqbar.book.sphinx.collect_literal_blocks(document)<EOL>cache_mapping = uqbar.book.sphinx.group_literal_blocks_by_cache_path(literal_blocks)<EOL>node_mapping = {}<EOL>use_cache = bool(app.config["<STR_LIT>"])<EOL>for cache_path, literal_block_groups in cache_mapping.items():<EOL><INDENT>kwargs = dict(<EOL>extensions=app.uqbar_book_extensions,<EOL>setup_lines=app.config["<STR_LIT>"],<EOL>teardown_lines=app.config["<STR_LIT>"],<EOL>use_black=bool(app.config["<STR_LIT>"]),<EOL>)<EOL>for literal_blocks in literal_block_groups:<EOL><INDENT>try:<EOL><INDENT>if use_cache:<EOL><INDENT>local_node_mapping = uqbar.book.sphinx.interpret_code_blocks_with_cache(<EOL>literal_blocks, cache_path, app.connection, **kwargs<EOL>)<EOL><DEDENT>else:<EOL><INDENT>local_node_mapping = uqbar.book.sphinx.interpret_code_blocks(<EOL>literal_blocks, **kwargs<EOL>)<EOL><DEDENT>node_mapping.update(local_node_mapping)<EOL><DEDENT>except ConsoleError as exception:<EOL><INDENT>message = exception.args[<NUM_LIT:0>].splitlines()[-<NUM_LIT:1>]<EOL>logger.warning(message, location=exception.args[<NUM_LIT:1>])<EOL>if app.config["<STR_LIT>"]:<EOL><INDENT>raise<EOL><DEDENT><DEDENT><DEDENT><DEDENT>uqbar.book.sphinx.rebuild_document(document, node_mapping)<EOL>
Hooks into Sphinx's ``doctree-read`` event.