or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

component-system.mdcontainer-management.mdframework-integrations.mdindex.mdprovider-system.mdscope-lifecycle.mdtype-markers.mdvalidation-configuration.md

provider-system.mddocs/

0

# Provider System

1

2

Modular provider classes and dependency registration functions for creating reusable dependency factories. Providers organize related dependencies and can be combined to build complex dependency graphs.

3

4

## Capabilities

5

6

### Provider Class

7

8

Main provider class for organizing and registering dependency factories with flexible configuration options.

9

10

```python { .api }

11

class Provider(BaseProvider):

12

def __init__(

13

self,

14

scope: BaseScope | None = None,

15

component: Component | None = None

16

):

17

"""

18

Create a new provider.

19

20

Parameters:

21

- scope: Default scope for dependencies registered in this provider

22

- component: Default component for dependencies in this provider

23

"""

24

25

def provide(

26

self,

27

source: Any,

28

*,

29

scope: BaseScope | None = None,

30

provides: Any | None = None,

31

cache: bool = True,

32

recursive: bool = False,

33

override: bool = False

34

) -> None:

35

"""

36

Register a dependency factory.

37

38

Parameters:

39

- source: Class or factory function to provide the dependency

40

- scope: Lifecycle scope (overrides provider default)

41

- provides: Type to provide (inferred from source if not specified)

42

- cache: Whether to cache instances within scope

43

- recursive: Whether to recursively provide parent types

44

- override: Whether to override existing registrations

45

"""

46

47

def provide_all(

48

self,

49

*provides: Any,

50

scope: BaseScope | None = None,

51

cache: bool = True,

52

recursive: bool = False,

53

override: bool = False

54

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

55

"""

56

Register multiple types from a single source.

57

58

Parameters:

59

- provides: Types to provide from the decorated source

60

- scope: Lifecycle scope (overrides provider default)

61

- cache: Whether to cache instances within scope

62

- recursive: Whether to recursively provide parent types

63

- override: Whether to override existing registrations

64

65

Returns:

66

Decorator function

67

"""

68

69

def alias(

70

self,

71

source: Any,

72

*,

73

provides: Any | None = None,

74

cache: bool = True,

75

component: Component | None = None,

76

override: bool = False

77

) -> None:

78

"""

79

Create an alias for an existing dependency.

80

81

Parameters:

82

- source: Type of the existing dependency to alias

83

- provides: Type to provide as alias (inferred if not specified)

84

- cache: Whether to cache the alias

85

- component: Component to look for source in

86

- override: Whether to override existing registrations

87

"""

88

89

def decorate(

90

self,

91

source: Any,

92

*,

93

provides: Any | None = None

94

) -> None:

95

"""

96

Register a decorator for dependency modification.

97

98

Parameters:

99

- source: Decorator function that modifies the dependency

100

- provides: Type to decorate (inferred if not specified)

101

"""

102

103

def from_context(

104

self,

105

provides: Any,

106

*,

107

scope: BaseScope | None = None,

108

override: bool = False

109

) -> None:

110

"""

111

Register a context variable as a dependency.

112

113

Parameters:

114

- provides: Type to provide from context

115

- scope: Lifecycle scope (overrides provider default)

116

- override: Whether to override existing registrations

117

"""

118

119

def to_component(self, component: Component) -> ProviderWrapper:

120

"""

121

Create a wrapper that registers all dependencies in a specific component.

122

123

Parameters:

124

- component: Component identifier

125

126

Returns:

127

ProviderWrapper for the specified component

128

"""

129

```

130

131

**Usage Example:**

132

133

```python

134

from dishka import Provider, Scope

135

from typing import Protocol

136

137

class Database(Protocol):

138

def query(self, sql: str) -> list: ...

139

140

class PostgreSQLDB:

141

def __init__(self, connection_string: str):

142

self.connection_string = connection_string

143

144

def query(self, sql: str) -> list:

145

return []

146

147

class UserService:

148

def __init__(self, db: Database):

149

self.db = db

150

151

# Create provider

152

provider = Provider(scope=Scope.REQUEST)

153

154

# Register dependencies

155

provider.provide(PostgreSQLDB, provides=Database, scope=Scope.APP)

156

provider.provide(UserService)

157

158

# Register with alias

159

provider.alias(Database, provides=Protocol)

160

```

