Ejemplo n.º 1
0
def sphinx_app(tmpdir_factory):
    if LooseVersion(sphinx.__version__) < LooseVersion('1.8'):
        # Previous versions throw an error trying to pickle the scraper
        pytest.skip('Sphinx 1.8+ required')
    temp_dir = (tmpdir_factory.getbasetemp() / 'root').strpath
    src_dir = op.join(op.dirname(__file__), 'tinybuild')

    def ignore(src, names):
        return ('_build', 'gen_modules', 'auto_examples')

    shutil.copytree(src_dir, temp_dir, ignore=ignore)
    # For testing iteration, you can get similar behavior just doing `make`
    # inside the tinybuild directory
    src_dir = temp_dir
    conf_dir = temp_dir
    out_dir = op.join(temp_dir, '_build', 'html')
    toctrees_dir = op.join(temp_dir, '_build', 'toctrees')
    # Avoid warnings about re-registration, see:
    # https://github.com/sphinx-doc/sphinx/issues/5038
    with docutils_namespace():
        app = Sphinx(src_dir,
                     conf_dir,
                     out_dir,
                     toctrees_dir,
                     buildername='html',
                     status=MixedEncodingStringIO())
        # need to build within the context manager
        # for automodule and backrefs to work
        app.build(False, [])
    return app
Ejemplo n.º 2
0
def sphinx_app_wrapper(tempdir, conf_file):
    _fixturedir = os.path.join(os.path.dirname(__file__), 'testconfs')
    srcdir = os.path.join(tempdir, "config_test")
    shutil.copytree(_fixturedir, srcdir)
    shutil.copytree(os.path.join(_fixturedir, "src"),
                    os.path.join(tempdir, "examples"))

    base_config = """
import os
import sphinx_gallery
extensions = ['sphinx_gallery.gen_gallery']
exclude_patterns = ['_build']
source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = u'Sphinx-Gallery <Tests>'\n\n
"""
    with open(os.path.join(srcdir, "conf.py"), "w") as conffile:
        conffile.write(base_config + conf_file['content'])

    return SphinxAppWrapper(srcdir,
                            srcdir,
                            os.path.join(srcdir, "_build"),
                            os.path.join(srcdir, "_build", "toctree"),
                            "html",
                            warning=MixedEncodingStringIO())
Ejemplo n.º 3
0
def test_junit(sphinx_app, tmpdir):
    out_dir = sphinx_app.outdir
    junit_file = op.join(out_dir, 'sphinx-gallery', 'junit-results.xml')
    assert op.isfile(junit_file)
    with codecs.open(junit_file, 'r', 'utf-8') as fid:
        contents = fid.read()
    assert contents.startswith('<?xml')
    assert 'errors="0" failures="0"' in contents
    assert 'tests="5"' in contents
    assert 'local_module' not in contents  # it's not actually run as an ex
    assert 'expected example failure' in contents
    assert '<failure message' not in contents
    src_dir = sphinx_app.srcdir
    new_src_dir = op.join(str(tmpdir), 'src')
    shutil.copytree(src_dir, new_src_dir)
    del src_dir
    new_out_dir = op.join(new_src_dir, '_build', 'html')
    new_toctree_dir = op.join(new_src_dir, '_build', 'toctrees')
    passing_fname = op.join(new_src_dir, 'examples',
                            'plot_numpy_matplotlib.py')
    failing_fname = op.join(new_src_dir, 'examples',
                            'plot_future_imports_broken.py')
    shutil.move(passing_fname, passing_fname + '.temp')
    shutil.move(failing_fname, passing_fname)
    shutil.move(passing_fname + '.temp', failing_fname)
    with docutils_namespace():
        app = Sphinx(new_src_dir,
                     new_src_dir,
                     new_out_dir,
                     new_toctree_dir,
                     buildername='html',
                     status=MixedEncodingStringIO())
        # need to build within the context manager
        # for automodule and backrefs to work
        with pytest.raises(ValueError, match='Here is a summary of the '):
            app.build(False, [])
    junit_file = op.join(new_out_dir, 'sphinx-gallery', 'junit-results.xml')
    assert op.isfile(junit_file)
    with codecs.open(junit_file, 'r', 'utf-8') as fid:
        contents = fid.read()
    assert 'errors="0" failures="2"' in contents
    assert 'tests="2"' in contents  # this time we only ran the two stale files
    if LooseVersion(sys.version) >= LooseVersion('3'):
        assert '<failure message="RuntimeError: Forcing' in contents
    else:
        assert '<failure message="SyntaxError: invalid' in contents
    assert 'Passed even though it was marked to fail' in contents
