or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

django-integration.mdindex.mdspecification-matching.mdversion-operations.md

version-operations.mddocs/

0

# Version Operations

1

2

Comprehensive functionality for creating, manipulating, comparing, and validating semantic version objects. The Version class provides complete SemVer 2.0.0 compliance with parsing, validation, comparison, and version bumping capabilities.

3

4

## Capabilities

5

6

### Version Creation

7

8

Create Version objects from strings or individual components with full SemVer 2.0.0 validation.

9

10

```python { .api }

11

class Version:

12

def __init__(

13

self,

14

version_string=None,

15

major=None,

16

minor=None,

17

patch=None,

18

prerelease=None,

19

build=None,

20

partial=False

21

):

22

"""

23

Create a Version object from string or components.

24

25

Args:

26

version_string: SemVer string like '1.2.3-alpha.1+build.456'

27

major: Major version number (required if using components)

28

minor: Minor version number (required if using components)

29

patch: Patch version number (required if using components)

30

prerelease: Tuple of prerelease identifiers

31

build: Tuple of build metadata identifiers

32

partial: Allow partial versions (deprecated)

33

34

Raises:

35

ValueError: If version string is invalid or components are invalid

36

"""

37

```

38

39

**Usage Examples:**

40

41

```python

42

# From version string

43

v1 = Version('1.2.3')

44

v2 = Version('1.2.3-alpha.1')

45

v3 = Version('1.2.3-alpha.1+build.456')

46

47

# From components

48

v4 = Version(major=1, minor=2, patch=3)

49

v5 = Version(major=1, minor=2, patch=3, prerelease=('alpha', '1'))

50

v6 = Version(major=1, minor=2, patch=3, prerelease=('alpha', '1'), build=('build', '456'))

51

52

# Invalid versions raise ValueError

53

try:

54

invalid = Version('1.2') # Missing patch version

55

except ValueError as e:

56

print(f"Invalid version: {e}")

57

```

58

59

### Version Parsing

60

61

Parse version strings with optional coercion for non-standard formats.

62

63

```python { .api }

64

@classmethod

65

def parse(cls, version_string, partial=False, coerce=False):

66

"""

67

Parse a version string into components.

68

69

Args:

70

version_string: Version string to parse

71

partial: Allow partial versions (deprecated)

72

coerce: Attempt to coerce invalid formats

73

74

Returns:

75

Tuple of (major, minor, patch, prerelease, build)

76

77

Raises:

78

ValueError: If version string cannot be parsed

79

"""

80

81

@classmethod

82

def coerce(cls, version_string, partial=False):

83

"""

84

Coerce a version-like string into a valid SemVer version.

85

86

Args:

87

version_string: Version-like string to coerce

88

partial: Allow partial versions (deprecated)

89

90

Returns:

91

Valid Version object

92

93

Examples:

94

Version.coerce('1') -> Version('1.0.0')

95

Version.coerce('1.2.3.4.5') -> Version('1.2.3+4.5')

96

Version.coerce('1.2.3a4') -> Version('1.2.3-a4')

97

"""

98

```

99

100

**Usage Examples:**

101

102

```python

103

# Parse version string

104

components = Version.parse('1.2.3-alpha.1+build.456')

105

print(components) # (1, 2, 3, ('alpha', '1'), ('build', '456'))

106

107

# Coerce non-standard formats

108

v1 = Version.coerce('1') # Version('1.0.0')

109

v2 = Version.coerce('1.2') # Version('1.2.0')

110

v3 = Version.coerce('1.2.3.4.5') # Version('1.2.3+4.5')

111

v4 = Version.coerce('1.2.3a4') # Version('1.2.3-a4')

112

```

113

114

### Version Properties

115

116

Access individual components of version objects.

117

118

