or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

console.mdcontainers.mdindex.mdinteractive.mdlayout.mdmarkdown.mdprogress.mdsyntax.mdtables.mdtext-styling.mdutilities.md

progress.mddocs/

0

# Progress Tracking

1

2

Advanced progress bar system with customizable columns, multiple tasks, and real-time updates. Rich provides comprehensive progress tracking capabilities for long-running operations with flexible display options.

3

4

## Capabilities

5

6

### Progress Class

7

8

Main progress tracking system with support for multiple concurrent tasks.

9

10

```python { .api }

11

class Progress:

12

"""

13

Multi-task progress tracker with customizable display.

14

15

Args:

16

*columns: Progress display columns

17

console: Console instance for output

18

auto_refresh: Enable automatic refresh

19

refresh_per_second: Refresh rate in Hz

20

speed_estimate_period: Period for speed calculation

21

transient: Remove progress display when complete

22

redirect_stdout: Redirect stdout during progress

23

redirect_stderr: Redirect stderr during progress

24

get_time: Function to get current time

25

disable: Disable progress display

26

expand: Expand progress bar to fit console width

27

"""

28

def __init__(

29

self,

30

*columns: Union[str, ProgressColumn],

31

console: Optional[Console] = None,

32

auto_refresh: bool = True,

33

refresh_per_second: float = 10,

34

speed_estimate_period: float = 30.0,

35

transient: bool = False,

36

redirect_stdout: bool = True,

37

redirect_stderr: bool = True,

38

get_time: Optional[GetTimeCallable] = None,

39

disable: bool = False,

40

expand: bool = False,

41

): ...

42

43

def add_task(

44

self,

45

description: str,

46

start: bool = True,

47

total: Optional[float] = 100.0,

48

completed: float = 0,

49

visible: bool = True,

50

**fields: Any,

51

) -> TaskID:

52

"""

53

Add a new progress task.

54

55

Args:

56

description: Task description

57

start: Start the task immediately

58

total: Total amount of work or None for indeterminate

59

completed: Initial completed amount

60

visible: Show task in display

61

**fields: Additional custom fields

62

63

Returns:

64

Task ID for future operations

65

"""

66

67

def remove_task(self, task_id: TaskID) -> None:

68

"""

69

Remove a task from progress tracking.

70

71

Args:

72

task_id: ID of task to remove

73

"""

74

75

def update(

76

self,

77

task_id: TaskID,

78

*,

79

total: Optional[float] = None,

80

completed: Optional[float] = None,

81

advance: Optional[float] = None,

82

description: Optional[str] = None,

83

visible: Optional[bool] = None,

84

refresh: bool = False,

85

**fields: Any,

86

) -> None:

87

"""

88

Update a progress task.

89

90

Args:

91

task_id: Task to update

92

total: New total amount

93

completed: New completed amount

94

advance: Amount to advance by

95

description: New description

96

visible: Show/hide task

97

refresh: Force display refresh

98

**fields: Update custom fields

99

"""

100

101

def advance(self, task_id: TaskID, advance: float = 1.0) -> None:

102

"""

103

Advance a task by specified amount.

104

105

Args:

106

task_id: Task to advance

107

advance: Amount to advance by

108

"""

109

110

def start_task(self, task_id: TaskID) -> None:

111

"""

112

Start a paused task.

113

114

Args:

115

task_id: Task to start

116

"""

117

118

def stop_task(self, task_id: TaskID) -> None:

119

"""

120

Stop/pause a task.

121

122

Args:

123

task_id: Task to stop

124

"""

125

126

def reset(

127

self,

128

task_id: TaskID,

129

*,

130

start: bool = True,

131

total: Optional[float] = None,

132

completed: float = 0,

133

visible: Optional[bool] = None,

134

description: Optional[str] = None,

135

**fields: Any,

136

) -> None:

137

"""

138

Reset a task to initial state.

139

140

Args:

141

task_id: Task to reset

142

start: Start task after reset

143

total: New total amount

144

completed: Reset completed amount

145

visible: Task visibility

146

description: New description

147

**fields: Reset custom fields

148

"""

149

150

def get_task(self, task_id: TaskID) -> Task:

151

"""

152

Get task information.

153

154

Args:

155

task_id: Task ID

156

157

Returns:

158

Task object with current state

159

"""

160

161

def refresh(self) -> None:

162

"""Force refresh of progress display."""

163

164

def start(self) -> None:

165

"""Start progress display."""

166

167

def stop(self) -> None:

168

"""Stop progress display."""

169

170

def track(

171

self,

172

sequence: Iterable[ProgressType],

173

task_id: Optional[TaskID] = None,

174

description: str = "Working...",

175

total: Optional[float] = None,

176

auto_refresh: bool = True,

177

console: Optional[Console] = None,

178

transient: bool = False,

179

get_time: Optional[GetTimeCallable] = None,

180

refresh_per_second: float = 10,

181

style: StyleType = "bar.back",

182

complete_style: StyleType = "bar.complete",

183

finished_style: StyleType = "bar.finished",

184

pulse_style: StyleType = "bar.pulse",

185

update_period: float = 0.1,

186

disable: bool = False,

187

show_speed: bool = True,

188

) -> Iterable[ProgressType]:

189

"""

190

Track progress of an iterable.

191

192

Args:

193

sequence: Iterable to track

194

task_id: Existing task ID or None for new task

195

description: Task description

196

total: Total items or None to auto-detect

197

auto_refresh: Enable automatic refresh

198

console: Console for output

199

transient: Remove when complete

200

get_time: Time function

201

refresh_per_second: Refresh rate

202

style: Progress bar style

203

complete_style: Completed portion style

204

finished_style: Finished bar style

205

pulse_style: Indeterminate pulse style

206

update_period: Update frequency

207

disable: Disable progress display

208

show_speed: Show processing speed

209

210

Returns:

211

Iterator that yields items while tracking progress

212

"""

213

214

@contextmanager

215

def wrap_file(

216

self,

217

file: BinaryIO,

218

total: int,

219

*,

220

task_id: Optional[TaskID] = None,

221

description: str = "Reading...",

222

) -> Iterator[BinaryIO]:

223

"""

224

Wrap a file for progress tracking.

225

226

Args:

227

file: File object to wrap

228

total: Total file size in bytes

229

task_id: Existing task ID or None for new task

230

description: Task description

231

232

Yields:

233

Wrapped file object that updates progress

234

"""

235

236

@contextmanager

237

def open(

238

self,

239

file: Union[str, "PathLike[str]", IO[bytes]],

240

mode: str = "rb",

241

*,

242

buffering: int = -1,

243

encoding: Optional[str] = None,

244

errors: Optional[str] = None,

245

newline: Optional[str] = None,

246

description: str = "Reading...",

247

auto_refresh: bool = True,

248

console: Optional[Console] = None,

249

transient: bool = False,

250

get_time: Optional[GetTimeCallable] = None,

251

refresh_per_second: float = 10,

252

style: StyleType = "bar.back",

253

complete_style: StyleType = "bar.complete",

254

finished_style: StyleType = "bar.finished",

255

pulse_style: StyleType = "bar.pulse",

256

disable: bool = False,

257

) -> Iterator[IO[Any]]:

258

"""

259

Open a file with progress tracking.

260

261

Args:

262

file: File path or file object

263

mode: File open mode

264

buffering: Buffer size

265

encoding: Text encoding

266

errors: Error handling

267

newline: Newline handling

268

description: Task description

269

auto_refresh: Enable automatic refresh

270

console: Console for output

271

transient: Remove when complete

272

get_time: Time function

273

refresh_per_second: Refresh rate

274

style: Progress bar style

275

complete_style: Completed portion style

276

finished_style: Finished bar style

277

pulse_style: Indeterminate pulse style

278

disable: Disable progress display

279

280

Yields:

281

File object with progress tracking

282

"""

283

284

# Properties

285

@property

286

def tasks(self) -> List[Task]:

287

"""Get list of all tasks."""

288

289

@property

290

def task_ids(self) -> List[TaskID]:

291

"""Get list of all task IDs."""

292

293

@property

294

def finished(self) -> bool:

295

"""Check if all tasks are finished."""

296

297

@property

298

def live(self) -> Live:

299

"""Get the underlying Live display."""

300

```

