ordering.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import re
  2. INTERFACE_NAME_REGEX = r'(^(?P<type>[^\d\.:]+)?)' \
  3. r'((?P<slot>\d+)/)?' \
  4. r'((?P<subslot>\d+)/)?' \
  5. r'((?P<position>\d+)/)?' \
  6. r'((?P<subposition>\d+)/)?' \
  7. r'((?P<id>\d+))?' \
  8. r'(:(?P<channel>\d+))?' \
  9. r'(.(?P<vc>\d+)$)?'
  10. def naturalize(value, max_length, integer_places=8):
  11. """
  12. Take an alphanumeric string and prepend all integers to `integer_places` places to ensure the strings
  13. are ordered naturally. For example:
  14. site9router21
  15. site10router4
  16. site10router19
  17. becomes:
  18. site00000009router00000021
  19. site00000010router00000004
  20. site00000010router00000019
  21. :param value: The value to be naturalized
  22. :param max_length: The maximum length of the returned string. Characters beyond this length will be stripped.
  23. :param integer_places: The number of places to which each integer will be expanded. (Default: 8)
  24. """
  25. if not value:
  26. return value
  27. output = []
  28. for segment in re.split(r'(\d+)', value):
  29. if segment.isdigit():
  30. output.append(segment.rjust(integer_places, '0'))
  31. elif segment:
  32. output.append(segment)
  33. ret = ''.join(output)
  34. return ret[:max_length]
  35. def naturalize_interface(value, max_length):
  36. """
  37. Similar in nature to naturalize(), but takes into account a particular naming format adapted from the old
  38. InterfaceManager.
  39. :param value: The value to be naturalized
  40. :param max_length: The maximum length of the returned string. Characters beyond this length will be stripped.
  41. """
  42. output = []
  43. match = re.search(INTERFACE_NAME_REGEX, value)
  44. if match is None:
  45. return value
  46. # First, we order by slot/position, padding each to four digits. If a field is not present,
  47. # set it to 9999 to ensure it is ordered last.
  48. for part_name in ('slot', 'subslot', 'position', 'subposition'):
  49. part = match.group(part_name)
  50. if part is not None:
  51. output.append(part.rjust(4, '0'))
  52. else:
  53. output.append('9999')
  54. # Append the type, if any.
  55. if match.group('type') is not None:
  56. output.append(match.group('type'))
  57. # Finally, append any remaining fields, left-padding to six digits each.
  58. for part_name in ('id', 'channel', 'vc'):
  59. part = match.group(part_name)
  60. if part is not None:
  61. output.append(part.rjust(6, '0'))
  62. else:
  63. output.append('000000')
  64. ret = ''.join(output)
  65. return ret[:max_length]