161

162

### Provide Decorator

163

164

Function and decorator for registering dependency factories with flexible configuration.

165

166

```python { .api }

167

def provide(

168

source: Any = None,

169

*,

170

scope: BaseScope | None = None,

171

provides: Any | None = None,

172

cache: bool = True,

173

recursive: bool = False,

174

override: bool = False

175

) -> Any:

176

"""

177

Register a dependency factory (can be used as decorator or direct call).

178

179

Parameters:

180

- source: Class or factory function (when used directly)

181

- scope: Lifecycle scope for the dependency

182

- provides: Type to provide (inferred from source if not specified)

183

- cache: Whether to cache instances within scope

184

- recursive: Whether to recursively provide parent types

185

- override: Whether to override existing registrations

186

187

Returns:

188

When used as decorator: decorator function

189

When used directly: CompositeDependencySource

190

"""

191

```

192

193

**Usage Examples:**

194

195

```python

196

# As a decorator

197

@provide(scope=Scope.APP, provides=Database)

198

def create_database() -> PostgreSQLDB:

199

return PostgreSQLDB("postgresql://localhost/db")

200

201

# On a class

202

@provide(scope=Scope.REQUEST)

203

class UserService:

204

def __init__(self, db: Database):

205

self.db = db

206

207

# Direct usage

208

provide(PostgreSQLDB, provides=Database, scope=Scope.APP)

209

210

# In a provider class

211

class DatabaseProvider(Provider):

212

@provide(scope=Scope.APP)

213

def connection_string(self) -> str:

214

return "postgresql://localhost/db"

215

216

@provide(scope=Scope.APP, provides=Database)

217

def database(self, conn_str: str) -> PostgreSQLDB:

218

return PostgreSQLDB(conn_str)

219

```

220

221

### Provide All Decorator

222

223

Decorator for registering multiple types from a single source.

224

225

```python { .api }

226

def provide_all(

227

*provides: Any,

228

scope: BaseScope | None = None,

229

cache: bool = True,

230

recursive: bool = False,

231

override: bool = False

232

) -> Callable[[Any], CompositeDependencySource]:

233

"""

234

Register multiple types from a single source.

235

236

Parameters:

237

- provides: Types to provide from the decorated source

238

- scope: Lifecycle scope for all provided types

239

- cache: Whether to cache instances within scope

240

- recursive: Whether to recursively provide parent types

241

- override: Whether to override existing registrations

242

243

Returns:

244

Decorator function

245

"""

246

```

247

248

**Usage Example:**

249

250

```python

251

from typing import Protocol

252

253

class Readable(Protocol):

254

def read(self) -> str: ...

255

256

class Writable(Protocol):

257

def write(self, data: str) -> None: ...

258

259

@provide_all(Readable, Writable, scope=Scope.REQUEST)

260

class FileHandler:

261

def __init__(self, filename: str):

262

self.filename = filename

263

264

def read(self) -> str:

265

return "file contents"

266

267

def write(self, data: str) -> None:

268

pass

269

```

270

271

### Alias Function

272

273

Function for creating dependency aliases to map interfaces to implementations.

274

275

```python { .api }

276

def alias(

277

source: Any,

278

*,

279

provides: Any | None = None,

280

cache: bool = True,

281

component: Component | None = None,

282

override: bool = False

283

) -> CompositeDependencySource:

284

"""

285

Create an alias for an existing dependency.

286

287

Parameters:

288

- source: Type of the existing dependency to alias

289

- provides: Type to provide as alias (inferred if not specified)

290

- cache: Whether to cache the alias

291

- component: Component to look for source in

292

- override: Whether to override existing registrations

293

294

Returns:

295

CompositeDependencySource for the alias

296

"""

297

```

