Example #1
0
def write_example(src_name, src_dir, rst_dir, cfg):
    """Write rst file from a given python example.

    Parameters
    ----------
    src_name : str
        Name of example file.
    src_dir : 'str'
        Source directory for python examples.
    rst_dir : 'str'
        Destination directory for rst files generated from python examples.
    cfg : config object
        Sphinx config object created by Sphinx.
    """
    last_dir = src_dir.psplit()[-1]
    # to avoid leading . in file names, and wrong names in links
    if last_dir == '.' or last_dir == 'examples':
        last_dir = Path('')
    else:
        last_dir += '_'

    src_path = src_dir.pjoin(src_name)
    example_file = rst_dir.pjoin(src_name)
    shutil.copyfile(src_path, example_file)

    image_dir = rst_dir.pjoin('images')
    thumb_dir = image_dir.pjoin('thumb')
    notebook_dir = rst_dir.pjoin('notebook')
    image_dir.makedirs()
    thumb_dir.makedirs()
    notebook_dir.makedirs()

    base_image_name = os.path.splitext(src_name)[0]
    image_path = image_dir.pjoin(base_image_name + '_{0}.png')

    basename, py_ext = os.path.splitext(src_name)

    rst_path = rst_dir.pjoin(basename + cfg.source_suffix_str)
    notebook_path = notebook_dir.pjoin(basename + '.ipynb')

    if _plots_are_current(src_path, image_path) and rst_path.exists and \
        notebook_path.exists:
        return

    print('plot2rst: %s' % basename)

    blocks = split_code_and_text_blocks(example_file)
    if blocks[0][2].startswith('#!'):
        blocks.pop(0) # don't add shebang line to rst file.

    rst_link = '.. _example_%s:\n\n' % (last_dir + src_name)
    figure_list, rst = process_blocks(blocks, src_path, image_path, cfg)

    has_inline_plots = any(cfg.plot2rst_plot_tag in b[2] for b in blocks)
    if has_inline_plots:
        example_rst = ''.join([rst_link, rst])
    else:
        # print first block of text, display all plots, then display code.
        first_text_block = [b for b in blocks if b[0] == 'text'][0]
        label, (start, end), content = first_text_block
        figure_list = save_all_figures(image_path)
        rst_blocks = [IMAGE_TEMPLATE % f.lstrip('/') for f in figure_list]

        example_rst = rst_link
        example_rst += eval(content)
        example_rst += ''.join(rst_blocks)
        code_info = dict(src_name=src_name, code_start=end)
        example_rst += LITERALINCLUDE.format(**code_info)

    example_rst += CODE_LINK.format(src_name)
    ipnotebook_name = src_name.replace('.py', '.ipynb')
    ipnotebook_name = './notebook/' + ipnotebook_name
    example_rst += NOTEBOOK_LINK.format(ipnotebook_name)

    with open(rst_path, 'w') as f:
        f.write(example_rst)

    thumb_path = thumb_dir.pjoin(src_name[:-3] + '.png')
    first_image_file = image_dir.pjoin(figure_list[0].lstrip('/'))
    if first_image_file.exists:
        first_image = io.imread(first_image_file)
        save_thumbnail(first_image, thumb_path, cfg.plot2rst_thumb_shape)

    if not thumb_path.exists:
        if cfg.plot2rst_default_thumb is None:
            print("WARNING: No plots found and default thumbnail not defined.")
            print("Specify 'plot2rst_default_thumb' in Sphinx config file.")
        else:
            shutil.copy(cfg.plot2rst_default_thumb, thumb_path)

    # Export example to IPython notebook
    nb = Notebook()

    # Add sphinx roles to the examples, otherwise docutils
    # cannot compile the ReST for the notebook
    sphinx_roles = PythonDomain.roles.keys()
    preamble = '\n'.join(f'.. role:: py:{role}(literal)\n'
                         for role in sphinx_roles)

    # Grab all references to inject them in cells where needed
    ref_regexp = re.compile('\n(\\.\\. \\[(\\d+)\\].*(?:\n[ ]{7,8}.*)+)')
    math_role_regexp = re.compile(':math:`(.*?)`')

    text = '\n'.join((content for (cell_type, _, content) in blocks
                     if cell_type != 'code'))

    references = re.findall(ref_regexp, text)

    for (cell_type, _, content) in blocks:
        if cell_type == 'code':
            nb.add_cell(content, cell_type='code')
        else:
            if content.startswith('r'):
                content = content.replace('r"""', '')
                escaped = False
            else:
                content = content.replace('"""', '')
                escaped = True

            if not escaped:
                content = content.replace("\\", "\\\\")

            content = content.replace('.. seealso::', '**See also:**')
            content = re.sub(math_role_regexp, r'$\1$', content)

            # Remove math directive when rendering notebooks
            # until we implement a smarter way of capturing and replacing
            # its content
            content = content.replace('.. math::', '')

            if not content.strip():
                continue

            content = (preamble + content).rstrip('\n')
            content = '\n'.join([line for line in content.split('\n') if
                                 not line.startswith('.. image')])

            # Remove reference links until we can figure out a better way to
            # preserve them
            for (reference, ref_id) in references:
                ref_tag = f'[{ref_id}]_'
                if ref_tag in content:
                    content = content.replace(ref_tag, ref_tag[:-1])

            html = publish_parts(content, writer_name='html')['html_body']
            nb.add_cell(html, cell_type='markdown')

    with open(notebook_path, 'w') as f:
        f.write(nb.json())
