[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