Skip to content

Commit efabdf9

Browse files
author
Andreas Maier
committed
Added support for suppressing spinner when not on a TTY.
Signed-off-by: Andreas Maier <andras.r.maier@gmx.de>
1 parent 65771c5 commit efabdf9

File tree

4 files changed

+67
-10
lines changed

4 files changed

+67
-10
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ notifications:
88
- yoav@yoavram.com
99
install:
1010
- pip install click
11+
- pip install six
1112
- python setup.py install
1213
script: py.test
1314
deploy:

click_spinner/__init__.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@
77
class Spinner(object):
88
spinner_cycle = itertools.cycle(['-', '/', '|', '\\'])
99

10-
def __init__(self):
10+
def __init__(self, force=False):
11+
self._force = force
1112
self.stop_running = None
1213
self.spin_thread = None
1314

1415
def start(self):
15-
self.stop_running = threading.Event()
16-
self.spin_thread = threading.Thread(target=self.init_spin)
17-
self.spin_thread.start()
16+
if sys.stdout.isatty() or self._force:
17+
self.stop_running = threading.Event()
18+
self.spin_thread = threading.Thread(target=self.init_spin)
19+
self.spin_thread.start()
1820

1921
def stop(self):
20-
self.stop_running.set()
21-
self.spin_thread.join()
22+
if self.spin_thread:
23+
self.stop_running.set()
24+
self.spin_thread.join()
2225

2326
def init_spin(self):
2427
while not self.stop_running.is_set():
@@ -34,9 +37,16 @@ def __exit__(self, exc_type, exc_val, exc_tb):
3437
self.stop()
3538

3639

37-
def spinner():
40+
def spinner(force=False):
3841
"""This function creates a context manager that is used to display a
39-
spinner as long as the context has not exited.
42+
spinner on stdout as long as the context has not exited.
43+
44+
The spinner is created only if stdout is not redirected, or if the spinner
45+
is forced using the `force` parameter.
46+
47+
Parameters:
48+
49+
force (bool): Force creation of spinner even when stdout is redirected.
4050
4151
Example usage::
4252
@@ -45,7 +55,7 @@ def spinner():
4555
do_something_else()
4656
4757
"""
48-
return Spinner()
58+
return Spinner(force)
4959

5060

5161
from ._version import get_versions

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
description='Spinner for Click',
1919
extras_require={
2020
'test': [
21-
'click'
21+
'click',
2222
'pytest',
23+
'six',
2324
]
2425
}
2526
)

tests/test_spinner.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import sys
2+
import os
3+
import time
4+
import tempfile
5+
from six import StringIO
16
import click
27
from click.testing import CliRunner
38

@@ -33,3 +38,43 @@ def cli():
3338
result = runner.invoke(cli, [])
3439
assert result.exception is None
3540

41+
42+
def test_spinner_redirect():
43+
@click.command()
44+
def cli():
45+
stdout_io = StringIO()
46+
saved_stdout = sys.stdout
47+
sys.stdout = stdout_io # redirect stdout to a string buffer
48+
spinner = click_spinner.Spinner()
49+
spinner.start()
50+
time.sleep(1) # allow time for a few spins
51+
spinner.stop()
52+
sys.stdout = saved_stdout
53+
stdout_io.flush()
54+
stdout_str = stdout_io.getvalue()
55+
assert len(stdout_str) == 0
56+
57+
runner = CliRunner()
58+
result = runner.invoke(cli, [])
59+
assert result.exception is None
60+
61+
62+
def test_spinner_redirect_force():
63+
@click.command()
64+
def cli():
65+
stdout_io = StringIO()
66+
saved_stdout = sys.stdout
67+
sys.stdout = stdout_io # redirect stdout to a string buffer
68+
spinner = click_spinner.Spinner(force=True)
69+
spinner.start()
70+
time.sleep(1) # allow time for a few spins
71+
spinner.stop()
72+
sys.stdout = saved_stdout
73+
stdout_io.flush()
74+
stdout_str = stdout_io.getvalue()
75+
assert len(stdout_str) > 0
76+
77+
runner = CliRunner()
78+
result = runner.invoke(cli, [])
79+
assert result.exception is None
80+

0 commit comments

Comments
 (0)