0
# Basic Spinner Operations
1
2
Core functionality for creating, starting, stopping, and managing spinner lifecycle. Provides multiple usage patterns including context managers, decorators, and manual control.
3
4
## Capabilities
5
6
### Halo Constructor
7
8
Creates a new spinner instance with comprehensive configuration options for appearance and behavior.
9
10
```python { .api }
11
def __init__(
12
self,
13
text="",
14
color="cyan",
15
text_color=None,
16
spinner=None,
17
animation=None,
18
placement="left",
19
interval=-1,
20
enabled=True,
21
stream=sys.stdout
22
):
23
"""
24
Initialize a Halo spinner.
25
26
Parameters:
27
- text (str): Text to display alongside spinner (default: "")
28
- color (str): Spinner color - "cyan", "red", "green", etc. (default: "cyan")
29
- text_color (str): Text color, same options as color (default: None)
30
- spinner (str|dict): Spinner type name or custom spinner definition (default: "dots")
31
- animation (str): Text animation for long strings - "bounce", "marquee" (default: None)
32
- placement (str): Spinner position - "left" or "right" (default: "left")
33
- interval (int): Frame interval in milliseconds, -1 for spinner default (default: -1)
34
- enabled (bool): Whether spinner is active (default: True)
35
- stream (io.TextIOWrapper): Output stream (default: sys.stdout)
36
"""
37
```
38
39
### Manual Spinner Control
40
41
Start and stop spinners manually with full control over timing and lifecycle.
42
43
```python { .api }
44
def start(self, text=None):
45
"""
46
Start the spinner on a separate thread.
47
48
Parameters:
49
- text (str, optional): Update spinner text when starting
50
51
Returns:
52
- Halo: Self for method chaining
53
"""
54
55
def stop(self):
56
"""
57
Stop the spinner and clear the line.
58
59
Returns:
60
- Halo: Self for method chaining
61
"""
62
63
def clear(self):
64
"""
65
Clear the current line and return cursor to start.
66
67
Returns:
68
- Halo: Self for method chaining
69
"""
70
71
def render(self):
72
"""
73
Manually render frames in a loop until stopped.
74
75
Returns:
76
- Halo: Self for method chaining
77
"""
78
79
def frame(self):
80
"""
81
Build and return the next frame to be rendered.
82
83
Returns:
84
- str: Complete frame string with spinner and text
85
"""
86
87
def text_frame(self):
88
"""
89
Build and return the text portion of the frame.
90
91
Returns:
92
- str: Text frame with color and animation applied
93
"""
94
```
95
96
**Usage Example:**
97
98
```python
99
from halo import Halo
100
import time
101
102
# Basic manual control
103
spinner = Halo(text='Loading data', spinner='dots')
104
spinner.start()
105
106
# Update text while running
107
time.sleep(1)
108
spinner.text = 'Processing data'
109
time.sleep(1)
110
spinner.text = 'Saving results'
111
time.sleep(1)
112
113
spinner.stop()
114
```
115
116
### Context Manager Support
117
118
Use spinners in `with` statements for automatic lifecycle management and exception safety.
119
120
```python { .api }
121
def __enter__(self):
122
"""
123
Start spinner for context manager usage.
124
125
Returns:
126
- Halo: Self instance
127
"""
128
129
def __exit__(self, type, value, traceback):
130
"""
131
Stop spinner when exiting context.
132
133
Parameters:
134
- type: Exception type (if any)
135
- value: Exception value (if any)
136
- traceback: Exception traceback (if any)
137
"""
138
```
139
140
**Usage Example:**
141
142
```python
143
from halo import Halo
144
import time
145
146
# Context manager automatically handles start/stop
147
with Halo(text='Loading', spinner='dots'):
148
time.sleep(2)
149
# Spinner automatically stops when exiting block
150
151
# Works with exceptions too
152
try:
153
with Halo(text='Risky operation', spinner='dots'):
154
time.sleep(1)
155
raise ValueError("Something went wrong")
156
except ValueError:
157
print("Exception occurred, spinner was cleaned up")
158
```
159
160
### Decorator Support
161
162
Apply spinners to functions as decorators for seamless integration with existing code.
163
164
```python { .api }
165
def __call__(self, f):
166
"""
167
Allow Halo instance to be used as function decorator.
168
169
Parameters:
170
- f (callable): Function to wrap with spinner
171
172
Returns:
173
- callable: Wrapped function
174
"""
175
```
176
177
**Usage Example:**
178
179
```python
180
from halo import Halo
181
import time
182
183
# Decorator with configuration
184
@Halo(text='Processing data', spinner='dots', color='green')
185
def process_data():
186
time.sleep(3)
187
return "processed_data"
188
189
# Function runs with spinner automatically
190
result = process_data()
191
192
# Reusable spinner decorator
193
spinner_decorator = Halo(text='Working', spinner='star')
194
195
@spinner_decorator
196
def task_one():
197
time.sleep(2)
198
199
@spinner_decorator
200
def task_two():
201
time.sleep(1)
202
203
task_one()
204
task_two()
205
```
206
207
### Spinner Status and Inspection
208
209
Get information about the current spinner state and thread ID.
210
211
```python { .api }
212
@property
213
def spinner_id(self):
214
"""
215
Get the thread ID of the currently running spinner.
216
217
Returns:
218
- str: Thread name/ID of the spinner thread, or None if not running
219
"""
220
```
221
222
**Usage Example:**
223
224
```python
225
from halo import Halo
226
import time
227
228
spinner = Halo(text='Processing', spinner='dots')
229
print(f"Spinner ID before start: {spinner.spinner_id}") # None
230
231
spinner.start()
232
print(f"Spinner ID while running: {spinner.spinner_id}") # Thread-1 (or similar)
233
234
time.sleep(1)
235
spinner.stop()
236
print(f"Spinner ID after stop: {spinner.spinner_id}") # None
237
```
238
239
## Advanced Usage Patterns
240
241
### Dynamic Text Updates
242
243
```python
244
spinner = Halo(text='Starting', spinner='dots')
245
spinner.start()
246
247
for i in range(1, 101):
248
spinner.text = f'Progress: {i}%'
249
time.sleep(0.1)
250
251
spinner.stop()
252
```
253
254
### Conditional Spinners
255
256
```python
257
import sys
258
259
# Disable spinner for non-interactive environments
260
spinner = Halo(
261
text='Processing',
262
enabled=sys.stdout.isatty() # Only show in terminal
263
)
264
265
with spinner:
266
time.sleep(2)
267
```
268
269
### Custom Output Streams
270
271
```python
272
import io
273
274
# Capture spinner output
275
buffer = io.StringIO()
276
spinner = Halo(text='Working', stream=buffer)
277
278
with spinner:
279
time.sleep(1)
280
281
# spinner output captured in buffer
282
```