or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build.mdcheck.mdconfiguration.mdcreate.mdfragments.mdindex.mdproject.mdvcs.md

configuration.mddocs/

0

# Configuration Management

1

2

Load and manage towncrier configuration from TOML files with validation, defaults, and flexible discovery.

3

4

## Capabilities

5

6

### Configuration Loading

7

8

Load configuration from directories or specific files with automatic discovery.

9

10

```python { .api }

11

def load_config_from_options(

12

directory: str | None,

13

config_path: str | None

14

) -> tuple[str, Config]:

15

"""

16

Load configuration from directory or file.

17

18

Args:

19

directory: Directory to search for config (None for current)

20

config_path: Explicit config file path (None for auto-discovery)

21

22

Returns:

23

tuple: (base_directory, config_object)

24

25

Raises:

26

ConfigError: If configuration is invalid or not found

27

"""

28

29

def load_config(directory: str) -> Config | None:

30

"""

31

Load configuration from a directory.

32

33

Args:

34

directory: Directory to search for towncrier configuration

35

36

Returns:

37

Config | None: Configuration object or None if not found

38

"""

39

40

def traverse_for_config(path: str | None) -> tuple[str, Config]:

41

"""

42

Search for configuration in current and parent directories.

43

44

Args:

45

path: Starting directory (None for current directory)

46

47

Returns:

48

tuple: (base_directory, config_object)

49

50

Raises:

51

ConfigError: If no configuration found in directory tree

52

"""

53

```

54

55

### File Operations

56

57

Load and parse TOML configuration files.

58

59

```python { .api }

60

def load_config_from_file(directory: str, config_file: str) -> Config:

61

"""

62

Load configuration from a specific file.

63

64

Args:

65

directory: Base directory for relative paths

66

config_file: Path to configuration file

67

68

Returns:

69

Config: Parsed configuration object

70

71

Raises:

72

ConfigError: If file cannot be loaded or parsed

73

"""

74

75

def load_toml_from_file(config_file: str) -> Mapping[str, Any]:

76

"""

77

Load raw TOML data from file.

78

79

Args:

80

config_file: Path to TOML file

81

82

Returns:

83

Mapping[str, Any]: Raw TOML data

84

85

Raises:

86

ConfigError: If file cannot be read or parsed

87

"""

88

89

def parse_toml(base_path: str, config: Mapping[str, Any]) -> Config:

90

"""

91

Parse TOML data into Config object.

92

93

Args:

94

base_path: Base directory for resolving relative paths

95

config: Raw TOML configuration data

96

97

Returns:

98

Config: Validated configuration object

99

100

Raises:

101

ConfigError: If configuration is invalid

102

"""

103

```

104

105

## Configuration Object

106

107

### Config Class

108

109

The main configuration dataclass containing all towncrier settings.

110

111

```python { .api }

112

@dataclasses.dataclass

113

class Config:

114

"""Complete towncrier configuration."""

115

116

# Required fields

117

sections: Mapping[str, str]

118

types: Mapping[str, Mapping[str, Any]]

119

template: str | tuple[str, str]

120

start_string: str

121

122

# Optional fields with defaults

123

package: str = ""

124

package_dir: str = "."

125

single_file: bool = True

126

filename: str = "NEWS.rst"

127

directory: str | None = None

128

version: str | None = None

129

name: str = ""

130

title_format: str | Literal[False] = ""

131

issue_format: str | None = None

132

underlines: Sequence[str] = ("=", "-", "~")

133

wrap: bool = False

134

all_bullets: bool = True

135

orphan_prefix: str = "+"

136

create_eof_newline: bool = True

137

create_add_extension: bool = True

138

ignore: list[str] | None = None

139

issue_pattern: str = ""

140

```

141

142

### ConfigError Exception

143

144

Exception raised for configuration validation errors.

145

146

```python { .api }

147

class ConfigError(ClickException):

148

"""Configuration validation or loading error."""

149

150

def __init__(self, *args: str, **kwargs: str):

151

"""

152

Initialize configuration error.

153

154

Args:

155

*args: Error message components

156

**kwargs: Additional error context

157

failing_option: The configuration option that failed

158

"""

159

self.failing_option = kwargs.get("failing_option")

160

super().__init__(*args)

161

```

162

163

## Configuration Discovery

164

165

### File Discovery Order

166

167

Towncrier searches for configuration files in this order:

168

169

1. Explicit `--config` parameter

170

2. `towncrier.toml` in current/parent directories

171

3. `pyproject.toml` with `[tool.towncrier]` section

172

4. Continue searching up directory tree

173

174

### Section Locations

175

176

Configuration sections are searched in:

177

178

- `[tool.towncrier]` in `pyproject.toml`

179

- Root level in `towncrier.toml`

180

181

## Configuration Options

182

183

### Core Settings

184