```python { .api }

119

@property

120

def major(self):

121

"""Major version number."""

122

123

@property

124

def minor(self):

125

"""Minor version number (None only for partial versions - deprecated)."""

126

127

@property

128

def patch(self):

129

"""Patch version number (None only for partial versions - deprecated)."""

130

131

@property

132

def prerelease(self):

133

"""Tuple of prerelease identifiers."""

134

135

@property

136

def build(self):

137

"""Tuple of build metadata identifiers."""

138

139

@property

140

def partial(self):

141

"""Whether this is a partial version (deprecated)."""

142

143

@property

144

def precedence_key(self):

145

"""Key used for version sorting and comparison."""

146

147

def __iter__(self):

148

"""Iterate over version components: (major, minor, patch, prerelease, build)."""

149

150

def __str__(self):

151

"""String representation in SemVer format."""

152

153

def __repr__(self):

154

"""Debug representation of the Version object."""

155

156

def __hash__(self):

157

"""Hash for use in sets and dictionaries."""

158

```

159

160

**Usage Examples:**

161

162

```python

163

version = Version('1.2.3-alpha.1+build.456')

164

165

print(version.major) # 1

166

print(version.minor) # 2

167

print(version.patch) # 3

168

print(version.prerelease) # ('alpha', '1')

169

print(version.build) # ('build', '456')

170

print(version.partial) # False

171

172

# Iterate over components

173

for component in version:

174

print(component)

175

# Output: 1, 2, 3, ('alpha', '1'), ('build', '456')

176

```

177

178

### Version Comparison

179

180

Compare versions using standard Python comparison operators following SemVer precedence rules.

181

182

```python { .api }

183

def __lt__(self, other: 'Version') -> bool: ...

184

def __le__(self, other: 'Version') -> bool: ...

185

def __eq__(self, other: 'Version') -> bool: ...

186

def __ne__(self, other: 'Version') -> bool: ...

187

def __gt__(self, other: 'Version') -> bool: ...

188

def __ge__(self, other: 'Version') -> bool: ...

189

```

190

191

**Usage Examples:**

192

193

```python

194

v1 = Version('1.0.0')

195

v2 = Version('1.0.1')

196

v3 = Version('1.0.0-alpha')

197

v4 = Version('1.0.0+build.1')

198

199

# Basic comparison

200

print(v1 < v2) # True

201

print(v1 > v3) # True (release > prerelease)

202

print(v1 == v4) # True (build metadata ignored in comparison)

203

204

# Sorting versions

205

versions = [Version('2.0.0'), Version('1.0.0'), Version('1.1.0')]

206

sorted_versions = sorted(versions)

207

print([str(v) for v in sorted_versions]) # ['1.0.0', '1.1.0', '2.0.0']

208

```

209

210

### Version Bumping

211

212

Generate new versions by incrementing major, minor, or patch components.

213

214

```python { .api }

215

def next_major(self) -> 'Version':

216

"""

217

Return the next major version.

218

219

Returns:

220

New Version with major incremented, minor/patch reset to 0,

221

prerelease and build metadata removed.

222

"""

223

224

def next_minor(self) -> 'Version':

225

"""

226

Return the next minor version.

227

228

Returns:

229

New Version with minor incremented, patch reset to 0,

230

prerelease and build metadata removed.

231

"""

232

233

def next_patch(self) -> 'Version':

234

"""

235

Return the next patch version.

236

237

Returns:

238

New Version with patch incremented,

239

prerelease and build metadata removed.

240

"""

241

```

242

243

**Usage Examples:**

244

245

```python

246

version = Version('1.2.3-alpha.1+build.456')

247

248

major = version.next_major()

249

print(major) # Version('2.0.0')

250

251

minor = version.next_minor()

252

print(minor) # Version('1.3.0')

253

254

patch = version.next_patch()

255

print(patch) # Version('1.2.4')

256

```

257

258

### Version Truncation

259

260

Truncate versions to specific precision levels.

261

262

```python { .api }

263

def truncate(self, level: str = 'patch') -> 'Version':

264

"""

265

Truncate version to specified level.

266

267

Args:

268

level: Truncation level ('major', 'minor', 'patch', 'prerelease', 'build')

269

270

Returns:

271

New Version truncated to specified level

272

"""

273

```

