diff --git a/src/icalendar/prop.py b/src/icalendar/prop.py index 594c582..44f67cc 100644 --- a/src/icalendar/prop.py +++ b/src/icalendar/prop.py @@ -1,5 +1,4 @@ # -*- coding: latin-1 -*- - """ This module contains the parser/generators (or coders/encoders if you prefer) @@ -111,7 +110,6 @@ class vBinary: from_ical = staticmethod(from_ical) - class vBoolean(int): """ Returns specific string according to state @@ -151,8 +149,6 @@ class vBoolean(int): from_ical = staticmethod(from_ical) - - class vCalAddress(str): """ This just returns an unquoted string @@ -257,8 +253,238 @@ class LocalTimezone(tzinfo): tt = _time.localtime(stamp) return tt.tm_isdst > 0 -#################################################### +class vFloat(float): + """ + Just a float. + >>> f = vFloat(1.0) + >>> f.to_ical() + '1.0' + >>> vFloat.from_ical('42') + 42.0 + >>> vFloat(42).to_ical() + '42.0' + """ + + def __new__(cls, *args, **kwargs): + self = super(vFloat, cls).__new__(cls, *args, **kwargs) + self.params = Parameters() + return self + + def to_ical(self): + return str(self) + + def from_ical(ical): + "Parses the data format from ical text format" + try: + return float(ical) + except: + raise ValueError, 'Expected float value, got: %s' % ical + from_ical = staticmethod(from_ical) + + +class vInt(int): + """ + Just an int. + >>> f = vInt(42) + >>> f.to_ical() + '42' + >>> vInt.from_ical('13') + 13 + >>> vInt.from_ical('1s3') + Traceback (most recent call last): + ... + ValueError: Expected int, got: 1s3 + """ + + def __new__(cls, *args, **kwargs): + self = super(vInt, cls).__new__(cls, *args, **kwargs) + self.params = Parameters() + return self + + def to_ical(self): + return str(self) + + def from_ical(ical): + "Parses the data format from ical text format" + try: + return int(ical) + except: + raise ValueError, 'Expected int, got: %s' % ical + from_ical = staticmethod(from_ical) + + +class vDDDLists: + """ + A list of vDDDTypes values. + + >>> dt_list = vDDDLists.from_ical('19960402T010000Z') + >>> type(dt_list) + + + >>> len(dt_list) + 1 + + >>> type(dt_list[0]) + + + >>> str(dt_list[0]) + '1996-04-02 01:00:00+00:00' + + >>> dt_list = vDDDLists.from_ical('19960402T010000Z,19960403T010000Z,19960404T010000Z') + >>> len(dt_list) + 3 + + >>> str(dt_list[0]) + '1996-04-02 01:00:00+00:00' + >>> str(dt_list[2]) + '1996-04-04 01:00:00+00:00' + + >>> dt_list = vDDDLists('19960402T010000Z') + Traceback (most recent call last): + ... + ValueError: Value MUST be a list (of date instances) + + >>> dt_list = vDDDLists([]) + >>> dt_list.to_ical() + '' + + >>> dt_list = vDDDLists([datetime(2000,1,1)]) + >>> dt_list.to_ical() + '20000101T000000' + + >>> dt_list = vDDDLists([datetime(2000,1,1), datetime(2000,11,11)]) + >>> dt_list.to_ical() + '20000101T000000,20001111T000000' + """ + + def __init__(self, dt_list): + if not isinstance(dt_list, list): + raise ValueError('Value MUST be a list (of date instances)') + vDDD = [] + for dt in dt_list: + vDDD.append(vDDDTypes(dt)) + self.dts = vDDD + + def to_ical(self): + ''' + Generates the text string in the iCalendar format. + ''' + dts_ical = [dt.to_ical() for dt in self.dts] + return ",".join(dts_ical) + + def from_ical(ical): + ''' + Parses the list of data formats from ical text format. + @param ical: ical text format + ''' + out = [] + ical_dates = ical.split(",") + for ical_dt in ical_dates: + out.append(vDDDTypes.from_ical(ical_dt)) + return out + from_ical = staticmethod(from_ical) + + +class vDDDTypes: + """ + A combined Datetime, Date or Duration parser/generator. Their format cannot + be confused, and often values can be of either types. So this is practical. + + >>> d = vDDDTypes.from_ical('20010101T123000') + >>> type(d) + + + >>> repr(vDDDTypes.from_ical('20010101T123000Z'))[:65] + 'datetime.datetime(2001, 1, 1, 12, 30, tzinfo=>> d = vDDDTypes.from_ical('20010101') + >>> type(d) + + + >>> vDDDTypes.from_ical('P31D') + datetime.timedelta(31) + + >>> vDDDTypes.from_ical('-P31D') + datetime.timedelta(-31) + + Bad input + >>> vDDDTypes(42) + Traceback (most recent call last): + ... + ValueError: You must use datetime, date or timedelta + """ + + def __init__(self, dt): + "Returns vDate from" + if type(dt) not in (datetime, date, timedelta): + raise ValueError ('You must use datetime, date or timedelta') + if isinstance(dt, datetime): + self.params = Parameters(dict(value='DATE-TIME')) + elif isinstance(dt, date): # isinstance(datetime_object, date) => True + self.params = Parameters(dict(value='DATE')) + self.dt = dt + + def to_ical(self): + dt = self.dt + if isinstance(dt, datetime): + return vDatetime(dt).to_ical() + elif isinstance(dt, date): + return vDate(dt).to_ical() + elif isinstance(dt, timedelta): + return vDuration(dt).to_ical() + else: + raise ValueError('Unknown date type') + + def from_ical(ical): + "Parses the data format from ical text format" + u = ical.upper() + if u.startswith('-P') or u.startswith('P'): + return vDuration.from_ical(ical) + try: + return vDatetime.from_ical(ical) + except: + return vDate.from_ical(ical) + from_ical = staticmethod(from_ical) + + +class vDate: + """ + Render and generates iCalendar date format. + >>> d = date(2001, 1,1) + >>> vDate(d).to_ical() + '20010101' + + >>> vDate.from_ical('20010102') + datetime.date(2001, 1, 2) + + >>> vDate('d').to_ical() + Traceback (most recent call last): + ... + ValueError: Value MUST be a date instance + """ + + def __init__(self, dt): + if not isinstance(dt, date): + raise ValueError('Value MUST be a date instance') + self.dt = dt + self.params = Parameters(dict(value='DATE')) + + def to_ical(self): + return self.dt.strftime("%Y%m%d") + + def from_ical(ical): + "Parses the data format from ical text format" + try: + timetuple = map(int, (( + ical[:4], # year + ical[4:6], # month + ical[6:8], # day + ))) + return date(*timetuple) + except: + raise ValueError, 'Wrong date format %s' % ical + from_ical = staticmethod(from_ical) class vDatetime: @@ -327,49 +553,6 @@ class vDatetime: from_ical = staticmethod(from_ical) - - -class vDate: - """ - Render and generates iCalendar date format. - >>> d = date(2001, 1,1) - >>> vDate(d).to_ical() - '20010101' - - >>> vDate.from_ical('20010102') - datetime.date(2001, 1, 2) - - >>> vDate('d').to_ical() - Traceback (most recent call last): - ... - ValueError: Value MUST be a date instance - """ - - def __init__(self, dt): - if not isinstance(dt, date): - raise ValueError('Value MUST be a date instance') - self.dt = dt - self.params = Parameters(dict(value='DATE')) - - def to_ical(self): - return self.dt.strftime("%Y%m%d") - - def from_ical(ical): - "Parses the data format from ical text format" - try: - timetuple = map(int, (( - ical[:4], # year - ical[4:6], # month - ical[6:8], # day - ))) - return date(*timetuple) - except: - raise ValueError, 'Wrong date format %s' % ical - from_ical = staticmethod(from_ical) - - - - class vDuration: """ Subclass of timedelta that renders itself in the iCalendar DURATION format. @@ -470,206 +653,6 @@ class vDuration: from_ical = staticmethod(from_ical) - - -class vFloat(float): - """ - Just a float. - >>> f = vFloat(1.0) - >>> f.to_ical() - '1.0' - >>> vFloat.from_ical('42') - 42.0 - >>> vFloat(42).to_ical() - '42.0' - """ - - def __new__(cls, *args, **kwargs): - self = super(vFloat, cls).__new__(cls, *args, **kwargs) - self.params = Parameters() - return self - - def to_ical(self): - return str(self) - - def from_ical(ical): - "Parses the data format from ical text format" - try: - return float(ical) - except: - raise ValueError, 'Expected float value, got: %s' % ical - from_ical = staticmethod(from_ical) - - - -class vInt(int): - """ - Just an int. - >>> f = vInt(42) - >>> f.to_ical() - '42' - >>> vInt.from_ical('13') - 13 - >>> vInt.from_ical('1s3') - Traceback (most recent call last): - ... - ValueError: Expected int, got: 1s3 - """ - - def __new__(cls, *args, **kwargs): - self = super(vInt, cls).__new__(cls, *args, **kwargs) - self.params = Parameters() - return self - - def to_ical(self): - return str(self) - - def from_ical(ical): - "Parses the data format from ical text format" - try: - return int(ical) - except: - raise ValueError, 'Expected int, got: %s' % ical - from_ical = staticmethod(from_ical) - - - -class vDDDTypes: - """ - A combined Datetime, Date or Duration parser/generator. Their format cannot - be confused, and often values can be of either types. So this is practical. - - >>> d = vDDDTypes.from_ical('20010101T123000') - >>> type(d) - - - >>> repr(vDDDTypes.from_ical('20010101T123000Z'))[:65] - 'datetime.datetime(2001, 1, 1, 12, 30, tzinfo=>> d = vDDDTypes.from_ical('20010101') - >>> type(d) - - - >>> vDDDTypes.from_ical('P31D') - datetime.timedelta(31) - - >>> vDDDTypes.from_ical('-P31D') - datetime.timedelta(-31) - - Bad input - >>> vDDDTypes(42) - Traceback (most recent call last): - ... - ValueError: You must use datetime, date or timedelta - """ - - def __init__(self, dt): - "Returns vDate from" - if type(dt) not in (datetime, date, timedelta): - raise ValueError ('You must use datetime, date or timedelta') - if isinstance(dt, datetime): - self.params = Parameters(dict(value='DATE-TIME')) - elif isinstance(dt, date): # isinstance(datetime_object, date) => True - self.params = Parameters(dict(value='DATE')) - self.dt = dt - - def to_ical(self): - dt = self.dt - if isinstance(dt, datetime): - return vDatetime(dt).to_ical() - elif isinstance(dt, date): - return vDate(dt).to_ical() - elif isinstance(dt, timedelta): - return vDuration(dt).to_ical() - else: - raise ValueError('Unknown date type') - - def from_ical(ical): - "Parses the data format from ical text format" - u = ical.upper() - if u.startswith('-P') or u.startswith('P'): - return vDuration.from_ical(ical) - try: - return vDatetime.from_ical(ical) - except: - return vDate.from_ical(ical) - from_ical = staticmethod(from_ical) - - - -class vDDDLists: - """ - A list of vDDDTypes values. - - >>> dt_list = vDDDLists.from_ical('19960402T010000Z') - >>> type(dt_list) - - - >>> len(dt_list) - 1 - - >>> type(dt_list[0]) - - - >>> str(dt_list[0]) - '1996-04-02 01:00:00+00:00' - - >>> dt_list = vDDDLists.from_ical('19960402T010000Z,19960403T010000Z,19960404T010000Z') - >>> len(dt_list) - 3 - - >>> str(dt_list[0]) - '1996-04-02 01:00:00+00:00' - >>> str(dt_list[2]) - '1996-04-04 01:00:00+00:00' - - >>> dt_list = vDDDLists('19960402T010000Z') - Traceback (most recent call last): - ... - ValueError: Value MUST be a list (of date instances) - - >>> dt_list = vDDDLists([]) - >>> dt_list.to_ical() - '' - - >>> dt_list = vDDDLists([datetime(2000,1,1)]) - >>> dt_list.to_ical() - '20000101T000000' - - >>> dt_list = vDDDLists([datetime(2000,1,1), datetime(2000,11,11)]) - >>> dt_list.to_ical() - '20000101T000000,20001111T000000' - """ - - def __init__(self, dt_list): - if not isinstance(dt_list, list): - raise ValueError('Value MUST be a list (of date instances)') - vDDD = [] - for dt in dt_list: - vDDD.append(vDDDTypes(dt)) - self.dts = vDDD - - def to_ical(self): - ''' - Generates the text string in the iCalendar format. - ''' - dts_ical = [dt.to_ical() for dt in self.dts] - return ",".join(dts_ical) - - def from_ical(ical): - ''' - Parses the list of data formats from ical text format. - @param ical: ical text format - ''' - out = [] - ical_dates = ical.split(",") - for ical_dt in ical_dates: - out.append(vDDDTypes.from_ical(ical_dt)) - return out - from_ical = staticmethod(from_ical) - - - class vPeriod: """ A precise period of time. @@ -777,6 +760,7 @@ class vPeriod: p = (self.start, self.end) return 'vPeriod(%s)' % repr(p) + class vWeekday(str): """ This returns an unquoted weekday abbrevation @@ -843,8 +827,6 @@ class vWeekday(str): from_ical = staticmethod(from_ical) - - class vFrequency(str): """ A simple class that catches illegal values. @@ -887,8 +869,6 @@ class vFrequency(str): from_ical = staticmethod(from_ical) - - class vRecur(CaselessDict): """ Let's see how close we can get to one from the rfc: @@ -1010,7 +990,6 @@ class vRecur(CaselessDict): from_ical = staticmethod(from_ical) - class vText(unicode): """ Simple text @@ -1097,8 +1076,6 @@ class vText(unicode): from_ical = staticmethod(from_ical) - - class vTime(time): """ A subclass of datetime, that renders itself in the iCalendar time @@ -1135,8 +1112,6 @@ class vTime(time): from_ical = staticmethod(from_ical) - - class vUri(str): """ Uniform resource identifier is basically just an unquoted string. @@ -1164,8 +1139,6 @@ class vUri(str): from_ical = staticmethod(from_ical) - - class vGeo: """ A special type that is only indirectly defined in the rfc. @@ -1211,8 +1184,6 @@ class vGeo: from_ical = staticmethod(from_ical) - - class vUTCOffset: """ Renders itself as a utc offset @@ -1305,8 +1276,6 @@ class vUTCOffset: from_ical = staticmethod(from_ical) - - class vInline(str): """ This is an especially dumb class that just holds raw unparsed text and has @@ -1338,7 +1307,6 @@ class vInline(str): from_ical = staticmethod(from_ical) - class TypesFactory(CaselessDict): """ All Value types defined in rfc 2445 are registered in this factory class. To