16 NOT_EXECUTABLE, NO_SUCH_BINARY, NO_SUCH_DIRECTORY |
16 NOT_EXECUTABLE, NO_SUCH_BINARY, NO_SUCH_DIRECTORY |
17 from VirtualMailManager.errors import VMMError |
17 from VirtualMailManager.errors import VMMError |
18 |
18 |
19 |
19 |
20 _version_re = re.compile(r'^(\d+)\.(\d+)\.(?:(\d+)|(alpha|beta|rc)(\d+))$') |
20 _version_re = re.compile(r'^(\d+)\.(\d+)\.(?:(\d+)|(alpha|beta|rc)(\d+))$') |
|
21 _version_level = dict(alpha=0xA, beta=0xB, rc=0xC) |
21 _ = lambda msg: msg |
22 _ = lambda msg: msg |
22 |
23 |
23 |
24 |
24 def expand_path(path): |
25 def expand_path(path): |
25 """Expands paths, starting with ``.`` or ``~``, to an absolute path.""" |
26 """Expands paths, starting with ``.`` or ``~``, to an absolute path.""" |
64 get_unicode(binary), NOT_EXECUTABLE) |
65 get_unicode(binary), NOT_EXECUTABLE) |
65 return binary |
66 return binary |
66 |
67 |
67 |
68 |
68 def version_hex(version_string): |
69 def version_hex(version_string): |
69 """Convert a Dovecot version, e.g.: '1.2.3' or '2.0.beta4', to an int. |
70 """Converts a Dovecot version, e.g.: '1.2.3' or '2.0.beta4', to an int. |
70 Raises a `ValueError` if the *version_string* has the wrong™ format. |
71 Raises a `ValueError` if the *version_string* has the wrong™ format. |
71 |
72 |
72 version_hex('1.2.3') -> 16909296 |
73 version_hex('1.2.3') -> 270548736 |
73 hex(version_hex('1.2.3')) -> '0x10203f0' |
74 hex(version_hex('1.2.3')) -> '0x10203f00' |
74 """ |
75 """ |
75 version = 0 |
76 version = 0 |
76 version_level = dict(alpha=0xA, beta=0xB, rc=0xC) |
|
77 version_mo = _version_re.match(version_string) |
77 version_mo = _version_re.match(version_string) |
78 if not version_mo: |
78 if not version_mo: |
79 raise ValueError('Invalid version string: %r' % version_string) |
79 raise ValueError('Invalid version string: %r' % version_string) |
80 major, minor, patch, level, serial = version_mo.groups() |
80 major, minor, patch, level, serial = version_mo.groups() |
81 version += int(major) << 24 |
81 major = int(major) |
82 version += int(minor) << 16 |
82 minor = int(minor) |
83 if patch: |
83 if patch: |
84 version += int(patch) << 8 |
84 patch = int(patch) |
85 version += version_level.get(level, 0xF) << 4 |
|
86 if serial: |
85 if serial: |
87 version += int(serial) |
86 serial = int(serial) |
|
87 |
|
88 if major > 0xFF or minor > 0xFF or \ |
|
89 patch and patch > 0xFF or serial and serial > 0xFF: |
|
90 raise ValueError('Invalid version string: %r' % version_string) |
|
91 |
|
92 version += major << 28 |
|
93 version += minor << 20 |
|
94 if patch: |
|
95 version += patch << 12 |
|
96 version += _version_level.get(level, 0xF) << 8 |
|
97 if serial: |
|
98 version += serial |
|
99 |
88 return version |
100 return version |
89 |
101 |
|
102 |
|
103 def version_str(version): |
|
104 """Converts a Dovecot version previously converted with version_hex back to |
|
105 a string. |
|
106 Raises a `TypeError` if *version* is not an int/long. |
|
107 Raises a `ValueError` if *version* is an incorrect int version. |
|
108 """ |
|
109 if not isinstance(version, (int, long)): |
|
110 raise TypeError('Argument is not a int/long: %r', version) |
|
111 major = (version >> 28) & 0xFF |
|
112 minor = (version >> 20) & 0xFF |
|
113 patch = (version >> 12) & 0xFF |
|
114 level = (version >> 8) & 0x0F |
|
115 serial = version & 0xFF |
|
116 |
|
117 levels = dict(zip(_version_level.values(), _version_level.keys())) |
|
118 if level == 0xF and not serial: |
|
119 version_string = '%u.%u.%u' % (major, minor, patch) |
|
120 elif level in levels and not patch: |
|
121 version_string = '%u.%u.%s%u' % (major, minor, levels[level], serial) |
|
122 else: |
|
123 raise ValueError('Invalid version: %r' % hex(version)) |
|
124 |
|
125 return version_string |
|
126 |
90 del _ |
127 del _ |