0
# Version Management
1
2
Pluggable version sources and schemes for flexible version handling across different project structures and workflows. The version system enables dynamic version resolution and manipulation through configurable plugins.
3
4
## Capabilities
5
6
### Version Source Interface
7
8
Abstract interface for version source plugins that determine project versions from various sources.
9
10
```python { .api }
11
class VersionSourceInterface(ABC):
12
def get_version_data(self) -> dict:
13
"""
14
Get the current version data.
15
16
Returns:
17
dict: Dictionary with 'version' key and current version string
18
19
Raises:
20
RuntimeError: If version cannot be determined
21
"""
22
23
def set_version(self, version: str, version_data: dict) -> None:
24
"""
25
Set the version with data from get_version_data.
26
27
Args:
28
version: Version string to set
29
version_data: Data dictionary from get_version_data
30
31
Raises:
32
RuntimeError: If version cannot be set
33
NotImplementedError: If version setting is not supported
34
"""
35
```
36
37
### Version Scheme Interface
38
39
Abstract interface for version scheme plugins that manipulate and validate version strings.
40
41
```python { .api }
42
class VersionSchemeInterface(ABC):
43
def update(self, version: str, **kwargs) -> str:
44
"""
45
Update a version string according to scheme rules.
46
47
Args:
48
version: Version string to update
49
**kwargs: Additional update parameters (e.g., part="patch")
50
51
Returns:
52
str: Updated version string
53
"""
54
55
def parse(self, version: str) -> dict:
56
"""
57
Parse a version string into components.
58
59
Args:
60
version: Version string to parse
61
62
Returns:
63
dict: Version components (e.g., {"major": 1, "minor": 2, "patch": 3})
64
"""
65
66
def normalize(self, version: str) -> str:
67
"""
68
Normalize a version string according to scheme rules.
69
70
Args:
71
version: Version string to normalize
72
73
Returns:
74
str: Normalized version string
75
"""
76
```
77
78
## Built-in Version Sources
79
80
### Code Source
81
82
Extracts version from Python code using AST parsing.
83
84
```python { .api }
85
class CodeSource(VersionSourceInterface):
86
"""
87
Extract version from Python code files.
88
89
Configuration:
90
path: Path to Python file containing version
91
pattern: Regex pattern to find version (optional)
92
search-paths: Additional paths to search (optional)
93
"""
94
```
95
96
Configuration example:
97
```toml
98
[tool.hatch.version]
99
source = "code"
100
path = "src/package/__about__.py"
101
```
102
103
### Regex Source
104
105
Extracts version using regular expression patterns on files.
106
107
```python { .api }
108
class RegexSource(VersionSourceInterface):
109
"""
110
Extract version using regex patterns.
111
112
Configuration:
113
path: Path to file containing version
114
pattern: Regex pattern with named group 'version'
115
"""
116
```
117
118
Configuration example:
119
```toml
120
[tool.hatch.version]
121
source = "regex"
122
path = "VERSION.txt"
123
pattern = 'version = "(?P<version>[^"]+)"'
124
```
125
126
### Environment Variable Source
127
128
Gets version from environment variables.
129
130
```python { .api }
131
class EnvSource(VersionSourceInterface):
132
"""
133
Get version from environment variables.
134
135
Configuration:
136
variable: Environment variable name
137
"""
138
```
139
140
Configuration example:
141
```toml
142
[tool.hatch.version]
143
source = "env"
144
variable = "PACKAGE_VERSION"
145
```
146
147
## Built-in Version Schemes
148
149
### Standard Scheme
150
151
Standard PEP 440 compliant version scheme with semantic versioning support.
152
153
```python { .api }
154
class StandardScheme(VersionSchemeInterface):
155
"""
156
Standard PEP 440 compliant version scheme.
157
158
Supports:
159
- Semantic versioning (MAJOR.MINOR.PATCH)
160
- Pre-release versions (alpha, beta, rc)
161
- Post-release versions
162
- Development versions
163
- Local versions
164
"""
165
```
166
167
Configuration example:
168
```toml
169
[tool.hatch.version]
170
scheme = "standard"
171
```
172
173
## Version File Management
174
175
### Version File Handling
176
177
```python { .api }
178
class VersionFile:
179
def __init__(self, path: str, search_paths: list[str] | None = None):
180
"""
181
Initialize version file handler.
182
183
Args:
184
path: Path to version file
185
search_paths: Additional search paths
186
"""
187
188
def read(self) -> str:
189
"""
190
Read version from file.
191
192
Returns:
193
str: Version string
194
"""
195
196
def write(self, version: str) -> None:
197
"""
198
Write version to file.
199
200
Args:
201
version: Version string to write
202
"""
203
```
204
205
## Configuration Examples
206
207
### Code Source Configuration
208
209
Extract version from Python file:
210
211
```toml
212
[tool.hatch.version]
213
source = "code"
214
path = "src/mypackage/__about__.py"
215
```
216
217
Python file content:
218
```python
219
# src/mypackage/__about__.py
220
__version__ = "1.2.3"
221
```
222
223
### Regex Source Configuration
224
225
Extract version from any text file:
226
227
```toml
228
[tool.hatch.version]
229
source = "regex"
230
path = "VERSION"
231
pattern = '(?P<version>\d+\.\d+\.\d+)'
232
```
233
234
File content:
235
```
236
Version: 1.2.3
237
```
238
239
### Environment Variable Configuration
240
241
Get version from environment:
242
243
```toml
244
[tool.hatch.version]
245
source = "env"
246
variable = "PACKAGE_VERSION"
247
```
248
249
### Custom Pattern Configuration
250
251
Use custom regex pattern:
252
253
```toml
254
[tool.hatch.version]
255
source = "regex"
256
path = "Cargo.toml"
257
pattern = 'version = "(?P<version>[^"]+)"'
258
```
259
260
## Version Manipulation
261
262
### Dynamic Version Updates
263
264
```python
265
from hatchling.version.core import VersionFile
266
267
# Read current version
268
version_file = VersionFile("src/package/__about__.py")
269
current_version = version_file.read()
270
print(f"Current version: {current_version}")
271
272
# Update version
273
version_file.write("1.3.0")
274
```
275
276
### Scheme-based Version Updates
277
278
```python
279
from hatchling.version.scheme.standard import StandardScheme
280
281
scheme = StandardScheme()
282
283
# Parse version components
284
components = scheme.parse("1.2.3")
285
print(components) # {"major": 1, "minor": 2, "patch": 3}
286
287
# Update version
288
new_version = scheme.update("1.2.3", part="minor")
289
print(new_version) # "1.3.0"
290
291
# Normalize version
292
normalized = scheme.normalize("01.02.03")
293
print(normalized) # "1.2.3"
294
```
295
296
## CLI Integration
297
298
### Version Commands
299
300
Check current version:
301
```bash
302
hatchling version
303
```
304
305
Set new version:
306
```bash
307
hatchling version 2.0.0
308
```
309
310
Preview version change:
311
```bash
312
hatchling version 2.0.0 --dry-run
313
```
314
315
## Custom Version Sources
316
317
### Creating Custom Version Source
318
319
```python
320
from hatchling.version.source.plugin.interface import VersionSourceInterface
321
322
class GitTagSource(VersionSourceInterface):
323
PLUGIN_NAME = "git-tag"
324
325
def get_version(self):
326
import subprocess
327
result = subprocess.run(
328
["git", "describe", "--tags", "--abbrev=0"],
329
capture_output=True, text=True
330
)
331
if result.returncode == 0:
332
return result.stdout.strip().lstrip('v')
333
raise RuntimeError("No git tags found")
334
335
def set_version(self, version):
336
import subprocess
337
subprocess.run(["git", "tag", f"v{version}"], check=True)
338
```
339
340
Register the plugin:
341
```toml
342
[project.entry-points.hatch_version_source]
343
git-tag = "mypackage.version:GitTagSource"
344
```
345
346
Use the custom source:
347
```toml
348
[tool.hatch.version]
349
source = "git-tag"
350
```
351
352
## Custom Version Schemes
353
354
### Creating Custom Version Scheme
355
356
```python
357
from hatchling.version.scheme.plugin.interface import VersionSchemeInterface
358
import re
359
360
class CalendarScheme(VersionSchemeInterface):
361
PLUGIN_NAME = "calendar"
362
363
def update(self, version, **kwargs):
364
from datetime import datetime
365
return datetime.now().strftime("%Y.%m.%d")
366
367
def parse(self, version):
368
match = re.match(r'(\d{4})\.(\d{2})\.(\d{2})', version)
369
if match:
370
return {
371
"year": int(match.group(1)),
372
"month": int(match.group(2)),
373
"day": int(match.group(3))
374
}
375
return {}
376
377
def normalize(self, version):
378
components = self.parse(version)
379
if components:
380
return f"{components['year']}.{components['month']:02d}.{components['day']:02d}"
381
return version
382
```
383
384
## Error Handling
385
386
Common version-related exceptions:
387
388
- `FileNotFoundError`: Version file not found
389
- `ValueError`: Invalid version format
390
- `RuntimeError`: Version source/scheme operation failed
391
- `NotImplementedError`: Unsupported operation
392
393
## Best Practices
394
395
### Version Source Selection
396
397
- **Code source**: Best for Python packages with `__version__` attributes
398
- **Regex source**: Flexible for any text-based version storage
399
- **Environment source**: Useful for CI/CD and containerized deployments
400
401
### Version Scheme Guidelines
402
403
- Use **standard scheme** for PEP 440 compliance
404
- Implement custom schemes for specialized versioning needs
405
- Always validate version strings before operations
406
407
### Configuration Recommendations
408
409
```toml
410
# Recommended for Python packages
411
[tool.hatch.version]
412
source = "code"
413
path = "src/package/__about__.py"
414
scheme = "standard"
415
416
# Recommended for multi-language projects
417
[tool.hatch.version]
418
source = "regex"
419
path = "VERSION"
420
pattern = '(?P<version>\d+\.\d+\.\d+)'
421
scheme = "standard"
422
```
423
424
The version management system provides flexible, pluggable version handling that adapts to different project structures and workflows while maintaining PEP 440 compliance.