File: test_misc.py

package info (click to toggle)
python-mne 1.9.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 131,492 kB
  • sloc: python: 213,302; javascript: 12,910; sh: 447; makefile: 144
file content (161 lines) | stat: -rw-r--r-- 4,797 bytes parent folder | download
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.

import os
import subprocess
import sys
from contextlib import nullcontext

import pytest

import mne
from mne.utils import _clean_names, catch_logging, run_subprocess, sizeof_fmt


def test_sizeof_fmt():
    """Test sizeof_fmt."""
    assert sizeof_fmt(0) == "0 bytes"
    assert sizeof_fmt(1) == "1 byte"
    assert sizeof_fmt(1000) == "1000 bytes"


def test_html_repr():
    """Test switching _repr_html_ between HTML and plain text."""
    key = "MNE_REPR_HTML"
    existing_value = os.getenv(key, None)

    os.environ[key] = "True"  # HTML repr on
    info = mne.create_info(10, 256)
    r = info._repr_html_()
    assert r.startswith("<script type=")
    assert r.endswith("</table>")
    os.environ[key] = "False"  # HTML repr off
    r = info._repr_html_()
    assert r.startswith("<pre>")
    assert r.endswith("</pre>")

    del os.environ[key]
    if existing_value is not None:
        os.environ[key] = existing_value


@pytest.mark.parametrize("kind", ("stdout", "stderr"))
@pytest.mark.parametrize("do_raise", (True, False))
def test_run_subprocess(tmp_path, capsys, kind, do_raise):
    """Test run_subprocess."""
    fname = tmp_path / "subp.py"
    extra = ""
    if do_raise:
        extra = """
raise RuntimeError('This is a test')
"""
        raise_context = pytest.raises(subprocess.CalledProcessError)
    else:
        extra = ""
        raise_context = nullcontext()
    with open(fname, "w") as fid:
        fid.write(
            f"""\
import sys
import time
print('foo', file=sys.{kind})
print('bar', file=sys.{kind})
"""
            + extra
        )
    with catch_logging() as log, raise_context:
        stdout, stderr = run_subprocess([sys.executable, str(fname)], verbose=True)
    if do_raise:
        exc = raise_context.excinfo.value
        stdout = exc.stdout
        stderr = exc.stderr
    log = log.getvalue()
    log = "\n".join(log.split("\n")[1:])  # get rid of header
    log = log.replace("\r\n", "\n")  # Windows
    orig_log = log
    stdout = stdout.replace("\r\n", "\n")
    stderr = stderr.replace("\r\n", "\n")
    if do_raise:  # remove traceback

        def remove_traceback(log):
            return "\n".join(
                line
                for line in log.split("\n")
                if not line.strip().startswith(
                    ("File ", "raise ", "RuntimeError: ", "Traceback ")
                )
            )

        log = remove_traceback(log)
        stderr = remove_traceback(stderr)
    want = "foo\nbar\n"
    assert log == want, orig_log
    if kind == "stdout":
        std = stdout
        other = stderr
    else:
        std = stderr
        other = stdout
    assert std == want
    assert other == ""
    stdout, stderr = capsys.readouterr()
    assert stdout == ""
    assert stderr == ""

    # Now make sure we can pass other stuff as stdout/stderr
    capsys.readouterr()  # clear
    stdout_fname = tmp_path / "stdout.txt"
    stderr_fname = tmp_path / "stderr.txt"
    stdout_file = open(stdout_fname, "w")
    stderr_file = open(stderr_fname, "w")
    if do_raise:
        raise_context = pytest.raises(subprocess.CalledProcessError)
    else:
        raise_context = nullcontext()
    with catch_logging() as log, stdout_file, stderr_file, raise_context:
        stdout, stderr = run_subprocess(
            [sys.executable, str(fname)],
            verbose=False,
            stdout=stdout_file,
            stderr=stderr_file,
        )
    if do_raise:
        exc = raise_context.excinfo.value
        assert exc.stdout is None
        assert exc.stderr is None
    else:
        assert stdout == ""
        assert stderr == ""
    log = log.getvalue()
    assert log == ""
    stdout, stderr = capsys.readouterr()
    assert stdout == ""
    assert stderr == ""
    stdout = stdout_fname.read_text()
    stderr = stderr_fname.read_text()
    if do_raise:
        stderr = "\n".join(stderr.split("\n")[:-5])
        if stderr:
            stderr += "\n"
    if kind == "stdout":
        std = stdout
        other = stderr
    else:
        std = stderr
        other = stdout
    assert std == want
    assert other == ""


def test_clean_names():
    """Test cleaning names on OPM dataset.

    This channel name list is a subset from a user OPM dataset reported on the forum
    https://mne.discourse.group/t/error-when-trying-to-plot-projectors-ssp/8456
    where the function _clean_names ended up creating a duplicate channel name L108_bz.
    """
    ch_names = ["R305_bz-s2", "L108_bz-s77", "R112_bz-s109", "L108_bz-s110"]
    ch_names_clean = _clean_names(ch_names, before_dash=True)
    assert ch_names == ch_names_clean
    assert len(set(ch_names_clean)) == len(ch_names_clean)