0
# Version and Local Schemes
1
2
setuptools-scm uses configurable schemes to transform SCM metadata into version strings. Version schemes determine the main version format, while local schemes control the local version identifier (the part after `+`).
3
4
## Capabilities
5
6
### Version Schemes
7
8
Functions that determine how the main version string is calculated from SCM metadata.
9
10
```python { .api }
11
def guess_next_dev_version(version: ScmVersion) -> str:
12
"""
13
Default version scheme. Returns exact tag for clean repos,
14
or guessed next version with .dev suffix for repos with commits after tag.
15
16
Examples:
17
- Exact tag "1.0.0" → "1.0.0"
18
- Tag "1.0.0" + 3 commits → "1.0.1.dev3"
19
"""
20
21
def no_guess_dev_version(version: ScmVersion) -> str:
22
"""
23
Returns exact tag for clean repos, tag with .dev suffix for dirty repos.
24
Does not attempt to guess next version.
25
26
Examples:
27
- Exact tag "1.0.0" → "1.0.0"
28
- Tag "1.0.0" + 3 commits → "1.0.0.dev3"
29
"""
30
31
def only_version(version: ScmVersion) -> str:
32
"""
33
Always returns the exact tag version, ignoring distance and dirty state.
34
35
Examples:
36
- Tag "1.0.0" (any state) → "1.0.0"
37
"""
38
39
def postrelease_version(version: ScmVersion) -> str:
40
"""
41
Uses post-release versioning scheme with .post suffix.
42
43
Examples:
44
- Exact tag "1.0.0" → "1.0.0"
45
- Tag "1.0.0" + 3 commits → "1.0.0.post3"
46
"""
47
48
def simplified_semver_version(version: ScmVersion) -> str:
49
"""
50
Simplified semantic versioning that bumps appropriate version component.
51
52
Examples:
53
- Exact tag "1.0.0" → "1.0.0"
54
- Tag "1.0.0" + commits → "1.0.1.dev{distance}"
55
- Feature branch → "1.1.0.dev{distance}"
56
"""
57
58
def release_branch_semver_version(version: ScmVersion) -> str:
59
"""
60
Semantic versioning with release branch support.
61
Different bumping strategy based on branch patterns.
62
"""
63
64
def calver_by_date(version: ScmVersion) -> str:
65
"""
66
Calendar versioning scheme using current date.
67
68
Examples:
69
- Tag "2023.1.0" + commits → "2023.1.1.dev{distance}"
70
"""
71
```
72
73
### Local Schemes
74
75
Functions that determine the local version identifier (part after `+` in version string).
76
77
```python { .api }
78
def get_local_node_and_date(version: ScmVersion) -> str:
79
"""
80
Default local scheme. Includes commit hash and date.
81
82
Examples:
83
- Clean repo → "" (no local part)
84
- Dirty repo → "+g{node}.d20231201"
85
- Commits after tag → "+g{node}.d20231201"
86
"""
87
88
def get_local_node_and_timestamp(version: ScmVersion) -> str:
89
"""
90
Local scheme with commit hash and timestamp.
91
92
Examples:
93
- Dirty repo → "+g{node}.{timestamp}"
94
"""
95
96
def get_local_dirty_tag(version: ScmVersion) -> str:
97
"""
98
Simple local scheme that only adds suffix for dirty repos.
99
100
Examples:
101
- Clean repo → "" (no local part)
102
- Dirty repo → "+dirty"
103
"""
104
105
def get_no_local_node(version: ScmVersion) -> str:
106
"""
107
No local version identifier scheme.
108
109
Examples:
110
- Any state → "" (no local part)
111
"""
112
```
113
114
### Version Helper Functions
115
116
Utility functions for version processing and manipulation.
117
118
```python { .api }
119
def tag_to_version(tag: str, config: Configuration) -> Version | None:
120
"""
121
Convert a tag string to a Version object using tag regex.
122
123
Parameters:
124
- tag: Tag string from SCM
125
- config: Configuration with tag_regex pattern
126
127
Returns:
128
Version object or None if tag doesn't match regex
129
"""
130
131
def meta(
132
tag: str,
133
*,
134
distance: int = 0,
135
dirty: bool = False,
136
node: str | None = None,
137
preformatted: bool = False,
138
branch: str | None = None,
139
config: Configuration,
140
node_date: date | None = None
141
) -> ScmVersion:
142
"""
143
Create ScmVersion object from tag metadata.
144
145
Parameters:
146
- tag: Version tag string
147
- distance: Number of commits since tag
148
- dirty: Whether working directory has uncommitted changes
149
- node: Commit hash/node identifier
150
- preformatted: Whether tag is already formatted
151
- branch: Branch name
152
- config: Configuration object
153
- node_date: Date of the commit
154
155
Returns:
156
ScmVersion object with parsed metadata
157
"""
158
159
def format_version(version: ScmVersion, **kwargs) -> str:
160
"""
161
Format ScmVersion to final version string using configured schemes.
162
163
Parameters:
164
- version: ScmVersion object to format
165
- **kwargs: Additional formatting arguments
166
167
Returns:
168
Final formatted version string
169
"""
170
171
def guess_next_version(tag_version: ScmVersion) -> str:
172
"""
173
Guess the next version based on current tag.
174
Used internally by guess_next_dev_version scheme.
175
176
Parameters:
177
- tag_version: ScmVersion with current tag information
178
179
Returns:
180
Guessed next version string
181
"""
182
183
def guess_next_simple_semver(
184
version: ScmVersion,
185
retain: int,
186
increment: bool = True
187
) -> str:
188
"""
189
Guess next semantic version with configurable component retention.
190
191
Parameters:
192
- version: ScmVersion object
193
- retain: Number of version components to retain (1=major, 2=minor, 3=patch)
194
- increment: Whether to increment the last retained component
195
196
Returns:
197
Next semantic version string
198
"""
199
```
200
201
## Usage Examples
202
203
### Custom Version Schemes
204
205
```python
206
from setuptools_scm import get_version
207
208
# Use different version schemes
209
dev_version = get_version(version_scheme="guess-next-dev")
210
post_version = get_version(version_scheme="post-release")
211
exact_version = get_version(version_scheme="only-version")
212
semver_version = get_version(version_scheme="python-simplified-semver")
213
214
print(f"Dev: {dev_version}") # e.g., "1.0.1.dev3+g1234567.d20231201"
215
print(f"Post: {post_version}") # e.g., "1.0.0.post3+g1234567.d20231201"
216
print(f"Exact: {exact_version}") # e.g., "1.0.0+g1234567.d20231201"
217
print(f"Semver: {semver_version}") # e.g., "1.0.1.dev3+g1234567.d20231201"
218
```
219
220
### Custom Local Schemes
221
222
```python
223
from setuptools_scm import get_version
224
225
# Use different local schemes
226
node_date = get_version(local_scheme="node-and-date")
227
node_timestamp = get_version(local_scheme="node-and-timestamp")
228
dirty_only = get_version(local_scheme="dirty-tag")
229
no_local = get_version(local_scheme="no-local-version")
230
231
print(f"Node+Date: {node_date}") # e.g., "1.0.0+g1234567.d20231201"
232
print(f"Node+Time: {node_timestamp}") # e.g., "1.0.0+g1234567.1701432000"
233
print(f"Dirty: {dirty_only}") # e.g., "1.0.0+dirty" or "1.0.0"
234
print(f"No local: {no_local}") # e.g., "1.0.0"
235
```
236
237
### pyproject.toml Configuration
238
239
```toml
240
[tool.setuptools_scm]
241
version_scheme = "python-simplified-semver"
242
local_scheme = "no-local-version"
243
tag_regex = "^(?P<version>[vV]?\\d+(?:\\.\\d+){0,2}[^\\+]*)(?:\\+.*)?$"
244
fallback_version = "0.0.0"
245
```
246
247
### Custom Schemes via Entry Points
248
249
You can define custom schemes by creating entry points in your package:
250
251
```toml
252
[project.entry-points."setuptools_scm.version_scheme"]
253
"my-custom-scheme" = "mypackage.version:my_version_scheme"
254
255
[project.entry-points."setuptools_scm.local_scheme"]
256
"my-local-scheme" = "mypackage.version:my_local_scheme"
257
```
258
259
```python
260
# mypackage/version.py
261
def my_version_scheme(version):
262
"""Custom version scheme implementation"""
263
if version.exact:
264
return str(version.tag)
265
return f"{version.tag}.custom{version.distance}"
266
267
def my_local_scheme(version):
268
"""Custom local scheme implementation"""
269
if version.dirty:
270
return "+modified"
271
return ""
272
```
273
274
### Working with ScmVersion Objects
275
276
```python
277
from setuptools_scm.version import meta
278
from setuptools_scm import Configuration
279
280
config = Configuration()
281
282
# Create ScmVersion manually (normally done internally)
283
scm_ver = meta(
284
tag="1.0.0",
285
distance=3,
286
dirty=True,
287
node="abc1234",
288
branch="main",
289
config=config
290
)
291
292
# Use built-in formatting methods
293
clean_fmt = scm_ver.format_choice("{tag}", "{tag}.dirty{distance}")
294
custom_fmt = scm_ver.format_with("v{tag}-{distance}-{node}")
295
296
print(f"Clean/Dirty: {clean_fmt}") # "1.0.0.dirty3"
297
print(f"Custom: {custom_fmt}") # "v1.0.0-3-abc1234"
298
```
299
300
## Constants
301
302
```python { .api }
303
DEFAULT_VERSION_SCHEME: str = "guess-next-dev"
304
DEFAULT_LOCAL_SCHEME: str = "node-and-date"
305
DEFAULT_TAG_REGEX: Pattern[str] # Regex pattern: ^(?:[\w-]+-)?(?P<version>[vV]?\d+(?:\.\d+){0,2}[^\+]*)(?:\+.*)?$
306
```