301

302

### Task Class

303

304

Task information and state.

305

306

```python { .api }

307

class Task:

308

"""

309

Progress task data and state.

310

311

Attributes:

312

id: Unique task identifier

313

description: Task description text

314

total: Total amount of work or None for indeterminate

315

completed: Amount of work completed

316

visible: Whether task is visible in display

317

fields: Custom data fields

318

created_time: Time when task was created

319

started_time: Time when task was started

320

stopped_time: Time when task was stopped

321

finished_time: Time when task finished

322

"""

323

id: TaskID

324

description: str

325

total: Optional[float]

326

completed: float

327

visible: bool

328

fields: Dict[str, Any]

329

created_time: float

330

started_time: Optional[float]

331

stopped_time: Optional[float]

332

finished_time: Optional[float]

333

334

@property

335

def elapsed(self) -> Optional[float]:

336

"""Get elapsed time since task started."""

337

338

@property

339

def finished(self) -> bool:

340

"""Check if task is finished."""

341

342

@property

343

def percentage(self) -> float:

344

"""Get completion percentage (0-100)."""

345

346

@property

347

def speed(self) -> Optional[float]:

348

"""Get current processing speed."""

349

350

@property

351

def time_remaining(self) -> Optional[float]:

352

"""Get estimated time remaining."""

353

```

