Rewrite parse_alphanumeric_range to fix #13722

This commit is contained in:
Per von Zweigbergk 2023-09-09 14:41:19 +02:00
parent a8c6f10b06
commit e485ed30c7
2 changed files with 19 additions and 27 deletions

View File

@ -2,6 +2,11 @@
NUMERIC_EXPANSION_PATTERN = r'\[((?:\d+[?:,-])+\d+)\]' NUMERIC_EXPANSION_PATTERN = r'\[((?:\d+[?:,-])+\d+)\]'
ALPHANUMERIC_EXPANSION_PATTERN = r'\[((?:[a-zA-Z0-9]+[?:,-])+[a-zA-Z0-9]+)\]' ALPHANUMERIC_EXPANSION_PATTERN = r'\[((?:[a-zA-Z0-9]+[?:,-])+[a-zA-Z0-9]+)\]'
# Patterns for parts of string expansion patterns
ALPHABETIC_RANGE_PATTERN = fr'(?:[A-Z]-[A-Z]|[a-z]-[a-z])'
NUMERIC_RANGE_PATTERN = r'(?:[0-9]+-[0-9]+)'
ALPHANUMERIC_SINGLETON_PATTERN = r'(?:[a-zA-Z0-9]+)'
# IP address expansion patterns # IP address expansion patterns
IP4_EXPANSION_PATTERN = r'\[((?:[0-9]{1,3}[?:,-])+[0-9]{1,3})\]' IP4_EXPANSION_PATTERN = r'\[((?:[0-9]{1,3}[?:,-])+[0-9]{1,3})\]'
IP6_EXPANSION_PATTERN = r'\[((?:[0-9a-f]{1,4}[?:,-])+[0-9a-f]{1,4})\]' IP6_EXPANSION_PATTERN = r'\[((?:[0-9a-f]{1,4}[?:,-])+[0-9a-f]{1,4})\]'

View File

@ -48,38 +48,25 @@ def parse_alphanumeric_range(string):
Expand an alphanumeric range (continuous or not) into a list. Expand an alphanumeric range (continuous or not) into a list.
'a-d,f' => [a, b, c, d, f] 'a-d,f' => [a, b, c, d, f]
'0-3,a-d' => [0, 1, 2, 3, a, b, c, d] '0-3,a-d' => [0, 1, 2, 3, a, b, c, d]
'9-11' => [9, 10, 11]
""" """
values = [] values = []
for dash_range in string.split(','): for dash_range in string.split(','):
try: if re.fullmatch(ALPHABETIC_RANGE_PATTERN, dash_range):
begin, end = dash_range.split('-') begin, end = map(ord, dash_range.split('-'))
vals = begin + end if begin > end:
# Break out of loop if there's an invalid pattern to return an error raise forms.ValidationError(f'Range "{dash_range}" is invalid, because {begin} comes after {end}')
if (not (vals.isdigit() or vals.isalpha())) or (vals.isalpha() and not (vals.isupper() or vals.islower())): values.extend(map(chr, range(begin, end + 1)))
return [] elif re.fullmatch(NUMERIC_RANGE_PATTERN, dash_range):
except ValueError: begin, end = map(int, dash_range.split('-'))
begin, end = dash_range, dash_range if begin > end:
if begin.isdigit() and end.isdigit(): raise forms.ValidationError(f'Range "{dash_range}" is invalid, because {begin} comes after {end}')
if int(begin) >= int(end): values.extend(map(str, range(begin, end + 1)))
raise forms.ValidationError(f'Range "{dash_range}" is invalid.') elif re.fullmatch(ALPHANUMERIC_SINGLETON_PATTERN, dash_range):
values.append(dash_range)
for n in list(range(int(begin), int(end) + 1)):
values.append(n)
else: else:
# Value-based raise forms.ValidationError(f'Range "{dash_range}" is invalid, must be a range of numbers (e.g. 7-11) or a range of letters (e.g. f-h or F-H)')
if begin == end:
values.append(begin)
# Range-based
else:
# Not a valid range (more than a single character)
if not len(begin) == len(end) == 1:
raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
if ord(begin) >= ord(end):
raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
for n in list(range(ord(begin), ord(end) + 1)):
values.append(chr(n))
return values return values