or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-backend.mdbuilders.mdcli.mdindex.mdmetadata.mdplugins.mdversion.md

plugins.mddocs/

0

# Plugin System

1

2

Extensible plugin architecture supporting custom builders, build hooks, version sources, version schemes, and metadata hooks. The plugin system enables third-party extensions and customization of hatchling's functionality.

3

4

## Capabilities

5

6

### Plugin Manager

7

8

Central plugin management system that discovers, loads, and manages all plugin types.

9

10

```python { .api }

11

class PluginManager:

12

def __init__(self):

13

"""

14

Initialize plugin manager.

15

16

Note:

17

The PluginManager uses dynamic initialization and does not

18

require parameters during construction.

19

"""

20

21

@property

22

def builders(self) -> dict[str, type[BuilderInterface]]:

23

"""Dictionary of available builder plugins."""

24

25

@property

26

def build_hooks(self) -> dict[str, type[BuildHookInterface]]:

27

"""Dictionary of available build hook plugins."""

28

29

@property

30

def version_sources(self) -> dict[str, type[VersionSourceInterface]]:

31

"""Dictionary of available version source plugins."""

32

33

@property

34

def version_schemes(self) -> dict[str, type[VersionSchemeInterface]]:

35

"""Dictionary of available version scheme plugins."""

36

37

@property

38

def metadata_hooks(self) -> dict[str, type[MetadataHookInterface]]:

39

"""Dictionary of available metadata hook plugins."""

40

```

41

42

### Builder Interface

43

44

Abstract base class for all builder plugins.

45

46

```python { .api }

47

class BuilderInterface(ABC, Generic[BuilderConfigBound, PluginManagerBound]):

48

def build(

49

self, *,

50

directory: str | None = None,

51

versions: list[str] | None = None,

52

hooks_only: bool | None = None,

53

clean: bool | None = None,

54

clean_hooks_after: bool | None = None,

55

clean_only: bool | None = False

56

) -> Generator[str, None, None]:

57

"""

58

Build distributions and yield paths to built files.

59

60

Args:

61

directory: Output directory for built distributions (default: "dist")

62

versions: List of version types to build

63

hooks_only: Whether to run only build hooks

64

clean: Whether to clean build directory before building

65

clean_hooks_after: Whether to clean hooks after building

66

clean_only: Whether to only clean without building

67

68

Yields:

69

str: Paths to built distribution files

70

"""

71

72

def get_version_api(self) -> dict[str, Callable]:

73

"""

74

Get version API information for this builder.

75

76

Returns:

77

dict: Version API information

78

"""

79

80

def iter_build_targets(self, versions: list[str]) -> Iterator[tuple[str, str]]:

81

"""

82

Iterate over build targets for given versions.

83

84

Args:

85

versions: List of version types

86

87

Yields:

88

tuple[str, str]: (version, target_name) pairs

89

"""

90

```

91

92

### Build Hook Interface

93

94

Abstract base class for build hooks that customize the build process.

95

96

```python { .api }

97

class BuildHookInterface(Generic[BuilderConfigBound]):

98

def clean(self, versions: list[str]) -> None:

99

"""

100

Clean up build artifacts for specified versions.

101

102

Args:

103

versions: List of version types to clean

104

"""

105

106

def initialize(self, version: str, build_data: dict[str, Any]) -> None:

107

"""

108

Initialize hook before building.

109

110

Args:

111

version: Version being built

112

build_data: Build data dictionary

113

"""

114

115

def finalize(self, version: str, build_data: dict[str, Any], artifact_path: str) -> None:

116

"""

117

Finalize hook after building.

118

119

Args:

120

version: Version that was built

121

build_data: Build data dictionary

122

artifact_path: Path to built artifact

123

"""

124

```

125

126

### Version Source Interface

127

128

Abstract base class for version source plugins that determine project versions.

129

130

```python { .api }

131

class VersionSourceInterface(ABC):

132

def get_version_data(self) -> dict:

133

"""

134

Get the current version data.

135

136

Returns:

137

dict: Dictionary with 'version' key and current version string

138

"""

139

140

def set_version(self, version: str, version_data: dict) -> None:

141

"""

142

Set the version.

143

144

Args:

145

version: Version string to set

146

"""

147

```

148

149

### Version Scheme Interface

150

151

Abstract base class for version scheme plugins that manipulate version strings.

152

153

