Package zeroinstall :: Package injector :: Module versions
[frames] | no frames]

Source Code for Module zeroinstall.injector.versions

  1  """Functions for processing version numbers. 
  2  @since: 1.13 
  3  """ 
  4   
  5  # Copyright (C) 2012, Thomas Leonard 
  6  # See the README file for details, or visit http://0install.net. 
  7   
  8  import re 
  9   
 10  from zeroinstall import SafeException, _ 
 11   
 12  _version_mod_to_value = { 
 13          'pre': -2, 
 14          'rc': -1, 
 15          '': 0, 
 16          'post': 1, 
 17  } 
 18   
 19  # Reverse mapping 
 20  _version_value_to_mod = {} 
 21  for x in _version_mod_to_value: _version_value_to_mod[_version_mod_to_value[x]] = x 
 22  del x 
 23   
 24  _version_re = re.compile('-([a-z]*)') 
 25   
26 -def parse_version(version_string):
27 """Convert a version string to an internal representation. 28 The parsed format can be compared quickly using the standard Python functions. 29 - Version := DottedList ("-" Mod DottedList?)* 30 - DottedList := (Integer ("." Integer)*) 31 @type version_string: str 32 @rtype: tuple (opaque) 33 @raise SafeException: if the string isn't a valid version 34 @since: 0.24 (moved from L{reader}, from where it is still available):""" 35 if version_string is None: return None 36 parts = _version_re.split(version_string) 37 if parts[-1] == '': 38 del parts[-1] # Ends with a modifier 39 else: 40 parts.append('') 41 if not parts: 42 raise SafeException(_("Empty version string!")) 43 l = len(parts) 44 try: 45 for x in range(0, l, 2): 46 part = parts[x] 47 if part: 48 parts[x] = list(map(int, parts[x].split('.'))) 49 else: 50 parts[x] = [] # (because ''.split('.') == [''], not []) 51 for x in range(1, l, 2): 52 parts[x] = _version_mod_to_value[parts[x]] 53 return parts 54 except ValueError as ex: 55 raise SafeException(_("Invalid version format in '%(version_string)s': %(exception)s") % {'version_string': version_string, 'exception': ex}) 56 except KeyError as ex: 57 raise SafeException(_("Invalid version modifier in '%(version_string)s': %(exception)s") % {'version_string': version_string, 'exception': str(ex).strip("u")})
58
59 -def format_version(version):
60 """Format a parsed version for display. Undoes the effect of L{parse_version}. 61 @rtype: str 62 @see: L{model.Implementation.get_version} 63 @since: 0.24""" 64 version = version[:] 65 l = len(version) 66 for x in range(0, l, 2): 67 version[x] = '.'.join(map(str, version[x])) 68 for x in range(1, l, 2): 69 version[x] = '-' + _version_value_to_mod[version[x]] 70 if version[-1] == '-': del version[-1] 71 return ''.join(version)
72 73
74 -def parse_version_range(r):
75 """Parse a range expression. 76 @param r: the range expression 77 @type r: str 78 @return: a function which returns whether a parsed version is in the range 79 @rtype: parsed_version -> bool 80 @since: 1.13""" 81 parts = r.split('..', 1) 82 if len(parts) == 1: 83 if r.startswith('!'): 84 v = parse_version(r[1:]) 85 return lambda x: x != v 86 else: 87 v = parse_version(r) 88 return lambda x: x == v 89 90 start, end = parts 91 if start: 92 start = parse_version(start) 93 else: 94 start = None 95 if end: 96 if not end.startswith('!'): 97 raise SafeException("End of range must be exclusive (use '..!{end}', not '..{end}')".format(end = end)) 98 end = parse_version(end[1:]) 99 else: 100 end = None 101 102 def test(v): 103 if start is not None and v < start: return False 104 if end is not None and v >= end: return False 105 return True
106 107 return test 108
109 -def parse_version_expression(expr):
110 """Parse an expression of the form "RANGE | RANGE | ...". 111 @param expr: the expression to parse 112 @type expr: str 113 @return: a function which tests whether a parsed version is in the range 114 @rtype: parsed_version -> bool 115 @since: 1.13""" 116 tests = [parse_version_range(r.strip()) for r in expr.split('|')] 117 return lambda v: any(test(v) for test in tests)
118