1# Copyright 2020 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7#     https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14"""Spinner!"""
15
16import contextlib
17import os
18import sys
19import threading
20import time
21
22PW_ENVSETUP_DISABLE_SPINNER = os.environ.get('PW_ENVSETUP_DISABLE_SPINNER')
23
24
25class Spinner(object):  # pylint: disable=useless-object-inheritance
26    """Spinner!"""
27    def __init__(self):
28        self._done = None
29        self._thread = None
30
31    def __del__(self):
32        self._done = True
33
34    def _spin(self):
35        i = 0
36        chars = '|/-\\'
37        while not self._done:
38            sys.stdout.write('[{}]'.format(chars[i]))
39            sys.stdout.flush()
40            time.sleep(0.1)
41            sys.stdout.write('\b\b\b')
42            i = (i + 1) % len(chars)
43
44    def start(self):
45        if PW_ENVSETUP_DISABLE_SPINNER:
46            return
47
48        self._done = False
49        self._thread = threading.Thread(target=self._spin)
50        self._thread.start()
51
52    def stop(self):
53        if PW_ENVSETUP_DISABLE_SPINNER:
54            return
55
56        assert self._thread
57        self._done = True
58        self._thread.join()
59        self._thread = None
60
61    @contextlib.contextmanager
62    def __call__(self):
63        try:
64            self.start()
65            yield self
66        finally:
67            self.stop()
68
69    @contextlib.contextmanager
70    def pause(self):
71        try:
72            self.stop()
73            yield self
74        finally:
75            self.start()
76