semantic-version-tools 1.4.0__tar.gz → 1.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- semantic_version_tools-1.5.0/CHANGELOG.md +39 -0
- semantic_version_tools-1.5.0/PKG-INFO +73 -0
- semantic_version_tools-1.5.0/README.md +64 -0
- semantic_version_tools-1.5.0/pyproject.toml +45 -0
- semantic_version_tools-1.5.0/pyproject.toml.orig +35 -0
- semantic_version_tools-1.5.0/src/semantic_version_tools/__init__.py +1 -0
- semantic_version_tools-1.5.0/src/semantic_version_tools/version.py +158 -0
- semantic_version_tools-1.4.0/PKG-INFO +0 -137
- semantic_version_tools-1.4.0/README.md +0 -122
- semantic_version_tools-1.4.0/pyproject.toml +0 -33
- semantic_version_tools-1.4.0/src/semantic_version_tools/__init__.py +0 -1
- semantic_version_tools-1.4.0/src/semantic_version_tools/version.py +0 -198
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Version-Tools Changelog
|
|
2
|
+
|
|
3
|
+
## Version 1.5.0 (2026-11-09)
|
|
4
|
+
|
|
5
|
+
- Support and test Python 3.10 through 3.15.
|
|
6
|
+
- Use uv for dependency management and builds, with Ruff for linting and formatting.
|
|
7
|
+
- Validate complete version strings, preserve build metadata and accept prereleases with an omitted patch.
|
|
8
|
+
- Return a new version from addition. Augmented assignment rebinds the left-hand variable.
|
|
9
|
+
- Add regression tests and an 80% coverage threshold to the documented test command.
|
|
10
|
+
|
|
11
|
+
## Version 1.4.0 (2025-10-22)
|
|
12
|
+
|
|
13
|
+
- test for python 3.14
|
|
14
|
+
|
|
15
|
+
## Version 1.3.2 (2025-09-25)
|
|
16
|
+
|
|
17
|
+
- update of dependencies
|
|
18
|
+
|
|
19
|
+
## Version 1.3.1 (2025-03-03)
|
|
20
|
+
|
|
21
|
+
- add the \_\_add__ method
|
|
22
|
+
- improve documentation
|
|
23
|
+
|
|
24
|
+
## Version 1.3.0 (2025-02-25)
|
|
25
|
+
|
|
26
|
+
- Moved to standalone module
|
|
27
|
+
- Add tests
|
|
28
|
+
|
|
29
|
+
## Version 1.2.0 (2024-11-18)
|
|
30
|
+
|
|
31
|
+
- accept string as imput
|
|
32
|
+
|
|
33
|
+
## Version 1.1.0 (2024-10-04)
|
|
34
|
+
|
|
35
|
+
- The patch is now not mandatory
|
|
36
|
+
|
|
37
|
+
## Version 1.0.0 (2021-09-07)
|
|
38
|
+
|
|
39
|
+
- First implementation of the class
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: semantic-version-tools
|
|
3
|
+
Version: 1.5.0
|
|
4
|
+
Summary: Class to manage semantic versioning
|
|
5
|
+
Author: Romolo Politi
|
|
6
|
+
Author-email: Romolo Politi <romolo.politi@inaf.it>
|
|
7
|
+
Requires-Python: >=3.10, <3.16
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# Version-Tools
|
|
11
|
+
|
|
12
|
+
`semantic-version-tools` provides `Vers`, a Python class for parsing,
|
|
13
|
+
comparing and incrementing version numbers. It supports Python 3.10–3.15.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
Install from PyPI with pip or add the package to a uv project.
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
pip install semantic-version-tools
|
|
21
|
+
uv add semantic-version-tools
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```pycon
|
|
27
|
+
>>> from semantic_version_tools import Vers
|
|
28
|
+
>>> Vers("1.2")
|
|
29
|
+
Version 1.2
|
|
30
|
+
>>> Vers((1, 2, 0, "d", 1))
|
|
31
|
+
Version 1.2.0-devel.1
|
|
32
|
+
>>> Vers("1.2-dev.1+sha.abc").full()
|
|
33
|
+
'1.2.0-devel.1+sha.abc'
|
|
34
|
+
>>> Vers("1.2.0-rc.1") < Vers("1.2.0")
|
|
35
|
+
True
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Tuples contain two to five fields in this order: major, minor, patch,
|
|
39
|
+
prerelease code and build number. The prerelease codes are `d` (development),
|
|
40
|
+
`a` (alpha), `b` (beta), `rc` (release candidate) and `f` (final).
|
|
41
|
+
A prerelease string with an omitted patch uses patch zero. Metadata after
|
|
42
|
+
`+` is preserved in the full version and ignored in comparisons.
|
|
43
|
+
`short()` returns the numeric version without the prerelease or metadata.
|
|
44
|
+
|
|
45
|
+
Addition returns a new `Vers` instance. Integers increment the minor
|
|
46
|
+
component. Floats use the integer and fractional digits as major and minor
|
|
47
|
+
increments. Adding another `Vers` combines the numeric components and
|
|
48
|
+
preserves the left operand's precision and release information.
|
|
49
|
+
|
|
50
|
+
```pycon
|
|
51
|
+
>>> current = Vers("1.2.3")
|
|
52
|
+
>>> current + 1
|
|
53
|
+
Version 1.3.3
|
|
54
|
+
>>> current + 1.2
|
|
55
|
+
Version 2.4.3
|
|
56
|
+
>>> current
|
|
57
|
+
Version 1.2.3
|
|
58
|
+
>>> current += Vers("1.0.1")
|
|
59
|
+
>>> current
|
|
60
|
+
Version 2.2.4
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Development
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
git clone https://github.com/RomoloPoliti-INAF/version-tools.git
|
|
67
|
+
cd version-tools
|
|
68
|
+
uv sync --locked
|
|
69
|
+
uv run --locked ruff check
|
|
70
|
+
uv run --locked ruff format --check
|
|
71
|
+
uv run --locked pytest --cov=semantic_version_tools --cov-branch --cov-report=term-missing --cov-fail-under=80
|
|
72
|
+
uv build
|
|
73
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Version-Tools
|
|
2
|
+
|
|
3
|
+
`semantic-version-tools` provides `Vers`, a Python class for parsing,
|
|
4
|
+
comparing and incrementing version numbers. It supports Python 3.10–3.15.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Install from PyPI with pip or add the package to a uv project.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
pip install semantic-version-tools
|
|
12
|
+
uv add semantic-version-tools
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```pycon
|
|
18
|
+
>>> from semantic_version_tools import Vers
|
|
19
|
+
>>> Vers("1.2")
|
|
20
|
+
Version 1.2
|
|
21
|
+
>>> Vers((1, 2, 0, "d", 1))
|
|
22
|
+
Version 1.2.0-devel.1
|
|
23
|
+
>>> Vers("1.2-dev.1+sha.abc").full()
|
|
24
|
+
'1.2.0-devel.1+sha.abc'
|
|
25
|
+
>>> Vers("1.2.0-rc.1") < Vers("1.2.0")
|
|
26
|
+
True
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Tuples contain two to five fields in this order: major, minor, patch,
|
|
30
|
+
prerelease code and build number. The prerelease codes are `d` (development),
|
|
31
|
+
`a` (alpha), `b` (beta), `rc` (release candidate) and `f` (final).
|
|
32
|
+
A prerelease string with an omitted patch uses patch zero. Metadata after
|
|
33
|
+
`+` is preserved in the full version and ignored in comparisons.
|
|
34
|
+
`short()` returns the numeric version without the prerelease or metadata.
|
|
35
|
+
|
|
36
|
+
Addition returns a new `Vers` instance. Integers increment the minor
|
|
37
|
+
component. Floats use the integer and fractional digits as major and minor
|
|
38
|
+
increments. Adding another `Vers` combines the numeric components and
|
|
39
|
+
preserves the left operand's precision and release information.
|
|
40
|
+
|
|
41
|
+
```pycon
|
|
42
|
+
>>> current = Vers("1.2.3")
|
|
43
|
+
>>> current + 1
|
|
44
|
+
Version 1.3.3
|
|
45
|
+
>>> current + 1.2
|
|
46
|
+
Version 2.4.3
|
|
47
|
+
>>> current
|
|
48
|
+
Version 1.2.3
|
|
49
|
+
>>> current += Vers("1.0.1")
|
|
50
|
+
>>> current
|
|
51
|
+
Version 2.2.4
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Development
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
git clone https://github.com/RomoloPoliti-INAF/version-tools.git
|
|
58
|
+
cd version-tools
|
|
59
|
+
uv sync --locked
|
|
60
|
+
uv run --locked ruff check
|
|
61
|
+
uv run --locked ruff format --check
|
|
62
|
+
uv run --locked pytest --cov=semantic_version_tools --cov-branch --cov-report=term-missing --cov-fail-under=80
|
|
63
|
+
uv build
|
|
64
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "semantic-version-tools"
|
|
3
|
+
version = "1.5.0"
|
|
4
|
+
description = "Class to manage semantic versioning"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10,<3.16"
|
|
7
|
+
dependencies = []
|
|
8
|
+
|
|
9
|
+
[[project.authors]]
|
|
10
|
+
name = "Romolo Politi"
|
|
11
|
+
email = "romolo.politi@inaf.it"
|
|
12
|
+
|
|
13
|
+
[dependency-groups]
|
|
14
|
+
dev = [
|
|
15
|
+
"pytest>=9.2.0,<10",
|
|
16
|
+
"pytest-cov>=7,<8",
|
|
17
|
+
"ruff>=0.17.4",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[build-system]
|
|
21
|
+
requires = ["uv_build>=0.13.7,<0.14"]
|
|
22
|
+
build-backend = "uv_build"
|
|
23
|
+
|
|
24
|
+
[tool.uv.build-backend]
|
|
25
|
+
source-include = ["CHANGELOG.md"]
|
|
26
|
+
|
|
27
|
+
[tool.ruff]
|
|
28
|
+
target-version = "py310"
|
|
29
|
+
line-length = 88
|
|
30
|
+
src = ["src"]
|
|
31
|
+
|
|
32
|
+
[tool.ruff.lint]
|
|
33
|
+
select = [
|
|
34
|
+
"E4",
|
|
35
|
+
"E7",
|
|
36
|
+
"E9",
|
|
37
|
+
"F",
|
|
38
|
+
"I",
|
|
39
|
+
"UP",
|
|
40
|
+
"B",
|
|
41
|
+
"RUF",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[tool.ruff.format]
|
|
45
|
+
docstring-code-format = true
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "semantic-version-tools"
|
|
3
|
+
version = "1.5.0"
|
|
4
|
+
description = "Class to manage semantic versioning"
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "Romolo Politi",email = "romolo.politi@inaf.it"}
|
|
7
|
+
]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.10,<3.16"
|
|
10
|
+
dependencies = []
|
|
11
|
+
|
|
12
|
+
[dependency-groups]
|
|
13
|
+
dev = [
|
|
14
|
+
"pytest>=9.2.0,<10",
|
|
15
|
+
"pytest-cov>=7,<8",
|
|
16
|
+
"ruff>=0.17.4",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[build-system]
|
|
20
|
+
requires = ["uv_build>=0.13.7,<0.14"]
|
|
21
|
+
build-backend = "uv_build"
|
|
22
|
+
|
|
23
|
+
[tool.uv.build-backend]
|
|
24
|
+
source-include = ["CHANGELOG.md"]
|
|
25
|
+
|
|
26
|
+
[tool.ruff]
|
|
27
|
+
target-version = "py310"
|
|
28
|
+
line-length = 88
|
|
29
|
+
src = ["src"]
|
|
30
|
+
|
|
31
|
+
[tool.ruff.lint]
|
|
32
|
+
select = ["E4", "E7", "E9", "F", "I", "UP", "B", "RUF"]
|
|
33
|
+
|
|
34
|
+
[tool.ruff.format]
|
|
35
|
+
docstring-code-format = true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from semantic_version_tools.version import Vers as Vers
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from copy import copy
|
|
3
|
+
from functools import total_ordering
|
|
4
|
+
from importlib.metadata import version
|
|
5
|
+
|
|
6
|
+
###################################
|
|
7
|
+
# Versioning Class
|
|
8
|
+
###################################
|
|
9
|
+
#
|
|
10
|
+
# This class is used to manage the versioning of the
|
|
11
|
+
# software or other products
|
|
12
|
+
#
|
|
13
|
+
# The versioning is based on the Semantic Versioning 2.0.0
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
__version__ = version("semantic_version_tools")
|
|
18
|
+
|
|
19
|
+
code = {"d": "devel", "a": "alpha", "b": "beta", "rc": "ReleaseCandidate", "f": "Final"}
|
|
20
|
+
|
|
21
|
+
numeric_map = {"d": 1, "a": 2, "b": 3, "rc": 4, "f": 5}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@total_ordering
|
|
25
|
+
class Vers:
|
|
26
|
+
"""
|
|
27
|
+
Class for the manipulation of objects version following the Semantic Versioning
|
|
28
|
+
|
|
29
|
+
major.minor.patch-<prerel>.<build>
|
|
30
|
+
|
|
31
|
+
Is implemented a special dialect.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
The admitted pre-release values are
|
|
36
|
+
|
|
37
|
+
* d for the developing version
|
|
38
|
+
* a for the alpha version
|
|
39
|
+
* b for the beta version
|
|
40
|
+
* rc for the release candidate
|
|
41
|
+
* f for the final version
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, ver: tuple | str) -> None:
|
|
45
|
+
|
|
46
|
+
self.metadata = None
|
|
47
|
+
if isinstance(ver, str):
|
|
48
|
+
match = re.fullmatch(
|
|
49
|
+
r"(\d+)\.(\d+)(?:\.(\d+))?"
|
|
50
|
+
r"(?:[-.]([a-zA-Z]+)(?:\.?(\d+))?)?"
|
|
51
|
+
r"(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?",
|
|
52
|
+
ver,
|
|
53
|
+
)
|
|
54
|
+
if match is None:
|
|
55
|
+
raise ValueError(f"Invalid version: {ver!r}")
|
|
56
|
+
|
|
57
|
+
major, minor, patch, release, build, self.metadata = match.groups()
|
|
58
|
+
ver = (int(major), int(minor))
|
|
59
|
+
if patch is not None or release is not None:
|
|
60
|
+
ver += (int(patch or 0),)
|
|
61
|
+
if release is not None:
|
|
62
|
+
aliases = {
|
|
63
|
+
"dev": "d",
|
|
64
|
+
"development": "d",
|
|
65
|
+
**{name.lower(): key for key, name in code.items()},
|
|
66
|
+
}
|
|
67
|
+
release = release.lower()
|
|
68
|
+
ver += (aliases.get(release, release), int(build or 1))
|
|
69
|
+
|
|
70
|
+
if not isinstance(ver, tuple):
|
|
71
|
+
raise TypeError("Version must be a string or tuple")
|
|
72
|
+
if not 2 <= len(ver) <= 5:
|
|
73
|
+
raise ValueError("Version tuple must contain two to five elements")
|
|
74
|
+
|
|
75
|
+
self.major, self.minor = ver[:2]
|
|
76
|
+
self._len = min(len(ver), 3)
|
|
77
|
+
self.patch = ver[2] if len(ver) >= 3 else 0
|
|
78
|
+
self.type = ver[3] if len(ver) >= 4 else "f"
|
|
79
|
+
self.build = ver[4] if len(ver) == 5 else 1
|
|
80
|
+
if self.type is not None:
|
|
81
|
+
if not isinstance(self.type, str):
|
|
82
|
+
raise TypeError(
|
|
83
|
+
"The fourth element of the version number must be a string"
|
|
84
|
+
)
|
|
85
|
+
if self.type not in code:
|
|
86
|
+
raise ValueError(
|
|
87
|
+
f"The fourth element of the version must be one of {','.join(code)}"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
def full(self) -> str:
|
|
91
|
+
"""
|
|
92
|
+
Return the full version
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
str: the version string
|
|
96
|
+
"""
|
|
97
|
+
if self.type is None or self.type.lower() == "f":
|
|
98
|
+
nVer = self.short()
|
|
99
|
+
# elif:
|
|
100
|
+
# nVer = f"{self.major}.{self.minor}.{self.patch}"
|
|
101
|
+
else:
|
|
102
|
+
nVer = (
|
|
103
|
+
f"{self.major}.{self.minor}.{self.patch}-{code[self.type]}.{self.build}"
|
|
104
|
+
)
|
|
105
|
+
if self.metadata is not None:
|
|
106
|
+
return f"{nVer}+{self.metadata}"
|
|
107
|
+
return nVer
|
|
108
|
+
|
|
109
|
+
def short(self) -> str:
|
|
110
|
+
"""
|
|
111
|
+
Return the version in the form major.minor.patch
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
str: the version string
|
|
115
|
+
"""
|
|
116
|
+
return f"{self.major}.{self.minor}{f'.{self.patch}' if self._len == 3 else ''}"
|
|
117
|
+
|
|
118
|
+
def __repr__(self) -> str:
|
|
119
|
+
return f"Version {self.full()}"
|
|
120
|
+
|
|
121
|
+
def __str__(self) -> str:
|
|
122
|
+
return f"Version {self.full()}"
|
|
123
|
+
|
|
124
|
+
def _precedence(self) -> tuple:
|
|
125
|
+
return (
|
|
126
|
+
self.major,
|
|
127
|
+
self.minor,
|
|
128
|
+
self.patch,
|
|
129
|
+
numeric_map[self.type or "f"],
|
|
130
|
+
self.build,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
def __eq__(self, other) -> bool:
|
|
134
|
+
if not isinstance(other, Vers):
|
|
135
|
+
return NotImplemented
|
|
136
|
+
return self._precedence() == other._precedence()
|
|
137
|
+
|
|
138
|
+
def __lt__(self, other) -> bool:
|
|
139
|
+
if not isinstance(other, Vers):
|
|
140
|
+
return NotImplemented
|
|
141
|
+
return self._precedence() < other._precedence()
|
|
142
|
+
|
|
143
|
+
def __add__(self, other: "Vers | int | float") -> "Vers":
|
|
144
|
+
result = copy(self)
|
|
145
|
+
if isinstance(other, int):
|
|
146
|
+
result.minor += other
|
|
147
|
+
elif isinstance(other, float):
|
|
148
|
+
major, minor = str(other).split(".")
|
|
149
|
+
result.major += int(major)
|
|
150
|
+
result.minor += int(minor)
|
|
151
|
+
elif isinstance(other, Vers):
|
|
152
|
+
result.major += other.major
|
|
153
|
+
result.minor += other.minor
|
|
154
|
+
if result._len == 3:
|
|
155
|
+
result.patch += other.patch
|
|
156
|
+
else:
|
|
157
|
+
return NotImplemented
|
|
158
|
+
return result
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: semantic-version-tools
|
|
3
|
-
Version: 1.4.0
|
|
4
|
-
Summary: Class to manage semantic versioning
|
|
5
|
-
Author: Romolo Politi
|
|
6
|
-
Author-email: romolo.politi@inaf.it
|
|
7
|
-
Requires-Python: >=3.10,<3.15
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
-
Requires-Dist: setuptools (>=80.9.0,<81.0.0)
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# Version-Tools
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
20
|
-
|
|
21
|
-
### From Repository
|
|
22
|
-
|
|
23
|
-
To install the Version-Tools package from the repository, run the following commands:
|
|
24
|
-
|
|
25
|
-
```sh
|
|
26
|
-
git clone https://github.com/RomoloPoliti-INAF/version-tools.git
|
|
27
|
-
cd version-tools
|
|
28
|
-
poetry install
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### From PyPi
|
|
32
|
-
|
|
33
|
-
To install the Version-Tools package from PyPi, run the following command:
|
|
34
|
-
|
|
35
|
-
```sh
|
|
36
|
-
pip install semantic-version-tools
|
|
37
|
-
```
|
|
38
|
-
### Using poetry
|
|
39
|
-
|
|
40
|
-
To add the package to your poetry project, you can run the command:
|
|
41
|
-
|
|
42
|
-
```sh
|
|
43
|
-
poetry add semantic-versioning-tools
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
## Usage
|
|
48
|
-
|
|
49
|
-
To use the library it's necessary import the class *Vers*, than you can comapare or manipulate the version numbers.
|
|
50
|
-
|
|
51
|
-
### Initialize and print version
|
|
52
|
-
|
|
53
|
-
```python
|
|
54
|
-
>>> from semantic_version_tools import Vers
|
|
55
|
-
|
|
56
|
-
>>> main_ver=Vers('1.0')
|
|
57
|
-
>>> print(main_ver)
|
|
58
|
-
|
|
59
|
-
Version 1.0
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
The version number could be a string or a tuple, whit 2 or 5 elements:
|
|
63
|
-
- the major version number
|
|
64
|
-
- the minor version number
|
|
65
|
-
- the patch number
|
|
66
|
-
- pre-release type
|
|
67
|
-
- build number
|
|
68
|
-
|
|
69
|
-
For the pre-release are used letters as reported below:
|
|
70
|
-
|
|
71
|
-
- **d**: developing version
|
|
72
|
-
- **a**: alpha release
|
|
73
|
-
- **b**: beta release
|
|
74
|
-
- **rc**: release candidate
|
|
75
|
-
- **f**: final release
|
|
76
|
-
|
|
77
|
-
```python
|
|
78
|
-
>>> main_version = Vers((0,1,0,'d',1))
|
|
79
|
-
>>> print(main_version)
|
|
80
|
-
|
|
81
|
-
Version 0.1.0-devel.1
|
|
82
|
-
|
|
83
|
-
>>> main_version = Vers('0.1.0-a.1')
|
|
84
|
-
>>> print(main_version)
|
|
85
|
-
|
|
86
|
-
Version 0.1.0-alpha.1
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### Compare versions
|
|
90
|
-
|
|
91
|
-
In the class Vers are implemented the main comparison operators.
|
|
92
|
-
For example:
|
|
93
|
-
|
|
94
|
-
```python
|
|
95
|
-
>>> a=Vers('1.0.0')
|
|
96
|
-
>>> b=Vers('1.0.1')
|
|
97
|
-
|
|
98
|
-
>>> a>b
|
|
99
|
-
False
|
|
100
|
-
>>> a==b
|
|
101
|
-
False
|
|
102
|
-
>>> a<b
|
|
103
|
-
True
|
|
104
|
-
a<=b
|
|
105
|
-
True
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### Sum and increase
|
|
109
|
-
|
|
110
|
-
It's possible sum tro version number or icrease it.
|
|
111
|
-
|
|
112
|
-
```python
|
|
113
|
-
>>> a = Vers('1.0.0')
|
|
114
|
-
>>> b = Vers('1.0.1')
|
|
115
|
-
>>> c=a+b
|
|
116
|
-
>>> c
|
|
117
|
-
Version 2.0.1
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
>>> a = Vers('1.0.0')
|
|
121
|
-
>>> a=a+1
|
|
122
|
-
>>> a
|
|
123
|
-
Version 1.1.0
|
|
124
|
-
# equivalent to
|
|
125
|
-
>>> a +=1
|
|
126
|
-
>>> a
|
|
127
|
-
Version 1.1.0
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
The summ add a minor version. To add a major version you must add a float
|
|
131
|
-
|
|
132
|
-
```python
|
|
133
|
-
>>> a = Vers('1.0.0')
|
|
134
|
-
>>> a += 1.0
|
|
135
|
-
>>> a
|
|
136
|
-
Version 2.0.0
|
|
137
|
-
```
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# Version-Tools
|
|
3
|
-
|
|
4
|
-
## Installation
|
|
5
|
-
|
|
6
|
-
### From Repository
|
|
7
|
-
|
|
8
|
-
To install the Version-Tools package from the repository, run the following commands:
|
|
9
|
-
|
|
10
|
-
```sh
|
|
11
|
-
git clone https://github.com/RomoloPoliti-INAF/version-tools.git
|
|
12
|
-
cd version-tools
|
|
13
|
-
poetry install
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
### From PyPi
|
|
17
|
-
|
|
18
|
-
To install the Version-Tools package from PyPi, run the following command:
|
|
19
|
-
|
|
20
|
-
```sh
|
|
21
|
-
pip install semantic-version-tools
|
|
22
|
-
```
|
|
23
|
-
### Using poetry
|
|
24
|
-
|
|
25
|
-
To add the package to your poetry project, you can run the command:
|
|
26
|
-
|
|
27
|
-
```sh
|
|
28
|
-
poetry add semantic-versioning-tools
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
## Usage
|
|
33
|
-
|
|
34
|
-
To use the library it's necessary import the class *Vers*, than you can comapare or manipulate the version numbers.
|
|
35
|
-
|
|
36
|
-
### Initialize and print version
|
|
37
|
-
|
|
38
|
-
```python
|
|
39
|
-
>>> from semantic_version_tools import Vers
|
|
40
|
-
|
|
41
|
-
>>> main_ver=Vers('1.0')
|
|
42
|
-
>>> print(main_ver)
|
|
43
|
-
|
|
44
|
-
Version 1.0
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
The version number could be a string or a tuple, whit 2 or 5 elements:
|
|
48
|
-
- the major version number
|
|
49
|
-
- the minor version number
|
|
50
|
-
- the patch number
|
|
51
|
-
- pre-release type
|
|
52
|
-
- build number
|
|
53
|
-
|
|
54
|
-
For the pre-release are used letters as reported below:
|
|
55
|
-
|
|
56
|
-
- **d**: developing version
|
|
57
|
-
- **a**: alpha release
|
|
58
|
-
- **b**: beta release
|
|
59
|
-
- **rc**: release candidate
|
|
60
|
-
- **f**: final release
|
|
61
|
-
|
|
62
|
-
```python
|
|
63
|
-
>>> main_version = Vers((0,1,0,'d',1))
|
|
64
|
-
>>> print(main_version)
|
|
65
|
-
|
|
66
|
-
Version 0.1.0-devel.1
|
|
67
|
-
|
|
68
|
-
>>> main_version = Vers('0.1.0-a.1')
|
|
69
|
-
>>> print(main_version)
|
|
70
|
-
|
|
71
|
-
Version 0.1.0-alpha.1
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Compare versions
|
|
75
|
-
|
|
76
|
-
In the class Vers are implemented the main comparison operators.
|
|
77
|
-
For example:
|
|
78
|
-
|
|
79
|
-
```python
|
|
80
|
-
>>> a=Vers('1.0.0')
|
|
81
|
-
>>> b=Vers('1.0.1')
|
|
82
|
-
|
|
83
|
-
>>> a>b
|
|
84
|
-
False
|
|
85
|
-
>>> a==b
|
|
86
|
-
False
|
|
87
|
-
>>> a<b
|
|
88
|
-
True
|
|
89
|
-
a<=b
|
|
90
|
-
True
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
### Sum and increase
|
|
94
|
-
|
|
95
|
-
It's possible sum tro version number or icrease it.
|
|
96
|
-
|
|
97
|
-
```python
|
|
98
|
-
>>> a = Vers('1.0.0')
|
|
99
|
-
>>> b = Vers('1.0.1')
|
|
100
|
-
>>> c=a+b
|
|
101
|
-
>>> c
|
|
102
|
-
Version 2.0.1
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
>>> a = Vers('1.0.0')
|
|
106
|
-
>>> a=a+1
|
|
107
|
-
>>> a
|
|
108
|
-
Version 1.1.0
|
|
109
|
-
# equivalent to
|
|
110
|
-
>>> a +=1
|
|
111
|
-
>>> a
|
|
112
|
-
Version 1.1.0
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
The summ add a minor version. To add a major version you must add a float
|
|
116
|
-
|
|
117
|
-
```python
|
|
118
|
-
>>> a = Vers('1.0.0')
|
|
119
|
-
>>> a += 1.0
|
|
120
|
-
>>> a
|
|
121
|
-
Version 2.0.0
|
|
122
|
-
```
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
[project]
|
|
2
|
-
name = "semantic-version-tools"
|
|
3
|
-
version = "1.4.0"
|
|
4
|
-
description = "Class to manage semantic versioning"
|
|
5
|
-
authors = [
|
|
6
|
-
{name = "Romolo Politi",email = "romolo.politi@inaf.it"}
|
|
7
|
-
]
|
|
8
|
-
readme = "README.md"
|
|
9
|
-
dependencies = [
|
|
10
|
-
"setuptools (>=80.9.0,<81.0.0)"
|
|
11
|
-
]
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
[tool.poetry]
|
|
15
|
-
packages = [{include = "semantic_version_tools", from = "src"}]
|
|
16
|
-
include = ["CHANGELOG.md"]
|
|
17
|
-
name="semantic-version-tools"
|
|
18
|
-
version="1.3.1"
|
|
19
|
-
description="Class to manage semantic versioning"
|
|
20
|
-
authors = [
|
|
21
|
-
"Romolo Politi <romolo.politi@inaf.it>"
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
[tool.poetry.dependencies]
|
|
25
|
-
python = ">=3.10, <3.15"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
[tool.poetry.group.dev.dependencies]
|
|
29
|
-
pytest = "^8.3.4"
|
|
30
|
-
|
|
31
|
-
[build-system]
|
|
32
|
-
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
33
|
-
build-backend = "poetry.core.masonry.api"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from semantic_version_tools.version import Vers
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import re
|
|
3
|
-
from importlib.metadata import version
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
###################################
|
|
7
|
-
# Versioning Class
|
|
8
|
-
###################################
|
|
9
|
-
#
|
|
10
|
-
# This class is used to manage the versioning of the
|
|
11
|
-
# software or other products
|
|
12
|
-
#
|
|
13
|
-
# The versioning is based on the Semantic Versioning 2.0.0
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
__version__ = version('semantic_version_tools')
|
|
18
|
-
|
|
19
|
-
code = {"d": "devel", "a": "alpha", "b": "beta", "rc": "ReleaseCandidate", "f": "Final"}
|
|
20
|
-
|
|
21
|
-
numeric_map = {"d": 1, "a": 2, "b": 3, "rc": 4, "f": 5}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class Vers:
|
|
25
|
-
"""
|
|
26
|
-
Class for the manipulation of objects version following the Semantic Versioning
|
|
27
|
-
|
|
28
|
-
major.minor.patch-<prerel>.<build>
|
|
29
|
-
|
|
30
|
-
Is implemented a special dialect.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
The admitted pre-release values are
|
|
35
|
-
|
|
36
|
-
* d for the developing version
|
|
37
|
-
* a for the alpha version
|
|
38
|
-
* b for the beta version
|
|
39
|
-
* rc for the release candidate
|
|
40
|
-
* f for the final version
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
def __init__(self, ver: tuple | str) -> None:
|
|
44
|
-
|
|
45
|
-
if isinstance(ver, str):
|
|
46
|
-
a = re.match(
|
|
47
|
-
r"(\d+)\.(\d+)(?:\.(\d+))?(?:[-\.]([a-zA-Z]*)(?:\.?(\d+))?)?", ver
|
|
48
|
-
)
|
|
49
|
-
prt = list(a.groups())
|
|
50
|
-
prt[0:2] = [int(i) for i in prt[0:2]]
|
|
51
|
-
if prt[2] is not None:
|
|
52
|
-
prt[2] = int(prt[2])
|
|
53
|
-
if prt[3] is not None:
|
|
54
|
-
if prt[3].lower() in "development":
|
|
55
|
-
prt[3] = "d"
|
|
56
|
-
elif prt[3].lower() in "alpha":
|
|
57
|
-
prt[3] = "a"
|
|
58
|
-
elif prt[3].lower() in "beta":
|
|
59
|
-
prt[3] = "b"
|
|
60
|
-
elif prt[3].lower() in "releasecandidate":
|
|
61
|
-
prt[3] = "rc"
|
|
62
|
-
elif prt[3].lower() in "final":
|
|
63
|
-
prt[3] = "f"
|
|
64
|
-
else:
|
|
65
|
-
prt[3] = None
|
|
66
|
-
if prt[3] is not None and prt[4] is None:
|
|
67
|
-
prt[4] = None
|
|
68
|
-
else:
|
|
69
|
-
if prt[3] is not None:
|
|
70
|
-
prt[4] = int(prt[4])
|
|
71
|
-
ver = tuple([x for x in prt if x is not None])
|
|
72
|
-
# print(ver)
|
|
73
|
-
self._len = 3
|
|
74
|
-
if len(ver) < 3:
|
|
75
|
-
self.major, self.minor, *extra = ver
|
|
76
|
-
self.patch = 0
|
|
77
|
-
self._len = 2
|
|
78
|
-
else:
|
|
79
|
-
self.major, self.minor, self.patch, *extra = ver
|
|
80
|
-
# self.patch = extra[0] if extra else None
|
|
81
|
-
self.type = extra[0] if len(extra) != 0 else 'f'
|
|
82
|
-
if self.type is not None:
|
|
83
|
-
if not isinstance(self.type, str):
|
|
84
|
-
raise Exception(
|
|
85
|
-
f"The fourth element of the version number must be a string"
|
|
86
|
-
)
|
|
87
|
-
if not self.type in code.keys():
|
|
88
|
-
raise ValueError(
|
|
89
|
-
f"the fourth element of the version mus be one of {
|
|
90
|
-
','.join(code.keys())}"
|
|
91
|
-
)
|
|
92
|
-
self.build = extra[1] if len(extra) > 1 else 1
|
|
93
|
-
|
|
94
|
-
def full(self) -> str:
|
|
95
|
-
"""
|
|
96
|
-
Return the full version
|
|
97
|
-
|
|
98
|
-
Returns:
|
|
99
|
-
str: the version string
|
|
100
|
-
"""
|
|
101
|
-
if self.type is None or self.type.lower() == "f":
|
|
102
|
-
nVer = f"{self.major}.{self.minor}{
|
|
103
|
-
f'.{self.patch}' if self._len == 3 else ''}"
|
|
104
|
-
# elif:
|
|
105
|
-
# nVer = f"{self.major}.{self.minor}.{self.patch}"
|
|
106
|
-
else:
|
|
107
|
-
nVer = f"{self.major}.{self.minor}.{
|
|
108
|
-
self.patch}-{code[self.type]}.{self.build}"
|
|
109
|
-
return nVer
|
|
110
|
-
|
|
111
|
-
def short(self) -> str:
|
|
112
|
-
"""
|
|
113
|
-
Return the version in the form major.minor.patch
|
|
114
|
-
|
|
115
|
-
Returns:
|
|
116
|
-
str: the version string
|
|
117
|
-
"""
|
|
118
|
-
return f"{self.major}.{self.minor}{f'.{self.patch}' if self._len==3 else ''}"
|
|
119
|
-
|
|
120
|
-
def __repr__(self) -> str:
|
|
121
|
-
return f"Version {self.full()}"
|
|
122
|
-
|
|
123
|
-
def __str__(self) -> str:
|
|
124
|
-
return f"Version {self.full()}"
|
|
125
|
-
|
|
126
|
-
def __eq__(self, other) -> bool:
|
|
127
|
-
if (
|
|
128
|
-
self.major == other.major
|
|
129
|
-
and self.minor == other.minor
|
|
130
|
-
and self.patch == other.patch
|
|
131
|
-
):
|
|
132
|
-
if self.type is None:
|
|
133
|
-
return True
|
|
134
|
-
else:
|
|
135
|
-
if self.type == other.type and self.build == other.build:
|
|
136
|
-
return True
|
|
137
|
-
else:
|
|
138
|
-
return False
|
|
139
|
-
else:
|
|
140
|
-
return False
|
|
141
|
-
# return all(getattr(self, item) == getattr(other, item) for item in self.__dict__ if not item.startswith('_'))
|
|
142
|
-
|
|
143
|
-
def __ne__(self, other) -> bool:
|
|
144
|
-
return not self == other
|
|
145
|
-
|
|
146
|
-
def __gt__(self, other) -> bool:
|
|
147
|
-
if self.major != other.major:
|
|
148
|
-
return self.major > other.major
|
|
149
|
-
elif self.minor != other.minor:
|
|
150
|
-
return self.minor > other.minor
|
|
151
|
-
elif self.patch != other.patch:
|
|
152
|
-
return self.patch > other.patch
|
|
153
|
-
elif numeric_map[self.type] != numeric_map[other.type]:
|
|
154
|
-
return numeric_map[self.type] > numeric_map[other.type]
|
|
155
|
-
else:
|
|
156
|
-
return self.build > other.build
|
|
157
|
-
|
|
158
|
-
def __ge__(self, other) -> bool:
|
|
159
|
-
if self > other or self == other:
|
|
160
|
-
return True
|
|
161
|
-
else:
|
|
162
|
-
return False
|
|
163
|
-
|
|
164
|
-
def __lt__(self, other) -> bool:
|
|
165
|
-
if self.major != other.major:
|
|
166
|
-
return self.major < other.major
|
|
167
|
-
elif self.minor != other.minor:
|
|
168
|
-
return self.minor < other.minor
|
|
169
|
-
elif self.patch != other.patch:
|
|
170
|
-
return self.patch < other.patch
|
|
171
|
-
elif numeric_map[self.type] != numeric_map[other.type]:
|
|
172
|
-
return numeric_map[self.type] < numeric_map[other.type]
|
|
173
|
-
else:
|
|
174
|
-
return self.build < other.build
|
|
175
|
-
|
|
176
|
-
def __le__(self, other) -> bool:
|
|
177
|
-
if self < other or self == other:
|
|
178
|
-
return True
|
|
179
|
-
else:
|
|
180
|
-
return False
|
|
181
|
-
|
|
182
|
-
def __add__(self, other:"Vers") -> "Vers":
|
|
183
|
-
|
|
184
|
-
if isinstance(other,int):
|
|
185
|
-
self.minor += other
|
|
186
|
-
|
|
187
|
-
if isinstance(other,float):
|
|
188
|
-
a=str(other).split(".")
|
|
189
|
-
self.major += int(a[0])
|
|
190
|
-
self.minor += int(a[1])
|
|
191
|
-
|
|
192
|
-
if isinstance(other, Vers):
|
|
193
|
-
self.major += other.major
|
|
194
|
-
self.minor += other.minor
|
|
195
|
-
if self._len == 3:
|
|
196
|
-
self.patch += other.patch
|
|
197
|
-
return self
|
|
198
|
-
# version = Vers(VERSION)
|