2020-02-07 11:36:22 -05:00
|
|
|
import re
|
|
|
|
|
2020-02-07 15:47:53 -05:00
|
|
|
INTERFACE_NAME_REGEX = r'(^(?P<type>[^\d\.:]+)?)' \
|
|
|
|
r'((?P<slot>\d+)/)?' \
|
|
|
|
r'((?P<subslot>\d+)/)?' \
|
|
|
|
r'((?P<position>\d+)/)?' \
|
|
|
|
r'((?P<subposition>\d+)/)?' \
|
|
|
|
r'((?P<id>\d+))?' \
|
|
|
|
r'(:(?P<channel>\d+))?' \
|
|
|
|
r'(.(?P<vc>\d+)$)?'
|
|
|
|
|
2020-02-07 11:36:22 -05:00
|
|
|
|
2020-02-13 21:41:00 -05:00
|
|
|
def naturalize(value, max_length, integer_places=8):
|
2020-02-07 11:36:22 -05:00
|
|
|
"""
|
|
|
|
Take an alphanumeric string and prepend all integers to `integer_places` places to ensure the strings
|
|
|
|
are ordered naturally. For example:
|
|
|
|
|
|
|
|
site9router21
|
|
|
|
site10router4
|
|
|
|
site10router19
|
|
|
|
|
|
|
|
becomes:
|
|
|
|
|
|
|
|
site00000009router00000021
|
|
|
|
site00000010router00000004
|
|
|
|
site00000010router00000019
|
|
|
|
|
|
|
|
:param value: The value to be naturalized
|
|
|
|
:param max_length: The maximum length of the returned string. Characters beyond this length will be stripped.
|
|
|
|
:param integer_places: The number of places to which each integer will be expanded. (Default: 8)
|
|
|
|
"""
|
2020-02-07 11:54:34 -05:00
|
|
|
if not value:
|
2020-02-07 12:24:38 -05:00
|
|
|
return value
|
2020-02-07 11:36:22 -05:00
|
|
|
output = []
|
|
|
|
for segment in re.split(r'(\d+)', value):
|
|
|
|
if segment.isdigit():
|
|
|
|
output.append(segment.rjust(integer_places, '0'))
|
|
|
|
elif segment:
|
|
|
|
output.append(segment)
|
|
|
|
ret = ''.join(output)
|
|
|
|
|
2020-02-13 21:41:00 -05:00
|
|
|
return ret[:max_length]
|
2020-02-07 15:47:53 -05:00
|
|
|
|
|
|
|
|
2020-02-13 21:41:00 -05:00
|
|
|
def naturalize_interface(value, max_length):
|
2020-02-07 15:47:53 -05:00
|
|
|
"""
|
|
|
|
Similar in nature to naturalize(), but takes into account a particular naming format adapted from the old
|
|
|
|
InterfaceManager.
|
|
|
|
|
|
|
|
:param value: The value to be naturalized
|
|
|
|
:param max_length: The maximum length of the returned string. Characters beyond this length will be stripped.
|
|
|
|
"""
|
|
|
|
output = []
|
|
|
|
match = re.search(INTERFACE_NAME_REGEX, value)
|
|
|
|
if match is None:
|
|
|
|
return value
|
|
|
|
|
|
|
|
# First, we order by slot/position, padding each to four digits. If a field is not present,
|
|
|
|
# set it to 9999 to ensure it is ordered last.
|
|
|
|
for part_name in ('slot', 'subslot', 'position', 'subposition'):
|
|
|
|
part = match.group(part_name)
|
|
|
|
if part is not None:
|
|
|
|
output.append(part.rjust(4, '0'))
|
|
|
|
else:
|
|
|
|
output.append('9999')
|
|
|
|
|
|
|
|
# Append the type, if any.
|
|
|
|
if match.group('type') is not None:
|
|
|
|
output.append(match.group('type'))
|
|
|
|
|
2020-02-13 15:13:43 -05:00
|
|
|
# Finally, append any remaining fields, left-padding to six digits each.
|
2020-02-07 15:47:53 -05:00
|
|
|
for part_name in ('id', 'channel', 'vc'):
|
|
|
|
part = match.group(part_name)
|
|
|
|
if part is not None:
|
|
|
|
output.append(part.rjust(6, '0'))
|
|
|
|
else:
|
|
|
|
output.append('000000')
|
|
|
|
|
|
|
|
ret = ''.join(output)
|
2020-02-13 21:41:00 -05:00
|
|
|
return ret[:max_length]
|