```python { .api }

154

class VersionSchemeInterface(ABC):

155

def update(self, version: str, **kwargs) -> str:

156

"""

157

Update a version string.

158

159

Args:

160

version: Version string to update

161

**kwargs: Additional update parameters

162

163

Returns:

164

str: Updated version string

165

"""

166

167

def parse(self, version: str) -> dict:

168

"""

169

Parse a version string into components.

170

171

Args:

172

version: Version string to parse

173

174

Returns:

175

dict: Version components

176

"""

177

178

def normalize(self, version: str) -> str:

179

"""

180

Normalize a version string.

181

182

Args:

183

version: Version string to normalize

184

185

Returns:

186

str: Normalized version string

187

"""

188

```

189

190

### Metadata Hook Interface

191

192

Abstract base class for metadata hook plugins that modify project metadata.

193

194

```python { .api }

195

class MetadataHookInterface(ABC):

196

def update(self, metadata: dict[str, Any]) -> None:

197

"""

198

Update project metadata.

199

200

Args:

201

metadata: Metadata dictionary to modify

202

"""

203

```

204

205

## Built-in Plugin Implementations

206

207

### Version Sources

208

209

Built-in version source implementations for common version management patterns.

210

211

```python { .api }

212

class CodeSource(VersionSourceInterface):

213

"""Extract version from Python code using AST parsing."""

214

215

class RegexSource(VersionSourceInterface):

216

"""Extract version using regular expression patterns."""

217

218

class EnvSource(VersionSourceInterface):

219

"""Get version from environment variables."""

220

```

221

222

### Version Schemes

223

224

```python { .api }

225

class StandardScheme(VersionSchemeInterface):

226

"""Standard PEP 440 compliant version scheme."""

227

```

228

229

### Build Hooks

230

231

```python { .api }

232

class VersionBuildHook(BuildHookInterface):

233

"""Hook for managing version information during builds."""

234

235

class CustomBuildHook:

236

"""Custom user-defined build hook loaded from scripts."""

237

```

238

239

### Metadata Hooks

240

241

```python { .api }

242

class CustomMetadataHook:

243

"""Custom user-defined metadata hook loaded from scripts."""

244

```

245

246

## Plugin Registration

247

248

### Registration Functions

249

250

Functions for registering built-in plugins.

251

252

```python { .api }

253

def hatch_register_builder() -> list[type[BuilderInterface]]:

254

"""Register built-in builder plugins."""

255

256

def hatch_register_build_hook() -> list[type[BuildHookInterface]]:

257

"""Register built-in build hook plugins."""

258

```

259

260

### Plugin Entry Points

261

262

Plugins are discovered through entry points in setup.py or pyproject.toml:

263

264

```toml

265

[project.entry-points.hatch_builder]

266

my_builder = "my_package.builders:MyBuilder"

267

268

[project.entry-points.hatch_build_hook]

269

my_hook = "my_package.hooks:MyBuildHook"

270

271

[project.entry-points.hatch_version_source]

272

my_source = "my_package.version:MyVersionSource"

273

274

[project.entry-points.hatch_version_scheme]

275

my_scheme = "my_package.version:MyVersionScheme"

276

277

[project.entry-points.hatch_metadata_hook]

278

my_metadata = "my_package.metadata:MyMetadataHook"

279

```

280

281

## Plugin Development

282

283

### Creating Custom Builders

284

285

```python

286

from hatchling.builders.plugin.interface import BuilderInterface

287

288

class MyBuilder(BuilderInterface):

289

PLUGIN_NAME = "my-builder"

290

291

def build(self, *, directory="dist", versions=None):

292

# Custom build logic

293

yield self.create_my_distribution(directory)

294

295

def get_version_api(self):

296

return {"my-version": "1.0"}

297

```

298

299

### Creating Build Hooks

300

301

```python

302

from hatchling.builders.hooks.plugin.interface import BuildHookInterface

303

304

class MyBuildHook(BuildHookInterface):

305

PLUGIN_NAME = "my-hook"

306

307

def initialize(self, version, build_data):

308

# Pre-build customization

309

build_data["custom_setting"] = "value"

310

311

def finalize(self, version, build_data, artifact_path):

312

# Post-build customization

313

print(f"Built {artifact_path}")

314

```

315

316

### Creating Version Sources

317

318

```python

319

from hatchling.version.source.plugin.interface import VersionSourceInterface

320

321

class MyVersionSource(VersionSourceInterface):

322

PLUGIN_NAME = "my-source"

323

324

def get_version_data(self):

325

# Custom version retrieval logic

326

return {"version": "1.0.0"}

327

328

def set_version(self, version, version_data):

329

# Custom version setting logic

330

pass

331

```