Example #2
0
def write_example(src_name, src_dir, rst_dir, cfg):
    """Write rst file from a given python example.

    Parameters
    ----------
    src_name : str
        Name of example file.
    src_dir : 'str'
        Source directory for python examples.
    rst_dir : 'str'
        Destination directory for rst files generated from python examples.
    cfg : config object
        Sphinx config object created by Sphinx.
    """
    last_dir = src_dir.psplit()[-1]
    # to avoid leading . in file names, and wrong names in links
    if last_dir == '.' or last_dir == 'examples':
        last_dir = Path('')
    else:
        last_dir += '_'

    src_path = src_dir.pjoin(src_name)
    example_file = rst_dir.pjoin(src_name)
    shutil.copyfile(src_path, example_file)

    image_dir = rst_dir.pjoin('images')
    thumb_dir = image_dir.pjoin('thumb')
    notebook_dir = rst_dir.pjoin('notebook')
    image_dir.makedirs()
    thumb_dir.makedirs()
    notebook_dir.makedirs()

    base_image_name = os.path.splitext(src_name)[0]
    image_path = image_dir.pjoin(base_image_name + '_{0}.png')

    basename, py_ext = os.path.splitext(src_name)

    rst_path = rst_dir.pjoin(basename + cfg.source_suffix_str)
    notebook_path = notebook_dir.pjoin(basename + '.ipynb')

    if _plots_are_current(src_path, image_path) and rst_path.exists and \
        notebook_path.exists:
        return

    print('plot2rst: %s' % basename)

    blocks = split_code_and_text_blocks(example_file)
    if blocks[0][2].startswith('#!'):
        blocks.pop(0) # don't add shebang line to rst file.

    rst_link = '.. _example_%s:\n\n' % (last_dir + src_name)
    figure_list, rst = process_blocks(blocks, src_path, image_path, cfg)

    has_inline_plots = any(cfg.plot2rst_plot_tag in b[2] for b in blocks)
    if has_inline_plots:
        example_rst = ''.join([rst_link, rst])
    else:
        # print first block of text, display all plots, then display code.
        first_text_block = [b for b in blocks if b[0] == 'text'][0]
        label, (start, end), content = first_text_block
        figure_list = save_all_figures(image_path)
        rst_blocks = [IMAGE_TEMPLATE % f.lstrip('/') for f in figure_list]

        example_rst = rst_link
        example_rst += eval(content)
        example_rst += ''.join(rst_blocks)
        code_info = dict(src_name=src_name, code_start=end)
        example_rst += LITERALINCLUDE.format(**code_info)

    example_rst += CODE_LINK.format(src_name)
    ipnotebook_name = src_name.replace('.py', '.ipynb')
    ipnotebook_name = './notebook/' + ipnotebook_name
    example_rst += NOTEBOOK_LINK.format(ipnotebook_name)

    with open(rst_path, 'w') as f:
        f.write(example_rst)

    thumb_path = thumb_dir.pjoin(src_name[:-3] + '.png')
    first_image_file = image_dir.pjoin(figure_list[0].lstrip('/'))
    if first_image_file.exists:
        first_image = io.imread(first_image_file)
        save_thumbnail(first_image, thumb_path, cfg.plot2rst_thumb_shape)

    if not thumb_path.exists:
        if cfg.plot2rst_default_thumb is None:
            print("WARNING: No plots found and default thumbnail not defined.")
            print("Specify 'plot2rst_default_thumb' in Sphinx config file.")
        else:
            shutil.copy(cfg.plot2rst_default_thumb, thumb_path)

    # Export example to IPython notebook
    nb = Notebook()

    # Add sphinx roles to the examples, otherwise docutils
    # cannot compile the ReST for the notebook
    sphinx_roles = PythonDomain.roles.keys()
    preamble = '\n'.join('.. role:: py:{0}(literal)\n'.format(role)
                         for role in sphinx_roles)

    # Grab all references to inject them in cells where needed
    ref_regexp = re.compile('\n(\.\. \[(\d+)\].*(?:\n[ ]{7,8}.*)+)')
    math_role_regexp = re.compile(':math:`(.*?)`')

    text = '\n'.join((content for (cell_type, _, content) in blocks
                     if cell_type != 'code'))

    references = re.findall(ref_regexp, text)

    for (cell_type, _, content) in blocks:
        if cell_type == 'code':
            nb.add_cell(content, cell_type='code')
        else:
            if content.startswith('r'):
                content = content.replace('r"""', '')
                escaped = False
            else:
                content = content.replace('"""', '')
                escaped = True

            if not escaped:
                content = content.replace("\\", "\\\\")

            content = content.replace('.. seealso::', '**See also:**')
            content = re.sub(math_role_regexp, r'$\1$', content)

            # Remove math directive when rendering notebooks
            # until we implement a smarter way of capturing and replacing
            # its content
            content = content.replace('.. math::', '')

            if not content.strip():
                continue

            content = (preamble + content).rstrip('\n')
            content = '\n'.join([line for line in content.split('\n') if
                                 not line.startswith('.. image')])

            # Remove reference links until we can figure out a better way to
            # preserve them
            for (reference, ref_id) in references:
                ref_tag = '[{0}]_'.format(ref_id)
                if ref_tag in content:
                    content = content.replace(ref_tag, ref_tag[:-1])

            html = publish_parts(content, writer_name='html')['html_body']
            nb.add_cell(html, cell_type='markdown')

    with open(notebook_path, 'w') as f:
        f.write(nb.json())