354

355

### Progress Columns

356

357

Customizable display columns for progress bars.

358

359

```python { .api }

360

class ProgressColumn(ABC):

361

"""Base class for progress display columns."""

362

363

@abstractmethod

364

def render(self, task: Task) -> RenderableType:

365

"""

366

Render column content for a task.

367

368

Args:

369

task: Task to render

370

371

Returns:

372

Renderable content

373

"""

374

375

class RenderableColumn(ProgressColumn):

376

"""Column that displays a fixed renderable."""

377

378

def __init__(self, renderable: RenderableType, *, table_column: Optional[Column] = None): ...

379

380

class SpinnerColumn(ProgressColumn):

381

"""Column with animated spinner."""

382

383

def __init__(

384

self,

385

spinner_name: str = "dots",

386

style: Optional[StyleType] = None,

387

speed: float = 1.0,

388

finished_text: TextType = "✓",

389

table_column: Optional[Column] = None,

390

): ...

391

392

class TextColumn(ProgressColumn):

393

"""Column displaying task text/description."""

394

395

def __init__(

396

self,

397

text_format: str = "[progress.description]{task.description}",

398

style: StyleType = "",

399

justify: JustifyMethod = "left",

400

markup: bool = True,

401

highlighter: Optional[Highlighter] = None,

402

table_column: Optional[Column] = None,

403

): ...

404

405

class BarColumn(ProgressColumn):

406

"""Progress bar column."""

407

408

def __init__(

409

self,

410

bar_width: Optional[int] = 40,

411

style: StyleType = "bar.back",

412

complete_style: StyleType = "bar.complete",

413

finished_style: StyleType = "bar.finished",

414

pulse_style: StyleType = "bar.pulse",

415

table_column: Optional[Column] = None,

416

): ...

417

418

class TaskProgressColumn(TextColumn):

419

"""Column showing task progress percentage."""

420

421

def __init__(

422

self,

423

text_format: str = "[progress.percentage]{task.percentage:>3.1f}%",

424

style: StyleType = "",

425

justify: JustifyMethod = "left",

426

markup: bool = True,

427

highlighter: Optional[Highlighter] = None,

428

table_column: Optional[Column] = None,

429

): ...

430

431

class TimeElapsedColumn(ProgressColumn):

432

"""Column showing elapsed time."""

433

434

def __init__(self, table_column: Optional[Column] = None): ...

435

436

class TimeRemainingColumn(ProgressColumn):

437

"""Column showing estimated time remaining."""

438

439

def __init__(

440

self,

441

compact: bool = False,

442

elapsed_when_finished: bool = False,

443

table_column: Optional[Column] = None,

444

): ...

445

446

class FileSizeColumn(ProgressColumn):

447

"""Column showing file size completed."""

448

449

def __init__(self, table_column: Optional[Column] = None): ...

450

451

class TotalFileSizeColumn(ProgressColumn):

452

"""Column showing total file size."""

453

454

def __init__(self, table_column: Optional[Column] = None): ...

455

456

class MofNCompleteColumn(ProgressColumn):

457

"""Column showing 'M of N' completion."""

458

459

def __init__(

460

self,

461

separator: str = "/",

462

table_column: Optional[Column] = None,

463

): ...

464

465

class DownloadColumn(ProgressColumn):

466

"""Column for download progress with speed."""

467

468

def __init__(

469

self,

470

binary_units: bool = False,

471

table_column: Optional[Column] = None,

472

): ...

473

474

class TransferSpeedColumn(ProgressColumn):

475

"""Column showing transfer speed."""

476

477

def __init__(self, table_column: Optional[Column] = None): ...

478

```

