Beautiful multi-step terminal progress widget for Rich. Connected indicators, per-step logging, elapsed timers, and optional progress bars.
Project description
rich-stepper
Beautiful multi-step terminal progress widget for Rich. Connected indicators, per-step logging, elapsed timers, and optional progress bars — all rendered live in your terminal.
Installation
pip install rich-stepper
Requires Python 3.10+ and Rich 13+.
Quick Start
from rich.console import Console
from stepper import StepDefinition, StepStatus, Stepper
steps = [
StepDefinition("Clone repository", StepStatus.COMPLETED),
StepDefinition("Install dependencies", StepStatus.ACTIVE),
StepDefinition("Run tests", StepStatus.PENDING),
StepDefinition("Deploy", StepStatus.PENDING),
]
stepper = Stepper(steps=steps)
Console().print(stepper)
Renders a connected vertical stepper with status indicators:
● Clone repository
│
◉ Install dependencies
│
○ Run tests
│
○ Deploy
Live Updates
Use the context manager for animated step progression:
import time
from stepper import StepDefinition, StepStatus, Stepper
steps = [
StepDefinition("Connecting", StepStatus.ACTIVE),
StepDefinition("Downloading", StepStatus.PENDING),
StepDefinition("Installing", StepStatus.PENDING),
StepDefinition("Done", StepStatus.PENDING),
]
stepper = Stepper(steps=steps)
with stepper:
for i in range(len(steps)):
time.sleep(0.5)
if i > 0:
stepper.set_step_status(i, StepStatus.ACTIVE)
time.sleep(0.5)
stepper.set_step_status(i, StepStatus.COMPLETED)
Per-Step Logging
Append log messages to any step with stepper.log():
from rich.console import Console
from stepper import StepDefinition, StepStatus, Stepper, StepperTheme
theme = StepperTheme(max_log_rows=3, log_style="dim italic", log_prefix="›")
stepper = Stepper(
steps=[
StepDefinition("Fetch schema", StepStatus.COMPLETED, step_description="200 OK"),
StepDefinition("Migrate database", StepStatus.ACTIVE, step_description="Applying patches…"),
StepDefinition("Seed data", StepStatus.PENDING),
],
theme=theme,
console=Console(),
auto_refresh=False,
)
stepper.log(0, "Connected to postgres://db:5432")
stepper.log(0, "Fetched 42 table definitions")
stepper.log(1, "Applying 001_create_users.sql")
stepper.log(1, "Applying 002_add_indexes.sql")
stepper.log(1, "Applying 003_seed_config.sql")
stepper.log(1, "Applying 004_migrate_orders.sql") # oldest dropped (max_log_rows=3)
Console().print(stepper)
Logs render inline below (or above) each step label. Set max_log_rows to cap visible lines, or leave it None for terminal-height-aware truncation.
Log position
Control where logs appear relative to the step label:
from stepper import LogPosition, StepperTheme
theme = StepperTheme(log_position=LogPosition.ABOVE) # logs above the label
Progress Bars
Enable per-step progress bars with show_bar=True:
theme = StepperTheme(show_bar=True, bar_width=20)
stepper = Stepper(steps=steps, theme=theme, console=Console(), auto_refresh=False)
stepper.set_step_progress(1, 0.6) # 60% complete
Console().print(stepper)
The percent argument is clamped to [0.0, 1.0].
Elapsed Time
Show elapsed time per step:
theme = StepperTheme(show_elapsed_time=True)
Completed and active steps show elapsed time. Pending steps display -:--:--. Time freezes when a step is marked completed.
Dynamic Steps
Add steps at runtime inside a context manager:
with Stepper(theme=theme, console=console) as stepper:
for url, label in sites:
idx = stepper.add_step(label, status=StepStatus.ACTIVE, step_description=url)
stepper.log(idx, f"Fetching {url}")
# ... do work ...
stepper.set_step_status(idx, StepStatus.COMPLETED)
Theming
StepperTheme is a frozen dataclass — set any combination of fields at construction:
Symbols and styles
theme = StepperTheme(
completed_symbol="✓",
active_symbol="◎",
pending_symbol="○",
completed_style="green bold",
active_style="magenta bold",
pending_style="bright_black",
)
Connectors
theme = StepperTheme(
connector_symbol="│",
connector_style="bright_black",
line_thickness=2, # repeat connector symbol N times
step_gap=1, # blank lines between steps
)
Label formatting
theme = StepperTheme(
label_style="",
step_description_style="dim",
label_padding=2, # spaces before label text
)
Progress bar styling
theme = StepperTheme(
show_bar=True,
bar_width=20,
bar_complete_style="bar.complete",
bar_finished_style="bar.finished",
bar_pulse_style="bar.pulse",
)
Log styling
from stepper import LogPosition
theme = StepperTheme(
log_position=LogPosition.BELOW, # or LogPosition.ABOVE
max_log_rows=5, # None for terminal-aware
log_style="dim italic",
log_prefix="›",
)
Time column
theme = StepperTheme(
show_elapsed_time=True,
time_style="progress.elapsed",
)
API Reference
Stepper
Extends rich.progress.Progress. All Progress constructor args are forwarded.
| Method | Description |
|---|---|
Stepper(steps, theme, console, ...) |
Create stepper with optional initial steps and theme |
add_step(label, status, step_description) |
Add a step, returns TaskID |
add_steps(steps) |
Add multiple steps from StepDefinition list |
set_step_status(index, status) |
Update step status |
set_step_progress(index, percent) |
Set progress bar (0.0–1.0) |
log(index, message) |
Append a log message to a step |
StepStatus
| Value | Description |
|---|---|
StepStatus.PENDING |
Not yet started |
StepStatus.ACTIVE |
Currently running |
StepStatus.COMPLETED |
Finished |
LogPosition
| Value | Description |
|---|---|
LogPosition.BELOW |
Logs render below the step label (default) |
LogPosition.ABOVE |
Logs render above the step label |
StepDefinition
StepDefinition(label, status=StepStatus.PENDING, step_description=None)
StepperTheme
All fields have sensible defaults. Override any combination:
| Field | Type | Default |
|---|---|---|
completed_symbol |
str |
"●" |
active_symbol |
str |
"◉" |
pending_symbol |
str |
"○" |
completed_style |
str |
"green" |
active_style |
str |
"cyan bold" |
pending_style |
str |
"bright_black" |
connector_symbol |
str |
"│" |
connector_style |
str |
"bright_black" |
line_thickness |
int |
1 |
step_gap |
int |
0 |
label_style |
str |
"" |
step_description_style |
str |
"dim" |
label_padding |
int |
1 |
show_elapsed_time |
bool |
False |
time_style |
str |
"progress.elapsed" |
show_bar |
bool |
False |
bar_width |
int | None |
20 |
bar_complete_style |
str |
"bar.complete" |
bar_finished_style |
str |
"bar.finished" |
bar_pulse_style |
str |
"bar.pulse" |
log_position |
LogPosition |
LogPosition.BELOW |
max_log_rows |
int | None |
None |
log_style |
str |
"dim italic" |
log_prefix |
str |
"›" |
Examples
The examples/ directory contains 17 runnable scripts covering every feature:
| Example | Description |
|---|---|
01_basic |
Default theme with mixed statuses |
02_custom_colors |
Custom symbol and style colors |
03_emoji_symbols |
Emoji-based step indicators |
04_thick_connectors |
Multi-line connector glyphs |
05_step_gap |
Blank lines between steps |
06_all_completed |
All steps in completed state |
07_in_progress |
Partially completed workflow |
08_minimal_theme |
Stripped-down minimal appearance |
09_dense_layout |
Compact layout with descriptions |
10_many_steps |
Handling 10+ steps |
11_single_step |
Single-step edge case |
12_live_update |
Animated context manager usage |
13_elapsed_time |
Elapsed time column |
14_progress_bar |
Per-step progress bars |
15_step_logging |
Inline log messages |
16_full_featured |
Everything combined |
17_web_scraper |
Real-world web scraper demo |
Run any example directly:
python examples/16_full_featured.py
How It Works
Stepper extends Rich's Progress class with custom columns:
- StepIndicatorColumn — renders status symbols and vertical connectors
- StepLabelColumn — renders labels, descriptions, and inline logs
- StepperTimeColumn — renders elapsed/frozen time per step
Status mapping and log rendering are handled by shared StatusMapper and LogRenderer helpers for consistency across columns.
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rich_stepper-0.1.0.tar.gz.
File metadata
- Download URL: rich_stepper-0.1.0.tar.gz
- Upload date:
- Size: 26.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc1d848f5966f572d12515da331554de4110b76ef54a6571168737e063d7c427
|
|
| MD5 |
a017ebf0a17e8b20e48ffdcd66cd7e56
|
|
| BLAKE2b-256 |
0cd261cc0feed5b776e0359f0c63bc5f7fef8abe3e26eac0c6e2655bca5ed200
|
Provenance
The following attestation bundles were made for rich_stepper-0.1.0.tar.gz:
Publisher:
publish.yml on abbazs/rich-stepper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rich_stepper-0.1.0.tar.gz -
Subject digest:
dc1d848f5966f572d12515da331554de4110b76ef54a6571168737e063d7c427 - Sigstore transparency entry: 1193352048
- Sigstore integration time:
-
Permalink:
abbazs/rich-stepper@6607307515fd10cbdc701878805bd368909e0265 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/abbazs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6607307515fd10cbdc701878805bd368909e0265 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rich_stepper-0.1.0-py3-none-any.whl.
File metadata
- Download URL: rich_stepper-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f165aa0a8e2167c712309aca54c5aef3848c78c241431c9db2bcc331bbf0a8b
|
|
| MD5 |
a4a4f85ad44bbf2e3e16d0d1001f02ed
|
|
| BLAKE2b-256 |
bb7d8068bd7c56c1d8c5c05a3c38b6af3c9344496f13b872a430b769029f8990
|
Provenance
The following attestation bundles were made for rich_stepper-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on abbazs/rich-stepper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rich_stepper-0.1.0-py3-none-any.whl -
Subject digest:
3f165aa0a8e2167c712309aca54c5aef3848c78c241431c9db2bcc331bbf0a8b - Sigstore transparency entry: 1193352054
- Sigstore integration time:
-
Permalink:
abbazs/rich-stepper@6607307515fd10cbdc701878805bd368909e0265 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/abbazs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6607307515fd10cbdc701878805bd368909e0265 -
Trigger Event:
push
-
Statement type: