Ejemplo n.º 1
0
def test_save_matplotlib_figures(gallery_conf, ext):
    """Test matplotlib figure save"""
    if ext == 'svg':
        gallery_conf['image_scrapers'] = (matplotlib_svg_scraper(),)
    import matplotlib.pyplot as plt  # nest these so that Agg can be set
    plt.plot(1, 1)
    fname_template = os.path.join(gallery_conf['gallery_dir'], 'image{0}.png')
    image_path_iterator = ImagePathIterator(fname_template)
    block = ('',) * 3
    block_vars = dict(image_path_iterator=image_path_iterator)
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(image_path_iterator) == 1
    fname = '/image1.{0}'.format(ext)
    assert fname in image_rst
    fname = gallery_conf['gallery_dir'] + fname
    assert os.path.isfile(fname)

    # Test capturing 2 images with shifted start number
    image_path_iterator.next()
    image_path_iterator.next()
    plt.plot(1, 1)
    plt.figure()
    plt.plot(1, 1)
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(image_path_iterator) == 5
    for ii in range(4, 6):
        fname = '/image{0}.{1}'.format(ii, ext)
        assert fname in image_rst
        fname = gallery_conf['gallery_dir'] + fname
        assert os.path.isfile(fname)
Ejemplo n.º 2
0
def test_save_matplotlib_figures(gallery_conf, ext, req_mpl, req_pil):
    """Test matplotlib figure save."""
    if ext == 'svg':
        gallery_conf['image_scrapers'] = (matplotlib_svg_scraper(),)
    import matplotlib.pyplot as plt  # nest these so that Agg can be set
    plt.plot(1, 1)
    fname_template = os.path.join(gallery_conf['gallery_dir'], 'image{0}.png')
    image_path_iterator = ImagePathIterator(fname_template)
    block = ('',) * 3
    block_vars = dict(image_path_iterator=image_path_iterator)
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(image_path_iterator) == 1
    fname = '/image1.{0}'.format(ext)
    assert fname in image_rst
    fname = gallery_conf['gallery_dir'] + fname
    assert os.path.isfile(fname)

    # Test capturing 2 images with shifted start number
    image_path_iterator.next()
    image_path_iterator.next()
    plt.plot(1, 1)
    plt.figure()
    plt.plot(1, 1)
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(image_path_iterator) == 5
    for ii in range(4, 6):
        fname = '/image{0}.{1}'.format(ii, ext)
        assert fname in image_rst
        fname = gallery_conf['gallery_dir'] + fname
        assert os.path.isfile(fname)
Ejemplo n.º 3
0
def test_save_mayavi_figures(gallery_conf, req_mpl, req_pil):
    """Test file naming when saving figures. Requires mayavi."""
    Image = _get_image()
    try:
        from mayavi import mlab
    except ImportError:
        raise pytest.skip('Mayavi not installed')
    import matplotlib.pyplot as plt
    mlab.options.offscreen = True

    gallery_conf.update(
        image_scrapers=(matplotlib_scraper, mayavi_scraper))
    fname_template = os.path.join(gallery_conf['gallery_dir'], 'image{0}.png')
    image_path_iterator = ImagePathIterator(fname_template)
    block = ('',) * 3
    block_vars = dict(image_path_iterator=image_path_iterator)

    plt.axes([-0.1, -0.1, 1.2, 1.2])
    plt.pcolor([[0]], cmap='Greens')
    mlab.test_plot3d()
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(plt.get_fignums()) == 0
    assert len(image_path_iterator) == 2
    assert '/image0.png' not in image_rst
    assert '/image1.png' in image_rst
    assert '/image2.png' in image_rst
    assert '/image3.png' not in image_rst
    assert not os.path.isfile(fname_template.format(0))
    assert os.path.isfile(fname_template.format(1))
    assert os.path.isfile(fname_template.format(2))
    assert not os.path.isfile(fname_template.format(0))
    with Image.open(fname_template.format(1)) as img:
        pixels = np.asarray(img.convert("RGB"))
    assert (pixels == [247, 252, 245]).all()  # plt first

    # Test next-value handling, plus image_scrapers modification
    gallery_conf.update(image_scrapers=(matplotlib_scraper,))
    mlab.test_plot3d()
    plt.axes([-0.1, -0.1, 1.2, 1.2])
    plt.pcolor([[0]], cmap='Reds')
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(plt.get_fignums()) == 0
    assert len(image_path_iterator) == 3
    assert '/image1.png' not in image_rst
    assert '/image2.png' not in image_rst
    assert '/image3.png' in image_rst
    assert '/image4.png' not in image_rst
    assert not os.path.isfile(fname_template.format(0))
    for ii in range(3):
        assert os.path.isfile(fname_template.format(ii + 1))
    assert not os.path.isfile(fname_template.format(4))
    with Image.open(fname_template.format(3)) as img:
        pixels = np.asarray(img.convert("RGB"))
    assert (pixels == [255, 245, 240]).all()
