pull/29/head
Johannes Raggam 2012-02-15 12:32:46 +01:00
rodzic 6ad97552da
commit 57b46fb5dd
1 zmienionych plików z 232 dodań i 264 usunięć

Wyświetl plik

@ -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)
<type 'list'>
>>> len(dt_list)
1
>>> type(dt_list[0])
<type 'datetime.datetime'>
>>> 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)
<type 'datetime.datetime'>
>>> repr(vDDDTypes.from_ical('20010101T123000Z'))[:65]
'datetime.datetime(2001, 1, 1, 12, 30, tzinfo=<icalendar.prop.Utc '
>>> d = vDDDTypes.from_ical('20010101')
>>> type(d)
<type 'datetime.date'>
>>> 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)
<type 'datetime.datetime'>
>>> repr(vDDDTypes.from_ical('20010101T123000Z'))[:65]
'datetime.datetime(2001, 1, 1, 12, 30, tzinfo=<icalendar.prop.Utc '
>>> d = vDDDTypes.from_ical('20010101')
>>> type(d)
<type 'datetime.date'>
>>> 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)
<type 'list'>
>>> len(dt_list)
1
>>> type(dt_list[0])
<type 'datetime.datetime'>
>>> 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