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)
|