or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-data.mdconfiguration.mdcore-parsing.mdcustom-parsers.mdfile-secrets.mdframework-integration.mdindex.mdspecialized-types.mdvalidation.md

configuration.mddocs/

0

# Configuration Management

1

2

Environment configuration utilities including .env file reading, variable expansion, prefixed parsing, validation management, and configuration export capabilities.

3

4

## Capabilities

5

6

### Environment File Loading

7

8

Read .env files into the environment with automatic discovery, recursion control, and override management.

9

10

```python { .api }

11

@staticmethod

12

def read_env(path=None, *, recurse=True, verbose=False, override=False, return_path=False):

13

"""

14

Read a .env file into os.environ.

15

16

Parameters:

17

- path: str or Path, specific .env file path (optional, defaults to search)

18

- recurse: bool, whether to search parent directories (default: True)

19

- verbose: bool, whether to print loading information (default: False)

20

- override: bool, whether to override existing environment variables (default: False)

21

- return_path: bool, whether to return the path of loaded file (default: False)

22

23

Returns:

24

bool or str: Success status or file path if return_path=True

25

26

Notes:

27

When path is None, searches for .env starting from caller's directory.

28

With recurse=True, walks up directory tree until .env is found.

29

"""

30

```

31

32

Usage examples:

33

34

```python

35

from environs import Env, env

36

37

# Load .env from current directory or parents

38

env.read_env()

39

40

# Load specific .env file

41

env.read_env("/path/to/specific/.env")

42

43

# Load with verbose output

44

env.read_env(verbose=True)

45

46

# Override existing environment variables

47

env.read_env(override=True)

48

49

# Get the path of loaded file

50

env_path = env.read_env(return_path=True)

51

print(f"Loaded environment from: {env_path}")

52

53

# Class method usage

54

success = Env.read_env("./config/.env")

55

if success:

56

print("Environment file loaded successfully")

57

```

58

59

### Prefixed Environment Variables

60

61

Parse environment variables with common prefixes using context manager for clean scoping.

62

63

```python { .api }

64

def prefixed(self, prefix: str):

65

"""

66

Context manager for parsing environment variables with a common prefix.

67

68

Parameters:

69

- prefix: str, prefix to prepend to all variable names within context

70

71

Returns:

72

Iterator[Env]: Context manager yielding the current Env instance

73

74

Notes:

75

Prefixes can be nested. The context manager automatically manages

76

prefix state and restores previous prefix on exit.

77

"""

78

```

79

80

Usage examples:

81

82

```python

83

import os

84

from environs import env

85

86

# Set prefixed environment variables

87

os.environ["DB_HOST"] = "localhost"

88

os.environ["DB_PORT"] = "5432"

89

os.environ["DB_NAME"] = "myapp"

90

os.environ["REDIS_HOST"] = "redis.example.com"

91

os.environ["REDIS_PORT"] = "6379"

92

93

# Parse with prefix

94

with env.prefixed("DB_"):

95

host = env.str("HOST") # Reads DB_HOST

96

port = env.int("PORT") # Reads DB_PORT

97

name = env.str("NAME") # Reads DB_NAME

98

99

print(f"Database: {name} at {host}:{port}")

100

101

# Nested prefixes

102

os.environ["API_V1_ENDPOINT"] = "https://api.v1.example.com"

103

os.environ["API_V1_TIMEOUT"] = "30"

104

105

with env.prefixed("API_"):

106

with env.prefixed("V1_"):

107

endpoint = env.str("ENDPOINT") # Reads API_V1_ENDPOINT

108

timeout = env.int("TIMEOUT") # Reads API_V1_TIMEOUT

109

110

# Multiple prefix contexts

111

def load_db_config():

112

with env.prefixed("DB_"):

113

return {

114

"host": env.str("HOST", "localhost"),

115

"port": env.int("PORT", 5432),

116

"name": env.str("NAME", "app"),

117

"user": env.str("USER", "app"),

118

"password": env.str("PASSWORD")

119

}

120

121

def load_redis_config():

122

with env.prefixed("REDIS_"):

123

return {

124

"host": env.str("HOST", "localhost"),

125

"port": env.int("PORT", 6379),

126

"db": env.int("DB", 0)

127

}

128

129

db_config = load_db_config()

130

redis_config = load_redis_config()

131

```