Ejemplo n.º 4
0
def test_custom_scraper(gallery_conf, monkeypatch):
    """Test custom scrapers."""
    # Test the API contract for custom scrapers
    complete_args = (gallery_conf, gallery_conf['gallery_dir'], True, False)
    with monkeypatch.context() as m:
        m.setattr(sphinx_gallery,
                  '_get_sg_image_scraper',
                  lambda: _custom_func,
                  raising=False)
        for cust in (_custom_func, 'sphinx_gallery'):
            gallery_conf.update(image_scrapers=[cust])
            # smoke test that it works
            _complete_gallery_conf(*complete_args, check_keys=False)
    # degenerate
    # without the monkey patch to add sphinx_gallery._get_sg_image_scraper,
    # we should get an error
    gallery_conf.update(image_scrapers=['sphinx_gallery'])
    with pytest.raises(ConfigError,
                       match="has no attribute '_get_sg_image_scraper'"):
        _complete_gallery_conf(*complete_args, check_keys=False)

    # other degenerate conditions
    gallery_conf.update(image_scrapers=['foo'])
    with pytest.raises(ConfigError, match='Unknown image scraper'):
        _complete_gallery_conf(*complete_args, check_keys=False)
    gallery_conf.update(image_scrapers=[_custom_func])
    fname_template = os.path.join(gallery_conf['gallery_dir'], 'image{0}.png')
    image_path_iterator = ImagePathIterator(fname_template)
    block = ('', ) * 3
    block_vars = dict(image_path_iterator=image_path_iterator)
    with pytest.raises(ExtensionError, match='did not produce expected image'):
        save_figures(block, block_vars, gallery_conf)
    gallery_conf.update(image_scrapers=[lambda x, y, z: 1.])
    with pytest.raises(ExtensionError, match='was not a string'):
        save_figures(block, block_vars, gallery_conf)
    # degenerate string interface
    gallery_conf.update(image_scrapers=['sphinx_gallery'])
    with monkeypatch.context() as m:
        m.setattr(sphinx_gallery,
                  '_get_sg_image_scraper',
                  'foo',
                  raising=False)
        with pytest.raises(ConfigError, match='^Unknown image.*\n.*callable'):
            _complete_gallery_conf(*complete_args, check_keys=False)
    with monkeypatch.context() as m:
        m.setattr(sphinx_gallery,
                  '_get_sg_image_scraper',
                  lambda: 'foo',
                  raising=False)
        with pytest.raises(ConfigError, match='^Scraper.*was not callable'):
            _complete_gallery_conf(*complete_args, check_keys=False)
Ejemplo n.º 5
0
def test_custom_scraper(gallery_conf, monkeypatch):
    """Test custom scrapers."""
    # custom finders
    with monkeypatch.context() as m:
        m.setattr(sphinx_gallery,
                  '_get_sg_image_scraper',
                  lambda: _custom_func,
                  raising=False)
        for cust in (_custom_func, 'sphinx_gallery'):
            gallery_conf.update(image_scrapers=[cust])
            fname_template = os.path.join(gallery_conf['gallery_dir'],
                                          'image{0}.png')
            image_path_iterator = ImagePathIterator(fname_template)
            block = ('', ) * 3
            block_vars = dict(image_path_iterator=image_path_iterator)

    # degenerate
    gallery_conf.update(image_scrapers=['foo'])
    complete_args = (gallery_conf, gallery_conf['gallery_dir'], True, False)
    with pytest.raises(ValueError, match='Unknown image scraper'):
        _complete_gallery_conf(*complete_args)
    gallery_conf.update(
        image_scrapers=[lambda x, y, z: y['image_path_iterator'].next()])
    with pytest.raises(RuntimeError, match='did not produce expected image'):
        save_figures(block, block_vars, gallery_conf)
    gallery_conf.update(image_scrapers=[lambda x, y, z: 1.])
    with pytest.raises(TypeError, match='was not a string'):
        save_figures(block, block_vars, gallery_conf)
    # degenerate string interface
    gallery_conf.update(image_scrapers=['sphinx_gallery'])
    with monkeypatch.context() as m:
        m.setattr(sphinx_gallery,
                  '_get_sg_image_scraper',
                  'foo',
                  raising=False)
        with pytest.raises(ValueError, match='^Unknown image.*\n.*callable'):
            _complete_gallery_conf(*complete_args)
    with monkeypatch.context() as m:
        m.setattr(sphinx_gallery,
                  '_get_sg_image_scraper',
                  lambda: 'foo',
                  raising=False)
        with pytest.raises(ValueError, match='^Scraper.*was not callable'):
            _complete_gallery_conf(*complete_args)
