or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-support.mdcallbacks-hooks.mdcore-decorator.mdindex.mdretry-strategies.mdstop-conditions.mdutilities.mdwait-strategies.md

core-decorator.mddocs/

0

# Core Decorator & Classes

1

2

This document covers the main `@retry` decorator and core retry controller classes that form the foundation of tenacity's retry framework.

3

4

## Main Decorator

5

6

```python { .api }

7

from tenacity import retry

8

9

def retry(

10

sleep: Callable[[float], None] = sleep,

11

stop: StopBaseT = stop_never,

12

wait: WaitBaseT = wait_none(),

13

retry: RetryBaseT = retry_if_exception_type(),

14

before: Callable[[RetryCallState], None] = before_nothing,

15

after: Callable[[RetryCallState], None] = after_nothing,

16

before_sleep: Optional[Callable[[RetryCallState], None]] = None,

17

reraise: bool = False,

18

retry_error_cls: type = RetryError,

19

retry_error_callback: Optional[Callable[[RetryCallState], Any]] = None

20

) -> Callable[[WrappedFn], WrappedFn]:

21

"""

22

Main decorator to add retry behavior to functions.

23

24

Auto-detects async/tornado functions and applies appropriate retry controller.

25

Supports both synchronous and asynchronous functions seamlessly.

26

27

Parameters:

28

- sleep: Function to use for sleeping between retries (default: time.sleep)

29

- stop: Strategy determining when to stop retrying (default: never stop)

30

- wait: Strategy determining delay between retries (default: no wait)

31

- retry: Strategy determining whether to retry after failure (default: retry on any exception)

32

- before: Callback executed before each attempt (default: no-op)

33

- after: Callback executed after each attempt (default: no-op)

34

- before_sleep: Callback executed before sleeping between retries (default: None)

35

- reraise: If True, reraise original exception instead of RetryError (default: False)

36

- retry_error_cls: Exception class to raise when retries exhausted (default: RetryError)

37

- retry_error_callback: Callback executed when retries exhausted (default: None)

38

39

Returns:

40

Decorated function with retry behavior applied.

41

"""

42

```

43

44

### Usage Examples

45

46

```python { .api }

47

# Basic retry on any exception

48

@retry

49

def might_fail():

50

pass

51

52

# Retry with exponential backoff and attempt limit

53

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))

54

def api_call():

55

pass

56

57

# Retry specific exceptions only

58

@retry(retry=retry_if_exception_type((ConnectionError, TimeoutError)))

59

def network_operation():

60

pass

61

62

# Auto-detects async functions

63

@retry(stop=stop_after_delay(30))

64

async def async_operation():

65

pass

66

```

67

68

## Core Retry Controllers

69

70

### BaseRetrying

71

72

```python { .api }

73

from tenacity import BaseRetrying

74

75

class BaseRetrying(ABC):

76

"""

77

Abstract base class for all retry controllers.

78

79

Provides the common interface and shared functionality for retry behavior.

80

All concrete retry controllers inherit from this class.

81

"""

82

83

def __init__(

84

self,

85

sleep: Callable[[float], None] = sleep,

86

stop: StopBaseT = stop_never,

87

wait: WaitBaseT = wait_none(),

88

retry: RetryBaseT = retry_if_exception_type(),

89

before: Callable[[RetryCallState], None] = before_nothing,

90

after: Callable[[RetryCallState], None] = after_nothing,

91

before_sleep: Optional[Callable[[RetryCallState], None]] = None,

92

reraise: bool = False,

93

retry_error_cls: type = RetryError,

94

retry_error_callback: Optional[Callable[[RetryCallState], Any]] = None

95

):

96

"""Initialize retry controller with strategies and callbacks."""

97

98

def copy(self, **kwargs) -> 'Self':

99

"""

100

Create a copy of this retrying object with modified parameters.

101

102

Parameters can be any of the constructor parameters.

103

Useful for creating variations of retry behavior.

104

"""

105

106

def wraps(self, f: WrappedFn) -> WrappedFn:

107

"""

108

Wrap a function with this retry behavior.

109

110

Returns a new function that will retry according to this controller's configuration.

111

"""

112

113

def begin(self) -> RetryCallState:

114

"""

115

Initialize a new retry session.

116

117

Creates and returns a RetryCallState tracking the retry session.

118

"""

119

120

def iter(self, retry_state: RetryCallState) -> Iterator[AttemptManager]:

121

"""

122

Execute one iteration of the retry loop.

123

124

Yields AttemptManager context managers for each retry attempt.

125

"""

126

127

@abstractmethod

128

def __call__(self, fn: Callable[..., Any], *args, **kwargs) -> Any:

129

"""Execute function with retry logic. Must be implemented by subclasses."""

130

131

def __iter__(self) -> Iterator[AttemptManager]:

132

"""Iterator interface for attempt managers."""

133

134

@property

135

def statistics(self) -> dict:

136

"""Runtime statistics for this retry controller."""

137

138

@property

139

def iter_state(self) -> IterState:

140

"""Current iteration state."""

141

```