132

133

### Variable Expansion

134

135

Expand environment variables using `${VAR}` and `${VAR:-default}` syntax for dynamic configuration.

136

137

```python { .api }

138

# Variable expansion is enabled via constructor parameter

139

def __init__(self, *, expand_vars=False, **kwargs):

140

"""

141

Enable variable expansion in environment values.

142

143

Parameters:

144

- expand_vars: bool, whether to expand ${VAR} syntax (default: False)

145

146

Expansion syntax:

147

- ${VAR}: Expand to value of VAR, error if not set

148

- ${VAR:-default}: Expand to value of VAR, or 'default' if not set

149

- \\$: Escape $ character to prevent expansion

150

"""

151

```

152

153

Usage examples:

154

155

```python

156

import os

157

from environs import Env

158

159

# Set up base environment variables

160

os.environ["BASE_URL"] = "https://api.example.com"

161

os.environ["API_VERSION"] = "v1"

162

os.environ["USER_NAME"] = "john_doe"

163

164

# Environment variables with expansion syntax

165

os.environ["API_ENDPOINT"] = "${BASE_URL}/${API_VERSION}"

166

os.environ["USER_PROFILE_URL"] = "${BASE_URL}/${API_VERSION}/users/${USER_NAME}"

167

os.environ["BACKUP_PATH"] = "/backups/${USER_NAME:-anonymous}"

168

os.environ["LOG_FILE"] = "/var/log/${APP_NAME:-myapp}.log"

169

170

# Create Env with expansion enabled

171

env = Env(expand_vars=True)

172

173

# Parse expanded variables

174

api_endpoint = env.str("API_ENDPOINT") # => "https://api.example.com/v1"

175

profile_url = env.str("USER_PROFILE_URL") # => "https://api.example.com/v1/users/john_doe"

176

backup_path = env.str("BACKUP_PATH") # => "/backups/john_doe"

177

log_file = env.str("LOG_FILE") # => "/var/log/myapp.log" (uses default)

178

179

# Escaped variables

180

os.environ["LITERAL_DOLLAR"] = "Price: \\$19.99"

181

price = env.str("LITERAL_DOLLAR") # => "Price: $19.99"

182

```

183

184

### Validation and Sealing

185

186

Manage deferred validation and prevent further parsing after configuration is complete.

187

188

```python { .api }

189

def seal(self):

190

"""

191

Validate all parsed values and prevent new values from being added.

192

193

Raises:

194

EnvValidationError: If any parsed values failed validation

195

196

Notes:

197

After sealing, attempting to parse new variables raises EnvSealedError.

198

Useful for ensuring configuration is complete and valid before app startup.

199

"""

200

```

201

202

Usage examples:

203

204

```python

205

import os

206

from environs import Env, EnvValidationError, EnvSealedError

207

208

# Create non-eager env for deferred validation

209

env = Env(eager=False)

210

211

# Set up environment with some invalid values

212

os.environ["VALID_PORT"] = "8080"

213

os.environ["INVALID_PORT"] = "not_a_number"

214

os.environ["VALID_TIMEOUT"] = "30"

215

216

# Parse variables (errors collected, not raised immediately)

217

valid_port = env.int("VALID_PORT") # Success

218

invalid_port = env.int("INVALID_PORT") # Error collected

219

valid_timeout = env.int("VALID_TIMEOUT") # Success

220

221

# Validate all at once

222

try:

223

env.seal()

224

print("All configuration valid!")

225

except EnvValidationError as e:

226

print(f"Configuration errors: {e.error_messages}")

227

# Handle validation errors appropriately

228

229

# After sealing, no new parsing allowed

230

try:

231

new_value = env.str("NEW_VAR")

232

except EnvSealedError:

233

print("Cannot parse new variables after sealing")

234

```