274

275

**Usage Examples:**

276

277

```python

278

version = Version('1.2.3-alpha.1+build.456')

279

280

major_only = version.truncate('major')

281

print(major_only) # Version('1.0.0')

282

283

minor_only = version.truncate('minor')

284

print(minor_only) # Version('1.2.0')

285

286

no_build = version.truncate('prerelease')

287

print(no_build) # Version('1.2.3-alpha.1')

288

```

289

290

### Utility Functions

291

292

Standalone functions for common version operations.

293

294

```python { .api }

295

def compare(v1: str, v2: str) -> int:

296

"""

297

Compare two version strings.

298

299

Args:

300

v1: First version string

301

v2: Second version string

302

303

Returns:

304

-1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2

305

"""

306

307

def validate(version_string: str) -> bool:

308

"""

309

Check if a version string is valid SemVer.

310

311

Args:

312

version_string: Version string to validate

313

314

Returns:

315

True if valid, False otherwise

316

"""

317

```

318

319

**Usage Examples:**

320

321

```python

322

# Compare version strings directly

323

result = compare('1.0.0', '1.0.1')

324

print(result) # -1

325

326

result = compare('2.0.0', '1.9.9')

327

print(result) # 1

328

329

result = compare('1.0.0', '1.0.0+build')

330

print(result) # 0 (build metadata ignored)

331

332

# Validate version strings

333

print(validate('1.2.3')) # True

334

print(validate('1.2.3-alpha.1')) # True

335

print(validate('1.2')) # False

336

print(validate('invalid')) # False

337

```

338

339

## Version Validation Rules

340

341

The semantic_version library enforces strict SemVer 2.0.0 validation:

342

343

### Validation Patterns

344

345

```python { .api }

346

# Internal regex patterns used for validation

347

Version.version_re # Strict SemVer pattern for complete versions

348

Version.partial_version_re # Pattern allowing partial versions (deprecated)

349

```

350

351

### Validation Rules

352

353

- **Major, minor, patch**: Must be non-negative integers

354

- **Leading zeros**: Not allowed in numeric components (except single '0')

355

- **Prerelease identifiers**: Must be non-empty, can contain alphanumeric and hyphen

356

- **Build identifiers**: Must be non-empty, can contain alphanumeric and hyphen

357

- **Missing components**: Minor and patch default to 0 when using components, but string parsing requires all three

358

359

**Examples of validation:**

360

361

```python

362

# Valid versions

363

Version('1.2.3')

364

Version('1.2.3-alpha.1')

365

Version('1.2.3+build.456')

366

Version('1.2.3-alpha.1+build.456')

367

368

# Invalid versions (raise ValueError)

369

Version('1.2') # Missing patch

370

Version('01.2.3') # Leading zero in major

371

Version('1.02.3') # Leading zero in minor

372

Version('1.2.03') # Leading zero in patch

373

Version('1.2.3-') # Empty prerelease identifier

374

Version('1.2.3+') # Empty build identifier

375

```

376

377

## Error Handling

378

379

All version operations follow consistent error handling patterns:

380

381

- **ValueError**: Raised for invalid version strings or components

382

- **TypeError**: Raised for incompatible types in comparisons

383

- **DeprecationWarning**: Issued for deprecated functionality (partial versions)

384

385

```python

386

# Handle invalid versions

387

try:

388

invalid_version = Version('not.a.version')

389

except ValueError as e:

390

print(f"Invalid version: {e}")

391

392

# Handle type errors in comparison

393

try:

394

result = Version('1.0.0') < "1.0.1" # Should use Version object

395

except TypeError as e:

396

print(f"Type error: {e}")

397

398

# Handle leading zero errors

399

try:

400

leading_zero = Version('01.2.3')

401

except ValueError as e:

402

print(f"Leading zero error: {e}")

403

```