Modify userinfo output to indicate when domain defaults are displayed
When Account instances reference NULL tid/qid/ssid, the data must come from
the associated domain, and this should be indicated. For transport and
services, this is easy to do as the string passed in the info dict can simply
be modified. For quotalimit, however, another method must be used due to the
CLI-side formatting.
All approaches use a common formatter outsourced to the common.py file.
# -*- coding: UTF-8 -*-# Copyright (c) 2010 - 2011, Pascal Volk# See COPYING for distribution information.""" VirtualMailManager.common ~~~~~~~~~~~~~~~~~~~~~~~~~ Some common functions"""importlocaleimportosimportreimportstatfromVirtualMailManagerimportENCODINGfromVirtualMailManager.constantsimportNOT_EXECUTABLE,NO_SUCH_BINARYfromVirtualMailManager.errorsimportVMMErrorVERSION_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')deflisdir(path):"""Checks if `path` is a directory. Doesn't follow symbolic links. Returns bool. """try:lstat=os.lstat(path)exceptOSError:returnFalsereturnstat.S_ISDIR(lstat.st_mode)defexec_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"No such file: '%s'")%get_unicode(binary),NO_SUCH_BINARY)ifnotos.access(binary,os.X_OK):raiseVMMError(_(u"File is not executable: '%s'")%get_unicode(binary),NOT_EXECUTABLE)returnbinarydefhuman_size(size):"""Converts the `size` in bytes in human readable format."""ifnotisinstance(size,(long,int)):try:size=long(size)exceptValueError:raiseTypeError("'size' must be a positive long or int.")ifsize<0:raiseValueError("'size' must be a positive long or int.")ifsize<1024:returnstr(size)prefix_multiply=((_(u'TiB'),1<<40),(_(u'GiB'),1<<30),(_(u'MiB'),1<<20),(_(u'KiB'),1<<10))forprefix,multiplyinprefix_multiply:ifsize>=multiply:# TP: e.g.: '%(size)s %(prefix)s' -> '118.30 MiB'return_(u'%(size)s%(prefix)s')%{'size':locale.format('%.2f',float(size)/multiply,True),'prefix':prefix}defsize_in_bytes(size):"""Converts the string `size` to a long (size in bytes). The string `size` can be suffixed with *b* (bytes), *k* (kilobytes), *M* (megabytes) or *G* (gigabytes). """ifnotisinstance(size,basestring)ornotsize:raiseTypeError('size must be a non empty string.')ifsize[-1].upper()in('B','K','M','G'):try:num=int(size[:-1])exceptValueError:raiseValueError('Not a valid integer value: %r'%size[:-1])unit=size[-1].upper()ifunit=='B':returnnumelifunit=='K':returnnum<<10Lelifunit=='M':returnnum<<20Lelse:returnnum<<30Lelse:try:num=int(size)exceptValueError:raiseValueError('Not a valid size value: %r'%size)returnnumdefversion_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_cacheifversion_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_cacheifversionin_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_stringdefformat_domain_default(domaindata):return_(u'%s [domain default]')%domaindatadel_