235

236

### Configuration Export

237

238

Export parsed configuration as a dictionary for serialization or debugging.

239

240

```python { .api }

241

def dump(self):

242

"""

243

Dump parsed environment variables to a dictionary.

244

245

Returns:

246

dict: Dictionary of parsed values with simple data types

247

248

Notes:

249

Complex objects are serialized to simple types (strings, numbers).

250

Useful for logging configuration or creating configuration backups.

251

"""

252

```

253

254

Usage examples:

255

256

```python

257

import os

258

import json

259

from environs import env

260

from datetime import datetime

261

262

# Set up various environment variables

263

os.environ["APP_NAME"] = "MyApp"

264

os.environ["DEBUG"] = "true"

265

os.environ["PORT"] = "8080"

266

os.environ["CREATED_AT"] = "2023-12-25T10:30:00"

267

os.environ["FEATURES"] = "auth,logging,metrics"

268

269

# Parse various types

270

app_name = env.str("APP_NAME")

271

debug = env.bool("DEBUG")

272

port = env.int("PORT")

273

created_at = env.datetime("CREATED_AT")

274

features = env.list("FEATURES")

275

276

# Export configuration

277

config_dict = env.dump()

278

print("Current configuration:")

279

print(json.dumps(config_dict, indent=2, default=str))

280

281

# Save configuration to file

282

with open("config_backup.json", "w") as f:

283

json.dump(config_dict, f, indent=2, default=str)

284

285

# Use for debugging

286

def log_configuration():

287

config = env.dump()

288

print("Application started with configuration:")

289

for key, value in config.items():

290

# Don't log sensitive values

291

if "password" in key.lower() or "secret" in key.lower():

292

print(f" {key}: [REDACTED]")

293

else:

294

print(f" {key}: {value}")

295

```

296

297

### Initialization Options

298

299

Configure environment parsing behavior through constructor parameters.

300

301

```python { .api }

302

def __init__(self, *, eager=True, expand_vars=False, prefix=None):

303

"""

304

Initialize environment parser with behavior options.

305

306

Parameters:

307

- eager: bool, whether to raise validation errors immediately (default: True)

308

- expand_vars: bool, whether to expand ${VAR} syntax (default: False)

309

- prefix: str, global prefix for all variable names (default: None)

310

"""

311

```

312

313

Usage examples:

314

315

```python

316

from environs import Env

317

318

# Eager validation (default) - errors raised immediately

319

eager_env = Env(eager=True)

320

321

# Deferred validation - collect errors for later handling

322

deferred_env = Env(eager=False)

323

324

# Variable expansion enabled

325

expanding_env = Env(expand_vars=True)

326

327

# Global prefix

328

prefixed_env = Env(prefix="MYAPP_")

329

330

# Combined options

331

flexible_env = Env(

332

eager=False,

333

expand_vars=True,

334

prefix="APP_"

335

)

336

337

# Example with deferred validation

338

import os

339

os.environ["INVALID_NUMBER"] = "not_a_number"

340

341

deferred = Env(eager=False)

342

value = deferred.int("INVALID_NUMBER") # No error raised yet

343

344

try:

345

deferred.seal() # Now validation errors are raised

346

except EnvValidationError as e:

347

print(f"Validation failed: {e.error_messages}")

348

```

349

350

## Types

351

352

```python { .api }

353

from typing import Dict, Any, Union, Optional, Iterator

354

from pathlib import Path

355

356

ErrorMapping = Dict[str, List[str]]

357

ConfigDict = Dict[str, Any]

358

```