298

299

**Usage Example:**

300

301

```python

302

# Direct usage

303

alias(PostgreSQLDB, provides=Database)

304

305

# In a provider

306

provider = Provider()

307

provider.provide(PostgreSQLDB, scope=Scope.APP)

308

provider.alias(PostgreSQLDB, provides=Database)

309

310

# In a provider class

311

class DatabaseProvider(Provider):

312

postgres_db = provide(PostgreSQLDB, scope=Scope.APP)

313

database = alias(PostgreSQLDB, provides=Database)

314

```

315

316

### Decorate Function

317

318

Function and decorator for registering dependency decorators that modify existing dependencies.

319

320

```python { .api }

321

def decorate(

322

source: Any = None,

323

*,

324

provides: Any | None = None

325

) -> Any:

326

"""

327

Register a decorator for dependency modification.

328

329

Parameters:

330

- source: Decorator function (when used directly)

331

- provides: Type to decorate (inferred if not specified)

332

333

Returns:

334

When used as decorator: decorator function

335

When used directly: CompositeDependencySource

336

"""

337

```

338

339

**Usage Example:**

340

341

```python

342

# As a decorator

343

@decorate(provides=Database)

344

def add_logging(db: Database) -> Database:

345

class LoggingDatabase:

346

def __init__(self, wrapped_db: Database):

347

self.db = wrapped_db

348

349

def query(self, sql: str) -> list:

350

print(f"Executing: {sql}")

351

return self.db.query(sql)

352

353

return LoggingDatabase(db)

354

355

# In a provider class

356

class DatabaseProvider(Provider):

357

@decorate(provides=Database)

358

def add_metrics(self, db: Database) -> Database:

359

# Add metrics collection

360

return MetricsDatabase(db)

361

```

362

363

### Context Variable Registration

364

365

Function for registering context variables as injectable dependencies.

366

367

```python { .api }

368

def from_context(

369

provides: Any,

370

*,

371

scope: BaseScope | None = None,

372

override: bool = False

373

) -> CompositeDependencySource:

374

"""

375

Register a context variable as a dependency.

376

377

Parameters:

378

- provides: Type to provide from context

379

- scope: Lifecycle scope for the context variable

380

- override: Whether to override existing registrations

381

382

Returns:

383

CompositeDependencySource for the context variable

384

"""

385

```

386

387

**Usage Example:**

388

389

```python

390

# Register context variables

391

from_context(str, scope=Scope.REQUEST) # Get string from context

392

from_context(UserID, scope=Scope.REQUEST) # Get UserID from context

393

394

# In a provider

395

provider = Provider()

396

provider.from_context(str, scope=Scope.REQUEST)

397

398

# In a provider class

399

class ContextProvider(Provider):

400

user_id = from_context(UserID, scope=Scope.REQUEST)

401

request_id = from_context(RequestID, scope=Scope.REQUEST)

402

```

403

404

### Base Provider Interface

405

406

Base interface that all providers implement.

407

408

```python { .api }

409

class BaseProvider:

410

"""Base interface for dependency providers"""

411

412

def get_dependencies(self) -> dict[DependencyKey, DependencySource]:

413

"""Get all dependencies registered in this provider"""

414

415

class ProviderWrapper(BaseProvider):

416

"""Wrapper that applies component to all dependencies"""

417

418

def __init__(self, provider: BaseProvider, component: Component): ...

419

```

420

421

### Factory Functions

422

423

Helper functions for creating root context providers.

424

425

```python { .api }

426

def make_root_context_provider(

427

context: dict[DependencyKey, Any]

428

) -> BaseProvider:

429

"""

430

Create a provider that supplies values from a context dictionary.

431

432

Parameters:

433

- context: Dictionary mapping dependency keys to values

434

435

Returns:

436

BaseProvider that provides the context values

437

"""

438

```