Terminal progress bars via decorators
Project description
⏱ timeo
Terminal progress bars for Python functions — just add a decorator.
✓ process_files ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 12.4s
download_data ━━━━━━━━━━━━━━━━━━━━━━━ 72% 0:00:04
compress_output ━━━━━━ 20% 0:00:31
Why timeo?
Most progress bar libraries ask you to wrap your loops manually and manage the display yourself. timeo gets out of the way — decorate a function, iterate normally, done.
# before
for item in items:
process(item)
# after
@timeo.track
def run(items):
for item in timeo.iter(items):
process(item)
Installation
pip install timeo
Usage
Basic progress bar
@timeo.track wraps any function with a live progress bar. The total is inferred automatically from the first argument with a len(). Use timeo.iter() to advance the bar on each iteration — no manual bookkeeping needed.
import timeo
@timeo.track
def process_files(files):
for f in timeo.iter(files):
do_work(f)
process_files(my_files)
Prefer manual control? Use timeo.advance() instead:
@timeo.track
def process_files(files):
for f in files:
do_work(f)
timeo.advance()
Multiple concurrent functions
Every decorated function gets its own bar. They render together in a single live display. Finished bars collapse to a compact summary line so the output stays clean.
@timeo.track
def process_files(files):
for f in timeo.iter(files):
do_work(f)
@timeo.track
def download_data(urls):
for url in timeo.iter(urls):
fetch(url)
process_files(my_files)
download_data(my_urls)
✓ process_files ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 12.4s
download_data ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 72% 0:00:04
Concurrent execution (threads) is fully supported — each bar tracks its own function independently.
Learn mode
Add learn=True and timeo will remember how long your function takes across runs, building an EMA (exponential moving average) of its runtime. Instead of counting steps, the bar fills over the expected duration.
@timeo.track(learn=True)
def run_pipeline(data):
heavy_computation(data)
more_work(data)
| Run | Behaviour |
|---|---|
| First | Indeterminate spinner with run_pipeline (learning...) label |
| Subsequent | Determinate bar filling over the expected duration |
| After code change | Cache invalidates automatically — learning restarts |
The cache key is a hash of the function's bytecode — not its name — so renaming a function preserves its history, and changing its implementation resets it.
By default timing data is stored in your platform's user cache directory (e.g. ~/Library/Caches/timeo/timings.json on macOS). Use cache="project" to store it in .timeo/timings.json relative to the current directory instead — useful for per-project isolation or sharing timings with a team via version control:
@timeo.track(learn=True, cache="project")
def run_pipeline(data):
...
Note: If using
cache="project", add.timeo/to your.gitignoreunless you intentionally want to commit timing data.
cache= |
Location | Best for |
|---|---|---|
"user" (default) |
~/.cache/timeo/timings.json |
Personal scripts, cross-project reuse |
"project" |
.timeo/timings.json |
Per-project isolation, shared team timings |
Explicit display control
The live display starts and stops automatically in most cases. For complex scripts with branching logic or long-running setup, use timeo.live() to pin the display lifetime explicitly:
with timeo.live():
process_files(my_files)
download_data(my_urls)
# display stays open until the with-block exits
How it works
| Piece | Role |
|---|---|
@timeo.track |
Wraps the function, infers total from Sized args, manages the task lifecycle |
ProgressManager |
Singleton owning the rich live display; reference-counted so it tears down only when all tasks finish |
TrackedTask |
Dataclass holding per-function progress state |
timeo.iter() |
Thin generator wrapper that calls advance() on each item |
ContextVar |
Ensures timeo.advance() always updates the right bar, even across threads |
The display is built on rich.progress and rich.live.
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 timeo-0.3.0.tar.gz.
File metadata
- Download URL: timeo-0.3.0.tar.gz
- Upload date:
- Size: 32.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5accfe84ccf5c4d1b9983b7924a9d70b96e1f714d910f406dd9f5768d8f52505
|
|
| MD5 |
4bcc620a29fbf74336be4f8e0f157902
|
|
| BLAKE2b-256 |
e9c95f89220672b3f1206deaa379bbeb8a7fcbac62c7e4633ed86ab97ca30268
|
Provenance
The following attestation bundles were made for timeo-0.3.0.tar.gz:
Publisher:
publish.yml on wtewalt/timeo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
timeo-0.3.0.tar.gz -
Subject digest:
5accfe84ccf5c4d1b9983b7924a9d70b96e1f714d910f406dd9f5768d8f52505 - Sigstore transparency entry: 1263230849
- Sigstore integration time:
-
Permalink:
wtewalt/timeo@facfcac7ed680b9109e779b97710e3eb23863605 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/wtewalt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@facfcac7ed680b9109e779b97710e3eb23863605 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file timeo-0.3.0-py3-none-any.whl.
File metadata
- Download URL: timeo-0.3.0-py3-none-any.whl
- Upload date:
- Size: 11.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4169bce882209da6ad4ff2742f77976f12373112db00432979456c3521fb697
|
|
| MD5 |
6c86a0bcb7089e784f30f26b5ca48f24
|
|
| BLAKE2b-256 |
78fc0a97daa6752378f6acc393af39340c0579ab487cf8bc3e9b8d9645b35c0c
|
Provenance
The following attestation bundles were made for timeo-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on wtewalt/timeo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
timeo-0.3.0-py3-none-any.whl -
Subject digest:
d4169bce882209da6ad4ff2742f77976f12373112db00432979456c3521fb697 - Sigstore transparency entry: 1263230853
- Sigstore integration time:
-
Permalink:
wtewalt/timeo@facfcac7ed680b9109e779b97710e3eb23863605 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/wtewalt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@facfcac7ed680b9109e779b97710e3eb23863605 -
Trigger Event:
workflow_dispatch
-
Statement type: