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 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
|
"""Tests for the tqdm wrapper."""
from time import sleep
import pytest
from magicgui import magicgui
tqdm = pytest.importorskip("tqdm", reason="need tqdm installed to test tqdm")
from magicgui.tqdm import tqdm, trange # noqa
def test_tqdm_outside_of_functiongui():
"""Test that we can make a tqdm wrapper with ProgressBar outside of @magicgui."""
with trange(10) as pbar:
assert pbar.n == 0
assert pbar.total == 10
assert not pbar._mgui
assert tuple(trange(5)) == tuple(range(5))
def test_indeterminate_tqdm_outside_of_functiongui():
"""Test that we can have tqdm with an indeterminate total range."""
with tqdm(total=None) as pbar:
assert pbar.total is None
assert pbar.n == 0
pbar.update()
assert pbar.n == 1
def test_disabled_tqdm():
"""Test that a disabled tqdm does not have a progressbar or magicgui."""
@magicgui
def f():
with trange(10, disable=True) as pbar:
assert not hasattr(pbar, "progressbar")
assert not pbar._mgui
def test_no_leave_tqdm():
"""Test that leave=False hides the progressbar when done (tqdm API wording)"""
@magicgui
def f():
with trange(10, leave=True) as pbar1:
pass
assert pbar1.progressbar.visible is True
f.show()
f()
@magicgui
def f2():
with trange(10, leave=False) as pbar2:
pass
assert pbar2.progressbar.visible is False
f2.show()
f2()
def test_unbound_tqdm():
"""Test that tqdm without defined total sill have a range of (0, 0)."""
@magicgui
def f():
with tqdm() as pbar:
assert pbar.total is None
# undefined range will render as a "busy" indicator
assert pbar.progressbar.range == (0, 0)
f.show()
f()
def test_tqdm_std_err(capsys):
"""Test that tqdm inside an invisible magicgui falls back to console behavior."""
# outside of a magicgui it falls back to tqdm_std behavior
with tqdm(range(10)) as t_obj:
iter(t_obj)
captured = capsys.readouterr()
assert "0%|" in str(captured.err)
assert "| 0/10" in str(captured.err)
assert not str(captured.out)
def test_tqdm_in_visible_mgui_std_err(capsys):
"""Test that tqdm inside an mgui outputs to console only when mgui not visible."""
# inside of a of a magicgui it falls back to tqdm_std behavior
@magicgui
def f():
with tqdm(range(10)) as t_obj:
iter(t_obj)
f()
captured = capsys.readouterr()
assert "0%|" in str(captured.err)
assert "| 0/10" in str(captured.err)
assert not str(captured.out)
# showing the widget disables the output to console behavior
f.show()
f()
captured = capsys.readouterr()
assert not str(captured.err)
assert not str(captured.out)
# Test various ways that tqdm might need to traverse the frame stack:
def test_tqdm_inside_of_magicgui():
"""Test that tqdm can find the magicgui within which it is called."""
@magicgui
def long_func(steps=2):
for _i in tqdm([0, 1]):
sleep(0.02)
# before calling the function, we won't have any progress bars
long_func.show()
assert not long_func._tqdm_pbars
long_func()
# after calling the it, we should now have a progress bars
assert len(long_func._tqdm_pbars) == 1
# but calling it again won't add more
long_func()
assert len(long_func._tqdm_pbars) == 1
def test_trange_inside_of_magicgui():
"""Test that trange can find the magicgui within which it is called."""
@magicgui
def long_func(steps=2):
for _i in trange(4):
pass
long_func.show()
assert not long_func._tqdm_pbars
long_func()
assert len(long_func._tqdm_pbars) == 1
def test_indeterminate_tqdm_inside_magicgui():
"""Test that we can have tqdm with an indeterminate total range."""
@magicgui
def long_func():
"""Long running computation with indeterminate range."""
with tqdm(total=None):
pass
long_func.show()
assert not long_func._tqdm_pbars
long_func()
assert len(long_func._tqdm_pbars) == 1
def _indirectly_decorated(steps=2):
for _i in trange(4):
pass
def test_trange_inside_of_indirectly_decorated_magicgui():
"""Test that trange can find the magicgui within which it is called."""
indirectly_decorated = magicgui(_indirectly_decorated)
indirectly_decorated.show()
assert not indirectly_decorated._tqdm_pbars
indirectly_decorated()
assert len(indirectly_decorated._tqdm_pbars) == 1
def test_tqdm_nested():
"""Test that tqdm can find the magicgui within which it is called."""
@magicgui
def long_func():
for _i in trange(4):
for _x in trange(4):
pass
long_func.show()
# before calling the function, we won't have any progress bars
assert not long_func._tqdm_pbars
long_func()
# after calling the it, we should now have a progress bars
assert len(long_func._tqdm_pbars) == 2
# the depth is all that matters... not the total number of tqdms
@magicgui
def long_func2():
for _i in trange(4):
for _x in trange(4):
pass
for _x in trange(4):
pass
long_func2.show()
# before calling the function, we won't have any progress bars
assert not long_func2._tqdm_pbars
long_func2()
# after calling the it, we should now have a progress bars
assert len(long_func2._tqdm_pbars) == 2
|