Skip to content

Commit 72d9726

Browse files
authored
More updates (#2269)
* Updated check_version * Fixed check version * Updated version to 2.0.0 * Thwrow warning for any reason in check version
1 parent e4d6cce commit 72d9726

File tree

3 files changed

+119
-11
lines changed

3 files changed

+119
-11
lines changed

albumentations/check_version.py

+69-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
from __future__ import annotations
2+
13
import json
4+
import re
25
import urllib.request
36
from urllib.request import OpenerDirector
47
from warnings import warn
@@ -46,21 +49,77 @@ def parse_version(data: str) -> str:
4649
return ""
4750

4851

52+
def compare_versions(v1: tuple[int | str, ...], v2: tuple[int | str, ...]) -> bool:
53+
"""Compare two version tuples.
54+
Returns True if v1 > v2, False otherwise.
55+
56+
Special rules:
57+
1. Release version > pre-release version (e.g., (1, 4) > (1, 4, 'beta'))
58+
2. Numeric parts are compared numerically
59+
3. String parts are compared lexicographically
60+
"""
61+
# First compare common parts
62+
for p1, p2 in zip(v1, v2):
63+
if p1 != p2:
64+
# If both are same type, direct comparison works
65+
if isinstance(p1, int) and isinstance(p2, int):
66+
return p1 > p2
67+
if isinstance(p1, str) and isinstance(p2, str):
68+
return p1 > p2
69+
# If types differ, numbers are greater (release > pre-release)
70+
return isinstance(p1, int)
71+
72+
# If we get here, all common parts are equal
73+
# Longer version is greater only if next element is a number
74+
if len(v1) > len(v2):
75+
return isinstance(v1[len(v2)], int)
76+
if len(v2) > len(v1):
77+
# v2 is longer, so v1 is greater only if v2's next part is a string (pre-release)
78+
return isinstance(v2[len(v1)], str)
79+
80+
return False # Versions are equal
81+
82+
83+
def parse_version_parts(version_str: str) -> tuple[int | str, ...]:
84+
"""Convert version string to tuple of (int | str) parts following PEP 440 conventions.
85+
86+
Examples:
87+
"1.4.24" -> (1, 4, 24)
88+
"1.4beta" -> (1, 4, "beta")
89+
"1.4.beta2" -> (1, 4, "beta", 2)
90+
"1.4.alpha2" -> (1, 4, "alpha", 2)
91+
"""
92+
parts = []
93+
# First split by dots
94+
for part in version_str.split("."):
95+
# Then parse each part for numbers and letters
96+
segments = re.findall(r"([0-9]+|[a-zA-Z]+)", part)
97+
for segment in segments:
98+
if segment.isdigit():
99+
parts.append(int(segment))
100+
else:
101+
parts.append(segment.lower())
102+
return tuple(parts)
103+
104+
49105
def check_for_updates() -> None:
50106
try:
51107
data = fetch_version_info()
52108
latest_version = parse_version(data)
53-
if latest_version and latest_version != current_version:
54-
warn(
55-
f"A new version of Albumentations is available: {latest_version} (you have {current_version}). " # noqa: S608
56-
"Upgrade using: pip install -U albumentations. "
57-
"To disable automatic update checks, set the environment variable NO_ALBUMENTATIONS_UPDATE to 1.",
58-
UserWarning,
59-
stacklevel=2,
60-
)
61-
except Exception as e: # General exception catch to ensure silent failure # noqa: BLE001
109+
if latest_version:
110+
latest_parts = parse_version_parts(latest_version)
111+
current_parts = parse_version_parts(current_version)
112+
if compare_versions(latest_parts, current_parts):
113+
warn(
114+
f"A new version of Albumentations is available: {latest_version!r} (you have {current_version!r}). "
115+
"Upgrade using: pip install -U albumentations. "
116+
"To disable automatic update checks, set the environment variable NO_ALBUMENTATIONS_UPDATE to 1.",
117+
UserWarning,
118+
stacklevel=2,
119+
)
120+
except Exception as e: # General exception catch to ensure silent failure # noqa: BLE001
62121
warn(
63-
f"Failed to check for updates due to an unexpected error: {e}. " # noqa: S608
122+
f"Failed to check for updates due to error: {e}. "
64123
"To disable automatic update checks, set the environment variable NO_ALBUMENTATIONS_UPDATE to 1.",
65124
UserWarning,
66125
stacklevel=2,

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ requires = [ "setuptools>=45", "wheel" ]
66
[project]
77
name = "albumentations"
88

9-
version = "1.5.0"
9+
version = "2.0.0"
1010

1111
description = "Fast, flexible, and advanced augmentation library for deep learning, computer vision, and medical imaging. Albumentations offers a wide range of transformations for both 2D (images, masks, bboxes, keypoints) and 3D (volumes, volumetric masks) data, with optimized performance and seamless integration into ML workflows."
1212
readme = "README.md"
@@ -225,6 +225,7 @@ lint.ignore = [
225225
"PLR2004",
226226
"PTH123",
227227
"S311",
228+
"S608",
228229
"TC001",
229230
"TC002",
230231
"TC003",

tests/test_check_version.py

+48
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
from unittest.mock import MagicMock, patch
24

35
import pytest
@@ -7,6 +9,8 @@
79
fetch_version_info,
810
get_opener,
911
parse_version,
12+
parse_version_parts,
13+
compare_versions,
1014
)
1115

1216

@@ -127,3 +131,47 @@ def test_check_for_updates_with_update():
127131
with patch("albumentations.check_version.warn") as mock_warn: # Patch the imported warn
128132
check_for_updates()
129133
mock_warn.assert_called_once()
134+
135+
136+
137+
@pytest.mark.parametrize("version_str, expected", [
138+
# Standard versions
139+
("1.4.24", (1, 4, 24)),
140+
("0.0.1", (0, 0, 1)),
141+
("10.20.30", (10, 20, 30)),
142+
143+
# Pre-release versions
144+
("1.4beta", (1, 4, "beta")),
145+
("1.4beta2", (1, 4, "beta", 2)),
146+
("1.4.beta2", (1, 4, "beta", 2)),
147+
("1.4.alpha2", (1, 4, "alpha", 2)),
148+
("1.4rc1", (1, 4, "rc", 1)),
149+
("1.4.rc.1", (1, 4, "rc", 1)),
150+
151+
# Mixed case handling
152+
("1.4Beta2", (1, 4, "beta", 2)),
153+
("1.4ALPHA2", (1, 4, "alpha", 2)),
154+
])
155+
def test_parse_version_parts(version_str: str, expected: tuple[int | str, ...]) -> None:
156+
assert parse_version_parts(version_str) == expected
157+
158+
# Update the test to use the new comparison function
159+
@pytest.mark.parametrize("version1, version2, expected", [
160+
# Pre-release ordering
161+
("1.4beta2", "1.4beta1", True),
162+
("1.4", "1.4beta", True),
163+
("1.4beta", "1.4alpha", True),
164+
("1.4alpha2", "1.4alpha1", True),
165+
("1.4rc", "1.4beta", True),
166+
("2.0", "2.0rc1", True),
167+
168+
# Standard version ordering
169+
("1.5", "1.4", True),
170+
("1.4.1", "1.4", True),
171+
("1.4.24", "1.4.23", True),
172+
])
173+
def test_version_comparison(version1: str, version2: str, expected: bool) -> None:
174+
"""Test that version1 > version2 matches expected result."""
175+
v1 = parse_version_parts(version1)
176+
v2 = parse_version_parts(version2)
177+
assert compare_versions(v1, v2) == expected

0 commit comments

Comments
 (0)