Ejemplo n.º 6
0
def test_save_matplotlib_figures_hidpi(gallery_conf):
    """Test matplotlib hidpi figure save."""
    ext = 'png'
    gallery_conf['image_srcset'] = ["2x"]

    import matplotlib.pyplot as plt  # nest these so that Agg can be set
    plt.plot(1, 1)
    fname_template = os.path.join(gallery_conf['gallery_dir'], 'image{0}.png')
    image_path_iterator = ImagePathIterator(fname_template)
    block = ('', ) * 3
    block_vars = dict(image_path_iterator=image_path_iterator)
    image_rst = save_figures(block, block_vars, gallery_conf)

    fname = f'/image1.{ext}'
    assert fname in image_rst
    assert f'/image1_2_0x.{ext} 2.0x' in image_rst

    assert len(image_path_iterator) == 1
    fname = gallery_conf['gallery_dir'] + fname
    fnamehi = gallery_conf['gallery_dir'] + f'/image1_2_0x.{ext}'

    assert os.path.isfile(fname)
    assert os.path.isfile(fnamehi)

    # Test capturing 2 images with shifted start number
    image_path_iterator.next()
    image_path_iterator.next()
    plt.plot(1, 1)
    plt.figure()
    plt.plot(1, 1)
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(image_path_iterator) == 5
    for ii in range(4, 6):
        fname = f'/image{ii}.{ext}'
        assert fname in image_rst

        fname = gallery_conf['gallery_dir'] + fname
        assert os.path.isfile(fname)
        fname = f'/image{ii}_2_0x.{ext}'
        assert fname in image_rst
        fname = gallery_conf['gallery_dir'] + fname
        assert os.path.isfile(fname)
Ejemplo n.º 7
0
def test_save_matplotlib_figures(gallery_conf):
    """Test matplotlib figure save"""
    import matplotlib.pyplot as plt  # nest these so that Agg can be set
    plt.plot(1, 1)
    fname_template = os.path.join(gallery_conf['gallery_dir'], 'image{0}.png')
    image_path_iterator = ImagePathIterator(fname_template)
    block = ('',) * 3
    block_vars = dict(image_path_iterator=image_path_iterator)
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(image_path_iterator) == 1
    assert '/image1.png' in image_rst

    # Test capturing 2 images with shifted start number
    image_path_iterator.next()
    image_path_iterator.next()
    plt.plot(1, 1)
    plt.figure()
    plt.plot(1, 1)
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(image_path_iterator) == 5
    assert '/image4.png' in image_rst
    assert '/image5.png' in image_rst
Ejemplo n.º 8
0
def test_save_mayavi_figures(gallery_conf):
    """Test file naming when saving figures. Requires mayavi."""
    try:
        from mayavi import mlab
    except ImportError:
        raise pytest.skip('Mayavi not installed')
    import matplotlib.pyplot as plt
    mlab.options.offscreen = True

    gallery_conf.update(
        image_scrapers=(matplotlib_scraper, mayavi_scraper))
    fname_template = os.path.join(gallery_conf['gallery_dir'], 'image{0}.png')
    image_path_iterator = ImagePathIterator(fname_template)
    block = ('',) * 3
    block_vars = dict(image_path_iterator=image_path_iterator)

    plt.axes([-0.1, -0.1, 1.2, 1.2])
    plt.pcolor([[0]], cmap='Greens')
    mlab.test_plot3d()
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(plt.get_fignums()) == 0
    assert len(image_path_iterator) == 2
    assert '/image0.png' not in image_rst
    assert '/image1.png' in image_rst
    assert '/image2.png' in image_rst
    assert '/image3.png' not in image_rst
    assert not os.path.isfile(fname_template.format(0))
    assert os.path.isfile(fname_template.format(1))
    assert os.path.isfile(fname_template.format(2))
    assert not os.path.isfile(fname_template.format(0))
    with Image.open(fname_template.format(1)) as img:
        pixels = np.asarray(img.convert("RGB"))
    assert (pixels == [247, 252, 245]).all()  # plt first

    # Test next-value handling, plus image_scrapers modification
    gallery_conf.update(image_scrapers=(matplotlib_scraper,))
    mlab.test_plot3d()
    plt.axes([-0.1, -0.1, 1.2, 1.2])
    plt.pcolor([[0]], cmap='Reds')
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(plt.get_fignums()) == 0
    assert len(image_path_iterator) == 3
    assert '/image1.png' not in image_rst
    assert '/image2.png' not in image_rst
    assert '/image3.png' in image_rst
    assert '/image4.png' not in image_rst
    assert not os.path.isfile(fname_template.format(0))
    for ii in range(3):
        assert os.path.isfile(fname_template.format(ii + 1))
    assert not os.path.isfile(fname_template.format(4))
    with Image.open(fname_template.format(3)) as img:
        pixels = np.asarray(img.convert("RGB"))
    assert (pixels == [255, 245, 240]).all()

    # custom finders
    gallery_conf.update(image_scrapers=[lambda x, y, z: ''])
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(image_path_iterator) == 3

    # degenerate
    gallery_conf.update(image_scrapers=['foo'])
    with pytest.raises(ValueError, match='Unknown image scraper'):
        _complete_gallery_conf(
            gallery_conf, gallery_conf['gallery_dir'], True, False)
    gallery_conf.update(
        image_scrapers=[lambda x, y, z: y['image_path_iterator'].next()])
    with pytest.raises(RuntimeError, match='did not produce expected image'):
        save_figures(block, block_vars, gallery_conf)
    gallery_conf.update(image_scrapers=[lambda x, y, z: 1.])
    with pytest.raises(TypeError, match='was not a string'):
        save_figures(block, block_vars, gallery_conf)
Ejemplo n.º 9
0
def test_save_mayavi_figures(gallery_conf):
    """Test file naming when saving figures. Requires mayavi."""
    try:
        from mayavi import mlab
    except ImportError:
        raise pytest.skip('Mayavi not installed')
    import matplotlib.pyplot as plt
    mlab.options.offscreen = True

    gallery_conf.update(image_scrapers=(matplotlib_scraper, mayavi_scraper))
    fname_template = os.path.join(gallery_conf['gallery_dir'], 'image{0}.png')
    image_path_iterator = ImagePathIterator(fname_template)
    block = ('', ) * 3
    block_vars = dict(image_path_iterator=image_path_iterator)

    plt.axes([-0.1, -0.1, 1.2, 1.2])
    plt.pcolor([[0]], cmap='Greens')
    mlab.test_plot3d()
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(plt.get_fignums()) == 0
    assert len(image_path_iterator) == 2
    assert '/image0.png' not in image_rst
    assert '/image1.png' in image_rst
    assert '/image2.png' in image_rst
    assert '/image3.png' not in image_rst
    assert not os.path.isfile(fname_template.format(0))
    assert os.path.isfile(fname_template.format(1))
    assert os.path.isfile(fname_template.format(2))
    assert not os.path.isfile(fname_template.format(0))
    with Image.open(fname_template.format(1)) as img:
        pixels = np.asarray(img.convert("RGB"))
    assert (pixels == [247, 252, 245]).all()  # plt first

    # Test next-value handling, plus image_scrapers modification
    gallery_conf.update(image_scrapers=(matplotlib_scraper, ))
    mlab.test_plot3d()
    plt.axes([-0.1, -0.1, 1.2, 1.2])
    plt.pcolor([[0]], cmap='Reds')
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(plt.get_fignums()) == 0
    assert len(image_path_iterator) == 3
    assert '/image1.png' not in image_rst
    assert '/image2.png' not in image_rst
    assert '/image3.png' in image_rst
    assert '/image4.png' not in image_rst
    assert not os.path.isfile(fname_template.format(0))
    for ii in range(3):
        assert os.path.isfile(fname_template.format(ii + 1))
    assert not os.path.isfile(fname_template.format(4))
    with Image.open(fname_template.format(3)) as img:
        pixels = np.asarray(img.convert("RGB"))
    assert (pixels == [255, 245, 240]).all()

    # custom finders
    gallery_conf.update(image_scrapers=[lambda x, y, z: ''])
    image_rst = save_figures(block, block_vars, gallery_conf)
    assert len(image_path_iterator) == 3

    # degenerate
    gallery_conf.update(image_scrapers=['foo'])
    with pytest.raises(ValueError, match='Unknown image scraper'):
        _complete_gallery_conf(gallery_conf, gallery_conf['gallery_dir'], True,
                               False)
    gallery_conf.update(
        image_scrapers=[lambda x, y, z: y['image_path_iterator'].next()])
    with pytest.raises(RuntimeError, match='did not produce expected image'):
        save_figures(block, block_vars, gallery_conf)
    gallery_conf.update(image_scrapers=[lambda x, y, z: 1.])
    with pytest.raises(TypeError, match='was not a string'):
        save_figures(block, block_vars, gallery_conf)
Ejemplo n.º 10
0
def execute_code_block(compiler, block, example_globals, script_vars,
                       gallery_conf):
    """Executes the code block of the example file"""
    blabel, bcontent, lineno = block
    # If example is not suitable to run, skip executing its blocks
    if not script_vars["execute_script"] or blabel == "text":
        return ""

    cwd = os.getcwd()
    # Redirect output to stdout and
    orig_stdout, orig_stderr = sys.stdout, sys.stderr
    src_file = script_vars["src_file"]

    # First cd in the original example dir, so that any file
    # created by the example get created in this directory

    captured_std = StringIO()
    os.chdir(os.path.dirname(src_file))

    sys_path = copy.deepcopy(sys.path)
    sys.path.append(os.getcwd())
    sys.stdout = sys.stderr = LoggingTee(captured_std, logger, src_file)

    try:
        dont_inherit = 1
        if sys.version_info >= (3, 8):
            ast_Module = partial(ast.Module, type_ignores=[])
        else:
            ast_Module = ast.Module
        code_ast = ast_Module([bcontent])
        code_ast = compile(bcontent, src_file, "exec",
                           ast.PyCF_ONLY_AST | compiler.flags, dont_inherit)
        ast.increment_lineno(code_ast, lineno - 1)
        # capture output if last line is expression
        is_last_expr = False
        if len(code_ast.body) and isinstance(code_ast.body[-1], ast.Expr):
            is_last_expr = True
            last_val = code_ast.body.pop().value
            # exec body minus last expression
            _, mem_body = gen_rst._memory_usage(
                gen_rst._exec_once(compiler(code_ast, src_file, "exec"),
                                   example_globals),
                gallery_conf,
            )
            # exec last expression, made into assignment
            body = [
                ast.Assign(targets=[ast.Name(id="___", ctx=ast.Store())],
                           value=last_val)
            ]
            last_val_ast = ast_Module(body=body)
            ast.fix_missing_locations(last_val_ast)
            _, mem_last = gen_rst._memory_usage(
                gen_rst._exec_once(compiler(last_val_ast, src_file, "exec"),
                                   example_globals),
                gallery_conf,
            )
            # capture the assigned variable
            ___ = example_globals["___"]
            mem_max = max(mem_body, mem_last)
        else:
            _, mem_max = gen_rst._memory_usage(
                gen_rst._exec_once(compiler(code_ast, src_file, "exec"),
                                   example_globals),
                gallery_conf,
            )
        script_vars["memory_delta"].append(mem_max)

    except Exception:
        sys.stdout.flush()
        sys.stderr.flush()
        sys.stdout, sys.stderr = orig_stdout, orig_stderr
        except_rst = gen_rst.handle_exception(sys.exc_info(), src_file,
                                              script_vars, gallery_conf)
        code_output = u"\n{0}\n\n\n\n".format(except_rst)
        # still call this even though we won't use the images so that
        # figures are closed
        scrapers.save_figures(block, script_vars, gallery_conf)
    else:
        sys.stdout.flush()
        sys.stderr.flush()
        sys.stdout, orig_stderr = orig_stdout, orig_stderr
        sys.path = sys_path
        os.chdir(cwd)

        last_repr = None
        repr_meth = None
        if gallery_conf["capture_repr"] != () and is_last_expr:
            for meth in gallery_conf["capture_repr"]:
                try:
                    last_repr = getattr(___, meth)()
                    # for case when last statement is print()
                    if last_repr == "None":
                        repr_meth = None
                    else:
                        repr_meth = meth
                except Exception:
                    pass
                else:
                    if isinstance(last_repr, str):
                        break
        captured_std = captured_std.getvalue().expandtabs()
        # normal string output
        if repr_meth in ["__repr__", "__str__"] and last_repr:
            captured_std = u"{0}\n{1}".format(captured_std, last_repr)
        if captured_std and not captured_std.isspace():
            captured_std = CODE_OUTPUT.format(indent(captured_std, u" " * 4))
        else:
            captured_std = ""
        images_rst = scrapers.save_figures(block, script_vars, gallery_conf)
        # give html output its own header
        if repr_meth == "_repr_html_":
            captured_html = html_header.format(indent(last_repr, u" " * 8))
        else:
            captured_html = ""
        code_output = u"\n{0}\n\n{1}\n{2}\n\n".format(images_rst, captured_std,
                                                      captured_html)
    finally:
        os.chdir(cwd)
        sys.path = sys_path
        sys.stdout, sys.stderr = orig_stdout, orig_stderr

    return code_output