185

```toml

186

[tool.towncrier]

187

package = "mypackage" # Package name for version detection

188

package_dir = "src" # Directory containing package

189

filename = "CHANGELOG.md" # Output changelog filename

190

directory = "news" # Fragment directory (alternative to package-based)

191

```

192

193

### Template Configuration

194

195

```toml

196

template = "path/to/template.j2" # Local template file

197

template = "mypackage:template.j2" # Package resource template

198

start_string = "<!-- towncrier release notes start -->" # Insertion marker

199

```

200

201

### Fragment Types

202

203

```toml

204

[[tool.towncrier.type]]

205

directory = "feature"

206

name = "Features"

207

showcontent = true

208

209

[[tool.towncrier.type]]

210

directory = "bugfix"

211

name = "Bugfixes"

212

showcontent = true

213

214

[[tool.towncrier.type]]

215

directory = "doc"

216

name = "Improved Documentation"

217

showcontent = true

218

219

[[tool.towncrier.type]]

220

directory = "removal"

221

name = "Deprecations and Removals"

222

showcontent = true

223

224

[[tool.towncrier.type]]

225

directory = "misc"

226

name = "Misc"

227

showcontent = false

228

```

229

230

### Multi-Section Configuration

231

232

```toml

233

[[tool.towncrier.section]]

234

name = "" # Main section

235

path = ""

236

237

[[tool.towncrier.section]]

238

name = "Web"

239

path = "web"

240

241

[[tool.towncrier.section]]

242

name = "Core"

243

path = "core"

244

```

245

246

### Formatting Options

247

248

```toml

249

title_format = "{name} {version} ({date})"

250

issue_format = "`#{issue} <https://github.com/user/repo/issues/{issue}>`_"

251

underlines = ["=", "-", "~"]

252

wrap = false

253

all_bullets = true

254

```

255

256

### File Management

257

258

```toml

259

create_eof_newline = true # Add newline at end of fragments

260

create_add_extension = true # Auto-add file extensions

261

orphan_prefix = "+" # Prefix for orphan fragments

262

ignore = ["README.rst"] # Files to ignore in fragment directory

263

```

264

265

## Usage Examples

266

267

### Basic Configuration Loading

268

269

```python

270

from towncrier._settings import load_config_from_options

271

272

# Load from current directory

273

base_dir, config = load_config_from_options(

274

directory=None, # Current directory

275

config_path=None # Auto-discover config file

276

)

277

278

print(f"Base directory: {base_dir}")

279

print(f"Package: {config.package}")

280

print(f"Fragment types: {list(config.types.keys())}")

281

```

282

283

### Custom Configuration File

284

285

```python

286

# Load specific config file

287

base_dir, config = load_config_from_options(

288

directory="/path/to/project",

289

config_path="/path/to/custom-towncrier.toml"

290

)

291

```

292

293

### Configuration Traversal

294

295

```python

296

from towncrier._settings.load import traverse_for_config

297

298

# Search up directory tree

299

base_dir, config = traverse_for_config("/deep/nested/directory")

300

```

301

302

### Template Resolution

303

304

```python

305

# Template can be file path or package resource

306

if isinstance(config.template, tuple):

307

# Package resource: ("package.name", "template.j2")

308

package_name, template_name = config.template

309

print(f"Using template {template_name} from package {package_name}")

310

else:

311

# File path: "path/to/template.j2"

312

print(f"Using template file: {config.template}")

313

```

314

315

## Validation Rules

316

317

### Required Settings

318

319

- At least one fragment type must be defined

320

- Template must be specified (file path or package resource)

321

- Start string must be provided for file insertion

322

323

### Path Resolution

324

325

- Relative paths are resolved against the configuration file directory

326

- Package resources use the format `"package:resource"`

327

- Fragment directories are resolved based on package structure or explicit directory

328

329

### Type Validation

330

331

- Fragment types must have `directory` and `name` fields

332

- `showcontent` is optional (defaults to `true`)

333

- Type directories must be valid filesystem names

334

335

## Error Handling

336

337

Configuration loading handles these error scenarios:

338

339

- **File not found**: Configuration file doesn't exist

340

- **Parse errors**: Invalid TOML syntax

341

- **Validation errors**: Missing required fields or invalid values

342

- **Template errors**: Template file/resource not found

343

- **Permission errors**: Cannot read configuration files

344

- **Path resolution errors**: Invalid relative paths or package resources

345

346

## Integration with CLI

347

348

The configuration system integrates with CLI commands through the `config_option_help` constant:

349

350

```python { .api }

351

config_option_help = (

352

"Pass a custom config file at FILE_PATH. "

353

"Default: towncrier.toml or pyproject.toml file, "

354

"if both files exist, the first will take precedence."

355

)

356

```

357

358

This help text is used across all CLI commands that accept a `--config` option.