Added Record superclass for models, handling __repr__ consistently.
authorPeter Iannucci <iannucci@mit.edu>
Wed, 25 Feb 2009 21:00:43 +0000 (16:00 -0500)
committerPeter Iannucci <iannucci@mit.edu>
Wed, 25 Feb 2009 21:00:43 +0000 (16:00 -0500)
svn path=/trunk/packages/invirt-database/; revision=2187

python/database/models.py
python/database/owner.py
python/database/record.py [new file with mode: 0755]

index f93557c..6b53a2a 100644 (file)
@@ -5,6 +5,7 @@ from sqlalchemy.orm import create_session, relation
 from sqlalchemy.ext.sessioncontext import SessionContext
 from sqlalchemy.ext.assignmapper import assign_mapper
 
+from record import *
 from owner import Owner
 
 __all__ = ['meta',
@@ -100,37 +101,29 @@ machine_access_table = Table('machine_access', meta,
        Column('user', String, nullable=False, index=True),
        PrimaryKeyConstraint('machine_id', 'user'))
 
-class Machine(object):
-    def __repr__(self):
-        return "<Machine %s: name='%s' owner='%s'>" % (self.machine_id, self.name, self.owner)
+class Machine(Record):
+    _identity_field = 'name'
 
-class MachineAccess(object):
-    def __repr__(self):
-        return "<MachineAccess machine='%s' user='%s'>" % (self.machine, self.user)
+class MachineAccess(Record):
+    pass
 
-class NIC(object):
-    def __repr__(self):
-        return "<NIC: mac='%s' machine='%s' ip='%s' hostname='%s'>" % (self.mac_addr, self.machine_id, self.ip, self.hostname)
+class NIC(Record):
+    pass
 
-class Disk(object):
-    def __repr__(self):
-        return "<Disk: machine=%s device=%s size=%s>" % (self.machine_id, self.guest_device_name, self.size)
+class Disk(Record):
+    pass
 
-class Type(object):
-    def __repr__(self):
-        return "<Type %s: %s>" % (self.type_id, self.description)
+class Type(Record):
+    _identity_field = 'type_id'
 
-class Mirror(object):
-    def __repr__(self):
-        return "<Mirror %s>" % (self.mirror_id)
+class Mirror(Record):
+    _identity_field = 'mirror_id'
 
-class CDROM(object):
-    def __repr__(self):
-        return "<CDROM %s: %s>" % (self.cdrom_id, self.description)
+class CDROM(Record):
+    _identity_field = 'cdrom_id'
 
-class Autoinstall(object):
-    def __repr__(self):
-        return "<Autoinstall %s: %s (%s)>" % (self.autoinstall_id, self.description, self.type.type_id)
+class Autoinstall(Record):
+    _identity_field = 'autoinstall_id'
 
 session.mapper(Machine, machine_table,
               properties={'nics': relation(NIC, backref="machine"),
index 504a70f..adb176c 100755 (executable)
@@ -1,72 +1,40 @@
-MAX_MEMORY_TOTAL = 512
-MAX_MEMORY_SINGLE = 512
-MAX_DISK_TOTAL = 50
-MAX_DISK_SINGLE = 50
-MAX_VMS_TOTAL = 10
-MAX_VMS_ACTIVE = 4
+from record import NullableRecord
+
+class Owner(NullableRecord):
+    _f = {
+        'ram_quota_total': (512, 'MiB'),
+        'ram_quota_single': (512, 'MiB'),
+        'disk_quota_total': (50, 'GiB'),
+        'disk_quota_single': (50, 'GiB'),
+        'vms_quota_total': (10, ''),
+        'vms_quota_active': (4, '')
+    }
+    _default = dict([(_k,_v[0]) for _k,_v in _f.items()])
+    def _unitFormatter(unit):
+        return lambda v:'%s%s'%(v,unit)
+    _format = dict([(_k,_unitFormatter(_v[1])) for _k,_v in _f.items()])
+    _identity_field = 'owner_id'
 
-class Owner(object):
-    def __repr__(self):
-        a = self.ram_quota_total
-        b = self.ram_quota_single
-        c = self.disk_quota_total
-        d = self.disk_quota_single
-        e = self.vms_quota_total
-        f = self.vms_quota_active
-        if not a:
-            a = MAX_MEMORY_TOTAL
-        if not b:
-            b = MAX_MEMORY_SINGLE
-        if not c:
-            c = MAX_DISK_TOTAL
-        if not d:
-            d = MAX_DISK_SINGLE
-        if not e:
-            e = MAX_VMS_TOTAL
-        if not f:
-            f = MAX_VMS_ACTIVE
-        return """<Owner %s: ram_quota_total=%s MiB ram_quota_single=%s MiB
-disk_quota_total=%s GiB disk_quota_single=%s GiB
-vms_quota_total=%s vms_quota_active=%s >""" % (self.owner_id, a,b,c,d,e,f)
     def getMemoryQuotas(owner):
         owner_info = Owner.query().filter_by(owner_id=owner).first()
-        if owner_info != None:
-            quota_total = owner_info.ram_quota_total
-            if quota_total == None:
-                quota_total = MAX_MEMORY_TOTAL
-            quota_single = owner_info.ram_quota_single
-            if quota_single == None:
-                quota_single = MAX_MEMORY_SINGLE
-        else:
-            quota_total = MAX_MEMORY_TOTAL
-            quota_single = MAX_MEMORY_SINGLE
-        return (quota_total, quota_single)
+        if owner_info == None:
+            owner_info = Owner(owner_id=owner)
+        return (owner_info.get('ram_quota_total'), owner_info.get('ram_quota_single'))
     getMemoryQuotas = staticmethod(getMemoryQuotas)
+
     def getDiskQuotas(owner):
         owner_info = Owner.query().filter_by(owner_id=owner).first()
-        if owner_info != None:
-            quota_total = owner_info.disk_quota_total
-            if quota_total == None:
-                quota_total = MAX_DISK_TOTAL
-            quota_single = owner_info.disk_quota_single
-            if quota_single == None:
-                quota_single = MAX_DISK_SINGLE
-        else:
-            quota_total = MAX_DISK_TOTAL
-            quota_single = MAX_DISK_SINGLE
-        return (quota_total, quota_single)
+        if owner_info == None:
+            owner_info = Owner(owner_id=owner)
+        return (owner_info.get('disk_quota_total'), owner_info.get('disk_quota_single'))
     getDiskQuotas = staticmethod(getDiskQuotas)
+
     def getVMQuotas(owner):
         owner_info = Owner.query().filter_by(owner_id=owner).first()
-        if owner_info != None:
-            quota_total = owner_info.vms_quota_total
-            if quota_total == None:
-                quota_total = MAX_VMS_TOTAL
-            quota_active = owner_info.vms_quota_active
-            if quota_active == None:
-                quota_active = MAX_VMS_ACTIVE
-        else:
-            quota_total = MAX_VMS_TOTAL
-            quota_active = MAX_VMS_ACTIVE
-        return (quota_total, quota_active)
+        if owner_info == None:
+            owner_info = Owner(owner_id=owner)
+        return (owner_info.get('vms_quota_total'), owner_info.get('vms_quota_active'))
     getVMQuotas = staticmethod(getVMQuotas)
+
+    def _ignore(self):
+        return super(Owner, self)._ignore() + ['getMemoryQuotas', 'getDiskQuotas', 'getVMQuotas']
diff --git a/python/database/record.py b/python/database/record.py
new file mode 100755 (executable)
index 0000000..b1b46bb
--- /dev/null
@@ -0,0 +1,56 @@
+class Record(object):
+    _identity_field = None
+    def get(self, field):
+        try:
+            return self.__getattribute__(field)
+        except:
+            return None
+    def _formatField(self, field):
+        v = self.get(field)
+        if callable(v):
+            v = v()
+        if hasattr(v, '__iter__'):
+            if len(v) == 0:
+                return '[]'
+            else:
+                return '[%d x %s]'%(len(v), type(v[0]))
+        else:
+            return repr(v)
+    def _fields(self):
+        ignore = self._ignore()
+        keys = sorted(self.__class__.__dict__.keys())
+        return [(k,self._formatField(k)) for k in keys if k[0]!="_" and k not in ignore]
+    def __repr__(self):
+        classname = self.__class__.__name__
+
+        if self._identity_field:
+            identity = self.__dict__.get(self._identity_field)
+            identity = ' ' + (identity and repr(identity) or 'hash=%d'%hash(self))
+        else:
+            identity = ''
+
+        payload = " ".join(["%s=%s" % (k, v) for k,v in self._fields()])
+        if len(payload) > 0:
+            payload = ": "+payload
+
+        return "<%s%s%s>" % (classname, identity, payload)
+    def _ignore(self):
+        return [self._identity_field, 'c', 'query', 'get']
+
+class FormattableRecord(Record):
+    _format = {}
+    def _formatField(self, field):
+        func = self._format.get(field)
+        if func:
+            return func(self.get(field))
+        else:
+            return super(FormattableRecord, self)._formatField(field)
+
+class NullableRecord(FormattableRecord):
+    _default = {}
+    def get(self, field):
+        v = self.__dict__.get(field)
+        if v != None:
+            return v
+        else:
+            return self._default.get(field)