[CalendarServer-changes] [9716] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Aug 16 14:49:53 PDT 2012


Revision: 9716
          http://trac.macosforge.org/projects/calendarserver/changeset/9716
Author:   glyph at apple.com
Date:     2012-08-16 14:49:53 -0700 (Thu, 16 Aug 2012)
Log Message:
-----------
fill in default values, complain when there aren't enough values

Modified Paths:
--------------
    CalendarServer/trunk/twext/enterprise/dal/record.py
    CalendarServer/trunk/twext/enterprise/dal/test/test_record.py

Property Changed:
----------------
    CalendarServer/trunk/

Modified: CalendarServer/trunk/twext/enterprise/dal/record.py
===================================================================
--- CalendarServer/trunk/twext/enterprise/dal/record.py	2012-08-16 21:49:52 UTC (rev 9715)
+++ CalendarServer/trunk/twext/enterprise/dal/record.py	2012-08-16 21:49:53 UTC (rev 9716)
@@ -198,11 +198,30 @@
         self = cls()
         colmap = {}
         attrtocol = cls.__attrmap__
-        for attr in k:
-            setattr(self, attr, k[attr])
-            # FIXME: better error reporting
-            colmap[attrtocol[attr]] = k[attr]
-        yield Insert(colmap).on(transaction)
+        needsCols = []
+        needsAttrs = []
+
+        for attr in attrtocol:
+            col = attrtocol[attr]
+            if attr in k:
+                setattr(self, attr, k[attr])
+                colmap[col] = k.pop(attr)
+            else:
+                if col.model.needsValue():
+                    raise TypeError("required attribute " + repr(attr) +
+                                    " not passed")
+                else:
+                    needsCols.append(col)
+                    needsAttrs.append(attr)
+        if k:
+            raise TypeError("received unknown attribute{0}: {1}".format(
+                "s" if len(k) > 1 else "", ", ".join(sorted(k))
+            ))
+        result = yield (Insert(colmap, Return=needsCols if needsCols else None)
+                        .on(transaction))
+        if needsCols:
+            for neededAttr, neededValue in zip(needsAttrs, result[0]):
+                setattr(self, neededAttr, neededValue)
         self.transaction = transaction
         returnValue(self)
 

Modified: CalendarServer/trunk/twext/enterprise/dal/test/test_record.py
===================================================================
--- CalendarServer/trunk/twext/enterprise/dal/test/test_record.py	2012-08-16 21:49:52 UTC (rev 9715)
+++ CalendarServer/trunk/twext/enterprise/dal/test/test_record.py	2012-08-16 21:49:53 UTC (rev 9716)
@@ -41,11 +41,20 @@
 sth.id = lambda : __name__
 schemaString = """
 create table ALPHA (BETA integer primary key, GAMMA text);
+create table DELTA (PHI integer primary key default (nextval('myseq')),
+                    EPSILON text not null);
 """
-testSchema = SchemaSyntax(sth.schemaFromString(schemaString))
 
+# sqlite can be made to support nextval() as a function, but 'create sequence'
+# is syntax and can't.
+parseableSchemaString = """
+create sequence myseq;
+""" + schemaString
 
+testSchema = SchemaSyntax(sth.schemaFromString(parseableSchemaString))
 
+
+
 class TestRecord(Record, fromTable(testSchema.ALPHA)):
     """
     A sample test record.
@@ -53,6 +62,13 @@
 
 
 
+class TestAutoRecord(Record, fromTable(testSchema.DELTA)):
+    """
+    A sample test record with default values specified.
+    """
+
+
+
 class TestCRUD(TestCase):
     """
     Tests for creation, mutation, and deletion operations.
@@ -60,10 +76,16 @@
 
     def setUp(self):
         sqlitename = self.mktemp()
+        seqs = {}
         def connectionFactory(label=self.id()):
-            return sqlite3.connect(sqlitename)
+            conn = sqlite3.connect(sqlitename)
+            def nextval(seq):
+                result = seqs[seq] = seqs.get(seq, 0) + 1
+                return result
+            conn.create_function("nextval", 1, nextval)
+            return conn
         con = connectionFactory()
-        con.execute(schemaString)
+        con.executescript(schemaString)
         con.commit()
         self.pool = ConnectionPool(connectionFactory, paramstyle='numeric',
                                    dialect=SQLITE_DIALECT)
@@ -124,6 +146,47 @@
 
 
     @inlineCallbacks
+    def test_cantCreateWithoutRequiredValues(self):
+        """
+        When a L{Record} object is created without required values, it raises a
+        L{TypeError}.
+        """
+        txn = self.pool.connection()
+        te = yield self.failUnlessFailure(TestAutoRecord.create(txn),
+                                          TypeError)
+        self.assertIn("required attribute 'epsilon' not passed", str(te))
+
+
+    @inlineCallbacks
+    def test_tooManyAttributes(self):
+        """
+        When a L{Record} object is created with unknown attributes (those which
+        don't map to any column), it raises a L{TypeError}.
+        """
+        txn = self.pool.connection()
+        te = yield self.failUnlessFailure(TestRecord.create(
+                                        txn, beta=3, gamma=u'three',
+                                        extraBonusAttribute=u'nope',
+                                        otherBonusAttribute=4321,
+                                    ), TypeError)
+        self.assertIn("extraBonusAttribute, otherBonusAttribute", str(te))
+
+
+    @inlineCallbacks
+    def test_createFillsInPKey(self):
+        """
+        If L{Record.create} is called without an auto-generated primary key
+        value for its row, that value will be generated and set on the returned
+        object.
+        """
+        txn = self.pool.connection()
+        tr = yield TestAutoRecord.create(txn, epsilon=u'specified')
+        tr2 = yield TestAutoRecord.create(txn, epsilon=u'also specified')
+        self.assertEquals(tr.phi, 1)
+        self.assertEquals(tr2.phi, 2)
+
+
+    @inlineCallbacks
     def test_attributesArentMutableYet(self):
         """
         Changing attributes on a database object is not supported yet, because
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120816/91247d57/attachment-0001.html>


More information about the calendarserver-changes mailing list