332

333

## Plugin Configuration

334

335

Plugins are configured in pyproject.toml:

336

337

```toml

338

[tool.hatch.build]

339

builder = "my-builder"

340

hooks = ["my-hook"]

341

342

[tool.hatch.version]

343

source = "my-source"

344

scheme = "my-scheme"

345

346

[tool.hatch.metadata.hooks.my-metadata]

347

setting = "value"

348

```

349

350

## Plugin Utilities

351

352

### Plugin Loading

353

354

```python { .api }

355

def load_plugin_from_script(

356

path: str,

357

script_name: str,

358

plugin_class: type[T],

359

plugin_id: str

360

) -> type[T]:

361

"""

362

Load a plugin class from a Python script.

363

364

Args:

365

path: Path to script file

366

script_name: Name of the script

367

plugin_class: Expected plugin base class

368

plugin_id: Plugin identifier

369

370

Returns:

371

type[T]: Loaded plugin class

372

"""

373

```

374

375

### Plugin Management Classes

376

377

```python { .api }

378

class ClassRegister:

379

"""Registry for plugin classes with validation."""

380

381

class ThirdPartyPlugins:

382

"""Manager for third-party plugin discovery and loading."""

383

```

384

385

## Error Handling

386

387

```python { .api }

388

class UnknownPluginError(ValueError):

389

"""Raised when referencing an unknown plugin."""

390

```

391

392

## Usage Examples

393

394

### Using Plugin Manager

395

396

```python

397

from hatchling.metadata.core import ProjectMetadata

398

from hatchling.plugin.manager import PluginManager

399

400

# Create plugin manager

401

plugin_manager = PluginManager()

402

403

# List available plugins

404

print("Builders:", list(plugin_manager.builders.keys()))

405

print("Build hooks:", list(plugin_manager.build_hooks.keys()))

406

print("Version sources:", list(plugin_manager.version_sources.keys()))

407

print("Version schemes:", list(plugin_manager.version_schemes.keys()))

408

print("Metadata hooks:", list(plugin_manager.metadata_hooks.keys()))

409

410

# Get specific plugin

411

wheel_builder = plugin_manager.builders["wheel"]

412

standard_scheme = plugin_manager.version_schemes["standard"]

413

```

414

415

### Using Plugins in Configuration

416

417

```python

418

# Configure builder with plugins

419

from hatchling.builders.wheel import WheelBuilder

420

421

builder = WheelBuilder(

422

root=os.getcwd(),

423

plugin_manager=plugin_manager,

424

config={

425

"hooks": ["version", "my-custom-hook"],

426

"version-source": "code",

427

"version-scheme": "standard"

428

}

429

)

430

```

431

432

### Plugin Registration

433

434

Third-party plugins can be registered using hatchling's plugin system.

435

436

```python { .api }

437

from hatchling.plugin import hookimpl

438

439

@hookimpl

440

def hatch_register_builder():

441

"""Register a custom builder plugin."""

442

return MyBuilderClass

443

444

@hookimpl

445

def hatch_register_version_source():

446

"""Register a custom version source plugin."""

447

return MyVersionSourceClass

448

449

@hookimpl

450

def hatch_register_version_scheme():

451

"""Register a custom version scheme plugin."""

452

return MyVersionSchemeClass

453

454

@hookimpl

455

def hatch_register_metadata_hook():

456

"""Register a custom metadata hook plugin."""

457

return MyMetadataHookClass

458

459

@hookimpl

460

def hatch_register_build_hook():

461

"""Register a custom build hook plugin."""

462

return MyBuildHookClass

463

```

464

465

#### Usage Example

466

467

```python

468

# plugin.py

469

from hatchling.plugin import hookimpl

470

from hatchling.builders.plugin.interface import BuilderInterface

471

472

class CustomBuilder(BuilderInterface):

473

PLUGIN_NAME = 'custom'

474

475

def get_version_api(self):

476

return {'standard': self.build_standard}

477

478

def build_standard(self, directory, **build_data):

479

# Custom build logic

480

pass

481

482

@hookimpl

483

def hatch_register_builder():

484

return CustomBuilder

485

```

486

487

The plugin system makes hatchling highly extensible, allowing custom build logic, version management, and metadata processing to be implemented as reusable plugins.