Modify Account class to handle NULL references v0.6.x
authormartin f. krafft <madduck@madduck.net>
Fri, 13 Apr 2012 23:09:40 +0200
branchv0.6.x
changeset 531 cf3eb03c1c4f
parent 530 95dd123b552e
child 532 2bb40aaef94e
Modify Account class to handle NULL references This patch modifies the Account class to defer to using the associated domain's tid/ssid/qid fields if the per-instance fields are None/NULL.
VirtualMailManager/account.py
--- a/VirtualMailManager/account.py	Fri Apr 13 17:49:14 2012 +0200
+++ b/VirtualMailManager/account.py	Fri Apr 13 23:09:40 2012 +0200
@@ -59,9 +59,9 @@
                        self._addr.domainname, NO_SUCH_DOMAIN)
         self._uid = 0
         self._mail = None
-        self._qlimit = self._domain.quotalimit
-        self._services = self._domain.serviceset
-        self._transport = self._domain.transport
+        self._qlimit = None
+        self._services = None
+        self._transport = None
         self._passwd = None
         self._new = True
         self._load()
@@ -81,12 +81,19 @@
         dbc.close()
         if result:
             self._uid, _mid, _qid, _ssid, _tid = result
-            if _qid != self._qlimit.qid:
-                self._qlimit = QuotaLimit(self._dbh, qid=_qid)
-            if _ssid != self._services.ssid:
-                self._services = ServiceSet(self._dbh, ssid=_ssid)
-            if _tid != self._transport.tid:
-                self._transport = Transport(self._dbh, tid=_tid)
+
+            def load_helper(ctor, own, field, dbresult):
+                cur = None if own is None else getattr(own, field)
+                if cur != dbresult:
+                    kwargs = { field : dbresult }
+                    return None if dbresult is None \
+                                else ctor(self._dbh, **kwargs)
+
+            self._qlimit = load_helper(QuotaLimit, self._qlimit, 'qid', _qid)
+            self._services = load_helper(ServiceSet, self._services, 'ssid',
+                                         _ssid)
+            self._transport = load_helper(Transport, self._transport, 'tid',
+                                          _tid)
             self._mail = MailLocation(self._dbh, mid=_mid)
             self._new = False
 
@@ -223,8 +230,10 @@
                     'qid, ssid, tid) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)',
                     (self._addr.localpart,
                      pwhash(self._passwd, user=self._addr), self._uid,
-                     self._domain.gid, self._mail.mid, self._qlimit.qid,
-                     self._services.ssid, self._transport.tid))
+                     self._domain.gid, self._mail.mid,
+                     self._qlimit.qid if self._qlimit else None,
+                     self._services.ssid if self._services else None,
+                     self._transport.tid if self._transport else None))
         self._dbh.commit()
         dbc.close()
         self._new = False
@@ -267,11 +276,13 @@
             raise VMMError(_(u'PostgreSQL-based dictionary quota requires '
                              u'Dovecot >= v1.1.2.'), VMM_ERROR)
         self._chk_state()
-        assert isinstance(quotalimit, QuotaLimit)
         if quotalimit == self._qlimit:
             return
-        self._update_tables('qid', quotalimit.qid)
         self._qlimit = quotalimit
+        if quotalimit is not None:
+            assert isinstance(quotalimit, QuotaLimit)
+            quotalimit = quotalimit.qid
+        self._update_tables('qid', quotalimit)
 
     def update_serviceset(self, serviceset):
         """Assign a different set of services to the Account.
@@ -282,11 +293,13 @@
           the new service set.
         """
         self._chk_state()
-        assert isinstance(serviceset, ServiceSet)
         if serviceset == self._services:
             return
-        self._update_tables('ssid', serviceset.ssid)
         self._services = serviceset
+        if serviceset is not None:
+            assert isinstance(serviceset, ServiceSet)
+            serviceset = serviceset.ssid
+        self._update_tables('ssid', serviceset)
 
     def update_transport(self, transport):
         """Sets a new transport for the Account.
@@ -297,17 +310,39 @@
           the new transport
         """
         self._chk_state()
-        assert isinstance(transport, Transport)
         if transport == self._transport:
             return
-        if transport.transport.lower() in ('virtual', 'virtual:') and \
-           not self._mail.postfix:
-            raise AErr(_(u"Invalid transport '%(transport)s' for mailbox "
-                         u"format '%(mbfmt)s'.") %
-                       {'transport': transport, 'mbfmt': self._mail.mbformat},
-                       INVALID_MAIL_LOCATION)
-        self._update_tables('tid', transport.tid)
         self._transport = transport
+        if transport is not None:
+            assert isinstance(transport, Transport)
+            if transport.transport.lower() in ('virtual', 'virtual:') and \
+                not self._mail.postfix:
+                raise AErr(_(u"Invalid transport '%(transport)s' for mailbox "
+                             u"format '%(mbfmt)s'.") %
+                           {'transport': transport, 'mbfmt': self._mail.mbformat},
+                           INVALID_MAIL_LOCATION)
+            transport = transport.tid
+        self._update_tables('tid', transport)
+
+    def _get_info_transport(self):
+        if self._transport:
+            return self._transport.transport
+        return format_domain_default(self._domain.transport.transport)
+
+    def _get_info_serviceset(self):
+        if self._services:
+            services = self._services.services
+            fmt = lambda s: s
+        else:
+            services = self._domain.serviceset.services
+            fmt = format_domain_default
+
+        ret = {}
+        for service, state in services.iteritems():
+            # TP: A service (e.g. pop3 or imap) may be enabled/usable or
+            # disabled/unusable for a user.
+            ret[service] = fmt((_('disabled'), _('enabled'))[state])
+        return ret
 
     def get_info(self):
         """Returns a dict with some information about the Account.
@@ -326,10 +361,7 @@
         dbc.close()
         if info:
             info = dict(zip(('name', 'uq_bytes', 'uq_messages'), info))
-            for service, state in self._services.services.iteritems():
-                # TP: A service (e.g. pop3 or imap) may be enabled/usable or
-                # disabled/unusable for a user.
-                info[service] = (_('disabled'), _('enabled'))[state]
+            info.update(self._get_info_serviceset())
             info['address'] = self._addr
             info['gid'] = self._domain.gid
             info['home'] = '%s/%s' % (self._domain.directory, self._uid)