Revision 153533f3 lib/utils.py

b/lib/utils.py
109 109
#: ASN1 time regexp
110 110
_ASN1_TIME_REGEX = re.compile(r"^(\d+)([-+]\d\d)(\d\d)$")
111 111

  
112
_SORTER_RE = re.compile("^%s(.*)$" % (8 * "(\D+|\d+)?"))
113
_SORTER_DIGIT = re.compile("^\d+$")
114

  
112 115

  
113 116
class RunResult(object):
114 117
  """Holds the result of running external programs.
......
1279 1282
  return os.path.isdir("/sys/class/net/%s/bridge" % bridge)
1280 1283

  
1281 1284

  
1282
def NiceSort(name_list):
1285
def _NiceSortTryInt(val):
1286
  """Attempts to convert a string to an integer.
1287

  
1288
  """
1289
  if val and _SORTER_DIGIT.match(val):
1290
    return int(val)
1291
  else:
1292
    return val
1293

  
1294

  
1295
def _NiceSortKey(value):
1296
  """Extract key for sorting.
1297

  
1298
  """
1299
  return [_NiceSortTryInt(grp)
1300
          for grp in _SORTER_RE.match(value).groups()]
1301

  
1302

  
1303
def NiceSort(values, key=None):
1283 1304
  """Sort a list of strings based on digit and non-digit groupings.
1284 1305

  
1285 1306
  Given a list of names C{['a1', 'a10', 'a11', 'a2']} this function
......
1290 1311
  or no-digits. Only the first eight such groups are considered, and
1291 1312
  after that we just use what's left of the string.
1292 1313

  
1293
  @type name_list: list
1294
  @param name_list: the names to be sorted
1314
  @type values: list
1315
  @param values: the names to be sorted
1316
  @type key: callable or None
1317
  @param key: function of one argument to extract a comparison key from each
1318
    list element, must return string
1295 1319
  @rtype: list
1296 1320
  @return: a copy of the name list sorted with our algorithm
1297 1321

  
1298 1322
  """
1299
  _SORTER_BASE = "(\D+|\d+)"
1300
  _SORTER_FULL = "^%s%s?%s?%s?%s?%s?%s?%s?.*$" % (_SORTER_BASE, _SORTER_BASE,
1301
                                                  _SORTER_BASE, _SORTER_BASE,
1302
                                                  _SORTER_BASE, _SORTER_BASE,
1303
                                                  _SORTER_BASE, _SORTER_BASE)
1304
  _SORTER_RE = re.compile(_SORTER_FULL)
1305
  _SORTER_NODIGIT = re.compile("^\D*$")
1306
  def _TryInt(val):
1307
    """Attempts to convert a variable to integer."""
1308
    if val is None or _SORTER_NODIGIT.match(val):
1309
      return val
1310
    rval = int(val)
1311
    return rval
1312

  
1313
  to_sort = [([_TryInt(grp) for grp in _SORTER_RE.match(name).groups()], name)
1314
             for name in name_list]
1315
  to_sort.sort()
1316
  return [tup[1] for tup in to_sort]
1323
  if key is None:
1324
    keyfunc = _NiceSortKey
1325
  else:
1326
    keyfunc = lambda value: _NiceSortKey(key(value))
1327

  
1328
  return sorted(values, key=keyfunc)
1317 1329

  
1318 1330

  
1319 1331
def TryConvert(fn, val):

Also available in: Unified diff