142

143

### Retrying

144

145

```python { .api }

146

from tenacity import Retrying

147

148

class Retrying(BaseRetrying):

149

"""

150

Standard synchronous retry controller.

151

152

Handles retry logic for regular (non-async) functions.

153

This is the default controller used by the @retry decorator for sync functions.

154

"""

155

156

def __call__(self, fn: Callable[..., Any], *args, **kwargs) -> Any:

157

"""

158

Execute function with synchronous retry logic.

159

160

Parameters:

161

- fn: Function to execute with retries

162

- *args: Positional arguments to pass to fn

163

- **kwargs: Keyword arguments to pass to fn

164

165

Returns:

166

Result of successful function execution.

167

168

Raises:

169

RetryError: When all retry attempts are exhausted

170

"""

171

```

172

173

### AsyncRetrying

174

175

```python { .api }

176

from tenacity import AsyncRetrying

177

178

class AsyncRetrying(BaseRetrying):

179

"""

180

Asynchronous retry controller for coroutines.

181

182

Handles retry logic for async/await functions and coroutines.

183

Auto-detects trio vs asyncio for appropriate sleep function.

184

"""

185

186

async def __call__(self, fn: Callable[..., Any], *args, **kwargs) -> Any:

187

"""

188

Execute coroutine with asynchronous retry logic.

189

190

Parameters:

191

- fn: Async function/coroutine to execute with retries

192

- *args: Positional arguments to pass to fn

193

- **kwargs: Keyword arguments to pass to fn

194

195

Returns:

196

Result of successful coroutine execution.

197

198

Raises:

199

RetryError: When all retry attempts are exhausted

200

"""

201

202

def __aiter__(self) -> AsyncIterator[AttemptManager]:

203

"""Async iterator interface for attempt managers."""

204

205

async def __anext__(self) -> AttemptManager:

206

"""Async iteration support."""

207

```

208

209

### TornadoRetrying

210

211

```python { .api }

212

from tenacity.tornadoweb import TornadoRetrying

213

214

class TornadoRetrying(BaseRetrying):

215

"""

216

Tornado web framework retry controller.

217

218

Specialized retry controller for Tornado's @gen.coroutine decorated functions.

219

Uses Tornado's IOLoop for asynchronous sleep operations.

220

"""

221

222

@gen.coroutine

223

def __call__(self, fn: Callable[..., Any], *args, **kwargs) -> Any:

224

"""

225

Execute Tornado coroutine with retry logic.

226

227

Uses Tornado's generator-based coroutine model and IOLoop.sleep.

228

229

Parameters:

230

- fn: Tornado coroutine to execute with retries

231

- *args: Positional arguments to pass to fn

232

- **kwargs: Keyword arguments to pass to fn

233

234

Returns:

235

tornado.concurrent.Future with result of successful execution.

236

"""

237

```

238

239

## State Management Classes

240

241

### RetryCallState

242

243

```python { .api }

244

from tenacity import RetryCallState

245

246

class RetryCallState:

247

"""

248

Tracks the complete state of a retry session.

249

250

Contains all information about the current retry attempt, timing,

251

outcomes, and configuration. Passed to all callbacks and strategies.

252

"""

253

254

# Core execution context

255

start_time: float # When the retry session began

256

retry_object: BaseRetrying # The retry controller instance

257

fn: Callable[..., Any] # Function being retried

258

args: tuple # Function positional arguments

259

kwargs: dict # Function keyword arguments

260

261

# Attempt tracking

262

attempt_number: int # Current attempt number (starts at 1)

263

outcome: Future # Result of last attempt

264

outcome_timestamp: Optional[float] # When outcome was set

265

266

# Timing information

267

idle_for: float # Total time spent sleeping

268

upcoming_sleep: float # Next sleep duration

269

seconds_since_start: float # Elapsed time since first attempt

270

271

# Flow control

272

next_action: Optional[BaseAction] # Next action to take (retry/stop)

273

274

def prepare_for_next_attempt(self) -> None:

275

"""Reset state for the next retry attempt."""

276

277

def set_result(self, val: Any) -> None:

278

"""Set successful result for this attempt."""

279

280

def set_exception(self, exc_info: tuple) -> None:

281

"""Set exception result for this attempt."""

282

```

283

284

### Future

285

286

```python { .api }

287

from tenacity import Future

288

289

class Future:

290

"""

291

Container for attempt results (success or exception).

292

293

Encapsulates the outcome of a single retry attempt, including

294

the attempt number and whether it failed.

295

"""

296

297

def __init__(self, attempt_number: int):

298

"""

299

Initialize Future for given attempt number.

300

301

Parameters:

302

- attempt_number: Which attempt this result represents

303

"""

304

305

@property

306

def attempt_number(self) -> int:

307

"""The attempt number this result is from."""

308

309

@property

310

def failed(self) -> bool:

311

"""True if this attempt resulted in an exception."""

312

313

@classmethod

314

def construct(

315

cls,

316

attempt_number: int,

317

value: Any,

318

has_exception: bool

319

) -> 'Future':

320

"""

321

Create Future with result value or exception.

322

323

Parameters:

324

- attempt_number: Which attempt this represents

325

- value: The result value or exception

326

- has_exception: True if value is an exception

327

328

Returns:

329

Future instance with the result set

330

"""

331

```

