Skip to content

Commit e56149e

Browse files
committed
Refactor canonicalize_version to use _split_version helper function
This should make the code slightly more efficient, by not first concatenating the version parts with `.` and then later splitting on that.
1 parent 2b0ce4b commit e56149e

File tree

1 file changed

+46
-22
lines changed

1 file changed

+46
-22
lines changed

src/php_version_compare/versioning.py

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import sys
22
from itertools import zip_longest
3-
from typing import List, Union, Optional, overload
3+
from typing import Iterable, Optional, Union, overload
44

55
if sys.version_info >= (3, 8):
66
from typing import Literal
@@ -24,6 +24,43 @@
2424
}
2525

2626

27+
def _split_version(version: str) -> Iterable[str]:
28+
"""
29+
Split a version string into its components. This function is used to split a
30+
version string into its major, minor, patch, and suffix components.
31+
32+
Examples:
33+
>>> list(_split_version("1.0"))
34+
['1', '0']
35+
>>> list(_split_version("1.0-DEV"))
36+
['1', '0', 'DEV']
37+
>>> list(_split_version("1.0.1alpha"))
38+
['1', '0', '1', 'alpha']
39+
40+
Args:
41+
version: The version string to split.
42+
43+
Yields:
44+
The components of the version string.
45+
"""
46+
current_segment = []
47+
48+
for curr_char in version:
49+
if curr_char in "-+_.":
50+
yield "".join(current_segment)
51+
current_segment = []
52+
elif current_segment and (
53+
(current_segment[-1].isdigit() and curr_char.isalpha())
54+
or (current_segment[-1].isalpha() and curr_char.isdigit())
55+
):
56+
yield "".join(current_segment)
57+
current_segment = [curr_char]
58+
else:
59+
current_segment.append(curr_char)
60+
61+
yield "".join(current_segment)
62+
63+
2764
def canonicalize_version(version: str) -> str:
2865
"""
2966
Canonicalize a version string into a "PHP-style" version string. This
@@ -36,30 +73,17 @@ def canonicalize_version(version: str) -> str:
3673
'1.0.DEV'
3774
>>> canonicalize_version("1.0.1alpha")
3875
'1.0.1.alpha'
39-
"""
40-
41-
canonicalized: List[str] = []
42-
previous_char = None
43-
44-
for curr_char in version:
45-
if curr_char in "-+_":
46-
curr_char = "."
47-
elif previous_char and (
48-
(previous_char.isdigit() and curr_char.isalpha())
49-
or (previous_char.isalpha() and curr_char.isdigit())
50-
):
51-
canonicalized.append(".")
5276
53-
canonicalized.append(curr_char)
54-
previous_char = curr_char
77+
Args:
78+
version: The version string to canonicalize.
5579
56-
return "".join(canonicalized)
80+
Returns:
81+
The canonicalized version string.
82+
"""
83+
return ".".join(_split_version(version))
5784

5885

5986
def _version_compare(version1: str, version2: str) -> int:
60-
def _split_version(version: str) -> List[str]:
61-
return canonicalize_version(version).lower().split(".")
62-
6387
def _compare_part(part1: str, part2: str) -> int:
6488
if part1.isdigit() and part2.isdigit():
6589
return int(part1) - int(part2)
@@ -69,8 +93,8 @@ def _compare_part(part1: str, part2: str) -> int:
6993
return -1
7094
return _SUFFIX_WEIGHT.get(part1, -1) - _SUFFIX_WEIGHT.get(part2, -1)
7195

72-
version1_parts = _split_version(version1)
73-
version2_parts = _split_version(version2)
96+
version1_parts = [part.lower() for part in _split_version(version1)]
97+
version2_parts = [part.lower() for part in _split_version(version2)]
7498
for part1, part2 in zip_longest(version1_parts, version2_parts, fillvalue="#"):
7599
result = _compare_part(part1, part2)
76100
if result != 0:

0 commit comments

Comments
 (0)