summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PKG-INFO11
-rwxr-xr-xsetup.py11
-rw-r--r--src/vobject.egg-info/PKG-INFO11
-rw-r--r--src/vobject.egg-info/zip-safe1
-rw-r--r--src/vobject/base.py43
-rw-r--r--src/vobject/icalendar.py37
6 files changed, 99 insertions, 15 deletions
diff --git a/PKG-INFO b/PKG-INFO
index 2b87954..0979b92 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,14 +1,19 @@
Metadata-Version: 1.0
Name: vobject
-Version: 0.4.3
+Version: 0.4.4
Summary: VObject: module for reading vCard and vCalendar files
Home-page: http://vobject.skyhouseconsulting.com
Author: Jeffrey Harris
Author-email: jeffrey@osafoundation.org
License: Apache
-Description: Parses iCalendar and vCard files into Python data structures, decoding the relevant encodings. Also serializes vobject data structures to valid iCalendar or vCard unicode strings.
+Description: Parses iCalendar and vCard files into Python data structures, decoding the relevant encodings. Also serializes vobject data structures to iCalendar, vCard, or (expirementally) hCalendar unicode strings.
+
+ Requires python 2.4 or later, dateutil (http://labix.org/python-dateutil) 1.1 or later.
+
+ Recent changes: Merge in Apple CalendarServer patches, improve recurring VTODO support
+
+ For older changes, see http://vobject.skyhouseconsulting.com/history.html or http://websvn.osafoundation.org/listing.php?repname=vobject&path=/trunk/
- Requires dateutil (https://moin.conectiva.com.br/DateUtil) 0.9 or later.
Platform: any
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
diff --git a/setup.py b/setup.py
index 0ec0da6..466d83e 100755
--- a/setup.py
+++ b/setup.py
@@ -1,9 +1,14 @@
#!/usr/bin/env python
"""VObject: module for reading vCard and vCalendar files
-Parses iCalendar and vCard files into Python data structures, decoding the relevant encodings. Also serializes vobject data structures to valid iCalendar or vCard unicode strings.
+Parses iCalendar and vCard files into Python data structures, decoding the relevant encodings. Also serializes vobject data structures to iCalendar, vCard, or (expirementally) hCalendar unicode strings.
+
+Requires python 2.4 or later, dateutil (http://labix.org/python-dateutil) 1.1 or later.
+
+Recent changes: Merge in Apple CalendarServer patches, improve recurring VTODO support
+
+For older changes, see http://vobject.skyhouseconsulting.com/history.html or http://websvn.osafoundation.org/listing.php?repname=vobject&path=/trunk/
-Requires dateutil (https://moin.conectiva.com.br/DateUtil) 0.9 or later.
"""
# not using setuptools until Chandler's ready for eggs
@@ -16,7 +21,7 @@ from setuptools import setup, find_packages
# Metadata
PACKAGE_NAME = "vobject"
-PACKAGE_VERSION = "0.4.3"
+PACKAGE_VERSION = "0.4.4"
ALL_EXTS = ['*.py', '*.ics', '*.txt']
diff --git a/src/vobject.egg-info/PKG-INFO b/src/vobject.egg-info/PKG-INFO
index 2b87954..0979b92 100644
--- a/src/vobject.egg-info/PKG-INFO
+++ b/src/vobject.egg-info/PKG-INFO
@@ -1,14 +1,19 @@
Metadata-Version: 1.0
Name: vobject
-Version: 0.4.3
+Version: 0.4.4
Summary: VObject: module for reading vCard and vCalendar files
Home-page: http://vobject.skyhouseconsulting.com
Author: Jeffrey Harris
Author-email: jeffrey@osafoundation.org
License: Apache
-Description: Parses iCalendar and vCard files into Python data structures, decoding the relevant encodings. Also serializes vobject data structures to valid iCalendar or vCard unicode strings.
+Description: Parses iCalendar and vCard files into Python data structures, decoding the relevant encodings. Also serializes vobject data structures to iCalendar, vCard, or (expirementally) hCalendar unicode strings.
+
+ Requires python 2.4 or later, dateutil (http://labix.org/python-dateutil) 1.1 or later.
+
+ Recent changes: Merge in Apple CalendarServer patches, improve recurring VTODO support
+
+ For older changes, see http://vobject.skyhouseconsulting.com/history.html or http://websvn.osafoundation.org/listing.php?repname=vobject&path=/trunk/
- Requires dateutil (https://moin.conectiva.com.br/DateUtil) 0.9 or later.
Platform: any
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
diff --git a/src/vobject.egg-info/zip-safe b/src/vobject.egg-info/zip-safe
index 8b13789..e69de29 100644
--- a/src/vobject.egg-info/zip-safe
+++ b/src/vobject.egg-info/zip-safe
@@ -1 +0,0 @@
-
diff --git a/src/vobject/base.py b/src/vobject/base.py
index e68f366..9e22607 100644
--- a/src/vobject/base.py
+++ b/src/vobject/base.py
@@ -1,5 +1,6 @@
"""vobject module for reading vCard and vCalendar files."""
+import copy
import re
import sys
import logging
@@ -56,6 +57,12 @@ class VBase(object):
self.parentBehavior = None
self.isNative = False
+ def copy(self, copyit):
+ self.group = copyit.group
+ self.behavior = copyit.behavior
+ self.parentBehavior = copyit.parentBehavior
+ self.isNative = copyit.isNative
+
def validate(self, *args, **kwds):
"""Call the behavior's validate method, or return True."""
if self.behavior:
@@ -250,6 +257,21 @@ class ContentLine(VBase):
if qp:
self.value = str(self.value).decode('quoted-printable')
+ @classmethod
+ def duplicate(clz, copyit):
+ newcopy = clz('', {}, '')
+ newcopy.copy(copyit)
+ return newcopy
+
+ def copy(self, copyit):
+ super(ContentLine, self).copy(copyit)
+ self.name = copyit.name
+ self.value = copy.copy(copyit.value)
+ self.encoded = self.encoded
+ self.params = copy.copy(copyit.params)
+ self.singletonparams = copy.copy(copyit.singletonparams)
+ self.lineNumber = copyit.lineNumber
+
def __eq__(self, other):
try:
return (self.name == other.name) and (self.params == other.params) and (self.value == other.value)
@@ -361,6 +383,27 @@ class Component(VBase):
self.autoBehavior()
+ @classmethod
+ def duplicate(clz, copyit):
+ newcopy = clz()
+ newcopy.copy(copyit)
+ return newcopy
+
+ def copy(self, copyit):
+ super(Component, self).copy(copyit)
+
+ # deep copy of contents
+ self.contents = {}
+ for key, lvalue in copyit.contents.items():
+ newvalue = []
+ for value in lvalue:
+ newitem = value.duplicate(value)
+ newvalue.append(newitem)
+ self.contents[key] = newvalue
+
+ self.name = copyit.name
+ self.useBegin = copyit.useBegin
+
def setProfile(self, name):
"""Assign a PROFILE to this unnamed component.
diff --git a/src/vobject/icalendar.py b/src/vobject/icalendar.py
index a51ff14..1f3b3c8 100644
--- a/src/vobject/icalendar.py
+++ b/src/vobject/icalendar.py
@@ -381,8 +381,17 @@ class RecurringComponent(Component):
try:
dtstart = self.dtstart.value
except AttributeError, KeyError:
- # if there's no dtstart, just return None
- return None
+ # Special for VTODO - try DUE property instead
+ try:
+ if self.name == "VTODO":
+ dtstart = self.due.value
+ else:
+ # if there's no dtstart, just return None
+ return None
+ except AttributeError, KeyError:
+ # if there's no due, just return None
+ return None
+
# rrulestr complains about unicode, so cast to str
rule = dateutil.rrule.rrulestr(str(line.value),
dtstart=dtstart)
@@ -426,7 +435,16 @@ class RecurringComponent(Component):
return rruleset
def setrruleset(self, rruleset):
- dtstart = self.dtstart.value
+
+ # Get DTSTART from component (or DUE if no DTSTART in a VTODO)
+ try:
+ dtstart = self.dtstart.value
+ except AttributeError, KeyError:
+ if self.name == "VTODO":
+ dtstart = self.due.value
+ else:
+ raise
+
isDate = datetime.date == type(dtstart)
if isDate:
dtstart = datetime.datetime(dtstart.year,dtstart.month, dtstart.day)
@@ -492,7 +510,7 @@ class RecurringComponent(Component):
if rule._bymonth is not None and len(rule._bymonth) > 0:
if (rule._byweekday is not None or
- len(rrule._bynweekday or ()) > 0 or
+ len(rule._bynweekday or ()) > 0 or
not (rule._freq == dateutil.rrule.YEARLY and
len(rule._bymonth) == 1 and
rule._bymonth[0] == rule._dtstart.month)):
@@ -584,6 +602,8 @@ class DateTimeBehavior(behavior.Behavior):
if obj.value.tzinfo is None:
obj.params['X-VOBJ-FLOATINGTIME-ALLOWED'] = ['TRUE']
if obj.params.get('TZID'):
+ # Keep a copy of the original TZID around
+ obj.params['X-VOBJ-ORIGINAL-TZID'] = obj.params['TZID']
del obj.params['TZID']
return obj
@@ -596,6 +616,10 @@ class DateTimeBehavior(behavior.Behavior):
obj.value = dateTimeToString(obj.value, cls.forceUTC)
if not cls.forceUTC and tzid is not None:
obj.tzid_param = tzid
+ if obj.params.get('X-VOBJ-ORIGINAL-TZID'):
+ if not hasattr(obj, 'tzid_param'):
+ obj.tzid_param = obj.params['X-VOBJ-ORIGINAL-TZID']
+ del obj.params['X-VOBJ-ORIGINAL-TZID']
return obj
@@ -616,7 +640,10 @@ class DateOrDateTimeBehavior(behavior.Behavior):
obj.value=str(obj.value)
obj.value=parseDtstart(obj)
if getattr(obj, 'value_param', 'DATE-TIME').upper() == 'DATE-TIME':
- if hasattr(obj, 'tzid_param'): del obj.tzid_param
+ if hasattr(obj, 'tzid_param'):
+ # Keep a copy of the original TZID around
+ obj.params['X-VOBJ-ORIGINAL-TZID'] = obj.tzid_param
+ del obj.tzid_param
return obj
@staticmethod