11import sys
22from itertools import zip_longest
3- from typing import List , Union , Optional , overload
3+ from typing import Iterable , Optional , Union , overload
44
55if sys .version_info >= (3 , 8 ):
66 from typing import Literal
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+
2764def 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
5986def _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