[CalendarServer-changes] [11116] CalendarServer/branches/users/cdaboo/store-scheduling
source_changes at macosforge.org
source_changes at macosforge.org
Wed May 1 09:33:40 PDT 2013
Revision: 11116
http://trac.calendarserver.org//changeset/11116
Author: cdaboo at apple.com
Date: 2013-05-01 09:33:40 -0700 (Wed, 01 May 2013)
Log Message:
-----------
Calendar transp property is now a column on the bind table.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/store-scheduling/calendarserver/tools/calverify.py
CalendarServer/branches/users/cdaboo/store-scheduling/calendarserver/tools/test/test_calverify.py
CalendarServer/branches/users/cdaboo/store-scheduling/twext/enterprise/dal/syntax.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/directory/test/test_calendar.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/resource.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/scheduling_store/caldav/resource.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/scheduling_store/caldav/test/test_resource.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/sharing.py
CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/current.sql
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_tables.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_3_to_4.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/util.py
Added Paths:
-----------
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/__init__.py
CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/calendarserver/tools/calverify.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/calendarserver/tools/calverify.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/calendarserver/tools/calverify.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -59,7 +59,6 @@
from twisted.python import log, usage
from twisted.python.usage import Options
-from twistedcaldav import caldavxml
from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
from twistedcaldav.dateops import pyCalendarTodatetime
from twistedcaldav.directory.directory import DirectoryService
@@ -69,7 +68,6 @@
from twistedcaldav.stdconfig import DEFAULT_CONFIG_FILE
from twistedcaldav.util import normalizationLookup
-from txdav.base.propertystore.base import PropertyName
from txdav.caldav.icalendarstore import ComponentUpdateState
from txdav.common.datastore.sql_tables import schema, _BIND_MODE_OWN
from txdav.common.icommondatastore import InternalDataStoreError
@@ -1925,7 +1923,7 @@
details["rid"] = attresid
else:
# Find default calendar for VEVENTs
- defaultCalendar = (yield self.defaultCalendarForAttendee(home, inbox))
+ defaultCalendar = (yield self.defaultCalendarForAttendee(home))
if defaultCalendar is None:
raise ValueError("Cannot find suitable default calendar")
new_name = str(uuid.uuid4()) + ".ics"
@@ -1965,22 +1963,11 @@
@inlineCallbacks
- def defaultCalendarForAttendee(self, home, inbox):
+ def defaultCalendarForAttendee(self, home):
# Check for property
- default = inbox.properties().get(PropertyName.fromElement(caldavxml.ScheduleDefaultCalendarURL))
- if default:
- defaultName = str(default.children[0]).rstrip("/").split("/")[-1]
- defaultCalendar = (yield home.calendarWithName(defaultName))
- returnValue(defaultCalendar)
- else:
- # Iterate for the first calendar that supports VEVENTs
- calendars = (yield home.calendars())
- for calendar in calendars:
- if calendar.name() != "inbox" and calendar.isSupportedComponent("VEVENT"):
- returnValue(calendar)
- else:
- returnValue(None)
+ calendar = (yield home.defaultCalendar("VEVENT"))
+ returnValue(calendar)
def printAutoAccepts(self):
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/calendarserver/tools/test/test_calverify.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/calendarserver/tools/test/test_calverify.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/calendarserver/tools/test/test_calverify.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -22,16 +22,17 @@
from calendarserver.tools.calverify import BadDataService, \
SchedulingMismatchService, DoubleBookingService, DarkPurgeService
-from StringIO import StringIO
from pycalendar.datetime import PyCalendarDateTime
+
from twisted.internet import reactor
-from twisted.internet.defer import inlineCallbacks, returnValue
-from twistedcaldav import caldavxml
+from twisted.internet.defer import inlineCallbacks
+
from twistedcaldav.config import config
from twistedcaldav.test.util import StoreTestCase
-from txdav.base.propertystore.base import PropertyName
+
from txdav.common.datastore.test.util import populateCalendarsFrom
-from txdav.xml import element as davxml
+
+from StringIO import StringIO
import os
@@ -428,7 +429,7 @@
requirements = {
"home1" : {
- "calendar1" : {
+ "calendar_1" : {
"ok.ics" : (OK_ICS, metadata,),
"bad1.ics" : (BAD1_ICS, metadata,),
"bad2.ics" : (BAD2_ICS, metadata,),
@@ -475,36 +476,6 @@
return self._sqlCalendarStore
- @inlineCallbacks
- def homeUnderTest(self, txn=None):
- """
- Get the calendar home detailed by C{requirements['home1']}.
- """
- if txn is None:
- txn = self.transactionUnderTest()
- returnValue((yield txn.calendarHomeWithUID("home1")))
-
-
- @inlineCallbacks
- def calendarUnderTest(self, txn=None):
- """
- Get the calendar detailed by C{requirements['home1']['calendar1']}.
- """
- returnValue((yield
- (yield self.homeUnderTest(txn)).calendarWithName("calendar1"))
- )
-
-
- @inlineCallbacks
- def calendarObjectUnderTest(self, name, txn=None):
- """
- Get the calendar object detailed by C{requirements[home_name][calendar_name][name]}.
- """
- returnValue((yield
- (yield self.calendarUnderTest(txn)).calendarObjectWithName(name))
- )
-
-
def verifyResultsByUID(self, results, expected):
reported = set([(home, uid) for home, uid, _ignore_resid, _ignore_reason in results])
self.assertEqual(reported, expected)
@@ -611,7 +582,7 @@
self.assertNotEqual(sync_token_old, sync_token_new)
# Make sure mailto: fix results in urn:uuid value without SCHEDULE-AGENT
- obj = yield self.calendarObjectUnderTest("bad10.ics")
+ obj = yield self.calendarObjectUnderTest(name="bad10.ics")
ical = yield obj.component()
org = ical.getOrganizerProperty()
self.assertEqual(org.value(), "urn:uuid:D46F3D71-04B7-43C2-A7B6-6F92F92E61D0")
@@ -946,17 +917,6 @@
uuid3 = "AC478592-7783-44D1-B2AE-52359B4E8415"
uuidl1 = "75EA36BE-F71B-40F9-81F9-CF59BF40CA8F"
- @inlineCallbacks
- def setUp(self):
- yield super(CalVerifyMismatchTestsBase, self).setUp()
-
- inbox = (yield self.calendarUnderTest(self.uuid3, "inbox"))
- inbox.properties()[PropertyName.fromElement(caldavxml.ScheduleDefaultCalendarURL)] = caldavxml.ScheduleDefaultCalendarURL(
- davxml.HRef.fromString("/calendars/__uids__/%s/calendar2/" % (self.uuid3,))
- )
- yield self.commit()
-
-
def configure(self):
super(CalVerifyMismatchTestsBase, self).configure()
self.patch(config.DirectoryService.params, "xmlFile",
@@ -984,42 +944,6 @@
self.notifierFactory.reset()
- def storeUnderTest(self):
- """
- Create and return a L{CalendarStore} for testing.
- """
- return self._sqlCalendarStore
-
-
- @inlineCallbacks
- def homeUnderTest(self, name=None, txn=None):
- """
- Get the calendar home detailed by C{requirements[name]}.
- """
- if txn is None:
- txn = self.transactionUnderTest()
- returnValue((yield txn.calendarHomeWithUID(name)))
-
-
- @inlineCallbacks
- def calendarUnderTest(self, home_name, name="calendar", txn=None):
- """
- Get the calendar detailed by C{requirements[home_name][name]}.
- """
- returnValue((yield
- (yield self.homeUnderTest(home_name, txn)).calendarWithName(name))
- )
-
-
- @inlineCallbacks
- def calendarObjectUnderTest(self, home_name, calendar_name, name, txn=None):
- """
- Get the calendar object detailed by C{requirements[home_name][calendar_name][name]}.
- """
- returnValue((yield
- (yield self.calendarUnderTest(home_name, calendar_name, txn)).calendarObjectWithName(name))
- )
-
now = PyCalendarDateTime.getToday()
now.setDay(1)
now.offsetMonth(2)
@@ -1450,15 +1374,25 @@
}
@inlineCallbacks
+ def setUp(self):
+ yield super(CalVerifyMismatchTestsNonRecurring, self).setUp()
+
+ home = (yield self.homeUnderTest(name=self.uuid3))
+ calendar = (yield self.calendarUnderTest(name="calendar2", home=self.uuid3))
+ yield home.setDefaultCalendar(calendar)
+ yield self.commit()
+
+
+ @inlineCallbacks
def test_scanMismatchOnly(self):
"""
CalVerifyService.doScan without fix for mismatches. Make sure it detects
as much as it can. Make sure sync-token is not changed.
"""
- sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_old2 = (yield (yield self.calendarUnderTest(self.uuid2)).syncToken())
- sync_token_old3 = (yield (yield self.calendarUnderTest(self.uuid3)).syncToken())
+ sync_token_old1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_old2 = (yield (yield self.calendarUnderTest(home=self.uuid2, name="calendar")).syncToken())
+ sync_token_old3 = (yield (yield self.calendarUnderTest(home=self.uuid3, name="calendar")).syncToken())
self.commit()
options = {
@@ -1508,9 +1442,9 @@
self.assertTrue("Fix failures" not in calverify.results)
self.assertTrue("Auto-Accepts" not in calverify.results)
- sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_new2 = (yield (yield self.calendarUnderTest(self.uuid2)).syncToken())
- sync_token_new3 = (yield (yield self.calendarUnderTest(self.uuid3)).syncToken())
+ sync_token_new1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_new2 = (yield (yield self.calendarUnderTest(home=self.uuid2, name="calendar")).syncToken())
+ sync_token_new3 = (yield (yield self.calendarUnderTest(home=self.uuid3, name="calendar")).syncToken())
self.assertEqual(sync_token_old1, sync_token_new1)
self.assertEqual(sync_token_old2, sync_token_new2)
self.assertEqual(sync_token_old3, sync_token_new3)
@@ -1523,9 +1457,9 @@
and fixes as much as it can. Make sure sync-token is not changed.
"""
- sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_old2 = (yield (yield self.calendarUnderTest(self.uuid2)).syncToken())
- sync_token_old3 = (yield (yield self.calendarUnderTest(self.uuid3)).syncToken())
+ sync_token_old1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_old2 = (yield (yield self.calendarUnderTest(home=self.uuid2, name="calendar")).syncToken())
+ sync_token_old3 = (yield (yield self.calendarUnderTest(home=self.uuid3, name="calendar")).syncToken())
self.commit()
options = {
@@ -1599,19 +1533,19 @@
(self.uuid3, "calendar", "missing_organizer.ics",),
(self.uuid3, "calendar", "mismatched2_organizer.ics",),
)))
- obj = yield self.calendarObjectUnderTest(self.uuid2, "calendar", "missing_organizer.ics")
+ obj = yield self.calendarObjectUnderTest(home=self.uuid2, calendar_name="calendar", name="missing_organizer.ics")
self.assertEqual(obj, None)
- obj = yield self.calendarObjectUnderTest(self.uuid3, "calendar", "missing_organizer.ics")
+ obj = yield self.calendarObjectUnderTest(home=self.uuid3, calendar_name="calendar", name="missing_organizer.ics")
self.assertEqual(obj, None)
- obj = yield self.calendarObjectUnderTest(self.uuid3, "calendar", "mismatched2_organizer.ics")
+ obj = yield self.calendarObjectUnderTest(home=self.uuid3, calendar_name="calendar", name="mismatched2_organizer.ics")
self.assertEqual(obj, None)
self.assertEqual(calverify.results["Fix failures"], 0)
self.assertEqual(calverify.results["Auto-Accepts"], [])
- sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_new2 = (yield (yield self.calendarUnderTest(self.uuid2)).syncToken())
- sync_token_new3 = (yield (yield self.calendarUnderTest(self.uuid3)).syncToken())
+ sync_token_new1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_new2 = (yield (yield self.calendarUnderTest(home=self.uuid2, name="calendar")).syncToken())
+ sync_token_new3 = (yield (yield self.calendarUnderTest(home=self.uuid3, name="calendar")).syncToken())
self.assertEqual(sync_token_old1, sync_token_new1)
self.assertNotEqual(sync_token_old2, sync_token_new2)
self.assertNotEqual(sync_token_old3, sync_token_new3)
@@ -1733,8 +1667,8 @@
as much as it can. Make sure sync-token is not changed.
"""
- sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_old1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.commit()
options = {
@@ -1771,8 +1705,8 @@
self.assertTrue("Fix failures" not in calverify.results)
self.assertTrue("Auto-Accepts" not in calverify.results)
- sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_new1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.assertEqual(sync_token_old1, sync_token_new1)
self.assertEqual(sync_token_oldl1, sync_token_newl1)
@@ -1784,8 +1718,8 @@
and fixes as much as it can. Make sure sync-token is not changed.
"""
- sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_old1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.commit()
options = {
@@ -1838,8 +1772,8 @@
self.assertEqual(testResults[1]["uid"], "MISSING_ATTENDEE_ICS")
self.assertEqual(testResults[1]["start"].getText()[:8], "%(year)s%(month)02d07" % {"year": nowYear, "month": nowMonth})
- sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_new1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.assertEqual(sync_token_old1, sync_token_new1)
self.assertNotEqual(sync_token_oldl1, sync_token_newl1)
@@ -1960,8 +1894,8 @@
as much as it can. Make sure sync-token is not changed.
"""
- sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_old1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.commit()
options = {
@@ -1996,8 +1930,8 @@
self.assertTrue("Fix failures" not in calverify.results)
self.assertTrue("Auto-Accepts" not in calverify.results)
- sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_new1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.assertEqual(sync_token_old1, sync_token_new1)
self.assertEqual(sync_token_oldl1, sync_token_newl1)
@@ -2009,8 +1943,8 @@
and fixes as much as it can. Make sure sync-token is not changed.
"""
- sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_old1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.commit()
options = {
@@ -2056,8 +1990,8 @@
self.assertEqual(testResults[0]["uid"], "MISMATCH_ATTENDEE_ICS")
self.assertEqual(testResults[0]["start"].getText()[:8], "%(year)s%(month)02d07" % {"year": nowYear, "month": nowMonth})
- sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_new1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.assertEqual(sync_token_old1, sync_token_new1)
self.assertNotEqual(sync_token_oldl1, sync_token_newl1)
@@ -2469,8 +2403,8 @@
as much as it can. Make sure sync-token is not changed.
"""
- sync_token_old1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_old1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.commit()
options = {
@@ -2506,8 +2440,8 @@
self.assertEqual(calverify.results["Number of double-bookings"], 4)
self.assertEqual(calverify.results["Number of unique double-bookings"], 3)
- sync_token_new1 = (yield (yield self.calendarUnderTest(self.uuid1)).syncToken())
- sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_new1 = (yield (yield self.calendarUnderTest(home=self.uuid1, name="calendar")).syncToken())
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.assertEqual(sync_token_old1, sync_token_new1)
self.assertEqual(sync_token_oldl1, sync_token_newl1)
@@ -2632,7 +2566,7 @@
as much as it can. Make sure sync-token is not changed.
"""
- sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.commit()
options = {
@@ -2668,7 +2602,7 @@
self.assertTrue("Fix dark events" not in calverify.results)
self.assertTrue("Fix remove" not in calverify.results)
- sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.assertEqual(sync_token_oldl1, sync_token_newl1)
@@ -2679,7 +2613,7 @@
as much as it can. Make sure sync-token is changed.
"""
- sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.commit()
options = {
@@ -2715,7 +2649,7 @@
self.assertEqual(calverify.results["Fix dark events"], 2)
self.assertTrue("Fix remove" in calverify.results)
- sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.assertNotEqual(sync_token_oldl1, sync_token_newl1)
# Re-scan after changes to make sure there are no errors
@@ -2738,7 +2672,7 @@
as much as it can. Make sure sync-token is changed.
"""
- sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.commit()
options = {
@@ -2774,7 +2708,7 @@
self.assertEqual(calverify.results["Fix dark events"], 1)
self.assertTrue("Fix remove" in calverify.results)
- sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.assertNotEqual(sync_token_oldl1, sync_token_newl1)
# Re-scan after changes to make sure there are no errors
@@ -2797,7 +2731,7 @@
as much as it can. Make sure sync-token is changed.
"""
- sync_token_oldl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_oldl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.commit()
options = {
@@ -2833,7 +2767,7 @@
self.assertEqual(calverify.results["Fix dark events"], 3)
self.assertTrue("Fix remove" in calverify.results)
- sync_token_newl1 = (yield (yield self.calendarUnderTest(self.uuidl1)).syncToken())
+ sync_token_newl1 = (yield (yield self.calendarUnderTest(home=self.uuidl1, name="calendar")).syncToken())
self.assertNotEqual(sync_token_oldl1, sync_token_newl1)
# Re-scan after changes to make sure there are no errors
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twext/enterprise/dal/syntax.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twext/enterprise/dal/syntax.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twext/enterprise/dal/syntax.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -1602,8 +1602,9 @@
for (c, v) in sortedColumns]
)
)
- result.append(SQLFragment(' where '))
- result.append(self.Where.subSQL(queryGenerator, allTables))
+ if self.Where is not None:
+ result.append(SQLFragment(' where '))
+ result.append(self.Where.subSQL(queryGenerator, allTables))
return self._returningClause(queryGenerator, result, allTables)
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/directory/test/test_calendar.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/directory/test/test_calendar.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/directory/test/test_calendar.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -110,43 +110,29 @@
fbset = (yield inbox.readProperty(caldavxml.CalendarFreeBusySet, request))
self.assertEqual(fbset, caldavxml.CalendarFreeBusySet(
- davxml.HRef.fromString("/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/calendar"),
+ davxml.HRef.fromString("/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/calendar/"),
))
- # Now remove the dead property to simulate the old calendar server state with
+ # Now remove the property to simulate the old calendar server state with
# a calendar listed in the fbset
- yield calendar.removeDeadProperty(caldavxml.ScheduleCalendarTransp)
+ yield calendar._newStoreObject.setUsedForFreeBusy(False)
fbset = (yield inbox.readProperty(caldavxml.CalendarFreeBusySet, request))
- self.assertEqual(fbset, caldavxml.CalendarFreeBusySet(
- davxml.HRef.fromString("/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/calendar"),
- ))
+ self.assertEqual(fbset, caldavxml.CalendarFreeBusySet())
# Calendar has opaque property derived from inbox
transp = (yield calendar.hasProperty(caldavxml.ScheduleCalendarTransp, request))
self.assertTrue(transp)
transp = (yield calendar.readProperty(caldavxml.ScheduleCalendarTransp, request))
- self.assertEqual(transp, caldavxml.ScheduleCalendarTransp(caldavxml.Opaque()))
-
- # Now remove the dead property and the inbox fbset item to simulate the old calendar server state
- yield calendar.removeDeadProperty(caldavxml.ScheduleCalendarTransp)
- yield inbox.removeDeadProperty(caldavxml.CalendarFreeBusySet)
-
- # Calendar has transp property derived from inbox
- transp = (yield calendar.hasProperty(caldavxml.ScheduleCalendarTransp, request))
- self.assertTrue(transp)
-
- transp = (yield calendar.readProperty(caldavxml.ScheduleCalendarTransp, request))
self.assertEqual(transp, caldavxml.ScheduleCalendarTransp(caldavxml.Transparent()))
# Force trailing slash on fbset
- inbox.writeDeadProperty(caldavxml.CalendarFreeBusySet(
+ yield inbox.writeProperty(caldavxml.CalendarFreeBusySet(
davxml.HRef.fromString("/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/calendar/"),
- ))
+ ), request)
# Now remove the dead property to simulate the old calendar server state with
# a calendar listed in the fbset
- yield calendar.removeDeadProperty(caldavxml.ScheduleCalendarTransp)
fbset = (yield inbox.readProperty(caldavxml.CalendarFreeBusySet, request))
self.assertEqual(fbset, caldavxml.CalendarFreeBusySet(
davxml.HRef.fromString("/calendars/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/calendar/"),
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/resource.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/resource.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -670,17 +670,7 @@
))
elif qname == caldavxml.ScheduleCalendarTransp.qname() and self.isCalendarCollection():
- # For backwards compatibility, if the property does not exist we need to create
- # it and default to the old free-busy-set value.
- if not self.hasDeadProperty(property):
- # For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
- principal = (yield self.resourceOwnerPrincipal(request))
- fbset = (yield principal.calendarFreeBusyURIs(request))
- fbset = [fburl.rstrip("/") for fburl in fbset]
- url = (yield self.canonicalURL(request))
- url = url.rstrip("/")
- opaque = url in fbset
- self.writeDeadProperty(caldavxml.ScheduleCalendarTransp(caldavxml.Opaque() if opaque else caldavxml.Transparent()))
+ returnValue(caldavxml.ScheduleCalendarTransp(caldavxml.Opaque() if self._newStoreObject.isUsedForFreeBusy() else caldavxml.Transparent()))
elif qname == carddavxml.SupportedAddressData.qname() and self.isAddressBookCollection():
# CardDAV, section 6.2.2
@@ -734,7 +724,6 @@
returnValue(res)
- @inlineCallbacks
def _preProcessWriteProperty(self, property, request, isShare=False):
if property.qname() == caldavxml.SupportedCalendarComponentSet.qname():
if not self.isPseudoCalendarCollection():
@@ -793,21 +782,16 @@
"Property %s may only be set on calendar collection." % (property,)
))
- # For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
- principal = (yield self.resourceOwnerPrincipal(request))
- # Map owner to their inbox
- inboxURL = principal.scheduleInboxURL()
- if inboxURL:
- inbox = (yield request.locateResource(inboxURL))
- myurl = (yield self.canonicalURL(request))
- inbox.processFreeBusyCalendar(myurl, property.children[0] == caldavxml.Opaque())
-
-
@inlineCallbacks
def _writeGlobalProperty(self, property, request):
- yield self._preProcessWriteProperty(property, request)
+ self._preProcessWriteProperty(property, request)
+
+ if property.qname() == caldavxml.ScheduleCalendarTransp.qname():
+ yield self._newStoreObject.setUsedForFreeBusy(property == caldavxml.ScheduleCalendarTransp(caldavxml.Opaque()))
+ returnValue(None)
+
result = (yield super(CalDAVResource, self).writeProperty(property, request))
returnValue(result)
@@ -1072,49 +1056,6 @@
findSpecialCollections = findSpecialCollectionsFaster
- @inlineCallbacks
- def deletedCalendar(self, request):
- """
- Calendar has been deleted. Need to do some extra clean-up.
-
- @param request:
- @type request:
- """
-
- # For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
- principal = (yield self.resourceOwnerPrincipal(request))
- inboxURL = principal.scheduleInboxURL()
- if inboxURL:
- inbox = (yield request.locateResource(inboxURL))
- inbox.processFreeBusyCalendar(request.path, False)
-
-
- @inlineCallbacks
- def movedCalendar(self, request, destination, destination_uri):
- """
- Calendar has been moved. Need to do some extra clean-up.
- """
-
- # For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
- principal = (yield self.resourceOwnerPrincipal(request))
- inboxURL = principal.scheduleInboxURL()
- if inboxURL:
- inbox = (yield request.locateResource(inboxURL))
- inbox.processFreeBusyCalendar(request.path, False)
- inbox.processFreeBusyCalendar(destination_uri, destination.isCalendarOpaque())
-
-
- def isCalendarOpaque(self):
-
- assert self.isCalendarCollection()
-
- if self.hasDeadProperty((caldav_namespace, "schedule-calendar-transp")):
- property = self.readDeadProperty((caldav_namespace, "schedule-calendar-transp"))
- return property.children[0] == caldavxml.Opaque()
- else:
- return False
-
-
def isDefaultCalendar(self, request):
assert self.isCalendarCollection()
@@ -2091,11 +2032,9 @@
@classmethod
@inlineCallbacks
def createHomeResource(cls, parent, name, transaction):
- home, created = yield cls.homeFromTransaction(
+ home, _ignored_created = yield cls.homeFromTransaction(
transaction, name)
resource = cls(parent, name, transaction, home)
- if created:
- yield resource.postCreateHome()
returnValue(resource)
@@ -2116,10 +2055,6 @@
pass
- def postCreateHome(self):
- pass
-
-
def liveProperties(self):
props = super(CommonHomeResource, self).liveProperties() + (
@@ -2551,16 +2486,6 @@
self._provisionedChildren["notification"] = NotificationCollectionResource
- @inlineCallbacks
- def postCreateHome(self):
- # This is a bit of a hack. Really we ought to be always generating
- # this URL live from a back-end method that tells us what the
- # default calendar is.
- inbox = yield self.getChild("inbox")
- childURL = joinURL(self.url(), "calendar")
- inbox.processFreeBusyCalendar(childURL, True)
-
-
def canShare(self):
return config.Sharing.Enabled and config.Sharing.Calendars.Enabled and self.exists()
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/scheduling_store/caldav/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/scheduling_store/caldav/resource.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/scheduling_store/caldav/resource.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -43,14 +43,12 @@
from twisted.python.failure import Failure
from twistedcaldav import caldavxml, customxml
-from twistedcaldav.caldavxml import caldav_namespace, Opaque, \
- CalendarFreeBusySet, ScheduleCalendarTransp
+from twistedcaldav.caldavxml import caldav_namespace, CalendarFreeBusySet
from twistedcaldav.customxml import calendarserver_namespace
from twistedcaldav.ical import allowedComponents, Component
from twistedcaldav.resource import CalDAVResource
from twistedcaldav.resource import isCalendarCollectionResource
-from txdav.base.propertystore.base import PropertyName
from txdav.caldav.datastore.scheduling.caldav.scheduler import CalDAVScheduler
from txdav.caldav.icalendarstore import InvalidDefaultCalendar
from txdav.xml import element as davxml
@@ -155,6 +153,24 @@
return davxml.ResourceType.scheduleInbox
+ def hasProperty(self, property, request):
+ """
+ Need to special case calendar-free-busy-set for backwards compatability.
+ """
+
+ if type(property) is tuple:
+ qname = property
+ else:
+ qname = property.qname()
+
+ # Force calendar collections to always appear to have the property
+ if qname == caldavxml.CalendarFreeBusySet.qname():
+ return succeed(True)
+
+ else:
+ return super(ScheduleInboxResource, self).hasProperty(property, request)
+
+
@inlineCallbacks
def readProperty(self, property, request):
if type(property) is tuple:
@@ -163,15 +179,14 @@
qname = property.qname()
if qname == caldavxml.CalendarFreeBusySet.qname():
- # Always return at least an empty list
- if not self.hasDeadProperty(property):
- top = self.parent.url()
- values = []
- for cal in (yield self.parent._newStoreHome.calendars()):
- prop = cal.properties().get(PropertyName.fromString(ScheduleCalendarTransp.sname()))
- if prop == ScheduleCalendarTransp(Opaque()):
- values.append(HRef(joinURL(top, cal.name())))
- returnValue(CalendarFreeBusySet(*values))
+ # Synthesize value for calendar transparency state
+ top = self.parent.url()
+ values = []
+ for cal in (yield self.parent._newStoreHome.calendars()):
+ if cal.isUsedForFreeBusy():
+ values.append(HRef(joinURL(top, cal.name()) + "/"))
+ returnValue(CalendarFreeBusySet(*values))
+
elif qname in (caldavxml.ScheduleDefaultCalendarURL.qname(), customxml.ScheduleDefaultTasksURL.qname()):
result = (yield self.readDefaultCalendarProperty(request, qname))
returnValue(result)
@@ -201,10 +216,10 @@
# whether existing items in the property are still valid - only new ones.
property.children = [davxml.HRef(normalizeURL(str(href))) for href in property.children]
new_calendars = set([str(href) for href in property.children])
- if not self.hasDeadProperty(property):
- old_calendars = set()
- else:
- old_calendars = set([normalizeURL(str(href)) for href in self.readDeadProperty(property).children])
+ old_calendars = set()
+ for cal in (yield self.parent._newStoreHome.calendars()):
+ if cal.isUsedForFreeBusy():
+ old_calendars.add(HRef(joinURL(self.parent.url(), cal.name())))
added_calendars = new_calendars.difference(old_calendars)
for href in added_calendars:
cal = (yield request.locateResource(str(href)))
@@ -215,12 +230,21 @@
(caldav_namespace, "valid-calendar-url"),
"Invalid URI",
))
- for href in tuple(new_calendars):
+
+ # Remove old ones
+ for href in old_calendars.difference(new_calendars):
cal = (yield request.locateResource(str(href)))
- if cal is None or not cal.exists() or not isCalendarCollectionResource(cal):
- new_calendars.remove(href)
- property.children = [davxml.HRef(href) for href in new_calendars]
+ if cal is not None and cal.exists() and isCalendarCollectionResource(cal) and cal._newStoreObject.isUsedForFreeBusy():
+ yield cal._newStoreObject.setUsedForFreeBusy(False)
+ # Add new ones
+ for href in new_calendars:
+ cal = (yield request.locateResource(str(href)))
+ if cal is not None and cal.exists() and isCalendarCollectionResource(cal) and not cal._newStoreObject.isUsedForFreeBusy():
+ yield cal._newStoreObject.setUsedForFreeBusy(True)
+
+ returnValue(None)
+
elif property.qname() in (caldavxml.ScheduleDefaultCalendarURL.qname(), customxml.ScheduleDefaultTasksURL.qname()):
yield self.writeDefaultCalendarProperty(request, property)
returnValue(None)
@@ -228,23 +252,6 @@
yield super(ScheduleInboxResource, self).writeProperty(property, request)
- def processFreeBusyCalendar(self, uri, addit):
- uri = normalizeURL(uri)
-
- if not self.hasDeadProperty(caldavxml.CalendarFreeBusySet.qname()):
- fbset = set()
- else:
- fbset = set([normalizeURL(str(href)) for href in self.readDeadProperty(caldavxml.CalendarFreeBusySet.qname()).children])
- if addit:
- if uri not in fbset:
- fbset.add(uri)
- self.writeDeadProperty(caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in fbset]))
- else:
- if uri in fbset:
- fbset.remove(uri)
- self.writeDeadProperty(caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in fbset]))
-
-
@inlineCallbacks
def readDefaultCalendarProperty(self, request, qname):
"""
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/scheduling_store/caldav/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/scheduling_store/caldav/test/test_resource.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/scheduling_store/caldav/test/test_resource.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -14,158 +14,114 @@
# limitations under the License.
##
-from twext.web2 import responsecode, http_headers
-from twext.web2.dav.util import davXMLFromStream
-from twext.web2.iweb import IResponse
-from twext.web2.stream import MemoryStream
from twext.web2.test.test_server import SimpleRequest
from twisted.internet.defer import inlineCallbacks
from twistedcaldav import caldavxml, customxml
-from twistedcaldav.test.util import HomeTestCase, StoreTestCase, \
- SimpleStoreRequest
+from twistedcaldav.test.util import StoreTestCase, SimpleStoreRequest
from txdav.xml import element as davxml
+from twext.web2.http import HTTPError
-class Properties (HomeTestCase):
+class Properties (StoreTestCase):
"""
CalDAV properties
"""
- def test_free_busy_set_prop(self):
- """
- Test for PROPFIND on Inbox with missing calendar-free-busy-set property.
- """
- inbox_uri = "/inbox/"
-
- def propfind_cb(response):
- response = IResponse(response)
-
- if response.code != responsecode.MULTI_STATUS:
- self.fail("Incorrect response to PROPFIND: %s" % (response.code,))
-
- def got_xml(doc):
- if not isinstance(doc.root_element, davxml.MultiStatus):
- self.fail("PROPFIND response XML root element is not multistatus: %r" % (doc.root_element,))
-
- response = doc.root_element.childOfType(davxml.Response)
- href = response.childOfType(davxml.HRef)
- self.failUnless(str(href) == inbox_uri)
-
- for propstat in response.childrenOfType(davxml.PropertyStatus):
- status = propstat.childOfType(davxml.Status)
- if status.code != responsecode.OK:
- self.fail("Unable to read requested properties (%s): %r"
- % (status, propstat.childOfType(davxml.PropertyContainer).toxml()))
-
- container = propstat.childOfType(davxml.PropertyContainer)
-
- #
- # Check CalDAV:calendar-free-busy-set
- #
-
- free_busy_set = container.childOfType(caldavxml.CalendarFreeBusySet)
- if not free_busy_set:
- self.fail("Expected CalDAV:calendar-free-busy-set element; but got none.")
-
- if not free_busy_set.children:
- self.fail("Expected non-empty CalDAV:calendar-free-busy-set element.")
-
- return davXMLFromStream(response.stream).addCallback(got_xml)
-
- query = davxml.PropertyFind(
- davxml.PropertyContainer(
- caldavxml.CalendarFreeBusySet(),
- ),
- )
-
- request = SimpleRequest(
- self.site,
- "PROPFIND",
- inbox_uri,
- headers=http_headers.Headers({"Depth": "0"}),
- )
- request.stream = MemoryStream(query.toxml())
- return self.send(request, propfind_cb)
-
-
@inlineCallbacks
- def test_free_busy_set_remove_broken(self):
+ def test_free_busy_set_same(self):
"""
- ???
+ Test that calendar-free-busy-set has the correct value and can be reset to the same.
"""
- request = SimpleRequest(self.site, "GET", "/inbox/")
- inbox = yield request.locateResource("/inbox/")
- self.assertTrue(inbox.hasDeadProperty(caldavxml.CalendarFreeBusySet))
- oldfbset = set(("/calendar",))
- oldset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in oldfbset])
+ request = SimpleRequest(self.site, "GET", "/calendars/users/user01/inbox/")
+ inbox = yield request.locateResource("/calendars/users/user01/inbox/")
+ self.assertTrue((yield inbox.hasProperty(caldavxml.CalendarFreeBusySet, request)))
+ prop = (yield inbox.readProperty(caldavxml.CalendarFreeBusySet, request))
+ self.assertEqual(prop.children[0], davxml.HRef("/calendars/__uids__/user01/calendar/"))
newfbset = set()
- newfbset.update(oldfbset)
- newfbset.add("/calendar-broken")
+ newfbset.add("/calendars/users/user01/calendar/")
newset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in newfbset])
- inbox.writeDeadProperty(newset)
- changedset = inbox.readDeadProperty(caldavxml.CalendarFreeBusySet)
- self.assertEqual(tuple(changedset.children), tuple(newset.children))
-
yield inbox.writeProperty(newset, request)
+ yield request._newStoreTransaction.commit()
- changedset = inbox.readDeadProperty(caldavxml.CalendarFreeBusySet)
- self.assertEqual(tuple(changedset.children), tuple(oldset.children))
+ request = SimpleRequest(self.site, "GET", "/calendars/users/user01/inbox/")
+ inbox = yield request.locateResource("/calendars/users/user01/inbox/")
+ prop = (yield inbox.readProperty(caldavxml.CalendarFreeBusySet, request))
+ self.assertEqual(prop.children[0], davxml.HRef("/calendars/__uids__/user01/calendar/"))
+ yield request._newStoreTransaction.commit()
+ calendar = yield request.locateResource("/calendars/__uids__/user01/calendar/")
+ self.assertTrue(calendar._newStoreObject.isUsedForFreeBusy())
@inlineCallbacks
- def test_free_busy_set_strip_slash(self):
+ def test_free_busy_set_different(self):
"""
- ???
+ Test that calendar-free-busy-set has the correct value and can be reset to the same.
"""
- request = SimpleRequest(self.site, "GET", "/inbox/")
- inbox = yield request.locateResource("/inbox/")
- self.assertTrue(inbox.hasDeadProperty(caldavxml.CalendarFreeBusySet))
+ txn = self.transactionUnderTest()
+ home = (yield txn.calendarHomeWithUID("user01", create=True))
+ yield home.createCalendarWithName("calendar_new")
+ yield self.commit()
- oldfbset = set(("/calendar/",))
- oldset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in oldfbset])
- inbox.writeDeadProperty(oldset)
+ request = SimpleRequest(self.site, "GET", "/calendars/users/user01/inbox/")
+ inbox = yield request.locateResource("/calendars/users/user01/inbox/")
+ self.assertTrue((yield inbox.hasProperty(caldavxml.CalendarFreeBusySet, request)))
+ prop = (yield inbox.readProperty(caldavxml.CalendarFreeBusySet, request))
+ self.assertEqual(
+ set([str(child) for child in prop.children]),
+ set((
+ "/calendars/__uids__/user01/calendar/",
+ "/calendars/__uids__/user01/calendar_new/",
+ ))
+ )
+ calendar = yield request.locateResource("/calendars/__uids__/user01/calendar_new/")
+ self.assertTrue(calendar._newStoreObject.isUsedForFreeBusy())
+ calendar = yield request.locateResource("/calendars/__uids__/user01/calendar/")
+ self.assertTrue(calendar._newStoreObject.isUsedForFreeBusy())
- writefbset = set(("/calendar/",))
- writeset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in writefbset])
- yield inbox.writeProperty(writeset, request)
+ newfbset = set()
+ newfbset.add("/calendars/users/user01/calendar_new/")
+ newset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in newfbset])
- correctfbset = set(("/calendar",))
- correctset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in correctfbset])
- changedset = inbox.readDeadProperty(caldavxml.CalendarFreeBusySet)
- self.assertEqual(tuple(changedset.children), tuple(correctset.children))
+ yield inbox.writeProperty(newset, request)
+ yield request._newStoreTransaction.commit()
+ request = SimpleRequest(self.site, "GET", "/calendars/users/user01/inbox/")
+ inbox = yield request.locateResource("/calendars/users/user01/inbox/")
+ prop = (yield inbox.readProperty(caldavxml.CalendarFreeBusySet, request))
+ self.assertEqual(prop.children[0], davxml.HRef("/calendars/__uids__/user01/calendar_new/"))
+ yield request._newStoreTransaction.commit()
+ calendar = yield request.locateResource("/calendars/__uids__/user01/calendar_new/")
+ self.assertTrue(calendar._newStoreObject.isUsedForFreeBusy())
+ calendar = yield request.locateResource("/calendars/__uids__/user01/calendar/")
+ self.assertFalse(calendar._newStoreObject.isUsedForFreeBusy())
+
@inlineCallbacks
- def test_free_busy_set_strip_slash_remove(self):
+ def test_free_busy_set_invalid_url(self):
"""
- ???
+ Test that calendar-free-busy-set will generate an error if an invalid value is used.
"""
- request = SimpleRequest(self.site, "GET", "/inbox/")
- inbox = yield request.locateResource("/inbox/")
- self.assertTrue(inbox.hasDeadProperty(caldavxml.CalendarFreeBusySet))
+ request = SimpleRequest(self.site, "GET", "/calendars/users/user01/inbox/")
+ inbox = yield request.locateResource("/calendars/users/user01/inbox/")
+ self.assertTrue((yield inbox.hasProperty(caldavxml.CalendarFreeBusySet, request)))
+ oldfbset = set(("/calendar",))
- oldfbset = set(("/calendar/", "/broken/"))
- oldset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in oldfbset])
- inbox.writeDeadProperty(oldset)
+ newfbset = set()
+ newfbset.update(oldfbset)
+ newfbset.add("/calendar-broken")
+ newset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in newfbset])
- writefbset = set(("/calendar/", "/broken/"))
- writeset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in writefbset])
- yield inbox.writeProperty(writeset, request)
+ self.failUnlessFailure(inbox.writeProperty(newset, request), HTTPError)
- correctfbset = set(("/calendar",))
- correctset = caldavxml.CalendarFreeBusySet(*[davxml.HRef(url) for url in correctfbset])
- changedset = inbox.readDeadProperty(caldavxml.CalendarFreeBusySet)
- self.assertEqual(tuple(changedset.children), tuple(correctset.children))
-
class DefaultCalendar (StoreTestCase):
@inlineCallbacks
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/sharing.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/sharing.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -1228,7 +1228,7 @@
# Calendars always start out transparent and with empty default alarms
if isNewShare and shareeCollection.isCalendarCollection():
- yield shareeCollection.writeProperty(caldavxml.ScheduleCalendarTransp(caldavxml.Transparent()), request)
+ yield shareeCollection._newStoreObject.setUsedForFreeBusy(False)
yield shareeCollection.writeProperty(caldavxml.DefaultAlarmVEventDateTime.fromString(""), request)
yield shareeCollection.writeProperty(caldavxml.DefaultAlarmVEventDate.fromString(""), request)
yield shareeCollection.writeProperty(caldavxml.DefaultAlarmVToDoDateTime.fromString(""), request)
@@ -1287,14 +1287,6 @@
shared = (yield request.locateResource(shareURL))
displayname = shared.displayName()
- if self.isCalendarCollection():
- # For backwards compatibility we need to sync this up with the calendar-free-busy-set on the inbox
- principal = (yield self.resourceOwnerPrincipal(request))
- inboxURL = principal.scheduleInboxURL()
- if inboxURL:
- inbox = (yield request.locateResource(inboxURL))
- inbox.processFreeBusyCalendar(shareURL, False)
-
if share.direct():
yield share._sharerHomeChild.unshareWith(share._shareeHomeChild.viewerHome())
else:
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/twistedcaldav/storebridge.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -1256,10 +1256,6 @@
yield super(CalendarCollectionResource, self).storeRemove(request)
)
- if response == NO_CONTENT:
- # Do some clean up
- yield self.deletedCalendar(request)
-
returnValue(response)
@@ -1271,10 +1267,6 @@
that calendar's name.
"""
result = (yield super(CalendarCollectionResource, self).http_MOVE(request))
- if result == NO_CONTENT:
- destinationURI = urlsplit(request.headers.getHeader("destination"))[2]
- destination = yield request.locateResource(destinationURI)
- yield self.movedCalendar(request, destination, destinationURI)
returnValue(result)
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/caldav/datastore/sql.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -50,7 +50,6 @@
from twisted.python import hashlib
from twistedcaldav import caldavxml, customxml
-from twistedcaldav.caldavxml import ScheduleCalendarTransp, Opaque
from twistedcaldav.config import config
from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
from twistedcaldav.dateops import normalizeForIndex, datetimeMktime, \
@@ -85,7 +84,7 @@
CALENDAR_HOME_TABLE, CALENDAR_HOME_METADATA_TABLE, \
CALENDAR_AND_CALENDAR_BIND, CALENDAR_OBJECT_REVISIONS_AND_BIND_TABLE, \
CALENDAR_OBJECT_AND_BIND_TABLE, schema, _BIND_MODE_OWN, \
- _ATTACHMENTS_MODE_READ
+ _ATTACHMENTS_MODE_READ, _TRANSP_OPAQUE, _TRANSP_TRANSPARENT
from txdav.common.icommondatastore import IndexedSearchException, \
InternalDataStoreError, HomeChildNameAlreadyExistsError, \
HomeChildNameNotAllowedError, ObjectResourceTooBigError, \
@@ -552,8 +551,6 @@
# Default calendar
defaultCal = yield self.createCalendarWithName("calendar")
- props = defaultCal.properties()
- props[PropertyName(*ScheduleCalendarTransp.qname())] = ScheduleCalendarTransp(Opaque())
# Check whether components type must be separate
if config.RestrictCalendarsToOneComponentType:
@@ -562,8 +559,10 @@
# Default tasks
defaultTasks = yield self.createCalendarWithName("tasks")
yield defaultTasks.setSupportedComponents("VTODO")
+ yield defaultTasks.setUsedForFreeBusy(False)
- yield self.createCalendarWithName("inbox")
+ inbox = yield self.createCalendarWithName("inbox")
+ yield inbox.setUsedForFreeBusy(False)
@inlineCallbacks
@@ -848,6 +847,7 @@
self._index = PostgresLegacyInboxIndexEmulator(self)
else:
self._index = PostgresLegacyIndexEmulator(self)
+ self._transp = _TRANSP_OPAQUE
@classmethod
@@ -884,6 +884,32 @@
)
+ @classmethod
+ def additionalBindColumns(cls):
+ """
+ Return a list of column names for retrieval during creation. This allows
+ different child classes to have their own type specific data, but still make use of the
+ common base logic.
+ """
+
+ return (
+ cls._bindSchema.TRANSP,
+ )
+
+
+ @classmethod
+ def additionalBindAttributes(cls):
+ """
+ Return a list of attribute names for retrieval of during creation. This allows
+ different child classes to have their own type specific data, but still make use of the
+ common base logic.
+ """
+
+ return (
+ "_transp",
+ )
+
+
@property
def _calendarHome(self):
return self._home
@@ -1023,6 +1049,27 @@
return self.name() == "inbox"
+ @inlineCallbacks
+ def setUsedForFreeBusy(self, use_it):
+ """
+ Mark this calendar as being used for free busy request. Note this is a per-user setting so we are setting
+ this on the bind table entry which is related to the user viewing the calendar.
+
+ @param use_it: C{True} if used for free busy, C{False} otherwise
+ @type use_it: C{bool}
+ """
+
+ self._transp = _TRANSP_OPAQUE if use_it else _TRANSP_TRANSPARENT
+ cal = self._bindSchema
+ yield Update(
+ {
+ cal.TRANSP : self._transp
+ },
+ Where=(cal.CALENDAR_HOME_RESOURCE_ID == self.viewerHome()._resourceID).And(cal.CALENDAR_RESOURCE_ID == self._resourceID)
+ ).on(self._txn)
+ yield self.invalidateQueryCache()
+
+
def isUsedForFreeBusy(self):
"""
Indicates whether the contents of this calendar contributes to free busy.
@@ -1030,8 +1077,7 @@
@return: C{True} if it does, C{False} otherwise
@rtype: C{bool}
"""
- opaque = self.properties().get(PropertyName(*ScheduleCalendarTransp.qname()), ScheduleCalendarTransp(Opaque())) == ScheduleCalendarTransp(Opaque())
- return opaque and not self.isInbox()
+ return self._transp == _TRANSP_OPAQUE
def initPropertyStore(self, props):
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -2610,6 +2610,28 @@
@classmethod
+ def additionalBindColumns(cls):
+ """
+ Return a list of column names for retrieval during creation. This allows
+ different child classes to have their own type specific data, but still make use of the
+ common base logic.
+ """
+
+ return ()
+
+
+ @classmethod
+ def additionalBindAttributes(cls):
+ """
+ Return a list of attribute names for retrieval of during creation. This allows
+ different child classes to have their own type specific data, but still make use of the
+ common base logic.
+ """
+
+ return ()
+
+
+ @classmethod
@inlineCallbacks
def listObjects(cls, home):
"""
@@ -2658,6 +2680,7 @@
bind.RESOURCE_NAME,
bind.BIND_STATUS,
bind.MESSAGE]
+ columns.extend(cls.additionalBindColumns())
columns.extend(cls.metadataColumns())
return Select(columns,
From=child.join(
@@ -2920,15 +2943,17 @@
@classmethod
def _bindFor(cls, condition): #@NoSelf
bind = cls._bindSchema
+ columns = [bind.BIND_MODE,
+ bind.HOME_RESOURCE_ID,
+ bind.RESOURCE_ID,
+ bind.RESOURCE_NAME,
+ bind.BIND_STATUS,
+ bind.MESSAGE]
+ columns.extend(cls.additionalBindColumns())
return Select(
- [bind.BIND_MODE,
- bind.HOME_RESOURCE_ID,
- bind.RESOURCE_ID,
- bind.RESOURCE_NAME,
- bind.BIND_STATUS,
- bind.MESSAGE],
- From=bind,
- Where=condition
+ columns,
+ From=bind,
+ Where=condition
)
@@ -2963,7 +2988,10 @@
cls = self.__class__ # for ease of grepping...
result = []
- for bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage in acceptedRows: #@UnusedVariable
+ for item in acceptedRows:
+ bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = item[:6] #@UnusedVariable
+ additionalBind = item[6:]
+
assert bindStatus == _BIND_STATUS_ACCEPTED
# TODO: this could all be issued in parallel; no need to serialize
# the loop.
@@ -2973,7 +3001,7 @@
mode=bindMode, status=bindStatus,
message=bindMessage, ownerHome=self._home
)
- yield new.initFromStore()
+ yield new.initFromStore(additionalBind)
result.append(new)
returnValue(result)
@@ -3007,7 +3035,9 @@
cls = self.__class__ # for ease of grepping...
result = []
- for bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage in rows: #@UnusedVariable
+ for item in rows:
+ bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = item[:6] #@UnusedVariable
+ additionalBind = item[6:]
# TODO: this could all be issued in parallel; no need to serialize
# the loop.
new = cls(
@@ -3016,7 +3046,7 @@
mode=bindMode, status=bindStatus,
message=bindMessage, ownerHome=self._home
)
- yield new.initFromStore()
+ yield new.initFromStore(additionalBind)
result.append(new)
returnValue(result)
@@ -3059,7 +3089,8 @@
# Create the actual objects merging in properties
for items in dataRows:
bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = items[:6] #@UnusedVariable
- metadata = items[6:]
+ additionalBind = items[6:6 + len(cls.additionalBindColumns())]
+ metadata = items[6 + len(cls.additionalBindColumns()):]
if bindStatus == _BIND_MODE_OWN:
ownerHome = home
@@ -3076,6 +3107,8 @@
message=bindMessage,
ownerHome=ownerHome, ownerName=ownerName
)
+ for attr, value in zip(cls.additionalBindAttributes(), additionalBind):
+ setattr(child, attr, value)
for attr, value in zip(cls.metadataAttributes(), metadata):
setattr(child, attr, value)
child._syncTokenRevision = revisions[resourceID]
@@ -3120,7 +3153,9 @@
if not rows:
returnValue(None)
- bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = rows[0] #@UnusedVariable
+ item = rows[0]
+ bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = item[:6] #@UnusedVariable
+ additionalBind = item[6:]
#TODO: combine with _invitedBindForNameAndHomeID and sort results
ownerHomeID, ownerName = (yield cls._ownerHomeWithResourceID.on(home._txn, resourceID=resourceID))[0]
@@ -3133,7 +3168,7 @@
message=bindMessage,
ownerHome=ownerHome, ownerName=ownerName,
)
- yield child.initFromStore()
+ yield child.initFromStore(additionalBind)
returnValue(child)
@@ -3174,7 +3209,8 @@
rows = yield cls._childForNameAndHomeID.on(home._txn, name=name, homeID=home._resourceID)
if rows:
- bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = rows[0] #@UnusedVariable
+ item = rows[0]
+ bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = item[:6] #@UnusedVariable
# get ownerHomeID
if bindMode == _BIND_MODE_OWN:
ownerHomeID = homeID
@@ -3182,8 +3218,8 @@
else:
ownerHomeID, ownerName = (yield cls._ownerHomeWithResourceID.on(
home._txn, resourceID=resourceID))[0]
- rows[0].append(ownerHomeID)
- rows[0].append(ownerName)
+ rows[0].insert(6, ownerHomeID)
+ rows[0].insert(7, ownerName)
if rows and queryCacher:
# Cache the result
@@ -3192,7 +3228,9 @@
if not rows:
returnValue(None)
- bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage, ownerHomeID, ownerName = rows[0] #@UnusedVariable
+ item = rows[0] #@UnusedVariable
+ bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage, ownerHomeID, ownerName = item[:8]
+ additionalBind = item[8:]
if bindMode == _BIND_MODE_OWN:
ownerHome = home
@@ -3206,7 +3244,7 @@
message=bindMessage,
ownerHome=ownerHome, ownerName=ownerName,
)
- yield child.initFromStore()
+ yield child.initFromStore(additionalBind)
returnValue(child)
@@ -3239,7 +3277,9 @@
if not rows:
returnValue(None)
- bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = rows[0] #@UnusedVariable
+ item = rows[0]
+ bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = item[:6] #@UnusedVariable
+ additionalBind = item[6:]
if bindMode == _BIND_MODE_OWN:
ownerHome = home
@@ -3254,7 +3294,7 @@
message=bindMessage,
ownerHome=ownerHome, ownerName=ownerName,
)
- yield child.initFromStore()
+ yield child.initFromStore(additionalBind)
returnValue(child)
@@ -3352,7 +3392,7 @@
@inlineCallbacks
- def initFromStore(self):
+ def initFromStore(self, additionalBind=None):
"""
Initialise this object from the store, based on its already-populated
resource ID. We read in and cache all the extra metadata from the DB to
@@ -3374,6 +3414,10 @@
# Cache the results
yield queryCacher.setAfterCommit(self._txn, cacheKey, dataRows)
+ if additionalBind:
+ for attr, value in zip(self.additionalBindAttributes(), additionalBind):
+ setattr(self, attr, value)
+
for attr, value in zip(self.metadataAttributes(), dataRows):
setattr(self, attr, value)
yield self._loadPropertyStore()
@@ -3416,6 +3460,8 @@
if queryCacher is not None:
cacheKey = queryCacher.keyForHomeChildMetaData(self._resourceID)
yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
+ cacheKey = queryCacher.keyForObjectWithName(self._home._resourceID, self._name)
+ yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
def exists(self):
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/current-oracle-dialect.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/current-oracle-dialect.sql 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/current-oracle-dialect.sql 2013-05-01 16:33:40 UTC (rev 11116)
@@ -64,7 +64,8 @@
"CALENDAR_RESOURCE_NAME" nvarchar2(255),
"BIND_MODE" integer not null,
"BIND_STATUS" integer not null,
- "MESSAGE" nclob,
+ "MESSAGE" nclob,
+ "TRANSP" integer default 0 not null,
primary key("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_ID"),
unique("CALENDAR_HOME_RESOURCE_ID", "CALENDAR_RESOURCE_NAME")
);
@@ -87,6 +88,13 @@
insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('accepted', 1);
insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('declined', 2);
insert into CALENDAR_BIND_STATUS (DESCRIPTION, ID) values ('invalid', 3);
+create table CALENDAR_TRANSP (
+ "ID" integer primary key,
+ "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('opaque', 0);
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('transparent', 1);
create table CALENDAR_OBJECT (
"RESOURCE_ID" integer primary key,
"CALENDAR_RESOURCE_ID" integer not null references CALENDAR on delete cascade,
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/current.sql 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/current.sql 2013-05-01 16:33:40 UTC (rev 11116)
@@ -127,6 +127,7 @@
BIND_MODE integer not null, -- enum CALENDAR_BIND_MODE
BIND_STATUS integer not null, -- enum CALENDAR_BIND_STATUS
MESSAGE text,
+ TRANSP integer default 0 not null, -- enum CALENDAR_TRANSP
primary key(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_ID), -- implicit index
unique(CALENDAR_HOME_RESOURCE_ID, CALENDAR_RESOURCE_NAME) -- implicit index
@@ -159,6 +160,17 @@
insert into CALENDAR_BIND_STATUS values (3, 'invalid');
+-- Enumeration of transparency
+
+create table CALENDAR_TRANSP (
+ ID integer primary key,
+ DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_TRANSP values (0, 'opaque' );
+insert into CALENDAR_TRANSP values (1, 'transparent');
+
+
---------------------
-- Calendar Object --
---------------------
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/upgrades/oracle-dialect/upgrade_from_18_to_19.sql 2013-05-01 16:33:40 UTC (rev 11116)
@@ -24,7 +24,20 @@
add ("DEFAULT_EVENTS" integer default null,
"DEFAULT_TASKS" integer default null);
+
+-- Calendar bind related updates
+alter table CALENDAR_BIND
+ add ("TRANSP" integer default 0 not null);
+
+create table CALENDAR_TRANSP (
+ "ID" integer primary key,
+ "DESCRIPTION" nvarchar2(16) unique
+);
+
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('opaque', 0);
+insert into CALENDAR_TRANSP (DESCRIPTION, ID) values ('transparent', 1);
+
-- Now update the version
-- No data upgrades
update CALENDARSERVER set VALUE = '19' where NAME = 'VERSION';
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_schema/upgrades/postgres-dialect/upgrade_from_18_to_19.sql 2013-05-01 16:33:40 UTC (rev 11116)
@@ -26,6 +26,19 @@
add column DEFAULT_TASKS integer default null;
+-- Calendar bind related updates
+
+alter table CALENDAR_BIND
+ add column TRANSP integer default 0 not null;
+
+create table CALENDAR_TRANSP (
+ ID integer primary key,
+ DESCRIPTION varchar(16) not null unique
+);
+
+insert into CALENDAR_TRANSP values (0, 'opaque' );
+insert into CALENDAR_TRANSP values (1, 'transparent');
+
-- Now update the version
-- No data upgrades
update CALENDARSERVER set VALUE = '19' where NAME = 'VERSION';
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_tables.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_tables.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/sql_tables.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -153,6 +153,16 @@
_BIND_STATUS_DECLINED = _bindStatus('declined')
_BIND_STATUS_INVALID = _bindStatus('invalid')
+
+_transpValues = _schemaConstants(
+ schema.CALENDAR_TRANSP.DESCRIPTION,
+ schema.CALENDAR_TRANSP.ID
+)
+
+_TRANSP_OPAQUE = _transpValues('opaque')
+_TRANSP_TRANSPARENT = _transpValues('transparent')
+
+
_attachmentsMode = _schemaConstants(
schema.CALENDAR_OBJECT_ATTACHMENTS_MODE.DESCRIPTION,
schema.CALENDAR_OBJECT_ATTACHMENTS_MODE.ID
Added: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/__init__.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/__init__.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/__init__.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -0,0 +1,15 @@
+##
+# Copyright (c) 2011-2013 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
Added: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py (rev 0)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/test/test_upgrade_from_3_to_4.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -0,0 +1,108 @@
+##
+# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+from twistedcaldav.caldavxml import ScheduleDefaultCalendarURL, \
+ CalendarFreeBusySet, Opaque, ScheduleCalendarTransp
+from txdav.base.propertystore.base import PropertyName
+from txdav.caldav.datastore.test.util import CommonStoreTests
+from txdav.xml.element import HRef
+from twext.enterprise.dal.syntax import Update
+from txdav.common.datastore.upgrade.sql.upgrades.upgrade_from_3_to_4 import moveDefaultCalendarProperties, \
+ moveCalendarTranspProperties
+
+"""
+Tests for L{txdav.common.datastore.upgrade.sql.upgrade}.
+"""
+
+from twisted.internet.defer import inlineCallbacks
+
+class Upgrade_from_3_to_4(CommonStoreTests):
+ """
+ Tests for L{DefaultCalendarPropertyUpgrade}.
+ """
+
+ @inlineCallbacks
+ def test_defaultCalendarUpgrade(self):
+
+ # Set dead property on inbox
+ inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
+ inbox.properties()[PropertyName.fromElement(ScheduleDefaultCalendarURL)] = ScheduleDefaultCalendarURL(HRef.fromString("/calendars/__uids__/user01/calendar_1"))
+
+ # Force current default to null
+ home = (yield self.homeUnderTest(name="user01"))
+ chm = home._homeMetaDataSchema
+ yield Update(
+ {chm.DEFAULT_EVENTS: None},
+ Where=chm.RESOURCE_ID == home._resourceID,
+ ).on(self.transactionUnderTest())
+
+ # Force data version to previous
+ ch = home._homeSchema
+ yield Update(
+ {ch.DATAVERSION: 3},
+ Where=ch.RESOURCE_ID == home._resourceID,
+ ).on(self.transactionUnderTest())
+
+ yield self.commit()
+
+ # Trigger upgrade
+ yield moveDefaultCalendarProperties(self._sqlCalendarStore)
+
+ # Test results
+ home = (yield self.homeUnderTest(name="user01"))
+ calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
+ self.assertTrue(home.isDefaultCalendar(calendar))
+ inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
+ self.assertTrue(PropertyName.fromElement(ScheduleDefaultCalendarURL) not in inbox.properties())
+
+
+ @inlineCallbacks
+ def test_calendarTranspUpgrade(self):
+
+ # Set dead property on inbox
+ inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
+ inbox.properties()[PropertyName.fromElement(CalendarFreeBusySet)] = CalendarFreeBusySet(HRef.fromString("/calendars/__uids__/user01/calendar_1"))
+
+ # Force current to transparent
+ calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
+ yield calendar.setUsedForFreeBusy(False)
+ calendar.properties()[PropertyName.fromElement(ScheduleCalendarTransp)] = ScheduleCalendarTransp(Opaque())
+
+ # Force data version to previous
+ home = (yield self.homeUnderTest(name="user01"))
+ ch = home._homeSchema
+ yield Update(
+ {ch.DATAVERSION: 3},
+ Where=ch.RESOURCE_ID == home._resourceID,
+ ).on(self.transactionUnderTest())
+
+ yield self.commit()
+
+ calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
+ self.assertFalse(calendar.isUsedForFreeBusy())
+ self.assertTrue(PropertyName.fromElement(ScheduleCalendarTransp) in calendar.properties())
+ inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
+ self.assertTrue(PropertyName.fromElement(CalendarFreeBusySet) in inbox.properties())
+ yield self.commit()
+
+ # Trigger upgrade
+ yield moveCalendarTranspProperties(self._sqlCalendarStore)
+
+ # Test results
+ home = (yield self.homeUnderTest(name="user01"))
+ calendar = (yield self.calendarUnderTest(name="calendar_1", home="user01"))
+ self.assertTrue(calendar.isUsedForFreeBusy())
+ inbox = (yield self.calendarUnderTest(name="inbox", home="user01"))
+ self.assertTrue(PropertyName.fromElement(CalendarFreeBusySet) not in inbox.properties())
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_3_to_4.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_3_to_4.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_3_to_4.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -15,15 +15,16 @@
# limitations under the License.
##
-from twext.enterprise.dal.syntax import Update, Select, Delete, Parameter
+from twext.enterprise.dal.syntax import Select, Delete, Parameter
from twisted.internet.defer import inlineCallbacks
from twistedcaldav import caldavxml, customxml
from txdav.base.propertystore.base import PropertyName
-from txdav.common.datastore.sql_tables import schema
-from txdav.common.datastore.upgrade.sql.upgrades.util import rowsForProperty, updateDataVersion
+from txdav.common.datastore.sql_tables import schema, _BIND_MODE_OWN
+from txdav.common.datastore.upgrade.sql.upgrades.util import rowsForProperty, updateDataVersion, \
+ updateAllCalendarHomeDataVersions, removeProperty, cleanPropertyStore
from txdav.xml.parser import WebDAVDocument
"""
@@ -39,9 +40,11 @@
Do the required upgrade steps.
"""
yield moveDefaultCalendarProperties(sqlStore)
+ yield moveCalendarTranspProperties(sqlStore)
# Always bump the DB value
yield updateDataVersion(sqlStore, "CALENDAR-DATAVERSION", UPGRADE_TO_VERSION)
+ yield updateAllCalendarHomeDataVersions(sqlStore, UPGRADE_TO_VERSION)
@@ -67,7 +70,6 @@
Since the number of calendar homes may well be large, we need to do this in batches.
"""
- meta = schema.CALENDAR_HOME_METADATA
cb = schema.CALENDAR_BIND
rp = schema.RESOURCE_PROPERTY
@@ -103,12 +105,8 @@
calendar = (yield calendarHome.calendarWithName(calendarName))
if calendar is not None:
+ yield calendarHome.setDefaultCalendar(calendar, tasks=(propname == sqlStore, customxml.ScheduleDefaultTasksURL))
- yield Update(
- {colname : calendar.id(), },
- Where=(meta.RESOURCE_ID == calendarHome.id())
- ).on(sqlTxn)
-
# Always delete the row so that batch processing works correctly
yield Delete(
From=rp,
@@ -118,6 +116,73 @@
yield sqlTxn.commit()
+ yield cleanPropertyStore()
+
except RuntimeError:
yield sqlTxn.abort()
raise
+
+
+
+ at inlineCallbacks
+def moveCalendarTranspProperties(sqlStore):
+ """
+ Need to move all the CalDAV:schedule-calendar-transp properties in the
+ RESOURCE_PROPERTY table to the new CALENDAR_BIND table columns, extracting
+ the new value from the XML property.
+ """
+
+ cb = schema.CALENDAR_BIND
+ rp = schema.RESOURCE_PROPERTY
+
+ try:
+ calendars_for_id = {}
+ while True:
+ sqlTxn = sqlStore.newTransaction()
+ rows = (yield rowsForProperty(sqlTxn, caldavxml.ScheduleCalendarTransp, with_uid=True, batch=BATCH_SIZE))
+ if len(rows) == 0:
+ yield sqlTxn.commit()
+ break
+ delete_ids = []
+ for calendar_rid, value, viewer in rows:
+ delete_ids.append(calendar_rid)
+ if calendar_rid not in calendars_for_id:
+ ids = yield Select(
+ [cb.CALENDAR_HOME_RESOURCE_ID, cb.BIND_MODE, ],
+ From=cb,
+ Where=cb.CALENDAR_RESOURCE_ID == calendar_rid,
+ ).on(sqlTxn)
+ calendars_for_id[calendar_rid] = ids
+
+ if viewer:
+ calendarHome = (yield sqlTxn.calendarHomeWithUID(viewer))
+ else:
+ calendarHome = None
+ for row in calendars_for_id[calendar_rid]:
+ home_id, bind_mode = row
+ if bind_mode == _BIND_MODE_OWN:
+ calendarHome = (yield sqlTxn.calendarHomeWithResourceID(home_id))
+ break
+
+ if calendarHome is not None:
+ prop = WebDAVDocument.fromString(value).root_element
+ calendar = (yield calendarHome.childWithID(calendar_rid))
+ yield calendar.setUsedForFreeBusy(prop == caldavxml.ScheduleCalendarTransp(caldavxml.Opaque()))
+
+ # Always delete the row so that batch processing works correctly
+ yield Delete(
+ From=rp,
+ Where=(rp.RESOURCE_ID.In(Parameter("ids", len(delete_ids)))).And
+ (rp.NAME == PropertyName.fromElement(caldavxml.ScheduleCalendarTransp).toString()),
+ ).on(sqlTxn, ids=delete_ids)
+
+ yield sqlTxn.commit()
+
+ sqlTxn = sqlStore.newTransaction()
+ yield removeProperty(sqlTxn, PropertyName.fromElement(caldavxml.CalendarFreeBusySet))
+ yield sqlTxn.commit()
+ yield cleanPropertyStore()
+
+ except RuntimeError:
+ yield sqlTxn.abort()
+ raise
Modified: CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/util.py
===================================================================
--- CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/util.py 2013-04-30 19:20:15 UTC (rev 11115)
+++ CalendarServer/branches/users/cdaboo/store-scheduling/txdav/common/datastore/upgrade/sql/upgrades/util.py 2013-05-01 16:33:40 UTC (rev 11116)
@@ -18,14 +18,18 @@
from twisted.internet.defer import inlineCallbacks, returnValue
from txdav.base.propertystore.base import PropertyName
from txdav.common.datastore.sql_tables import schema
+from txdav.base.propertystore.sql import PropertyStore
@inlineCallbacks
-def rowsForProperty(txn, propelement, batch=None):
+def rowsForProperty(txn, propelement, with_uid=False, batch=None):
pname = PropertyName.fromElement(propelement)
rp = schema.RESOURCE_PROPERTY
+ columns = [rp.RESOURCE_ID, rp.VALUE, ]
+ if with_uid:
+ columns.append(rp.VIEWER_UID)
rows = yield Select(
- [rp.RESOURCE_ID, rp.VALUE, ],
+ columns,
From=rp,
Where=rp.NAME == pname.toString(),
Limit=batch,
@@ -36,6 +40,16 @@
@inlineCallbacks
+def cleanPropertyStore():
+ """
+ We have manually manipulated the SQL property store by-passing the underlying implementation's caching
+ mechanism. We need to clear out the cache.
+ """
+ yield PropertyStore._cacher.flushAll()
+
+
+
+ at inlineCallbacks
def removeProperty(txn, propelement):
pname = PropertyName.fromElement(propelement)
@@ -48,6 +62,31 @@
@inlineCallbacks
+def updateAllCalendarHomeDataVersions(store, version):
+
+ txn = store.newTransaction("updateAllCalendarHomeDataVersions")
+ ch = schema.CALENDAR_HOME
+ yield Update(
+ {ch.DATAVERSION: version},
+ Where=None,
+ ).on(txn)
+ yield txn.commit()
+
+
+
+ at inlineCallbacks
+def updateAllAddressBookHomeDataVersions(store, version):
+
+ txn = store.newTransaction("updateAllAddressBookHomeDataVersions")
+ ah = schema.ADDRESSBOOK_HOME
+ yield Update(
+ {ah.DATAVERSION: version},
+ ).on(txn)
+ yield txn.commit()
+
+
+
+ at inlineCallbacks
def updateDataVersion(store, key, version):
txn = store.newTransaction("updateDataVersion")
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130501/7ac2c79c/attachment-0001.html>
More information about the calendarserver-changes
mailing list