File: sample_summaries.py

package info (click to toggle)
pytest-mpl 0.17.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,132 kB
  • sloc: python: 2,514; javascript: 179; makefile: 16
file content (112 lines) | stat: -rw-r--r-- 3,203 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import os
import shutil
import pathlib
import tempfile
import subprocess

from docutils import nodes
from sphinx.util.docutils import SphinxRole
from sphinx.util.osutil import canon_path

REPO_ROOT = pathlib.Path(__file__).parent.parent
TEST_FILE = REPO_ROOT / "tests" / "subtests" / "test_subtest.py"
SAMPLE_DIR = "sample"


def run_pytest(test_name):

    # Create generated samples directory
    sample_dir_abs = pathlib.Path(__file__).parent / SAMPLE_DIR
    if not sample_dir_abs.exists():
        os.mkdir(sample_dir_abs)

    # Form path to current sample
    dest = sample_dir_abs / test_name
    if dest.exists():
        return dest  # skip if already generated

    # Generate the current sample
    tmp_dir = tempfile.mkdtemp()
    command = f"python -m pytest {TEST_FILE}::{test_name} -v --mpl --basetemp={tmp_dir}"
    subprocess.run(command, shell=True, check=True)

    # Find the name of the directory the sample is within
    # (directory name is sometimes truncated)
    src = next(filter(
        lambda x: x.name[:-1] in test_name,
        pathlib.Path(tmp_dir).glob("*0")
    )) / "results"
    shutil.copytree(src, dest)

    return dest


class SummaryButtons(nodes.General, nodes.Inline, nodes.TextElement):
    pass


class SummaryRole(SphinxRole):
    def run(self):
        node = SummaryButtons(name=self.text)
        return [node], []


def move_summaries(app, *args, **kwargs):
    gen_sample_dir = pathlib.Path(__file__).parent / SAMPLE_DIR
    out_sample_dir = pathlib.Path(app.outdir) / SAMPLE_DIR
    if out_sample_dir.exists():
        shutil.rmtree(out_sample_dir)
    shutil.copytree(gen_sample_dir, out_sample_dir)


def html_visit_summary(self, node):

    test_name = str(node["name"])
    out = run_pytest(test_name)

    classes = (
        "sd-sphinx-override sd-btn sd-text-wrap sd-btn-{importance} "
        "sd-shadow-sm sd-me-2 reference internal"
    )
    button = (
        '<a class="{classes}" href="{href}" style="margin-right: 0.5rem;">{label}</a>'
    )

    summary_types = {
        "HTML": "fig_comparison.html",
        "Basic HTML": "fig_comparison_basic.html",
        "JSON": "results.json",
    }

    current_filename = self.builder.current_docname + self.builder.out_suffix
    current_dir = pathlib.PurePath(current_filename).parent
    first_button = True
    for label, file in summary_types.items():
        if (out / file).exists():
            importance = "primary" if first_button else "secondary"
            self.body.append(button.format(
                classes=classes.format(importance=importance),
                href=canon_path((current_dir / SAMPLE_DIR / test_name / file).as_posix()),
                label=label,
            ))
            first_button = False

    raise nodes.SkipNode


def skip(self, node):
    raise nodes.SkipNode


def setup(app):
    app.connect("build-finished", move_summaries)
    app.add_node(
        SummaryButtons,
        html=(html_visit_summary, None),
        latex=(skip, None),
        text=(skip, None),
        man=(skip, None),
        texinfo=(skip, None),
    )
    app.add_role("summary", SummaryRole())
    return {"parallel_read_safe": True, "parallel_write_safe": True}