[CalendarServer-changes] [7090] CalendarServer/branches/users/cdaboo/pycalendar
source_changes at macosforge.org
source_changes at macosforge.org
Tue Mar 1 12:28:31 PST 2011
Revision: 7090
http://trac.macosforge.org/projects/calendarserver/changeset/7090
Author: cdaboo at apple.com
Date: 2011-03-01 12:28:29 -0800 (Tue, 01 Mar 2011)
Log Message:
-----------
Work in progress snapshot. ical.py now mostly implemented using pycalendar with test_icalendar.py passing.
Modified Paths:
--------------
CalendarServer/branches/users/cdaboo/pycalendar/twext/python/datetime.py
CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/caldavxml.py
CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/dateops.py
CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/ical.py
CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/instance.py
CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/query/calendarqueryfilter.py
CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/icaldiff.py
CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/itip.py
CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/test/test_icalendar.py
Modified: CalendarServer/branches/users/cdaboo/pycalendar/twext/python/datetime.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twext/python/datetime.py 2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twext/python/datetime.py 2011-03-01 20:28:29 UTC (rev 7090)
@@ -24,7 +24,6 @@
"dateordatetime",
"timerange",
"asTimeZone",
- "asUTC",
"iCalendarString",
]
@@ -32,7 +31,7 @@
datetime = __import__("datetime").datetime
from vobject.icalendar import dateTimeToString, dateToString
-from vobject.icalendar import utc, getTzid as tzWithID
+from vobject.icalendar import utc
# FIXME, add constants for begining/end of time
@@ -297,21 +296,17 @@
# Convenience functions
##
-def asTimeZone(dateOrDatetime, tzinfo):
+def asTimeZone(pydt, pytz):
"""
- Convert a L{date} or L{datetime} to the given time zone.
+ Convert a L{PyCalendarDateTime} to the given time zone.
"""
- return dateordatetime(dateOrDatetime).asTimeZone(tzinfo).dateOrDatetime()
+ dup = pydt.duplicate()
+ dup.adjustTimezone(pytz)
+ return dup
-def asUTC(dateOrDatetime):
+def iCalendarString(pydt):
"""
- Convert a L{date} or L{datetime} to UTC.
- """
- return dateordatetime(dateOrDatetime).asUTC().dateOrDatetime()
-
-def iCalendarString(dateOrDatetime):
- """
- Convert a L{date} or L{datetime} to a string appropriate for use
+ Convert a L{PyCalendarDateTime} to a string appropriate for use
in an iCalendar property.
"""
- return dateordatetime(dateOrDatetime).iCalendarString()
+ return pydt.getText()
Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/caldavxml.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/caldavxml.py 2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/caldavxml.py 2011-03-01 20:28:29 UTC (rev 7090)
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
+from pycalendar.datetime import PyCalendarDateTime
"""
CalDAV XML Support.
@@ -34,7 +35,6 @@
from twext.python.log import Logger
from twistedcaldav.ical import Component as iComponent
-from twistedcaldav.ical import parse_date_or_datetime
log = Logger()
@@ -93,8 +93,8 @@
if "start" not in attributes and "end" not in attributes:
raise ValueError("One of 'start' or 'end' must be present in CALDAV:time-range")
- self.start = parse_date_or_datetime(attributes["start"]) if "start" in attributes else None
- self.end = parse_date_or_datetime(attributes["end"]) if "end" in attributes else None
+ self.start = PyCalendarDateTime.parseText(attributes["start"]) if "start" in attributes else None
+ self.end = PyCalendarDateTime.parseText(attributes["end"]) if "end" in attributes else None
def valid(self, level=0):
"""
Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/dateops.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/dateops.py 2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/dateops.py 2011-03-01 20:28:29 UTC (rev 7090)
@@ -13,6 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.period import PyCalendarPeriod
+import datetime
+from vobject.icalendar import utc
"""
Date/time Utilities
@@ -30,91 +35,98 @@
]
import calendar
-import datetime
-from vobject.icalendar import utc
-from twext.python.datetime import dateordatetime
-
def normalizeForIndex(dt):
"""
- Normalize a L{datetime.date} or L{datetime.datetime} object for use in the Index.
- If it's a L{datetime.date}, convert to L{datetime.datetime} with HH:MM:SS set to 00:00:00 in UTC.
- If it's a L{datetime.datetime}, convert to UTC.
- @param dt: a L{datetime.date} or L{datetime.datetime} object to normalize
- @return: the normalized date or datetime
+ Normalize a L{PyCalendarDateTime} object for use in the Index.
+ Convert to date-time in UTC.
+ @param dt: a L{PyCalendarDateTime} object to normalize
+ @return: the normalized PyCalendarDateTime
"""
- if not isinstance(dt, datetime.date):
- raise TypeError("%r is not a datetime.date instance" % (dt,))
+ if not isinstance(dt, PyCalendarDateTime):
+ raise TypeError("%r is not a removeParameterValue instance" % (dt,))
- if isinstance(dt, datetime.datetime):
- if dt.tzinfo is not None:
- return dt.astimezone(utc)
- else:
- return dt
+ dt = dt.duplicate()
+ if dt.isDateOnly():
+ dt.setDateOnly(False)
+ dt.setHHMMSS(0, 0, 0)
+ dt.setTimezoneUTC(True)
+ return dt
+ elif dt.floating():
+ return dt
else:
- return datetime.datetime.fromordinal(dt.toordinal())
+ dt.adjustToUTC()
+ return dt
def normalizeToUTC(dt):
"""
- Normalize a L{datetime.date} or L{datetime.datetime} object to UTC.
+ Normalize a L{PyCalendarDateTime} object to UTC.
"""
- if not isinstance(dt, datetime.date):
- raise TypeError("%r is not a datetime.date instance" % (dt,))
+ if not isinstance(dt, PyCalendarDateTime):
+ raise TypeError("%r is not a PyCalendarDateTime instance" % (dt,))
- if isinstance(dt, datetime.datetime):
- if dt.tzinfo is not None:
- return dt.astimezone(utc)
- else:
- return dt.replace(tzinfo=utc)
+ dt = dt.duplicate()
+ if dt.isDateOnly():
+ dt.setDateOnly(False)
+ dt.setHHMMSS(0, 0, 0)
+ dt.setTimezoneUTC(True)
+ return dt
+ elif dt.floating():
+ dt.setTimezoneUTC(True)
+ return dt
else:
- return datetime.datetime.fromordinal(dt.toordinal()).replace(tzinfo=utc)
+ dt.adjustToUTC()
+ return dt
-def floatoffset(dt, tzinfo):
+def floatoffset(dt, pytz):
"""
Apply the timezone offset to the supplied time, then force tz to utc. This gives the local
date-time as if the local tz were UTC. It can be used in floating time comparisons with UTC date-times.
- @param dt: a L{datetime.datetime} object to normalize
- @param tzinfo: a L{datetime.tzinfo} object to apply offset from
- @return: the normalized datetime
+ @param dt: a L{PyCalendarDateTime} object to normalize
+ @param pytz: a L{PyCalendarTimezone} object to apply offset from
+ @return: the normalized PyCalendarDateTime
"""
- if tzinfo is None:
- tzinfo = utc
- return dt.astimezone(tzinfo).replace(tzinfo=utc)
+ if pytz is None:
+ pytz = PyCalendarTimezone(utc=True)
+
+ dt = dt.duplicate()
+ dt.adjustTimezone(pytz)
+ dt.setTimezoneUTC(True)
+ return dt
+def adjustFloatingToTimezone(dtadjust, dtcopyfrom, pytz=None):
+
+ dtadjust = dtadjust.duplicate()
+ dtadjust.setTimezone(pytz if pytz else dtcopyfrom.getTimezone())
+ return dtadjust
+
def compareDateTime(dt1, dt2, defaulttz=None):
- dt1 = dateordatetime(dt1, defaultTZ=defaulttz)
- dt2 = dateordatetime(dt2, defaultTZ=defaulttz)
- if dt1 == dt2:
- return 0
- elif dt1 < dt2:
- return -1
- else:
- return 1
+
+ if dt1.floating() and not dt2.floating():
+ dt1 = adjustFloatingToTimezone(dt1, dt2, defaulttz)
+ elif dt2.floating() and not dt1.floating():
+ dt2 = adjustFloatingToTimezone(dt2, dt1, defaulttz)
+
+ return dt1.compareDateTime(dt2)
def differenceDateTime(start, end, defaulttz = None):
- return dateordatetime(end, defaultTZ=defaulttz) - dateordatetime(start)
-#def timeRangesOverlap(start1, end1, start2, end2, defaulttz = None):
-# def dodt(d):
-# if d is None:
-# return None
-# else:
-# return dateordatetime(d, defaulttz)
-#
-# dodt1 = timerange(dodt(start1), dodt(end1))
-# dodt2 = timerange(dodt(start2), dodt(end2))
-#
-# return dodt1.overlapsWith(dodt2)
+ if start.floating() and not end.floating():
+ start = adjustFloatingToTimezone(start, end, defaulttz)
+ elif end.floating() and not start.floating():
+ end = adjustFloatingToTimezone(end, start, defaulttz)
+ return end - start
+
def timeRangesOverlap(start1, end1, start2, end2, defaulttz = None):
- # Can't compare datetime.date and datetime.datetime objects, so normalize
- # to date if they are mixed.
- if isinstance(start1, datetime.datetime) and (start2 is not None) and not isinstance(start2, datetime.datetime): start1 = start1.date()
- if isinstance(start2, datetime.datetime) and (start1 is not None) and not isinstance(start1, datetime.datetime): start2 = start2.date()
- if isinstance(end1, datetime.datetime) and (end2 is not None) and not isinstance(end2, datetime.datetime): end1 = end1.date()
- if isinstance(end2, datetime.datetime) and (end1 is not None) and not isinstance(end1, datetime.datetime): end2 = end2.date()
+ # Can't compare date-time and date only, so normalize
+ # to date only if they are mixed.
+ if not start1.isDateOnly() and (start2 is not None) and start2.isDateOnly(): start1 = start1.setDateOnly(True)
+ if not start2.isDateOnly() and (start1 is not None) and start1.isDateOnly(): start2 = start2.setDateOnly(True)
+ if not end1.isDateOnly() and (end2 is not None) and end2.isDateOnly(): end1 = end1.setDateOnly(True)
+ if not end2.isDateOnly() and (end1 is not None) and end1.isDateOnly(): end2 = end2.setDateOnly(True)
# Note that start times are inclusive and end times are not.
if start1 is not None and start2 is not None:
@@ -133,26 +145,8 @@
else:
return False
-def periodEnd(p):
+def normalizePeriodList(periods):
"""
- Calculate the end datetime of the period. Since a period is a
- tuple consisting of a pair of L{datetime.datetime}'s, or one
- L{datetime.datetime} and one L{datetime.timedelta}, we may need
- to add the duration to the start to get the actual end.
- @param p: the period whose end is to be determined.
- @return: the L{datetime.datetime} for the end.
- """
- assert len(p) == 2, "Period is not a tuple of two items: %r" % (p,)
- assert isinstance(p[0], datetime.datetime), "Period start is not a datetime: %r" % (p,)
- assert isinstance(p[1], datetime.datetime) or isinstance(p[1], datetime.timedelta), "Period end is not a datetime or timedelta: %r" % (p,)
-
- if isinstance(p[1], datetime.timedelta):
- return p[0] + p[1]
- else:
- return p[1]
-
-def normalizePeriodList(list):
- """
Normalize the list of periods by merging overlapping or consecutive ranges
and sorting the list by each periods start.
@param list: a list of tuples of L{datetime.datetime} pairs. The list is changed in place.
@@ -169,47 +163,42 @@
@return: 1 if p1>p2, 0 if p1==p2, -1 if p1<p2
"""
- assert len(p1) == 2, "Period is not a tuple of two items: %r" % (p1,)
- assert isinstance(p1[0], datetime.datetime), "Period start is not a datetime: %r" % (p1,)
- assert isinstance(p1[1], datetime.datetime) or isinstance(p1[1], datetime.timedelta), "Period end is not a datetime or timedelta: %r" % (p1,)
+ assert isinstance(p1, PyCalendarPeriod), "Period is not a PyCalendarPeriod: %r" % (p1,)
+ assert isinstance(p2, PyCalendarPeriod), "Period is not a PyCalendarPeriod: %r" % (p2,)
- assert len(p2) == 2, "Period is not a tuple of two items: %r" % (p2,)
- assert isinstance(p2[0], datetime.datetime), "Period start is not a datetime: %r" % (p2,)
- assert isinstance(p2[1], datetime.datetime) or isinstance(p2[1], datetime.timedelta), "Period end is not a datetime or timedelta: %r" % (p2,)
-
- if p1[0] == p2[0]:
- cmp1 = periodEnd(p1)
- cmp2 = periodEnd(p2)
+ if p1.getStart() == p2.getStart():
+ cmp1 = p1.getEnd()
+ cmp2 = p2.getEnd()
else:
- cmp1 = p1[0]
- cmp2 = p2[0]
+ cmp1 = p1.getStart()
+ cmp2 = p2.getStart()
return compareDateTime(cmp1, cmp2)
- list.sort(cmp=sortPeriods)
+ periods.sort(cmp=sortPeriods)
# Now merge overlaps and consecutive periods
index = None
p = None
pe = None
- for i in xrange(len(list)):
+ for i in xrange(len(periods)):
if p is None:
index = i
- p = list[i]
- pe = periodEnd(p)
+ p = periods[i]
+ pe = p.getEnd()
continue
- ie = periodEnd(list[i])
- if (pe >= list[i][0]):
+ ie = periods[i].getEnd()
+ if (pe >= periods[i].getStart()):
if ie > pe:
- list[index] = (list[index][0], ie)
+ periods[index] = (periods[index].getStart(), ie)
pe = ie
- list[i] = None
+ periods[i] = None
else:
index = i
- p = list[i]
- pe = periodEnd(p)
- list[:] = [x for x in list if x]
+ p = periods[i]
+ pe =p.getEnd()
+ periods[:] = [x for x in periods if x]
def clipPeriod(period, clipPeriod):
"""
@@ -219,10 +208,10 @@
@return: the (start, end) tuple for the clipped period, or
None if the period is outside the clip period
"""
- start = period[0]
- end = periodEnd(period)
- clipStart = clipPeriod[0]
- clipEnd = periodEnd(clipPeriod)
+ start = period.getStart()
+ end = period.getEnd()
+ clipStart = clipPeriod.getStart()
+ clipEnd = clipPeriod.getEnd()
if start < clipStart:
start = clipStart
@@ -234,10 +223,9 @@
return None
else:
# Try to preserve use of duration in period
- if isinstance(period[1], datetime.timedelta):
- return (start, end - start)
- else:
- return (start, end)
+ result = PyCalendarPeriod(start, end)
+ result.setUseDuration(period.getUseDuration())
+ return result
def parseSQLTimestamp(ts):
Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/ical.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/ical.py 2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/ical.py 2011-03-01 20:28:29 UTC (rev 7090)
@@ -14,6 +14,16 @@
# limitations under the License.
##
+from pycalendar import definitions
+from pycalendar.attribute import PyCalendarAttribute
+from pycalendar.calendar import PyCalendar
+from pycalendar.componentbase import PyCalendarComponentBase
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.duration import PyCalendarDuration
+from pycalendar.period import PyCalendarPeriod
+from pycalendar.property import PyCalendarProperty
+from pycalendar.timezone import PyCalendarTimezone
+
"""
iCalendar Utilities
"""
@@ -24,26 +34,14 @@
"allowedComponents",
"Property",
"Component",
- "FixedOffset",
- "parse_date",
- "parse_time",
- "parse_datetime",
- "parse_date_or_datetime",
- "parse_duration",
"tzexpand",
]
import cStringIO as StringIO
-import datetime
import heapq
import itertools
-from vobject import newFromBehavior, readComponents
-from vobject.base import Component as vComponent, ContentLine as vContentLine, ParseError as vParseError
-from vobject.icalendar import TimezoneComponent, dateTimeToString, deltaToOffset, getTransition, stringToDate, stringToDateTime, stringToDurations, utc
-
from twext.python.log import Logger
-from twext.python.datetime import dateordatetime, timerange, asUTC, iCalendarString
from twext.web2.stream import IStream
from twext.web2.dav.util import allDataFromStream
@@ -81,7 +79,7 @@
"GEO": (None, {"VALUE": "FLOAT"}),
"LOCATION": (None, {"VALUE": "TEXT"}),
"PERCENT-COMPLETE": (None, {"VALUE": "INTEGER"}),
- "PRIORITY": ("0", {"VALUE": "INTEGER"}),
+ "PRIORITY": (0, {"VALUE": "INTEGER"}),
"RESOURCES": (None, {"VALUE": "TEXT"}),
"STATUS": (None, {"VALUE": "TEXT"}),
"SUMMARY": (None, {"VALUE": "TEXT"}),
@@ -116,12 +114,12 @@
"RDATE": (None, {"VALUE": "DATE-TIME"}),
"RRULE": (None, {"VALUE": "RECUR"}),
"ACTION": (None, {"VALUE": "TEXT"}),
- "REPEAT": ("0", {"VALUE": "INTEGER"}),
+ "REPEAT": (0, {"VALUE": "INTEGER"}),
"TRIGGER": (None, {"VALUE": "DURATION"}),
"CREATED": (None, {"VALUE": "DATE-TIME"}),
"DTSTAMP": (None, {"VALUE": "DATE-TIME"}),
"LAST-MODIFIED": (None, {"VALUE": "DATE-TIME"}),
- "SEQUENCE": ("0", {"VALUE": "INTEGER"}),
+ "SEQUENCE": (0, {"VALUE": "INTEGER"}),
"REQUEST-STATUS": (None, {"VALUE": "TEXT"}),
}
@@ -151,18 +149,19 @@
assert value is None
assert params is None
- vobj = kwargs["vobject"]
+ pyobj = kwargs["pycalendar"]
- if not isinstance(vobj, vContentLine):
- raise TypeError("Not a vContentLine: %r" % (property,))
+ if not isinstance(pyobj, PyCalendarProperty):
+ raise TypeError("Not a PyCalendarProperty: %r" % (property,))
- self._vobject = vobj
+ self._pycalendar = pyobj
else:
- # Convert params dictionary to list of lists format used by vobject
- lparams = [[key] + lvalue for key, lvalue in params.items()]
- self._vobject = vContentLine(name, lparams, value, isNative=True)
+ # Convert params dictionary to list of lists format used by pycalendar
+ self._pycalendar = PyCalendarProperty(name, value)
+ for attrname, attrvalue in params.items():
+ self._pycalendar.addAttribute(PyCalendarAttribute(attrname, attrvalue))
- def __str__ (self): return self._vobject.serialize()
+ def __str__ (self): return str(self._pycalendar)
def __repr__(self): return "<%s: %r: %r>" % (self.__class__.__name__, self.name(), self.value())
def __hash__(self):
@@ -171,7 +170,7 @@
def __ne__(self, other): return not self.__eq__(other)
def __eq__(self, other):
if not isinstance(other, Property): return False
- return self.name() == other.name() and self.value() == other.value() and self.params() == other.params()
+ return self._pycalendar == other._pycalendar
def __gt__(self, other): return not (self.__eq__(other) or self.__lt__(other))
def __lt__(self, other):
@@ -186,11 +185,11 @@
def __ge__(self, other): return self.__eq__(other) or self.__gt__(other)
def __le__(self, other): return self.__eq__(other) or self.__lt__(other)
- def name (self): return self._vobject.name
+ def name (self): return self._pycalendar.getName()
- def value (self): return self._vobject.value
+ def value (self): return self._pycalendar.getValue().getValue()
def setValue(self, value):
- self._vobject.value = value
+ self._pycalendar.setValue(value)
def params(self):
"""
@@ -199,20 +198,38 @@
Keys are parameter names, values are sequences containing
values for the named parameter.
"""
- return self._vobject.params
+ result = {}
+ for pyattrlist in self._pycalendar.getAttributes().values():
+ for pyattr in pyattrlist:
+ result.setdefault(pyattr.getName(), []).extend(pyattr.getValues())
+ return result
def paramValue(self, name):
"""
Returns a single value for the given parameter. Raises
InvalidICalendarDataError if the parameter has more than one value.
"""
- values = self._vobject.params.get(name, [None,])
- assert type(values) is list, "vobject returned non-list value for parameter %r in property %r" % (name, self)
- if len(values) != 1:
- raise InvalidICalendarDataError("Not exactly one %s value in property %r" % (name, self))
- return values[0]
+ try:
+ return self._pycalendar.getAttributeValue(name)
+ except KeyError:
+ return None
- def containsTimeRange(self, start, end, tzinfo=None):
+ def setParameter(self, paramname, paramvalue):
+ self._pycalendar.replaceAttribute(PyCalendarAttribute(paramname, paramvalue))
+
+ def removeParameter(self, paramname):
+ self._pycalendar.removeAttributes(paramname)
+
+ def removeParameterValue(self, paramname, paramvalue):
+
+ for attr in tuple(self._pycalendar.getAttributes()):
+ if attr.getName() == paramname:
+ for value in attr.getValues():
+ if value == paramvalue:
+ if not attr.removeValue(value):
+ self._pycalendar.removeAttributes(paramname)
+
+ def containsTimeRange(self, start, end, defaulttz=None):
"""
Determines whether this property contains a date/date-time within the specified
start/end period.
@@ -223,7 +240,7 @@
@param end: a L{datetime.datetime} or L{datetime.date} specifying the
end of the given time span. C{end} may be None, indicating that
there is no end date.
- @param tzinfo: the default L{datetime.tzinfo} to use in datetime comparisons.
+ @param defaulttz: the default L{PyTimezone} to use in datetime comparisons.
@return: True if the property's date/date-time value is within the given time range,
False if not, or the property is not an appropriate date/date-time value.
"""
@@ -234,24 +251,11 @@
return False
# get date/date-time value
- dt = self.value()
- assert isinstance(dt, datetime.date), "Not a date/date-time value: %r" % (self,)
+ dt = self.getDateTimeValue().getValue()
+ assert isinstance(dt, PyCalendarDateTime), "Not a date/date-time value: %r" % (self,)
- return timeRangesOverlap(dt, None, start, end, tzinfo)
+ return timeRangesOverlap(dt, None, start, end, defaulttz)
- def transformAllFromNative(self):
- transformed = self._vobject.isNative
- if transformed:
- self._vobject = self._vobject.transformFromNative()
- self._vobject.transformChildrenFromNative()
- return transformed
-
- def transformAllToNative(self):
- transformed = not self._vobject.isNative
- if transformed:
- self._vobject = self._vobject.transformToNative()
- self._vobject.transformChildrenToNative()
- return transformed
class Component (object):
"""
@@ -302,15 +306,12 @@
@return: a L{Component} representing the first component described by
C{stream}.
"""
- try:
- return clazz(None, vobject=readComponents(stream, findBegin=False).next())
- except UnicodeDecodeError, e:
+ cal = PyCalendar()
+ result = cal.parse(stream)
+ if not result:
stream.seek(0)
- raise InvalidICalendarDataError("%s: %s" % (e, stream.read()))
- except vParseError, e:
- raise InvalidICalendarDataError(e)
- except StopIteration, e:
- raise InvalidICalendarDataError(e)
+ raise InvalidICalendarDataError("%s" % (stream.read(),))
+ return clazz(None, pycalendar=cal)
@classmethod
def fromIStream(clazz, stream):
@@ -338,14 +339,14 @@
component.
"""
if name is None:
- if "vobject" in kwargs:
- vobj = kwargs["vobject"]
+ if "pycalendar" in kwargs:
+ pyobj = kwargs["pycalendar"]
- if vobj is not None:
- if not isinstance(vobj, vComponent):
- raise TypeError("Not a vComponent: %r" % (vobj,))
+ if pyobj is not None:
+ if not isinstance(pyobj, PyCalendarComponentBase):
+ raise TypeError("Not a PyCalendarComponentBase: %r" % (pyobj,))
- self._vobject = vobj
+ self._pycalendar = pyobj
else:
raise AssertionError("name may not be None")
@@ -362,59 +363,38 @@
else:
self._parent = None
else:
- self._vobject = newFromBehavior(name)
+ # FIXME: figure out creating an arbitrary component
+ raise NotImplementedError
+ self._pycalendar = PyCalendar.makeComponent(name)
self._parent = None
- def __str__ (self): return self._vobject.serialize()
- def __repr__(self): return "<%s: %r>" % (self.__class__.__name__, str(self._vobject))
+ def __str__ (self):
+ return str(self._pycalendar)
+ def __repr__(self):
+ return "<%s: %r>" % (self.__class__.__name__, str(self._pycalendar))
+
def __hash__(self):
return hash(str(self))
- def __ne__(self, other): return not self.__eq__(other)
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
def __eq__(self, other):
if not isinstance(other, Component):
return False
+ return self._pycalendar == other._pycalendar
- my_properties = set(self.properties())
- for property in other.properties():
- if property in my_properties:
- my_properties.remove(property)
- else:
- return False
- if my_properties:
- return False
-
- my_subcomponents = set(self.subcomponents())
- for subcomponent in other.subcomponents():
- for testcomponent in my_subcomponents:
- if subcomponent == testcomponent:
- my_subcomponents.remove(testcomponent)
- break
- else:
- return False
- if my_subcomponents:
- return False
-
- return True
-
# FIXME: Should this not be in __eq__?
def same(self, other):
- return self._vobject == other._vobject
+ return self._pycalendar == other._pycalendar
def name(self):
"""
@return: the name of the iCalendar type of this component.
"""
- return self._vobject.name
+ return self._pycalendar.getType()
- def setBehavior(self, behavior):
- """
- Set the behavior of the underlying iCal object.
- @param behavior: the behavior type to set.
- """
- self._vobject.setBehavior(behavior)
-
def mainType(self):
"""
Determine the primary type of iCal component in this calendar.
@@ -483,13 +463,13 @@
assert self.name() == "VCALENDAR", "Must be a VCALENDAR: %r" % (self,)
if isinstance(recurrence_id, str):
- recurrence_id = parse_date_or_datetime(recurrence_id) if recurrence_id else None
+ recurrence_id = PyCalendarDateTime.parseText(recurrence_id) if recurrence_id else None
for component in self.subcomponents():
if component.name() in ignoredComponents:
continue
rid = component.getRecurrenceIDUTC()
- if rid and recurrence_id and dateordatetime(rid) == recurrence_id:
+ if rid and recurrence_id and rid == recurrence_id:
return component
elif rid is None and recurrence_id is None:
return component
@@ -513,7 +493,7 @@
Duplicate this object and all its contents.
@return: the duplicated calendar.
"""
- return Component(None, vobject=vComponent.duplicate(self._vobject))
+ return Component(None, pycalendar=self._pycalendar.duplicate())
def subcomponents(self):
"""
@@ -521,9 +501,8 @@
of this component.
"""
return (
- Component(None, vobject=c, parent=self)
- for c in self._vobject.getChildren()
- if isinstance(c, vComponent)
+ Component(None, pycalendar=c, parent=self)
+ for c in self._pycalendar.getAllComponents()
)
def addComponent(self, component):
@@ -532,7 +511,7 @@
@param component: the L{Component} to add as a subcomponent of this
component.
"""
- self._vobject.add(component._vobject)
+ self._pycalendar.addComponent(component._pycalendar)
component._parent = self
def removeComponent(self, component):
@@ -540,17 +519,14 @@
Removes a subcomponent from this component.
@param component: the L{Component} to remove.
"""
- self._vobject.remove(component._vobject)
+ self._pycalendar.removeComponent(component._pycalendar)
def hasProperty(self, name):
"""
@param name: the name of the property whose existence is being tested.
@return: True if the named property exists, False otherwise.
"""
- try:
- return len(self._vobject.contents[name.lower()]) > 0
- except KeyError:
- return False
+ return self._pycalendar.hasProperty(name)
def getProperty(self, name):
"""
@@ -571,18 +547,15 @@
@return: an iterable of L{Property} objects, one for each property of
this component.
"""
+ properties = []
if name is None:
- properties = self._vobject.getChildren()
- else:
- try:
- properties = self._vobject.contents[name.lower()]
- except KeyError:
- return ()
+ [properties.extend(i) for i in self._pycalendar.getProperties().values()]
+ elif self._pycalendar.countProperty(name) > 0:
+ properties = self._pycalendar.getProperties()[name]
return (
- Property(None, None, None, vobject=p)
+ Property(None, None, None, pycalendar=p)
for p in properties
- if isinstance(p, vContentLine)
)
def propertyValue(self, name):
@@ -594,30 +567,6 @@
return None
- def propertyNativeValue(self, name):
- """
- Return the native property value for the named property in the supplied component.
- NB Assumes a single property exists in the component.
- @param name: the name of the property whose value is required
- @return: the native property value
- """
- properties = tuple(self.properties(name))
-
- if len(properties) == 1:
- transormed = properties[0].transformAllToNative()
-
- result = properties[0].value()
-
- if transormed:
- properties[0].transformAllFromNative()
-
- return result
-
- elif len(properties) > 1:
- raise InvalidICalendarDataError("More than one %s property in component %r" % (name, self))
- else:
- return None
-
def getStartDateUTC(self):
"""
Return the start date or date-time for the specified component
@@ -625,11 +574,8 @@
@param component: the Component whose start should be returned.
@return: the datetime.date or datetime.datetime for the start.
"""
- dtstart = self.propertyNativeValue("DTSTART")
- if dtstart is not None:
- return asUTC(dtstart)
- else:
- return None
+ dtstart = self.propertyValue("DTSTART")
+ return dtstart.duplicateAsUTC() if dtstart is not None else None
def getEndDateUTC(self):
"""
@@ -639,17 +585,14 @@
@param component: the Component whose end should be returned.
@return: the datetime.date or datetime.datetime for the end.
"""
- dtend = self.propertyNativeValue("DTEND")
+ dtend = self.propertyValue("DTEND")
if dtend is None:
- dtstart = self.propertyNativeValue("DTSTART")
- duration = self.propertyNativeValue("DURATION")
+ dtstart = self.propertyValue("DTSTART")
+ duration = self.propertyValue("DURATION")
if duration is not None:
dtend = dtstart + duration
- if dtend is not None:
- return asUTC(dtend)
- else:
- return None
+ return dtend.duplicateAsUTC() if dtend is not None else None
def getDueDateUTC(self):
"""
@@ -658,17 +601,14 @@
@param component: the Component whose start should be returned.
@return: the datetime.date or datetime.datetime for the start.
"""
- due = self.propertyNativeValue("DUE")
+ due = self.propertyValue("DUE")
if due is None:
- dtstart = self.propertyNativeValue("DTSTART")
- duration = self.propertyNativeValue("DURATION")
+ dtstart = self.propertyValue("DTSTART")
+ duration = self.propertyValue("DURATION")
if dtstart is not None and duration is not None:
due = dtstart + duration
- if due is not None:
- return asUTC(due)
- else:
- return None
+ return due.duplicateAsUTC() if due is not None else None
def getRecurrenceIDUTC(self):
"""
@@ -676,12 +616,8 @@
@param component: the Component whose r-id should be returned.
@return: the datetime.date or datetime.datetime for the r-id.
"""
- rid = self.propertyNativeValue("RECURRENCE-ID")
-
- if rid is not None:
- return asUTC(rid)
- else:
- return None
+ rid = self.propertyValue("RECURRENCE-ID")
+ return rid.duplicateAsUTC() if rid is not None else None
def getRange(self):
"""
@@ -710,7 +646,7 @@
assert self.name() == "VALARM", "Component is not a VAlARM: %r" % (self,)
# The trigger value
- trigger = self.propertyNativeValue("TRIGGER")
+ trigger = self.propertyValue("TRIGGER")
if trigger is None:
raise InvalidICalendarDataError("VALARM has no TRIGGER property: %r" % (self,))
@@ -722,26 +658,21 @@
related = (related == "START")
# Repeat property
- repeat = self.propertyNativeValue("REPEAT")
+ repeat = self.propertyValue("REPEAT")
if repeat is None: repeat = 0
else: repeat = int(repeat)
# Duration property
- duration = self.propertyNativeValue("DURATION")
+ duration = self.propertyValue("DURATION")
if repeat > 0 and duration is None:
raise InvalidICalendarDataError("VALARM has invalid REPEAT/DURATIOn properties: %r" % (self,))
return (trigger, related, repeat, duration)
- def getRRuleSet(self, addRDate = False):
- self.transformAllToNative()
- return self._vobject.getrruleset(addRDate)
+ def getRecurrenceSet(self):
+ return self._pycalendar.getRecurrenceSet()
- def setRRuleSet(self, rruleset):
- #self.transformAllToNative()
- return self._vobject.setrruleset(rruleset)
-
def getEffectiveStartEnd(self):
# Get the start/end range needed for instance comparisons
@@ -777,14 +708,14 @@
Adds a property to this component.
@param property: the L{Property} to add to this component.
"""
- self._vobject.add(property._vobject)
+ self._pycalendar.addProperty(property._pycalendar)
def removeProperty(self, property):
"""
Remove a property from this component.
@param property: the L{Property} to remove from this component.
"""
- self._vobject.remove(property._vobject)
+ self._pycalendar.removeProperty(property._pycalendar)
def replaceProperty(self, property):
"""
@@ -793,8 +724,7 @@
"""
# Remove all existing ones first
- for removeit in tuple(self.properties(property.name())):
- self.removeProperty(removeit)
+ self._pycalendar.removeProperties(property.name())
self.addProperty(property)
def timezoneIDs(self):
@@ -806,20 +736,10 @@
result = set()
for property in self.properties():
- for propertyname in ("TZID", "X-VOBJ-ORIGINAL-TZID"):
- tzid = property.paramValue(propertyname)
- if tzid is not None:
- result.add(tzid)
- break
- else:
- items = property.value()
- if type(items) is not list:
- items = [items]
- for item in items:
- tzinfo = getattr(item, 'tzinfo', None)
- tzid = TimezoneComponent.pickTzid(tzinfo)
- if tzid is not None:
- result.add(tzid)
+ tzid = property.paramValue("TZID")
+ if tzid is not None:
+ result.add(tzid)
+ break
return result
@@ -848,47 +768,48 @@
@type maximumCount: C{int}
@return: a C{bool} indicating whether a change was made or not
"""
-
+
changed = False
master = self.masterComponent()
if master and master.isRecurring():
- rrules = master.getRRuleSet()
+ rrules = master._pycalendar.getRecurrenceSet()
if rrules:
- for rrule in rrules._rrule:
- if rrule._count is not None:
+ for rrule in rrules.getRules():
+ if rrule.getUseCount():
# Make sure COUNT is less than the limit
- if rrule._count > maximumCount:
- rrule._count = maximumCount
+ if rrule.getCount() > maximumCount:
+ rrule.setCount(maximumCount)
changed = True
- elif rrule._until is not None:
+ elif rrule.getUseUntil():
# Need to figure out how to determine number of instances
# with this UNTIL and truncate if needed
start = master.getStartDateUTC()
- diff = differenceDateTime(start, rrule._until)
- diff = diff.days * 24 * 60 * 60 + diff.seconds
+ diff = differenceDateTime(start, rrule.getUntil())
+ diff = diff.getDays() * 24 * 60 * 60 + diff.getSeconds()
period = {
- 0: 365 * 24 * 60 * 60,
- 1: 30 * 24 * 60 * 60,
- 2: 7 * 24 * 60 * 60,
- 3: 1 * 24 * 60 * 60,
- 4: 60 * 60,
- 5: 60,
- 6: 1
- }[rrule._freq] * rrule._interval
+ definitions.eRecurrence_YEARLY: 365 * 24 * 60 * 60,
+ definitions.eRecurrence_MONTHLY: 30 * 24 * 60 * 60,
+ definitions.eRecurrence_WEEKLY: 7 * 24 * 60 * 60,
+ definitions.eRecurrence_DAILY: 1 * 24 * 60 * 60,
+ definitions.eRecurrence_HOURLY: 60 * 60,
+ definitions.eRecurrence_MINUTELY: 60,
+ definitions.eRecurrence_SECONDLY: 1
+ }[rrule.getFreq()] * rrule.getInterval()
if diff / period > maximumCount:
- rrule._until = None
- rrule._count = maximumCount
+ rrule.setUseUntil(False)
+ rrule.setUseCount(True)
+ rrule.setCount(maximumCount)
+ rrules.changed()
changed = True
else:
# For frequencies other than yearly we will truncate at our limit
- if rrule._freq != 0:
- rrule._count = maximumCount
+ if rrule.getFreq() != definitions.eRecurrence_YEARLY:
+ rrule.setUseCount(True)
+ rrule.setCount(maximumCount)
+ rrules.changed()
changed = True
-
- if changed:
- master.setRRuleSet(rrules)
return changed
@@ -903,7 +824,7 @@
@return: the L{Component} for the new calendar with expanded instances.
"""
- tzinfo = timezone.gettzinfo() if timezone else None
+ pytz = PyCalendarTimezone(timezone.getID()) if timezone else None
# Create new calendar object with same properties as the original, but
# none of the originals sub-components
@@ -918,7 +839,7 @@
first = True
for key in instances:
instance = instances[key]
- if timeRangesOverlap(instance.start, instance.end, start, end, tzinfo):
+ if timeRangesOverlap(instance.start, instance.end, start, end, pytz):
calendar.addComponent(self.expandComponent(instance, first))
first = False
@@ -943,8 +864,8 @@
# Convert all datetime properties to UTC unless they are floating
for property in newcomp.properties():
value = property.value()
- if isinstance(value, datetime.datetime) and value.tzinfo is not None:
- property.setValue(value.astimezone(utc))
+ if isinstance(value, PyCalendarDateTime) and value.local():
+ property.setValue(value.duplicateAsUTC())
# Now reset DTSTART, DTEND/DURATION
for property in newcomp.properties("DTSTART"):
@@ -1056,8 +977,7 @@
if master:
rrules = master.properties("RRULE")
for rrule in rrules:
- s = str(rrule)
- if "COUNT" not in s and "UNTIL" not in s:
+ if not rrule.value().getUseCount() and not rrule.value().getUseUntil():
return True
return False
@@ -1086,6 +1006,7 @@
didCancel = False
for exdate in tuple(master.properties("EXDATE")):
for exdateValue in exdate.value():
+ exdateValue = exdateValue.getValue()
if exdateValue == rid:
if allowCancelled:
exdate.value().remove(exdateValue)
@@ -1104,13 +1025,13 @@
# Check whether recurrence-id matches an RDATE - if so it is OK
rdates = set()
for rdate in master.properties("RDATE"):
- rdates.update([asUTC(item) for item in rdate.value()])
+ rdates.update([item.getValue().duplicateAsUTC() for item in rdate.value()])
if rid not in rdates:
# Check whether we have a truncated RRULE
rrules = master.properties("RRULE")
if len(tuple(rrules)):
- limit = rid
- limit += datetime.timedelta(days=365)
+ limit = rid.duplicate()
+ limit += PyCalendarDuration(days=365)
instances = self.cacheExpandedTimeRanges(limit)
rids = set([instances[key].rid for key in instances])
instance_rid = normalizeForIndex(rid)
@@ -1135,23 +1056,16 @@
if newcomp.hasProperty("DTEND"):
dtend = newcomp.getProperty("DTEND")
oldduration = dtend.value() - dtstart.value()
+
+ newdtstartValue = rid.duplicate()
+ if dtstart.value().local():
+ newdtstartValue.adjustTimezone(dtstart.value().getTimezone())
- if isinstance(dtstart.value(), datetime.datetime):
- if dtstart.value().tzinfo:
- newdtstartValue = rid.astimezone(dtstart.value().tzinfo)
- else:
- newdtstartValue = rid
- else:
- newdtstartValue = datetime.date.fromordinal(rid.toordinal())
-
dtstart.setValue(newdtstartValue)
if newcomp.hasProperty("DTEND"):
dtend.setValue(newdtstartValue + oldduration)
- try:
- rid_params = {"X-VOBJ-ORIGINAL-TZID":dtstart.params()["X-VOBJ-ORIGINAL-TZID"]}
- except KeyError:
- rid_params = {}
+ rid_params = {}
newcomp.addProperty(Property("RECURRENCE-ID", dtstart.value(), params=rid_params))
if didCancel:
@@ -1173,7 +1087,7 @@
non_master_rids = [rid for rid in rids if rid is not None]
if non_master_rids:
highest_rid = max(non_master_rids)
- self.cacheExpandedTimeRanges(highest_rid + datetime.timedelta(days=1))
+ self.cacheExpandedTimeRanges(highest_rid + PyCalendarDuration(days=1))
for rid in rids:
if self.validInstance(rid, clear_cache=False):
valid.add(rid)
@@ -1200,7 +1114,7 @@
return False
# Get expansion
- instances = self.cacheExpandedTimeRanges(rid + datetime.timedelta(days=1))
+ instances = self.cacheExpandedTimeRanges(rid + PyCalendarDuration(days=1))
new_rids = set([instances[key].rid for key in instances])
return rid in new_rids
@@ -1375,28 +1289,23 @@
# If they're not both date or both date-time, raise error
if (subcomponent.hasProperty("DTSTART") and
subcomponent.hasProperty("RRULE")):
- dtValue = subcomponent.propertyNativeValue("DTSTART")
- dtType = type(dtValue)
+ dtValue = subcomponent.propertyValue("DTSTART")
+ dtutc = dtValue.duplicateAsUTC()
# Using properties("RRULE") rather than getRRuleSet() here
# because the dateutil rrule's _until values are datetime
# even if the UNTIL is a date (and therefore we can't
# check validity without doing the following):
- for rrule in subcomponent.properties("RRULE"):
- indexedTokens = {}
- indexedTokens.update([valuePart.split("=")
- for valuePart in rrule.value().split(";")])
- until = indexedTokens.get("UNTIL", None)
- if until:
- untilType = datetime.date if len(until) == 8 else datetime.datetime
- if untilType is not dtType:
+ rrules = subcomponent._pycalendar.getRecurrenceSet()
+ for rrule in rrules.getRules():
+ if rrule.getUseUntil():
+ if rrule.getUntil().isDateOnly() ^ dtValue.isDateOnly():
msg = "Calendar resources must have matching type for DTSTART and UNTIL"
log.debug(msg)
if fix:
- rrules = subcomponent.getRRuleSet()
- if rrules:
- log.debug("Fixing mismatch")
- # vobject fixes DTSTART/UNTIL mismatches
- subcomponent.setRRuleSet(rrules)
+ log.debug("Fixing mismatch")
+ rrule.getUntil().setDateOnly(dtValue.isDateOnly())
+ rrule.getUntil().setHHMMSS(dtutc.getHours(), dtutc.getMinutes(), dtutc.getSeconds())
+ rrules.changed()
else:
raise InvalidICalendarDataError(msg)
@@ -1461,31 +1370,6 @@
return foundOrganizer
- def transformAllFromNative(self):
- self._vobject = self._vobject.transformFromNative()
- self._vobject.transformChildrenFromNative(False)
-
- def transformAllToNative(self):
- self._vobject = self._vobject.transformToNative()
- self._vobject.transformChildrenToNative()
-
- def gettzinfo(self):
- """
- Get the tzinfo for a Timezone component.
-
- @return: L{datetime.tzinfo} if this is a VTIMEZONE, otherwise None.
- """
- if self.name() == "VTIMEZONE":
- return self._vobject.gettzinfo()
- elif self.name() == "VCALENDAR":
- for component in self.subcomponents():
- if component.name() == "VTIMEZONE":
- return component.gettzinfo()
- else:
- return None
- else:
- return None
-
##
# iTIP stuff
##
@@ -1779,7 +1663,7 @@
continue
for property in component.properties(propname):
if propvalue is None or property.value() == propvalue:
- property.params()[paramname] = [paramvalue]
+ property.setParameter(paramname, paramvalue)
def hasPropertyInAnyComponent(self, properties):
"""
@@ -1988,7 +1872,7 @@
remaining -= 1
continue
rid = component.getRecurrenceIDUTC()
- if (iCalendarString(rid) if rid else "") not in rids:
+ if (rid.getText() if rid else "") not in rids:
self.removeComponent(component)
remaining -= 1
@@ -2064,7 +1948,7 @@
elif not xpname and remove_x_parameters:
for paramname in tuple(p.params()):
if paramname.startswith("X-"):
- del p.params()[paramname]
+ p.removeParameter(paramname)
def removePropertyParameters(self, property, params):
"""
@@ -2080,10 +1964,7 @@
props = self.properties(property)
for prop in props:
for param in params:
- try:
- del prop.params()[param]
- except KeyError:
- pass
+ prop.removeParameter(param)
def removePropertyParametersByValue(self, property, paramvalues):
"""
@@ -2099,14 +1980,7 @@
props = self.properties(property)
for prop in props:
for param, value in paramvalues:
- try:
- prop.params()[param].remove(value)
- if len(prop.params()[param]) == 0:
- del prop.params()[param]
- except KeyError:
- pass
- except InvalidICalendarDataError:
- pass
+ prop.removeParameterValue(param, value)
def normalizeAll(self):
@@ -2123,7 +1997,7 @@
# Remove any default parameters
for name, value in prop.params().items():
if value == [default_params.get(name),]:
- del prop.params()[name]
+ prop.removeParameter(name)
# If there are no parameters, remove the property if it has the default value
if len(prop.params()) == 0:
@@ -2162,48 +2036,35 @@
dtend = self.getProperty("DTEND")
duration = self.getProperty("DURATION")
- timeRange = timerange(
+ timeRange = PyCalendarPeriod(
start = dtstart.value(),
end = dtend.value() if dtend is not None else None,
duration = duration.value() if duration is not None else None,
)
- dtstart.setValue(timeRange.start().asUTC().dateOrDatetime())
- if "X-VOBJ-ORIGINAL-TZID" in dtstart.params():
- dtstart.params()["ORIGINAL-TZID"] = dtstart.params()["X-VOBJ-ORIGINAL-TZID"]
- del dtstart.params()["X-VOBJ-ORIGINAL-TZID"]
+ dtstart.setValue(timeRange.getStart().duplicateAsUTC())
if dtend is not None:
- dtend.setValue(timeRange.end().asUTC().dateOrDatetime())
- if "X-VOBJ-ORIGINAL-TZID" in dtend.params():
- dtend.params()["ORIGINAL-TZID"] = dtend.params()["X-VOBJ-ORIGINAL-TZID"]
- del dtend.params()["X-VOBJ-ORIGINAL-TZID"]
+ dtend.setValue(timeRange.getEnd().duplicateAsUTC())
elif duration is not None:
self.removeProperty(duration)
- self.addProperty(Property("DTEND", timeRange.end().asUTC().dateOrDatetime()))
+ self.addProperty(Property("DTEND", timeRange.getEnd().duplicateAsUTC()))
exdates = self.properties("EXDATE")
for exdate in exdates:
- exdate.setValue([asUTC(value) for value in exdate.value()])
- try:
- del exdate.params()["TZID"]
- except KeyError:
- pass
+ exdate.setValue([value.duplicateAsUTC() for value in exdate.value()])
+ exdate.removeParameter("TZID")
rid = self.getProperty("RECURRENCE-ID")
if rid is not None:
- rid.setValue(asUTC(rid.value()))
- try:
- del rid.params()["TZID"]
- except KeyError:
- pass
+ rid.setValue(rid.value().duplicateAsUTC())
+ rid.removeProperty("TZID")
# Recurrence rules - we need to normalize the order of the value parts
- rrules = self.properties("RRULE")
- for rrule in rrules:
- indexedTokens = {}
- indexedTokens.update([valuePart.split("=") for valuePart in rrule.value().split(";")])
- sortedValue = ";".join(["%s=%s" % (key, value,) for key, value in sorted(indexedTokens.iteritems(), key=lambda x:x[0])])
- rrule.setValue(sortedValue)
+# for rrule in self._pycalendar.getRecurrenceSet().getRules():
+# indexedTokens = {}
+# indexedTokens.update([valuePart.split("=") for valuePart in rrule.value().split(";")])
+# sortedValue = ";".join(["%s=%s" % (key, value,) for key, value in sorted(indexedTokens.iteritems(), key=lambda x:x[0])])
+# rrule.setValue(sortedValue)
def normalizePropertyValueLists(self, propname):
"""
@@ -2267,7 +2128,7 @@
continue
# Get any EMAIL parameter
- oldemail = prop.params().get("EMAIL", (None,))[0]
+ oldemail = prop.paramsValue("EMAIL")
if oldemail:
oldemail = "mailto:%s" % (oldemail,)
@@ -2310,12 +2171,9 @@
# Always re-write the CN parameter
if name:
- prop.params()["CN"] = [name,]
+ prop.setParameter("CN", name)
else:
- try:
- del prop.params()["CN"]
- except KeyError:
- pass
+ prop.removeParameter("CN")
# Re-write the EMAIL if its value no longer matches
if oldemail and oldemail not in cuaddrs or oldemail is None and toUUID:
@@ -2330,12 +2188,9 @@
email = None
if email:
- prop.params()["EMAIL"] = [email,]
+ prop.setParameter("EMAIL", email)
else:
- try:
- del prop.params()["EMAIL"]
- except KeyError:
- pass
+ prop.removeParameter("EMAIL")
def allPerUserUIDs(self):
@@ -2381,86 +2236,6 @@
return tuple(results)
##
-# Dates and date-times
-##
-
-class FixedOffset (datetime.tzinfo):
- """
- Fixed offset in minutes east from UTC.
- """
- def __init__(self, offset, name=None):
- self._offset = datetime.timedelta(minutes=offset)
- self._name = name
-
- def utcoffset(self, dt): return self._offset
- def tzname (self, dt): return self._name
- def dst (self, dt): return datetime.timedelta(0)
-
-def parse_date(date_string):
- """
- Parse an iCalendar-format DATE string. (RFC 2445, section 4.3.4)
- @param date_string: an iCalendar-format DATE string.
- @return: a L{datetime.date} object for the given C{date_string}.
- """
- try:
- return stringToDate(date_string)
- except (vParseError, InvalidICalendarDataError):
- raise InvalidICalendarDataError("Invalid iCalendar DATE: %r" % (date_string,))
-
-def parse_time(time_string):
- """
- Parse iCalendar-format TIME string. (RFC 2445, section 4.3.12)
- @param time_string: an iCalendar-format TIME string.
- @return: a L{datetime.time} object for the given C{time_string}.
- """
- try:
- # Parse this as a fake date-time string by prepending date
- with_date = "20000101T" + time_string
- return stringToDateTime(with_date).time()
- except (vParseError, InvalidICalendarDataError):
- raise InvalidICalendarDataError("Invalid iCalendar TIME: %r" % (time_string,))
-
-def parse_datetime(datetime_string):
- """
- Parse iCalendar-format DATE-TIME string. (RFC 2445, section 4.3.5)
- @param datetime_string: an iCalendar-format DATE-TIME string.
- @return: a L{datetime.datetime} object for the given C{datetime_string}.
- """
- try:
- return stringToDateTime(datetime_string)
- except (vParseError, InvalidICalendarDataError):
- raise InvalidICalendarDataError("Invalid iCalendar DATE-TIME: %r" % (datetime_string,))
-
-def parse_date_or_datetime(date_string):
- """
- Parse iCalendar-format DATE or DATE-TIME string. (RFC 2445, sections 4.3.4
- and 4.3.5)
- @param date_string: an iCalendar-format DATE or DATE-TIME string.
- @return: a L{datetime.date} or L{datetime.datetime} object for the given
- C{date_string}.
- """
- try:
- if len(date_string) == 8:
- return parse_date(date_string)
- else:
- return parse_datetime(date_string)
- except InvalidICalendarDataError:
- raise InvalidICalendarDataError("Invalid iCalendar DATE or DATE-TIME: %r" % (date_string,))
-
-def parse_duration(duration_string):
- """
- Parse iCalendar-format DURATION string. (RFC 2445, sections 4.3.6)
- @param duration_string: an iCalendar-format DURATION string.
- @return: a L{datetime.timedelta} object for the given C{duration_string}.
- """
- try:
- return stringToDurations(duration_string)[0]
- except (vParseError, InvalidICalendarDataError):
- raise InvalidICalendarDataError("Invalid iCalendar DURATION: %r" % (duration_string,))
-
-_regex_duration = None
-
-##
# Timezones
##
Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/instance.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/instance.py 2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/instance.py 2011-03-01 20:28:29 UTC (rev 7090)
@@ -13,19 +13,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.duration import PyCalendarDuration
+from pycalendar.period import PyCalendarPeriod
+from pycalendar.timezone import PyCalendarTimezone
"""
iCalendar Recurrence Expansion Utilities
"""
-import datetime
+from twistedcaldav.dateops import normalizeForIndex, differenceDateTime
-from vobject.icalendar import utc
-
-from twext.python.datetime import dateordatetime
-
-from twistedcaldav.dateops import normalizeForIndex, differenceDateTime, periodEnd
-
# The maximum number of instances we will expand out to.
# Raise a TooManyInstancesError exception if we exceed this.
max_allowed_instances = 1000
@@ -48,22 +46,11 @@
class Instance(object):
- __slots__ = ["component", "start", "end", "rid", "overridden", "future"]
-
def __init__(self, component, start = None, end = None, rid = None, overridden = False, future = False):
self.component = component
- if start is None:
- self.start = component.getStartDateUTC()
- else:
- self.start = start
- if end is None:
- self.end = component.getEndDateUTC()
- else:
- self.end = end
- if rid is None:
- self.rid = self.start
- else:
- self.rid = rid
+ self.start = component.getStartDateUTC() if start is None else start
+ self.end = component.getEndDateUTC() if end is None else end
+ self.rid = self.start if rid is None else rid
self.overridden = overridden
self.future = future
@@ -78,15 +65,12 @@
(trigger, related, repeat, duration) = alarm.getTriggerDetails()
# Handle relative vs absolute triggers
- if isinstance(trigger, datetime.date):
+ if isinstance(trigger, PyCalendarDateTime):
# Absolute trigger
start = trigger
else:
# Relative trigger
- if related:
- start = self.start + trigger
- else:
- start = self.end + trigger
+ start = (self.start if related else self.end) + trigger
triggers.add(start)
# Handle repeats
@@ -98,8 +82,6 @@
class InstanceList(object):
- __slots__ = ["instances", "limit", "ignoreInvalidInstances",]
-
def __init__(self, ignoreInvalidInstances=False):
self.instances = {}
self.limit = None
@@ -194,12 +176,12 @@
end = component.getEndDateUTC()
duration = None
if end is None:
- if isinstance(start, datetime.datetime):
+ if not start.isDateOnly():
# Timed event with zero duration
- duration = datetime.timedelta(days=0)
+ duration = PyCalendarDuration(days=0)
else:
# All day event default duration is one day
- duration = datetime.timedelta(days=1)
+ duration = PyCalendarDuration(days=1)
end = start + duration
else:
duration = differenceDateTime(start, end)
@@ -223,15 +205,13 @@
end = component.getEndDateUTC()
duration = None
if end is None:
- if isinstance(start, datetime.datetime):
+ if not start.isDateOnly():
# Timed event with zero duration
- duration = datetime.timedelta(days=0)
+ duration = PyCalendarDuration(days=0)
else:
# All day event default duration is one day
- duration = datetime.timedelta(days=1)
+ duration = PyCalendarDuration(days=1)
end = start + duration
- else:
- duration = differenceDateTime(start, end)
self._addOverrideComponent(component, limit, start, end, got_master)
@@ -280,34 +260,26 @@
self._addOverrideComponent(component, limit, start, due, got_master)
def _addMasterComponent(self, component, limit, start, end, duration):
- # Always add first instance if included in range.
- if dateordatetime(start) < limit:
- # dateutils does not do all-day - so convert to datetime.datetime
- start = normalizeForIndex(start)
- end = normalizeForIndex(end)
-
- # Do not add if in EXDATEs
- exdates = []
- for prop in component.properties("EXDATE"):
- exdates.extend(prop.value())
- exdates = [normalizeForIndex(exdate) for exdate in exdates]
- if start not in exdates:
- self.addInstance(Instance(component, start, end))
- else:
- self.limit = limit
- # Now expand recurrence
- # FIXME: Current Python implementation fails when RDATEs are PERIODs
- recur = component.getRRuleSet(True)
- if recur is not None:
- for startDate in recur:
- if dateordatetime(startDate) >= limit:
- self.limit = limit
- break
- endDate = startDate + duration
+ rrules = component.getRecurrenceSet()
+ if rrules is not None:
+ # Do recurrence set expansion
+ expanded = []
+ limited = rrules.expand(start, PyCalendarPeriod(start, limit), expanded)
+ for startDate in expanded:
startDate = normalizeForIndex(startDate)
- endDate = normalizeForIndex(endDate)
+ endDate = startDate + duration
self.addInstance(Instance(component, startDate, endDate))
+ if limited:
+ self.limit = limit
+ else:
+ # Always add main instance if included in range.
+ if start < limit:
+ start = normalizeForIndex(start)
+ end = normalizeForIndex(end)
+ self.addInstance(Instance(component, start, end))
+ else:
+ self.limit = limit
def _addOverrideComponent(self, component, limit, start, end, got_master):
@@ -321,12 +293,12 @@
rid = normalizeForIndex(rid)
# Make sure start is within the limit
- if dateordatetime(start) > limit and dateordatetime(rid) > limit:
+ if start > limit and rid > limit:
return
# Make sure override RECURRENCE-ID is a valid instance of the master
if got_master:
- if str(rid) not in self.instances and dateordatetime(rid) < limit:
+ if str(rid) not in self.instances and rid < limit:
if self.ignoreInvalidInstances:
return
else:
@@ -375,7 +347,7 @@
"""
start = component.getStartDateUTC()
- if start is not None and dateordatetime(start) >= limit:
+ if start is not None and start >= limit:
# If the free busy is beyond the end of the range we want, ignore it
return
@@ -389,10 +361,10 @@
assert isinstance(fb.value(), list), "FREEBUSY property does not contain a list of values: %r" % (fb,)
for period in fb.value():
# Ignore if period starts after limit
- if dateordatetime(period[0]) >= limit:
+ if period.getStart() >= limit:
continue
- start = normalizeForIndex(period[0])
- end = normalizeForIndex(periodEnd(period))
+ start = normalizeForIndex(period.getStart())
+ end = normalizeForIndex(period.getEnd())
self.addInstance(Instance(component, start, end))
def _addAvailabilityComponent(self, component, limit):
@@ -407,16 +379,16 @@
"""
start = component.getStartDateUTC()
- if start is not None and dateordatetime(start) >= limit:
+ if start is not None and start >= limit:
# If the free busy is beyond the end of the range we want, ignore it
return
if start is None:
- start = datetime.datetime(1900, 1, 1, 0, 0, 0, tzinfo=utc)
+ start = PyCalendarDateTime(1900, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
start = normalizeForIndex(start)
end = component.getEndDateUTC()
if end is None:
- end = datetime.datetime(3000, 1, 1, 0, 0, 0, tzinfo=utc)
+ end = PyCalendarDateTime(2100, 1, 1, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))
end = normalizeForIndex(end)
self.addInstance(Instance(component, start, end))
Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/query/calendarqueryfilter.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/query/calendarqueryfilter.py 2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/query/calendarqueryfilter.py 2011-03-01 20:28:29 UTC (rev 7090)
@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
+from pycalendar.datetime import PyCalendarDateTime
"""
Object model of CALDAV:filter element used in a calendar-query.
@@ -26,7 +27,7 @@
from twistedcaldav.caldavxml import caldav_namespace, CalDAVTimeZoneElement
from twistedcaldav.dateops import timeRangesOverlap
-from twistedcaldav.ical import Component, Property, parse_date_or_datetime
+from twistedcaldav.ical import Component, Property
from vobject.icalendar import utc
import datetime
@@ -552,8 +553,8 @@
if "start" not in xml_element.attributes and "end" not in xml_element.attributes:
raise ValueError("One of 'start' or 'end' must be present in CALDAV:time-range")
- self.start = parse_date_or_datetime(xml_element.attributes["start"]) if "start" in xml_element.attributes else None
- self.end = parse_date_or_datetime(xml_element.attributes["end"]) if "end" in xml_element.attributes else None
+ self.start = PyCalendarDateTime.parseText(xml_element.attributes["start"]) if "start" in xml_element.attributes else None
+ self.end = PyCalendarDateTime.parseText(xml_element.attributes["end"]) if "end" in xml_element.attributes else None
self.tzinfo = None
def settzinfo(self, tzinfo):
Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/icaldiff.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/icaldiff.py 2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/icaldiff.py 2011-03-01 20:28:29 UTC (rev 7090)
@@ -15,7 +15,7 @@
##
from twext.python.log import Logger
-from twext.python.datetime import timerange, asUTC, iCalendarString
+#from twext.python.datetime import timerange, asUTC, iCalendarString
from twistedcaldav.config import config
from twistedcaldav.ical import Component, Property
Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/itip.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/itip.py 2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/scheduling/itip.py 2011-03-01 20:28:29 UTC (rev 7090)
@@ -36,7 +36,7 @@
from vobject.icalendar import dateTimeToString
from twext.python.log import Logger
-from twext.python.datetime import asUTC, iCalendarString
+#from twext.python.datetime import asUTC, iCalendarString
from twistedcaldav.config import config
from twistedcaldav.ical import Property, iCalendarProductID, Component
Modified: CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/test/test_icalendar.py
===================================================================
--- CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/test/test_icalendar.py 2011-03-01 19:36:06 UTC (rev 7089)
+++ CalendarServer/branches/users/cdaboo/pycalendar/twistedcaldav/test/test_icalendar.py 2011-03-01 20:28:29 UTC (rev 7090)
@@ -15,19 +15,18 @@
##
import os
-import datetime
-from dateutil.tz import tzutc
from difflib import unified_diff
import itertools
from twisted.trial.unittest import SkipTest
-from twistedcaldav.ical import Component, parse_date, parse_datetime,\
- parse_date_or_datetime, parse_duration, Property, InvalidICalendarDataError
+from twistedcaldav.ical import Component, Property, InvalidICalendarDataError
from twistedcaldav.instance import InvalidOverriddenInstanceError
import twistedcaldav.test.util
-from vobject.icalendar import utc
+from pycalendar.datetime import PyCalendarDateTime
+from pycalendar.timezone import PyCalendarTimezone
+from pycalendar.duration import PyCalendarDuration
class iCalendar (twistedcaldav.test.util.TestCase):
"""
@@ -186,13 +185,13 @@
year = 2004
- instances = calendar.expandTimeRanges(datetime.date(2100, 1, 1))
+ instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
for key in instances:
instance = instances[key]
start = instance.start
end = instance.end
- self.assertEqual(start, datetime.datetime(year, 7, 4))
- self.assertEqual(end , datetime.datetime(year, 7, 5))
+ self.assertEqual(start, PyCalendarDateTime(year, 7, 4))
+ self.assertEqual(end , PyCalendarDateTime(year, 7, 5))
if year == 2050: break
year += 1
@@ -211,14 +210,14 @@
}
year = 2004
- instances = calendar.expandTimeRanges(datetime.date(2100, 1, 1))
+ instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
for key in instances:
instance = instances[key]
start = instance.start
end = instance.end
if year in results:
- self.assertEqual(start, datetime.datetime(year, results[year][0], results[year][1]))
- self.assertEqual(end , datetime.datetime(year, results[year][0], results[year][2]))
+ self.assertEqual(start, PyCalendarDateTime(year, results[year][0], results[year][1]))
+ self.assertEqual(end , PyCalendarDateTime(year, results[year][0], results[year][2]))
if year == 2050: break
year += 1
@@ -237,14 +236,14 @@
}
year = 2002
- instances = calendar.expandTimeRanges(datetime.date(2100, 1, 1))
+ instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
for key in instances:
instance = instances[key]
start = instance.start
end = instance.end
if year in results:
- self.assertEqual(start, datetime.datetime(year, results[year][0], results[year][1]))
- self.assertEqual(end , datetime.datetime(year, results[year][0], results[year][2]))
+ self.assertEqual(start, PyCalendarDateTime(year, results[year][0], results[year][1]))
+ self.assertEqual(end , PyCalendarDateTime(year, results[year][0], results[year][2]))
if year == 2050: break
year += 1
@@ -256,13 +255,13 @@
"""
calendar = Component.fromStream(file(os.path.join(self.data_dir, "Holidays", "C318ABFE-1ED0-11D9-A5E0-000A958A3252.ics")))
- instances = calendar.expandTimeRanges(datetime.date(2100, 1, 1))
+ instances = calendar.expandTimeRanges(PyCalendarDateTime(2100, 1, 1))
for key in instances:
instance = instances[key]
start = instance.start
end = instance.end
- self.assertEqual(start, datetime.datetime(2004, 11, 25))
- self.assertEqual(end, datetime.datetime(2004, 11, 27))
+ self.assertEqual(start, PyCalendarDateTime(2004, 11, 25))
+ self.assertEqual(end, PyCalendarDateTime(2004, 11, 27))
break;
#test_component_timerange.todo = "recurrence expansion should give us no end date here"
@@ -271,49 +270,41 @@
"""
parse_date()
"""
- self.assertEqual(parse_date("19970714"), datetime.date(1997, 7, 14))
+ self.assertEqual(PyCalendarDateTime.parseText("19970714"), PyCalendarDateTime(1997, 7, 14))
def test_parse_datetime(self):
"""
parse_datetime()
"""
- try: parse_datetime("19980119T2300")
- except ValueError: pass
- else: self.fail("Invalid DATE-TIME should raise ValueError")
+ dt = PyCalendarDateTime.parseText("19980118T230000")
+ self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
+ self.assertTrue(dt.floating())
- dt = parse_datetime("19980118T230000")
- self.assertEqual(dt, datetime.datetime(1998, 1, 18, 23, 0))
- self.assertNot(dt.tzinfo)
+ dt = PyCalendarDateTime.parseText("19980119T070000Z")
+ self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
- dt = parse_datetime("19980119T070000Z")
- self.assertEqual(dt, datetime.datetime(1998, 1, 19, 07, 0, tzinfo=utc))
-
def test_parse_date_or_datetime(self):
"""
parse_date_or_datetime()
"""
- self.assertEqual(parse_date_or_datetime("19970714"), datetime.date(1997, 7, 14))
+ self.assertEqual(PyCalendarDateTime.parseText("19970714"), PyCalendarDateTime(1997, 7, 14))
- try: parse_date_or_datetime("19980119T2300")
- except ValueError: pass
- else: self.fail("Invalid DATE-TIME should raise ValueError")
+ dt = PyCalendarDateTime.parseText("19980118T230000")
+ self.assertEqual(dt, PyCalendarDateTime(1998, 1, 18, 23, 0, 0))
+ self.assertTrue(dt.floating())
- dt = parse_date_or_datetime("19980118T230000")
- self.assertEqual(dt, datetime.datetime(1998, 1, 18, 23, 0))
- self.assertNot(dt.tzinfo)
+ dt = PyCalendarDateTime.parseText("19980119T070000Z")
+ self.assertEqual(dt, PyCalendarDateTime(1998, 1, 19, 7, 0, 0, tzid=PyCalendarTimezone(utc=True)))
- dt = parse_date_or_datetime("19980119T070000Z")
- self.assertEqual(dt, datetime.datetime(1998, 1, 19, 07, 0, tzinfo=utc))
-
def test_parse_duration(self):
"""
parse_duration()
"""
- self.assertEqual(parse_duration( "P15DT5H0M20S"), datetime.timedelta(days= 15, hours= 5, minutes=0, seconds= 20))
- self.assertEqual(parse_duration("+P15DT5H0M20S"), datetime.timedelta(days= 15, hours= 5, minutes=0, seconds= 20))
- self.assertEqual(parse_duration("-P15DT5H0M20S"), datetime.timedelta(days=-15, hours=-5, minutes=0, seconds=-20))
+ self.assertEqual(PyCalendarDuration.parseText( "P15DT5H0M20S"), PyCalendarDuration(days= 15, hours= 5, minutes=0, seconds= 20))
+ self.assertEqual(PyCalendarDuration.parseText("+P15DT5H0M20S"), PyCalendarDuration(days= 15, hours= 5, minutes=0, seconds= 20))
+ self.assertEqual(PyCalendarDuration.parseText("-P15DT5H0M20S"), PyCalendarDuration(days=-15, hours=-5, minutes=0, seconds=-20))
- self.assertEqual(parse_duration("P7W"), datetime.timedelta(weeks=7))
+ self.assertEqual(PyCalendarDuration.parseText("P7W"), PyCalendarDuration(weeks=7))
def test_correct_attendee_properties(self):
@@ -413,7 +404,7 @@
""",
(
("mailto:user1 at example.com", None),
- ("mailto:user1 at example.com", datetime.datetime(2008, 11, 14, 0, 0, tzinfo=tzutc()))
+ ("mailto:user1 at example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
)
),
(
@@ -437,7 +428,7 @@
""",
(
("mailto:user1 at example.com", None),
- ("mailto:user3 at example.com", datetime.datetime(2009, 11, 14, 0, 0, tzinfo=tzutc()))
+ ("mailto:user3 at example.com", PyCalendarDateTime(2009, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
)
),
(
@@ -542,8 +533,8 @@
False,
(
("mailto:user2 at example.com", None),
- ("mailto:user2 at example.com", datetime.datetime(2008, 11, 14, 0, 0, tzinfo=tzutc())),
- ("mailto:user3 at example.com", datetime.datetime(2008, 11, 14, 0, 0, tzinfo=tzutc()))
+ ("mailto:user2 at example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True))),
+ ("mailto:user3 at example.com", PyCalendarDateTime(2008, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)))
)
),
(
@@ -798,7 +789,7 @@
for original, result in data:
component = Component.fromString(original)
- component.addPropertyToAllComponents(Property("REQUEST-STATUS", ["2.0", "Success"]))
+ component.addPropertyToAllComponents(Property("REQUEST-STATUS", "2.0;Success"))
self.assertEqual(result, str(component).replace("\r", ""))
def test_attendees_views(self):
@@ -1751,7 +1742,7 @@
END:VCALENDAR
""",
False,
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),)
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),)
),
(
"Simple recurring",
@@ -1768,8 +1759,8 @@
""",
False,
(
- datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
)
),
(
@@ -1788,9 +1779,9 @@
""",
False,
(
- datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2007, 11, 16, 1, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2007, 11, 16, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
)
),
(
@@ -1809,8 +1800,8 @@
""",
False,
(
- datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2007, 11, 16, 0, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
)
),
(
@@ -1829,8 +1820,8 @@
""",
False,
(
- datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2007, 11, 16, 0, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2007, 11, 16, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
)
),
(
@@ -1854,8 +1845,8 @@
""",
False,
(
- datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2007, 11, 15, 1, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)),
)
),
(
@@ -1901,8 +1892,8 @@
""",
True,
(
- datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)),
)
),
)
@@ -1910,9 +1901,9 @@
for description, original, ignoreInvalidInstances, results in data:
component = Component.fromString(original)
if results is None:
- self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, datetime.date(2100, 1, 1), ignoreInvalidInstances)
+ self.assertRaises(InvalidOverriddenInstanceError, component.expandTimeRanges, PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances)
else:
- instances = component.expandTimeRanges(datetime.date(2100, 1, 1), ignoreInvalidInstances)
+ instances = component.expandTimeRanges(PyCalendarDateTime(2100, 1, 1), ignoreInvalidInstances)
self.assertTrue(len(instances.instances) == len(results), "%s: wrong number of instances" % (description,))
for instance in instances:
self.assertTrue(instances[instance].start in results, "%s: %s missing" % (description, instance,))
@@ -2631,7 +2622,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.datetime(2009, 1, 2, 8, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
"""BEGIN:VEVENT
UID:12345-67890-1
RECURRENCE-ID:20090102T080000Z
@@ -2654,7 +2645,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.datetime(2009, 1, 2, 18, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 2, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
"""BEGIN:VEVENT
UID:12345-67890-1
RECURRENCE-ID:20090102T180000Z
@@ -2678,7 +2669,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.datetime(2009, 1, 3, 18, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 3, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
"""BEGIN:VEVENT
UID:12345-67890-1
RECURRENCE-ID:20090103T180000Z
@@ -2700,7 +2691,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.datetime(2009, 1, 2, 9, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 2, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)),
None,
),
(
@@ -2717,7 +2708,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.datetime(2009, 1, 2, 19, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 2, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
None,
),
(
@@ -2735,7 +2726,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.datetime(2009, 1, 3, 19, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 3, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
None,
),
(
@@ -2751,7 +2742,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.date(2009, 1, 8),
+ PyCalendarDateTime(2009, 1, 8),
"""BEGIN:VEVENT
UID:12345-67890-1
RECURRENCE-ID;VALUE=DATE:20090108
@@ -2774,7 +2765,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.date(2009, 1, 3),
+ PyCalendarDateTime(2009, 1, 3),
"""BEGIN:VEVENT
UID:12345-67890-1
RECURRENCE-ID;VALUE=DATE:20090103
@@ -2798,7 +2789,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.date(2009, 1, 10),
+ PyCalendarDateTime(2009, 1, 10),
"""BEGIN:VEVENT
UID:12345-67890-1
RECURRENCE-ID;VALUE=DATE:20090110
@@ -2820,7 +2811,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.date(2009, 1, 3),
+ PyCalendarDateTime(2009, 1, 3),
None,
),
(
@@ -2837,7 +2828,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.date(2009, 1, 5),
+ PyCalendarDateTime(2009, 1, 5),
None,
),
(
@@ -2855,7 +2846,7 @@
END:VEVENT
END:VCALENDAR
""",
- datetime.datetime(2009, 1, 19),
+ PyCalendarDateTime(2009, 1, 19),
None,
),
)
@@ -2885,8 +2876,8 @@
END:VCALENDAR
""",
(
- datetime.datetime(2009, 1, 2, 8, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2009, 1, 4, 8, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 2, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2009, 1, 4, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
),
(
"""BEGIN:VEVENT
@@ -2920,8 +2911,8 @@
END:VCALENDAR
""",
(
- datetime.datetime(2009, 1, 2, 18, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2009, 1, 4, 8, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 2, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2009, 1, 4, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
),
(
"""BEGIN:VEVENT
@@ -2956,8 +2947,8 @@
END:VCALENDAR
""",
(
- datetime.datetime(2009, 1, 3, 18, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2009, 1, 5, 8, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 3, 18, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2009, 1, 5, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
),
(
"""BEGIN:VEVENT
@@ -2990,8 +2981,8 @@
END:VCALENDAR
""",
(
- datetime.datetime(2009, 1, 2, 9, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2009, 1, 3, 8, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 2, 9, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
),
(
None,
@@ -3019,8 +3010,8 @@
END:VCALENDAR
""",
(
- datetime.datetime(2009, 1, 2, 19, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2009, 1, 3, 8, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 2, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
),
(
None,
@@ -3049,8 +3040,8 @@
END:VCALENDAR
""",
(
- datetime.datetime(2009, 1, 3, 19, 0, 0, tzinfo=tzutc()),
- datetime.datetime(2009, 1, 3, 8, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2009, 1, 3, 19, 0, 0, tzid=PyCalendarTimezone(utc=True)),
+ PyCalendarDateTime(2009, 1, 3, 8, 0, 0, tzid=PyCalendarTimezone(utc=True)),
),
(
None,
@@ -3234,8 +3225,8 @@
""",
(
(None, True),
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), False),
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
)
),
(
@@ -3252,9 +3243,9 @@
""",
(
(None, True),
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 5, 0, 0, 0, tzinfo=tzutc()), False),
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 5, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
)
),
(
@@ -3271,10 +3262,10 @@
""",
(
(None, True),
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), False),
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
)
),
(
@@ -3292,11 +3283,11 @@
""",
(
(None, True),
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 2, 0, 0, tzinfo=tzutc()), False),
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
)
),
(
@@ -3315,12 +3306,12 @@
""",
(
(None, True),
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 2, 0, 0, tzinfo=tzutc()), False),
- (datetime.datetime(2009, 10, 3, 0, 0, 0, tzinfo=tzutc()), False),
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+ (PyCalendarDateTime(2009, 10, 3, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
)
),
(
@@ -3342,11 +3333,11 @@
""",
(
(None, True),
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2007, 11, 15, 1, 0, 0, tzinfo=tzutc()), False),
- (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), False),
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+ (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
)
),
(
@@ -3369,12 +3360,12 @@
""",
(
(None, True),
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2007, 11, 15, 1, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2007, 11, 15, 2, 0, 0, tzinfo=tzutc()), False),
- (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 1, 0, 0, tzinfo=tzutc()), False),
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2007, 11, 15, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2007, 11, 15, 2, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+ (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 1, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
)
),
(
@@ -3391,9 +3382,9 @@
""",
(
(None, False),
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), False),
- (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), True),
- (datetime.datetime(2009, 10, 4, 0, 0, 0, tzinfo=tzutc()), False),
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
+ (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
+ (PyCalendarDateTime(2009, 10, 4, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
)
),
(
@@ -3423,7 +3414,7 @@
END:VCALENDAR
""",
(
- (datetime.datetime(2007, 11, 14, 0, 0, 0, tzinfo=tzutc()), True),
+ (PyCalendarDateTime(2007, 11, 14, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), True),
)
),
(
@@ -3438,7 +3429,7 @@
END:VCALENDAR
""",
(
- (datetime.datetime(2007, 11, 15, 0, 0, 0, tzinfo=tzutc()), False),
+ (PyCalendarDateTime(2007, 11, 15, 0, 0, 0, tzid=PyCalendarTimezone(utc=True)), False),
)
),
)
@@ -3727,7 +3718,7 @@
),
),
(
- datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
),
@@ -3771,7 +3762,7 @@
),
),
(
- datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
("user01", False,),
@@ -3824,7 +3815,7 @@
),
),
(
- datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
("user01", False,),
@@ -3868,19 +3859,19 @@
),
),
(
- datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
),
),
(
- datetime.datetime(2008, 6, 3, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", True,),
),
),
(
- datetime.datetime(2008, 6, 4, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", True,),
),
@@ -3941,21 +3932,21 @@
),
),
(
- datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
("user01", True,),
),
),
(
- datetime.datetime(2008, 6, 3, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
("user01", True,),
),
),
(
- datetime.datetime(2008, 6, 4, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
("user01", False,),
@@ -4038,7 +4029,7 @@
),
),
(
- datetime.datetime(2008, 6, 2, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 2, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
("user01", True,),
@@ -4046,7 +4037,7 @@
),
),
(
- datetime.datetime(2008, 6, 3, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 3, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
("user01", True,),
@@ -4054,7 +4045,7 @@
),
),
(
- datetime.datetime(2008, 6, 4, 12, 0, 0, tzinfo=tzutc()),
+ PyCalendarDateTime(2008, 6, 4, 12, 0, 0, tzid=PyCalendarTimezone(utc=True)),
(
("", False,),
("user01", False,),
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110301/e7440aa9/attachment-0001.html>
More information about the calendarserver-changes
mailing list