332

333

### AttemptManager

334

335

```python { .api }

336

from tenacity import AttemptManager

337

338

class AttemptManager:

339

"""

340

Context manager for individual retry attempts.

341

342

Handles entering/exiting attempt context and capturing

343

results or exceptions from the attempt.

344

"""

345

346

def __init__(self, retry_state: RetryCallState):

347

"""Initialize attempt manager with retry state."""

348

349

def __enter__(self) -> 'AttemptManager':

350

"""Enter attempt context."""

351

352

def __exit__(

353

self,

354

exc_type: Optional[type],

355

exc_value: Optional[BaseException],

356

traceback: Optional[Any]

357

) -> Optional[bool]:

358

"""

359

Exit attempt context and capture result.

360

361

Captures successful results or exceptions and updates retry state.

362

"""

363

```

364

365

## Action Classes

366

367

### BaseAction

368

369

```python { .api }

370

from tenacity import BaseAction

371

372

class BaseAction:

373

"""

374

Abstract base class for retry actions.

375

376

Represents different actions that can be taken during retry logic.

377

"""

378

379

REPR_FIELDS: tuple = () # Fields to include in string representation

380

NAME: str = "" # Human-readable action name

381

```

382

383

### RetryAction

384

385

```python { .api }

386

from tenacity import RetryAction

387

388

class RetryAction(BaseAction):

389

"""

390

Action representing a retry with specified sleep time.

391

392

Indicates that another attempt should be made after sleeping

393

for the specified duration.

394

"""

395

396

def __init__(self, sleep: float):

397

"""

398

Initialize retry action with sleep duration.

399

400

Parameters:

401

- sleep: Number of seconds to sleep before next attempt

402

"""

403

404

@property

405

def sleep(self) -> float:

406

"""Sleep duration for this retry action."""

407

```

408

409

### Control Flow Markers

410

411

```python { .api }

412

from tenacity import DoAttempt, DoSleep

413

414

class DoAttempt:

415

"""Marker class indicating an attempt should be made."""

416

pass

417

418

class DoSleep(float):

419

"""

420

Marker class indicating sleep should occur.

421

422

Inherits from float to carry the sleep duration.

423

"""

424

pass

425

```

426

427

### IterState

428

429

```python { .api }

430

from tenacity import IterState

431

432

@dataclass

433

class IterState:

434

"""

435

Tracks iteration state within the retry loop.

436

437

Maintains the current state of retry condition evaluation,

438

actions to execute, and timing information.

439

"""

440

441

actions: list = field(default_factory=list)

442

retry_run_result: bool = False

443

delay_since_first_attempt: float = 0

444

stop_run_result: bool = False

445

is_explicit_retry: bool = False

446

447

def reset(self) -> None:

448

"""Reset all fields to their default values."""

449

```

450

451

## Constants and Utilities

452

453

```python { .api }

454

from tenacity import NO_RESULT, WrappedFn, WrappedFnReturnT

455

456

# Sentinel object for unset results

457

NO_RESULT: object

458

459

# Type variables for function wrapping

460

WrappedFn = TypeVar('WrappedFn', bound=Callable[..., Any])

461

WrappedFnReturnT = TypeVar('WrappedFnReturnT')

462

```

463

464

## Usage Patterns

465

466

### Direct Controller Usage

467

468

```python { .api }

469

# Create retry controller directly

470

retrying = Retrying(

471

stop=stop_after_attempt(3),

472

wait=wait_exponential(multiplier=1, min=4, max=10)

473

)

474

475

# Use with different functions

476

result1 = retrying(function1, arg1, arg2)

477

result2 = retrying(function2, kwarg=value)

478

479

# Create variations

480

fast_retrying = retrying.copy(wait=wait_fixed(1))

481

```

482

483

### Async Controller Usage

484

485

```python { .api }

486

# Async retry controller

487

async_retrying = AsyncRetrying(

488

stop=stop_after_delay(30),

489

retry=retry_if_exception_type(ConnectionError)

490

)

491

492

# Use with async functions

493

result = await async_retrying(async_function, param=value)

494

```

495

496

### Iterator Interface

497

498

```python { .api }

499

# Manual retry loop with attempt managers

500

retrying = Retrying(stop=stop_after_attempt(3))

501

502

for attempt in retrying:

503

with attempt:

504

# Your code that might fail

505

result = risky_operation()

506

break # Success - exit retry loop

507

```

508

509

This comprehensive coverage of core classes provides the foundation for understanding tenacity's retry framework and enables building sophisticated retry logic for any use case.