479

480

**Usage Examples:**

481

482

```python

483

from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn, TimeElapsedColumn

484

import time

485

486

# Basic progress bar

487

with Progress() as progress:

488

task = progress.add_task("Processing...", total=100)

489

490

for i in range(100):

491

time.sleep(0.1)

492

progress.update(task, advance=1)

493

494

# Custom progress layout

495

progress = Progress(

496

SpinnerColumn(),

497

TextColumn("[progress.description]{task.description}"),

498

BarColumn(),

499

TaskProgressColumn(),

500

TimeElapsedColumn(),

501

)

502

503

with progress:

504

task1 = progress.add_task("Download", total=1000)

505

task2 = progress.add_task("Process", total=500)

506

507

# Simulate work

508

for i in range(1000):

509

time.sleep(0.01)

510

progress.update(task1, advance=1)

511

if i % 2 == 0:

512

progress.update(task2, advance=1)

513

514

# Multiple concurrent tasks

515

with Progress() as progress:

516

tasks = [

517

progress.add_task("Task 1", total=100),

518

progress.add_task("Task 2", total=200),

519

progress.add_task("Task 3", total=150),

520

]

521

522

# Process tasks concurrently

523

import threading

524

525

def work(task_id, total):

526

for i in range(total):

527

time.sleep(0.05)

528

progress.update(task_id, advance=1)

529

530

threads = []

531

for task_id, total in zip(tasks, [100, 200, 150]):

532

thread = threading.Thread(target=work, args=(task_id, total))

533

threads.append(thread)

534

thread.start()

535

536

for thread in threads:

537

thread.join()

538

539

# Track iterable

540

from rich.progress import track

541

542

items = range(100)

543

for item in track(items, description="Processing items..."):

544

time.sleep(0.1) # Simulate work

545

546

# File download simulation

547

from rich.progress import Progress, DownloadColumn, TransferSpeedColumn

548

549

def download_file(url, size):

550

"""Simulate file download."""

551

progress = Progress(

552

TextColumn("[bold blue]{task.description}", justify="right"),

553

BarColumn(bar_width=None),

554

"[progress.percentage]{task.percentage:>3.1f}%",

555

"•",

556

DownloadColumn(),

557

"•",

558

TransferSpeedColumn(),

559

"•",

560

TimeElapsedColumn(),

561

)

562

563

with progress:

564

task = progress.add_task("download", filename=url, total=size)

565

for chunk_size in [500, 600, 300, 400, 800, 200]:

566

time.sleep(0.5) # Simulate network delay

567

progress.update(task, advance=chunk_size)

568

569

# Example: download_file("example.zip", 3000)

570

571

# Indeterminate progress (no known total)

572

with Progress() as progress:

573

task = progress.add_task("Scanning...", total=None)

574

575

for i in range(50):

576

time.sleep(0.1)

577

progress.update(task, advance=1) # Still advances for timing

578

579

# Progress with custom fields

580

with Progress() as progress:

581

task = progress.add_task("Custom Task", total=100, status="Starting")

582

583

for i in range(100):

584

status = f"Processing item {i+1}"

585

progress.update(task, advance=1, status=status)

586

time.sleep(0.05)

587

588

# File processing with progress

589

from rich.progress import Progress

590

591

def process_files(file_paths):

592

with Progress() as progress:

593

main_task = progress.add_task("Processing files", total=len(file_paths))

594

595

for file_path in file_paths:

596

# Process individual file

597

file_task = progress.add_task(f"Processing {file_path}", total=100)

598

599

for chunk in range(100):

600

time.sleep(0.01) # Simulate file processing

601

progress.update(file_task, advance=1)

602

603

progress.update(main_task, advance=1)

604

progress.remove_task(file_task)

605

606

# Example: process_files(["file1.txt", "file2.txt", "file3.txt"])

607

```