Metadata-Version: 2.4
Name: elapse
Version: 0.1.0
Summary: A lightweight stopwatch with context manager, live reads, lap support, and human-readable formatting
Project-URL: Repository, https://github.com/cathackk/elapse
Author: cathackk
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Benchmark
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# elapse

A lightweight Python stopwatch with context manager support, live reads mid-execution, lap timing, and human-readable duration formatting. Zero dependencies.

## Install

```bash
pip install elapse
```

## Usage

### Basic timing with context manager

```python
from elapse import StopWatch

with StopWatch() as sw:
    do_work()
    print(f"so far: {sw}")  # reads live while still running

print(f"total: {sw}")  # final time after exiting
```

Output:
```
so far: 1.234 s
total: 2.507 s
```

Durations auto-scale to human-readable units:

```
0.042 s
5 min 33.300 s
2 h 9 min 37.700 s
```

### Measuring multiple blocks

A stopped stopwatch can be reused to accumulate time across separate blocks:

```python
with StopWatch() as duration:
    stuff_1()

non_measured_stuff()

with duration:
    stuff_2()

print(duration)  # stuff_1() + stuff_2(), excluding non_measured_stuff()
```

### Nesting stopwatches

Use separate instances to measure total and per-phase time simultaneously:

```python
with StopWatch() as total:
    with StopWatch() as phase_1:
        stuff_1()
    with StopWatch() as phase_2:
        stuff_2()

print(f"total: {total}, phase 1: {phase_1}, phase 2: {phase_2}")
```

### Laps

```python
sw = StopWatch().start()
run_phase_1()
sw.lap()
run_phase_2()
sw.lap()
sw.stop()
print(sw)  # 5.200 s [2.100 s, 3.100 s]
```

### Manual start/stop

```python
sw = StopWatch()
sw.start()
# ... work ...
sw.stop()
print(sw.seconds())   # float
print(sw.delta())      # timedelta

sw.reset()
sw.start()
# ... more work ...
```

Calling `start()` on an already-running stopwatch raises `RuntimeError`. Calling `stop()` on a stopped watch is a no-op. `reset()` clears elapsed time and laps but keeps the watch running if it was running.

### Precision

Control decimal places with the `precision` parameter (default 3):

```python
print(StopWatch(elapsed_seconds=1.5, precision=1))  # 1.5 s
print(StopWatch(elapsed_seconds=1.5, precision=5))  # 1.50000 s
```

### Standalone duration formatting

```python
from elapse import duration_str

duration_str(90.5)      # '1 min 30.500 s'
duration_str(7200, 0)   # '2 h 0 min 0 s'
```

## License

MIT