Ejemplo n.º 4
0
def config_app(tempdir, conf_file):
    _fixturedir = os.path.join(os.path.dirname(__file__), 'testconfs')
    srcdir = os.path.join(tempdir, "config_test")
    shutil.copytree(_fixturedir, srcdir)
    shutil.copytree(os.path.join(_fixturedir, "src"),
                    os.path.join(tempdir, "examples"))

    with open(os.path.join(srcdir, "conf.py"), "w") as conffile:
        conffile.write(conf_file['content'])

    app = Sphinx(srcdir,
                 srcdir,
                 os.path.join(srcdir, "_build"),
                 os.path.join(srcdir, "_build", "toctree"),
                 "html",
                 warning=MixedEncodingStringIO())

    sphinx_compatibility._app = app
    return app
Ejemplo n.º 5
0
def test_rebuild(tmpdir_factory, sphinx_app):
    # Make sure that examples that haven't been changed aren't run twice.

    #
    # First run completes in the fixture.
    #
    status = sphinx_app._status.getvalue()
    want = '.*%s added, 0 changed, 0 removed$.*' % (N_RST, )
    assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None
    assert re.match('.*targets for 1 source files that are out of date$.*',
                    status, re.MULTILINE | re.DOTALL) is not None
    want = (
        '.*executed %d out of %d.*after excluding 0 files.*based on MD5.*' %
        (N_GOOD, N_TOT))
    assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None
    old_src_dir = (tmpdir_factory.getbasetemp() / 'root_old').strpath
    shutil.copytree(sphinx_app.srcdir, old_src_dir)
    generated_modules_0 = sorted(
        op.join(old_src_dir, 'gen_modules', f)
        for f in os.listdir(op.join(old_src_dir, 'gen_modules'))
        if op.isfile(op.join(old_src_dir, 'gen_modules', f)))
    generated_backrefs_0 = sorted(
        op.join(old_src_dir, 'gen_modules', 'backreferences', f)
        for f in os.listdir(
            op.join(old_src_dir, 'gen_modules', 'backreferences')))
    generated_rst_0 = sorted(
        op.join(old_src_dir, 'auto_examples', f)
        for f in os.listdir(op.join(old_src_dir, 'auto_examples'))
        if f.endswith('.rst'))
    generated_pickle_0 = sorted(
        op.join(old_src_dir, 'auto_examples', f)
        for f in os.listdir(op.join(old_src_dir, 'auto_examples'))
        if f.endswith('.pickle'))
    copied_py_0 = sorted(
        op.join(old_src_dir, 'auto_examples', f)
        for f in os.listdir(op.join(old_src_dir, 'auto_examples'))
        if f.endswith('.py'))
    copied_ipy_0 = sorted(
        op.join(old_src_dir, 'auto_examples', f)
        for f in os.listdir(op.join(old_src_dir, 'auto_examples'))
        if f.endswith('.ipynb'))
    assert len(generated_modules_0) > 0
    assert len(generated_backrefs_0) > 0
    assert len(generated_rst_0) > 0
    assert len(generated_pickle_0) > 0
    assert len(copied_py_0) > 0
    assert len(copied_ipy_0) > 0
    assert len(sphinx_app.config.sphinx_gallery_conf['stale_examples']) == 0
    assert op.isfile(
        op.join(sphinx_app.outdir, '_images',
                'sphx_glr_plot_numpy_matplotlib_001.png'))

    #
    # run a second time, no files should be updated
    #

    src_dir = sphinx_app.srcdir
    del sphinx_app  # don't accidentally use it below
    conf_dir = src_dir
    out_dir = op.join(src_dir, '_build', 'html')
    toctrees_dir = op.join(src_dir, '_build', 'toctrees')
    time.sleep(0.1)
    with docutils_namespace():
        new_app = Sphinx(src_dir,
                         conf_dir,
                         out_dir,
                         toctrees_dir,
                         buildername='html',
                         status=MixedEncodingStringIO())
        new_app.build(False, [])
    status = new_app._status.getvalue()
    lines = [line for line in status.split('\n') if '0 removed' in line]
    assert re.match('.*0 added, [2|3|6|7|8] changed, 0 removed$.*', status,
                    re.MULTILINE | re.DOTALL) is not None, lines
    want = ('.*executed 0 out of 1.*after excluding %s files.*based on MD5.*' %
            (N_GOOD, ))
    assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None
    n_stale = len(new_app.config.sphinx_gallery_conf['stale_examples'])
    assert n_stale == N_GOOD
    assert op.isfile(
        op.join(new_app.outdir, '_images',
                'sphx_glr_plot_numpy_matplotlib_001.png'))

    generated_modules_1 = sorted(
        op.join(new_app.srcdir, 'gen_modules', f)
        for f in os.listdir(op.join(new_app.srcdir, 'gen_modules'))
        if op.isfile(op.join(new_app.srcdir, 'gen_modules', f)))
    generated_backrefs_1 = sorted(
        op.join(new_app.srcdir, 'gen_modules', 'backreferences', f)
        for f in os.listdir(
            op.join(new_app.srcdir, 'gen_modules', 'backreferences')))
    generated_rst_1 = sorted(
        op.join(new_app.srcdir, 'auto_examples', f)
        for f in os.listdir(op.join(new_app.srcdir, 'auto_examples'))
        if f.endswith('.rst'))
    generated_pickle_1 = sorted(
        op.join(new_app.srcdir, 'auto_examples', f)
        for f in os.listdir(op.join(new_app.srcdir, 'auto_examples'))
        if f.endswith('.pickle'))
    copied_py_1 = sorted(
        op.join(new_app.srcdir, 'auto_examples', f)
        for f in os.listdir(op.join(new_app.srcdir, 'auto_examples'))
        if f.endswith('.py'))
    copied_ipy_1 = sorted(
        op.join(new_app.srcdir, 'auto_examples', f)
        for f in os.listdir(op.join(new_app.srcdir, 'auto_examples'))
        if f.endswith('.ipynb'))

    # mtimes for modules
    _assert_mtimes(generated_modules_0, generated_modules_1)

    # mtimes for backrefs (gh-394)
    _assert_mtimes(generated_backrefs_0, generated_backrefs_1)

    # generated RST files
    ignore = (
        # these two should almost always be different, but in case we
        # get extremely unlucky and have identical run times
        # on the one script that gets re-run (because it's a fail)...
        'sg_execution_times.rst',
        'plot_future_imports_broken.rst',
    )
    _assert_mtimes(generated_rst_0, generated_rst_1, ignore=ignore)

    # mtimes for pickles
    _assert_mtimes(generated_pickle_0, generated_pickle_1)

    # mtimes for .py files (gh-395)
    _assert_mtimes(copied_py_0, copied_py_1)

    # mtimes for .ipynb files
    _assert_mtimes(copied_ipy_0, copied_ipy_1)

    #
    # run a third time, changing one file
    #

    time.sleep(0.1)
    fname = op.join(src_dir, 'examples', 'plot_numpy_matplotlib.py')
    with codecs.open(fname, 'r', 'utf-8') as fid:
        lines = fid.readlines()
    with codecs.open(fname, 'w', 'utf-8') as fid:
        for line in lines:
            if line.startswith('FYI this'):
                line = 'A ' + line
            fid.write(line)
    with docutils_namespace():
        new_app = Sphinx(src_dir,
                         conf_dir,
                         out_dir,
                         toctrees_dir,
                         buildername='html',
                         status=MixedEncodingStringIO())
        new_app.build(False, [])
    status = new_app._status.getvalue()
    if LooseVersion(sphinx.__version__) <= LooseVersion('1.6'):
        n = N_RST
    else:
        n = '[2|3]'
    lines = [line for line in status.split('\n') if 'source files tha' in line]
    want = '.*targets for %s source files that are out of date$.*' % n
    assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None, lines
    want = ('.*executed 1 out of 2.*after excluding %s files.*based on MD5.*' %
            (N_GOOD - 1, ))
    assert re.match(want, status, re.MULTILINE | re.DOTALL) is not None
    n_stale = len(new_app.config.sphinx_gallery_conf['stale_examples'])
    assert n_stale == N_GOOD - 1
    assert op.isfile(
        op.join(new_app.outdir, '_images',
                'sphx_glr_plot_numpy_matplotlib_001.png'))

    generated_modules_1 = sorted(
        op.join(new_app.srcdir, 'gen_modules', f)
        for f in os.listdir(op.join(new_app.srcdir, 'gen_modules'))
        if op.isfile(op.join(new_app.srcdir, 'gen_modules', f)))
    generated_backrefs_1 = sorted(
        op.join(new_app.srcdir, 'gen_modules', 'backreferences', f)
        for f in os.listdir(
            op.join(new_app.srcdir, 'gen_modules', 'backreferences')))
    generated_rst_1 = sorted(
        op.join(new_app.srcdir, 'auto_examples', f)
        for f in os.listdir(op.join(new_app.srcdir, 'auto_examples'))
        if f.endswith('.rst'))
    generated_pickle_1 = sorted(
        op.join(new_app.srcdir, 'auto_examples', f)
        for f in os.listdir(op.join(new_app.srcdir, 'auto_examples'))
        if f.endswith('.pickle'))
    copied_py_1 = sorted(
        op.join(new_app.srcdir, 'auto_examples', f)
        for f in os.listdir(op.join(new_app.srcdir, 'auto_examples'))
        if f.endswith('.py'))
    copied_ipy_1 = sorted(
        op.join(new_app.srcdir, 'auto_examples', f)
        for f in os.listdir(op.join(new_app.srcdir, 'auto_examples'))
        if f.endswith('.ipynb'))

    # mtimes for modules
    _assert_mtimes(generated_modules_0, generated_modules_1)

    # mtimes for backrefs (gh-394)
    _assert_mtimes(generated_backrefs_0, generated_backrefs_1)

    # generated RST files
    different = (
        # this one should get rewritten as we retried it
        'plot_future_imports_broken.rst',
        'plot_numpy_matplotlib.rst',
    )
    ignore = (
        # this one should almost always be different, but in case we
        # get extremely unlucky and have identical run times
        # on the one script above that changes...
        'sg_execution_times.rst', )
    _assert_mtimes(generated_rst_0, generated_rst_1, different, ignore)

    # mtimes for pickles
    _assert_mtimes(generated_pickle_0,
                   generated_pickle_1,
                   different=('plot_numpy_matplotlib.codeobj.pickle'))

    # mtimes for .py files (gh-395)
    _assert_mtimes(copied_py_0,
                   copied_py_1,
                   different=('plot_numpy_matplotlib.py'))

    # mtimes for .ipynb files
    _assert_mtimes(copied_ipy_0,
                   copied_ipy_1,
                   different=('plot_numpy_matplotlib.ipynb'))