# -*- coding: UTF-8 -*-# Copyright (c) 2010, Pascal Volk# See COPYING for distribution information.""" VirtualMailManager.common Some common functions"""importosimportrefromVirtualMailManagerimportENCODINGfromVirtualMailManager.constants.ERRORimport \NOT_EXECUTABLE,NO_SUCH_BINARY,NO_SUCH_DIRECTORYfromVirtualMailManager.errorsimportVMMError_version_re=re.compile(r'^(\d+)\.(\d+)\.(?:(\d+)|(alpha|beta|rc)(\d+))$')_version_level=dict(alpha=0xA,beta=0xB,rc=0xC)_version_cache={}_=lambdamsg:msgdefexpand_path(path):"""Expands paths, starting with ``.`` or ``~``, to an absolute path."""ifpath.startswith('.'):returnos.path.abspath(path)ifpath.startswith('~'):returnos.path.expanduser(path)returnpathdefget_unicode(string):"""Converts `string` to `unicode`, if necessary."""ifisinstance(string,unicode):returnstringreturnunicode(string,ENCODING,'replace')defis_dir(path):"""Checks if `path` is a directory. Throws a `VMMError` if `path` is not a directory. """path=expand_path(path)ifnotos.path.isdir(path):raiseVMMError(_(u"'%s' is not a directory")%get_unicode(path),NO_SUCH_DIRECTORY)returnpathdefexec_ok(binary):"""Checks if the `binary` exists and if it is executable. Throws a `VMMError` if the `binary` isn't a file or is not executable. """binary=expand_path(binary)ifnotos.path.isfile(binary):raiseVMMError(_(u"'%s' is not a file")%get_unicode(binary),NO_SUCH_BINARY)ifnotos.access(binary,os.X_OK):raiseVMMError(_(u"File is not executable: '%s'")%get_unicode(binary),NOT_EXECUTABLE)returnbinarydefversion_hex(version_string):"""Converts a Dovecot version, e.g.: '1.2.3' or '2.0.beta4', to an int. Raises a `ValueError` if the *version_string* has the wrong™ format. version_hex('1.2.3') -> 270548736 hex(version_hex('1.2.3')) -> '0x10203f00' """global_version_cache,_version_level,_version_reifversion_stringin_version_cache:return_version_cache[version_string]version=0version_mo=_version_re.match(version_string)ifnotversion_mo:raiseValueError('Invalid version string: %r'%version_string)major,minor,patch,level,serial=version_mo.groups()major=int(major)minor=int(minor)ifpatch:patch=int(patch)ifserial:serial=int(serial)ifmajor>0xFForminor>0xFFor \patchandpatch>0xFForserialandserial>0xFF:raiseValueError('Invalid version string: %r'%version_string)version+=major<<28version+=minor<<20ifpatch:version+=patch<<12version+=_version_level.get(level,0xF)<<8ifserial:version+=serial_version_cache[version_string]=versionreturnversiondefversion_str(version):"""Converts a Dovecot version previously converted with version_hex back to a string. Raises a `TypeError` if *version* is not an int/long. Raises a `ValueError` if *version* is an incorrect int version. """global_version_cache,_version_levelifversionin_version_cache:return_version_cache[version]ifnotisinstance(version,(int,long)):raiseTypeError('Argument is not a int/long: %r',version)major=(version>>28)&0xFFminor=(version>>20)&0xFFpatch=(version>>12)&0xFFlevel=(version>>8)&0x0Fserial=version&0xFFlevels=dict(zip(_version_level.values(),_version_level.keys()))iflevel==0xFandnotserial:version_string='%u.%u.%u'%(major,minor,patch)eliflevelinlevelsandnotpatch:version_string='%u.%u.%s%u'%(major,minor,levels[level],serial)else:raiseValueError('Invalid version: %r'%hex(version))_version_cache[version]=version_stringreturnversion_stringdel_