remove unused tests, move examples.rst to docs/usage.rst, pep8 everything

pull/115/merge
Johannes Raggam 2013-12-24 01:29:05 +01:00
rodzic 6ded747631
commit a08849e099
25 zmienionych plików z 271 dodań i 384 usunięć

Wyświetl plik

@ -1,45 +0,0 @@
========
Examples
========
To open and parse a file::
>>> from icalendar import Calendar, Event
>>> cal = Calendar.from_ical(open('test.ics','rb').read())
>>> cal
VCALENDAR({'VERSION': vText(u'2.0'), 'METHOD': vText(u'Request'), 'PRODID': vText(u'-//My product//mxm.dk/')})
>>> for component in cal.walk():
... component.name
'VCALENDAR'
'VEVENT'
'VEVENT'
To create a calendar and write it to disk::
>>> cal = Calendar()
>>> from datetime import datetime
>>> cal.add('prodid', '-//My calendar product//mxm.dk//')
>>> cal.add('version', '2.0')
>>> import pytz
>>> event = Event()
>>> event.add('summary', 'Python meeting about calendaring')
>>> event.add('dtstart', datetime(2005,4,4,8,0,0,tzinfo=pytz.utc))
>>> event.add('dtend', datetime(2005,4,4,10,0,0,tzinfo=pytz.utc))
>>> event.add('dtstamp', datetime(2005,4,4,0,10,0,tzinfo=pytz.utc))
>>> event['uid'] = '20050115T101010/27346262376@mxm.dk'
>>> event.add('priority', 5)
>>> cal.add_component(event)
>>> f = open('example.ics', 'wb')
>>> f.write(cal.to_ical())
>>> f.close()
More documentation
==================
Have a look at the doctests in the tests directory of the package to get more
examples. All modules and classes also have doctests that show how they work.
There is also an `interfaces.py` file which describes the API.

Wyświetl plik

@ -9,7 +9,7 @@ Contents
about
install
examples
usage
RFC 5545 <rfc5545/index>
changelog
credits

Wyświetl plik

@ -283,5 +283,10 @@ Write to disk::
>>> f.write(cal.to_ical())
>>> f.close()
XXX We should check whether the write succeeded here..
More documentation
==================
Have a look at the tests of this package to get more examples.
All modules and classes docstrings, which document how they work.
There is also an `interfaces.py` file which describes the API.

Wyświetl plik

@ -3,7 +3,6 @@
files according to rfc2445.
These are the defined components.
"""
from __future__ import absolute_import
import pytz
@ -28,7 +27,6 @@ from .parser_tools import DEFAULT_ENCODING
class ComponentFactory(CaselessDict):
"""All components defined in rfc 2445 are registered in this factory class.
To get a component you can use it like this.
"""
def __init__(self, *args, **kwargs):
@ -59,15 +57,15 @@ class Component(CaselessDict):
"""Component is the base object for calendar, Event and the other
components defined in RFC 2445. normally you will not use this class
directy, but rather one of the subclasses.
"""
name = '' # must be defined in each component
required = () # These properties are required
singletons = () # These properties must only appear once
multiple = () # may occur more than once
exclusive = () # These properties are mutually exclusive
inclusive = () # if any occurs the other(s) MUST occur ('duration', 'repeat')
name = '' # must be defined in each component
required = () # These properties are required
singletons = () # These properties must only appear once
multiple = () # may occur more than once
exclusive = () # These properties are mutually exclusive
inclusive = () # if any occurs the other(s) MUST occur
# ('duration', 'repeat')
ignore_exceptions = False # if True, and we cannot parse this
# component, we will silently ignore
# it, rather than let the exception
@ -76,12 +74,12 @@ class Component(CaselessDict):
def __init__(self, *args, **kwargs):
"""Set keys to upper for initial dict.
"""
CaselessDict.__init__(self, *args, **kwargs)
# set parameters here for properties that use non-default values
self.subcomponents = [] # Components can be nested.
self.is_broken = False # True iff we ignored an exception while parsing a property
self.subcomponents = [] # Components can be nested.
self.is_broken = False # True if we ignored an exception while
# parsing a property
#def is_compliant(self, name):
# """Returns True is the given property name is compliant with the
@ -93,13 +91,11 @@ class Component(CaselessDict):
# """
# return name in not_compliant
#############################
# handling of property values
def _encode(self, name, value, cond=1):
"""Conditional convertion of values.
"""
if not cond:
return value
@ -124,7 +120,6 @@ class Component(CaselessDict):
def add(self, name, value, encode=1):
"""Add a property.
"""
if isinstance(value, datetime) and\
name.lower() in ('dtstamp', 'created', 'last-modified'):
@ -148,7 +143,6 @@ class Component(CaselessDict):
def _decode(self, name, value):
"""Internal for decoding property values.
"""
# TODO: Currently the decoded method calls the icalendar.prop instances
@ -167,7 +161,6 @@ class Component(CaselessDict):
def decoded(self, name, default=_marker):
"""Returns decoded value of property.
"""
# XXX: fail. what's this function supposed to do in the end?
# -rnix
@ -189,7 +182,6 @@ class Component(CaselessDict):
def get_inline(self, name, decode=1):
"""Returns a list of values (split on comma).
"""
vals = [v.strip('" ') for v in q_split(self[name])]
if decode:
@ -199,7 +191,6 @@ class Component(CaselessDict):
def set_inline(self, name, values, encode=1):
"""Converts a list of values into comma seperated string and sets value
to that.
"""
if encode:
values = [self._encode(name, value, 1) for value in values]
@ -210,13 +201,11 @@ class Component(CaselessDict):
def add_component(self, component):
"""Add a subcomponent to this component.
"""
self.subcomponents.append(component)
def _walk(self, name):
"""Walk to given component.
"""
result = []
if name is None or self.name == name:
@ -228,7 +217,6 @@ class Component(CaselessDict):
def walk(self, name=None):
"""Recursively traverses component and subcomponents. Returns sequence
of same. If name is passed, only components with name will be returned.
"""
if not name is None:
name = name.upper()
@ -240,7 +228,6 @@ class Component(CaselessDict):
def property_items(self, recursive=True):
"""Returns properties in this component and subcomponents as:
[(name, value), ...]
"""
vText = types_factory['text']
properties = [('BEGIN', vText(self.name).to_ical())]
@ -263,11 +250,10 @@ class Component(CaselessDict):
@classmethod
def from_ical(cls, st, multiple=False):
"""Populates the component recursively from a string.
"""
stack = [] # a stack of components
stack = [] # a stack of components
comps = []
for line in Contentlines.from_ical(st): # raw parsing
for line in Contentlines.from_ical(st): # raw parsing
if not line:
continue
name, params, vals = line.parts()
@ -279,7 +265,7 @@ class Component(CaselessDict):
c_name = vals.upper()
c_class = component_factory.get(c_name, cls)
component = c_class()
if not getattr(component, 'name', ''): # undefined components
if not getattr(component, 'name', ''): # undefined components
component.name = c_name
stack.append(component)
# check for end of event
@ -287,7 +273,7 @@ class Component(CaselessDict):
# we are done adding properties to this component
# so pop it from the stack and add it to the new top.
component = stack.pop()
if not stack: # we are at the end
if not stack: # we are at the end
comps.append(component)
else:
if not component.is_broken:
@ -338,7 +324,7 @@ class Component(CaselessDict):
for name, value in self.property_items():
cl = self.content_line(name, value)
contentlines.append(cl)
contentlines.append('') # remember the empty string in the end
contentlines.append('') # remember the empty string in the end
return contentlines
def to_ical(self):
@ -452,7 +438,6 @@ class Alarm(Component):
class Calendar(Component):
"""This is the base object for an iCalendar file.
"""
name = 'VCALENDAR'
canonical_order = ('VERSION', 'PRODID', 'CALSCALE', 'METHOD',)

Wyświetl plik

@ -6,7 +6,6 @@ from .parser_tools import to_unicode, data_encode
def canonsort_keys(keys, canonical_order=None):
"""Sorts leading keys according to canonical_order. Keys not specified in
canonical_order will appear alphabetically at the end.
"""
canonical_map = dict((k, i) for i, k in enumerate(canonical_order or []))
head = [k for k in keys if k in canonical_map]
@ -16,7 +15,6 @@ def canonsort_keys(keys, canonical_order=None):
def canonsort_items(dict1, canonical_order=None):
"""Returns a list of items from dict1, sorted by canonical_order.
"""
return [(k, dict1[k]) for \
k in canonsort_keys(dict1.keys(), canonical_order)]
@ -25,7 +23,6 @@ def canonsort_items(dict1, canonical_order=None):
class CaselessDict(dict):
"""A dictionary that isn't case sensitive, and only uses strings as keys.
Values retain their case.
"""
def __init__(self, *args, **kwargs):
@ -74,9 +71,7 @@ class CaselessDict(dict):
return dict.__contains__(self, key.upper())
def update(self, indict):
"""
Multiple keys where key1.upper() == key2.upper() will be lost.
"""
# Multiple keys where key1.upper() == key2.upper() will be lost.
for key, value in indict.items(): # TODO optimize in python 2
self[key] = value
@ -91,15 +86,13 @@ class CaselessDict(dict):
canonical_order = None
def sorted_keys(self):
"""
Sorts keys according to the canonical_order for the derived class.
"""Sorts keys according to the canonical_order for the derived class.
Keys not specified in canonical_order will appear at the end.
"""
return canonsort_keys(self.keys(), self.canonical_order)
def sorted_items(self):
"""
Sorts items according to the canonical_order for the derived class.
"""Sorts items according to the canonical_order for the derived class.
Items not specified in canonical_order will appear at the end.
"""
return canonsort_items(self, self.canonical_order)

Wyświetl plik

@ -17,6 +17,7 @@ from .parser_tools import (
)
import icalendar.compat as compat
def escape_char(text):
"""Format value according to iCalendar TEXT escaping rules.
"""
@ -163,15 +164,13 @@ def q_join(lst, sep=','):
class Parameters(CaselessDict):
"""
Parser and generator of Property parameter strings. It knows nothing of
"""Parser and generator of Property parameter strings. It knows nothing of
datatypes. Its main concern is textual structure.
"""
def params(self):
"""
in rfc2445 keys are called parameters, so this is to be consitent with
the naming conventions
"""In rfc2445 keys are called parameters, so this is to be consitent
with the naming conventions.
"""
return self.keys()
@ -211,7 +210,7 @@ class Parameters(CaselessDict):
@classmethod
def from_ical(cls, st, strict=False):
"Parses the parameter format from ical text format"
"""Parses the parameter format from ical text format."""
# parse into strings
result = cls()
@ -263,7 +262,6 @@ def unsescape_string(val):
class Contentline(compat.unicode_type):
"""A content line is basically a string that can be folded and parsed into
parts.
"""
def __new__(cls, value, strict=False, encoding=DEFAULT_ENCODING):
value = to_unicode(value, encoding=encoding)
@ -339,7 +337,7 @@ class Contentline(compat.unicode_type):
return cls(uFOLD.sub('', ical), strict=strict)
def to_ical(self):
"""Long content lines are folded so they are less than 75 characters.
"""Long content lines are folded so they are less than 75 characters
wide.
"""
return foldline(self).encode(DEFAULT_ENCODING)

Wyświetl plik

@ -34,7 +34,6 @@ primitive Python datatype. So it should allways be true that:
These types are mainly used for parsing and file generation. But you can set
them directly.
"""
from __future__ import absolute_import
import re
@ -130,7 +129,6 @@ class LocalTimezone(tzinfo):
class vBinary(object):
"""Binary property values are base 64 encoded.
"""
def __init__(self, obj):
@ -153,7 +151,6 @@ class vBinary(object):
class vBoolean(int):
"""Returns specific string according to state.
"""
BOOL_MAP = CaselessDict(true=True, false=False)
@ -177,7 +174,6 @@ class vBoolean(int):
class vCalAddress(compat.unicode_type):
"""This just returns an unquoted string.
"""
def __new__(cls, value, encoding=DEFAULT_ENCODING):
value = to_unicode(value, encoding=encoding)
@ -198,7 +194,6 @@ class vCalAddress(compat.unicode_type):
class vFloat(float):
"""Just a float.
"""
def __new__(cls, *args, **kwargs):
self = super(vFloat, cls).__new__(cls, *args, **kwargs)
@ -218,7 +213,6 @@ class vFloat(float):
class vInt(int):
"""Just an int.
"""
def __new__(cls, *args, **kwargs):
self = super(vInt, cls).__new__(cls, *args, **kwargs)
@ -238,7 +232,6 @@ class vInt(int):
class vDDDLists(object):
"""A list of vDDDTypes values.
"""
def __init__(self, dt_list):
if not hasattr(dt_list, '__iter__'):
@ -260,7 +253,6 @@ class vDDDLists(object):
dts_ical = (dt.to_ical() for dt in self.dts)
return b",".join(dts_ical)
@staticmethod
def from_ical(ical, timezone=None):
out = []
@ -274,7 +266,6 @@ class vDDDTypes(object):
"""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.
"""
def __init__(self, dt):
if type(dt) not in (datetime, date, timedelta, time):
@ -287,7 +278,7 @@ class vDDDTypes(object):
self.params = Parameters(dict(value='TIME'))
if (isinstance(dt, datetime) or isinstance(dt, time))\
and getattr(dt, 'tzinfo', False):
and getattr(dt, 'tzinfo', False):
tzinfo = dt.tzinfo
if tzinfo is not pytz.utc and not isinstance(tzinfo, tzutc):
# set the timezone as a parameter to the property
@ -327,7 +318,6 @@ class vDDDTypes(object):
class vDate(object):
"""Render and generates iCalendar date format.
"""
def __init__(self, dt):
if not isinstance(dt, date):
@ -362,7 +352,6 @@ class vDatetime(object):
tzinfo component, if present. Otherwise an timezone-naive object is
created. Be aware that there are certain limitations with timezone naive
DATE-TIME components in the icalendar standard.
"""
def __init__(self, dt):
self.dt = dt
@ -419,7 +408,6 @@ class vDatetime(object):
class vDuration(object):
"""Subclass of timedelta that renders itself in the iCalendar DURATION
format.
"""
def __init__(self, td):
@ -474,7 +462,6 @@ class vDuration(object):
class vPeriod(object):
"""A precise period of time.
"""
def __init__(self, per):
start, end_or_duration = per
@ -547,7 +534,6 @@ class vPeriod(object):
class vWeekday(compat.unicode_type):
"""This returns an unquoted weekday abbrevation.
"""
week_days = CaselessDict({
"SU": 0, "MO": 1, "TU": 2, "WE": 3, "TH": 4, "FR": 5, "SA": 6,
@ -582,7 +568,6 @@ class vWeekday(compat.unicode_type):
class vFrequency(compat.unicode_type):
"""A simple class that catches illegal values.
"""
frequencies = CaselessDict({
@ -616,7 +601,6 @@ class vFrequency(compat.unicode_type):
class vRecur(CaselessDict):
"""Recurrence definition.
"""
frequencies = ["SECONDLY", "MINUTELY", "HOURLY", "DAILY", "WEEKLY",
@ -685,7 +669,6 @@ class vRecur(CaselessDict):
class vText(compat.unicode_type):
"""Simple text.
"""
def __new__(cls, value, encoding=DEFAULT_ENCODING):
@ -709,7 +692,6 @@ class vText(compat.unicode_type):
class vTime(object):
"""Render and generates iCalendar time format.
"""
def __init__(self, *args):
@ -736,7 +718,6 @@ class vTime(object):
class vUri(compat.unicode_type):
"""Uniform resource identifier is basically just an unquoted string.
"""
def __new__(cls, value, encoding=DEFAULT_ENCODING):
@ -758,7 +739,6 @@ class vUri(compat.unicode_type):
class vGeo(object):
"""A special type that is only indirectly defined in the rfc.
"""
def __init__(self, geo):
@ -787,7 +767,6 @@ class vGeo(object):
class vUTCOffset(object):
"""Renders itself as a utc offset.
"""
def __init__(self, td):
@ -798,9 +777,9 @@ class vUTCOffset(object):
def to_ical(self):
if self.td<timedelta(0):
if self.td < timedelta(0):
sign = '-%s'
td = timedelta(0)-self.td # get timedelta relative to 0
td = timedelta(0)-self.td # get timedelta relative to 0
else:
# Google Calendar rejects '0000' but accepts '+0000'
sign = '+%s'
@ -841,7 +820,6 @@ class vInline(compat.unicode_type):
"""This is an especially dumb class that just holds raw unparsed text and
has parameters. Conversion of inline values are handled by the Component
class, so no further processing is needed.
"""
def __new__(cls, value, encoding=DEFAULT_ENCODING):
value = to_unicode(value, encoding=encoding)
@ -863,7 +841,6 @@ class TypesFactory(CaselessDict):
The value and parameter names don't overlap. So one factory is enough for
both kinds.
"""
def __init__(self, *args, **kwargs):

Wyświetl plik

@ -2,3 +2,4 @@
import unittest
if not hasattr(unittest.TestCase, 'assertIsNotNone'):
import unittest2 as unittest
unittest # pep 8

Wyświetl plik

@ -1,36 +0,0 @@
BEGIN:VCALENDAR
PRODID:-//RDU Software//NONSGML HandCal//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:US-Eastern
BEGIN:STANDARD
DTSTART:19981025T020000
RDATE:19981025T020000
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:EST
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19990404T020000
RDATE:19990404T020000
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:EDT
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:19980309T231000Z
UID:guid-1.host1.com
ORGANIZER;ROLE=CHAIR:MAILTO:mrbig@host.com
ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:
MAILTO:employee-A@host.com
DESCRIPTION:Project XYZ Review Meeting
CATEGORIES:MEETING
CLASS:PUBLIC
CREATED:19980309T130000Z
SUMMARY:XYZ Project Review
DTSTART;TZID=US-Eastern:19980312T083000
DTEND;TZID=US-Eastern:19980312T093000
LOCATION:1CP Conference Room 4350
END:VEVENT
END:VCALENDAR

Wyświetl plik

@ -1,25 +0,0 @@
BEGIN:VCALENDAR
METHOD:Request
PRODID:-//My product//mxm.dk/
VERSION:2.0
BEGIN:VEVENT
DESCRIPTION:This is a very long description that will be folded This is a
very long description that will be folded This is a very long description
that will be folded This is a very long description that will be folded Th
is is a very long description that will be folded This is a very long desc
ription that will be folded This is a very long description that will be f
olded This is a very long description that will be folded This is a very l
ong description that will be folded This is a very long description that w
ill be folded
PARTICIPANT;CN=Max M:MAILTO:maxm@mxm.dk
DTEND:20050107T160000
DTSTART:20050107T120000
SUMMARY:A second event
END:VEVENT
BEGIN:VEVENT
DTEND:20050108T235900
DTSTART:20050108T230000
SUMMARY:A single event
UID:42
END:VEVENT
END:VCALENDAR

Wyświetl plik

@ -1,13 +1,12 @@
# -*- coding: utf-8 -*-
from icalendar.tests import unittest
import icalendar
import pytz
import datetime
import icalendar
import os
import pytz
from . import unittest
class TestEncoding(unittest.TestCase):
def test_create_from_ical(self):
@ -23,8 +22,10 @@ class TestEncoding(unittest.TestCase):
event = cal.walk('VEVENT')[0]
self.assertEqual(event['SUMMARY'].to_ical().decode('utf-8'),
u'Non-ASCII Test: ÄÖÜ äöü €')
self.assertEqual(event['DESCRIPTION'].to_ical().decode('utf-8'),
u'icalendar should be able to handle non-ascii: €äüöÄÜÖ.')
self.assertEqual(
event['DESCRIPTION'].to_ical().decode('utf-8'),
u'icalendar should be able to handle non-ascii: €äüöÄÜÖ.'
)
self.assertEqual(event['LOCATION'].to_ical().decode('utf-8'),
u'Tribstrül')
@ -38,12 +39,24 @@ class TestEncoding(unittest.TestCase):
cal.add('x-wr-relcalid', u"12345")
event = icalendar.Event()
event.add('dtstart', datetime.datetime(2010, 10, 10, 10, 00, 00, tzinfo=pytz.utc))
event.add('dtend', datetime.datetime(2010, 10, 10, 12, 00, 00, tzinfo=pytz.utc))
event.add('created', datetime.datetime(2010, 10, 10, 0, 0, 0, tzinfo=pytz.utc))
event.add(
'dtstart',
datetime.datetime(2010, 10, 10, 10, 00, 00, tzinfo=pytz.utc)
)
event.add(
'dtend',
datetime.datetime(2010, 10, 10, 12, 00, 00, tzinfo=pytz.utc)
)
event.add(
'created',
datetime.datetime(2010, 10, 10, 0, 0, 0, tzinfo=pytz.utc)
)
event.add('uid', u'123456')
event.add('summary', u'Non-ASCII Test: ÄÖÜ äöü €')
event.add('description', u'icalendar should be able to de/serialize non-ascii.')
event.add(
'description',
u'icalendar should be able to de/serialize non-ascii.'
)
event.add('location', u'Tribstrül')
cal.add_component(event)
@ -53,13 +66,15 @@ class TestEncoding(unittest.TestCase):
def test_create_event_simple(self):
event = icalendar.Event()
event.add("dtstart", datetime.datetime(2010, 10, 10, 0, 0, 0, tzinfo=pytz.utc))
event.add(
"dtstart",
datetime.datetime(2010, 10, 10, 0, 0, 0, tzinfo=pytz.utc)
)
event.add("summary", u"åäö")
out = event.to_ical()
summary = b'SUMMARY:\xc3\xa5\xc3\xa4\xc3\xb6'
self.assertTrue(summary in out.splitlines())
def test_unicode_parameter_name(self):
# Test for issue #80
cal = icalendar.Calendar()
@ -67,7 +82,9 @@ class TestEncoding(unittest.TestCase):
event.add(u'DESCRIPTION', u'äöüßÄÖÜ')
cal.add_component(event)
c = cal.to_ical()
self.assertEqual(c,
b'BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDESCRIPTION:'\
+ b'\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x9f\xc3\x84\xc3\x96\xc3\x9c\r\n'\
+ b'END:VEVENT\r\nEND:VCALENDAR\r\n')
self.assertEqual(
c,
b'BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDESCRIPTION:'
+ b'\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x9f\xc3\x84\xc3\x96\xc3\x9c\r\n'
+ b'END:VEVENT\r\nEND:VCALENDAR\r\n'
)

Wyświetl plik

@ -8,7 +8,6 @@ import pytz
class TestIssues(unittest.TestCase):
def test_issue_53(self):
"""Issue #53 - Parsing failure on some descriptions?
https://github.com/collective/icalendar/issues/53
@ -28,7 +27,6 @@ class TestIssues(unittest.TestCase):
tz = timezones[0]
self.assertEqual(tz['tzid'].to_ical(), b"America/New_York")
def test_issue_55(self):
"""Issue #55 - Parse error on utc-offset with seconds value
https://github.com/collective/icalendar/issues/55
@ -45,13 +43,15 @@ END:STANDARD
END:VTIMEZONE"""
tz = icalendar.Timezone.from_ical(ical_str)
self.assertEqual(tz.to_ical(),
b'BEGIN:VTIMEZONE\r\nTZID:America/Los Angeles\r\nBEGIN:STANDARD\r\n'
self.assertEqual(
tz.to_ical(),
b'BEGIN:VTIMEZONE\r\nTZID:America/Los Angeles\r\n'
b'BEGIN:STANDARD\r\n'
b'DTSTART:18831118T120702\r\nRDATE:18831118T120702\r\nTZNAME:PST'
b'\r\nTZOFFSETFROM:-075258\r\nTZOFFSETTO:-0800\r\nEND:STANDARD\r\n'
b'\r\nTZOFFSETFROM:-075258\r\nTZOFFSETTO:-0800\r\n'
b'END:STANDARD\r\n'
b'END:VTIMEZONE\r\n')
def test_issue_58(self):
"""Issue #58 - TZID on UTC DATE-TIMEs
https://github.com/collective/icalendar/issues/58
@ -64,11 +64,12 @@ END:VTIMEZONE"""
event = icalendar.Event()
dt = pytz.utc.localize(datetime.datetime(2012, 7, 16, 0, 0, 0))
event.add('dtstart', dt)
self.assertEqual(event.to_ical(),
self.assertEqual(
event.to_ical(),
b"BEGIN:VEVENT\r\n"
b"DTSTART;VALUE=DATE-TIME:20120716T000000Z\r\n"
b"END:VEVENT\r\n")
b"END:VEVENT\r\n"
)
def test_issue_64(self):
"""Issue #64 - Event.to_ical() fails for unicode strings
@ -79,17 +80,21 @@ END:VTIMEZONE"""
event = icalendar.Event()
event.add("dtstart", datetime.datetime(2012, 9, 3, 0, 0, 0))
event.add("summary", u"abcdef")
self.assertEqual(event.to_ical(),
self.assertEqual(
event.to_ical(),
b"BEGIN:VEVENT\r\nSUMMARY:abcdef\r\nDTSTART;VALUE=DATE-TIME:"
b"20120903T000000\r\nEND:VEVENT\r\n")
b"20120903T000000\r\nEND:VEVENT\r\n"
)
# Unicode characters
event = icalendar.Event()
event.add("dtstart", datetime.datetime(2012, 9, 3, 0, 0, 0))
event.add("summary", u"åäö")
self.assertEqual(event.to_ical(),
self.assertEqual(
event.to_ical(),
b"BEGIN:VEVENT\r\nSUMMARY:\xc3\xa5\xc3\xa4\xc3\xb6\r\n"
b"DTSTART;VALUE=DATE-TIME:20120903T000000\r\nEND:VEVENT\r\n")
b"DTSTART;VALUE=DATE-TIME:20120903T000000\r\nEND:VEVENT\r\n"
)
def test_issue_70(self):
"""Issue #70 - e.decode("RRULE") causes Attribute Error
@ -111,10 +116,10 @@ END:VEVENT"""
cal = icalendar.Calendar.from_ical(ical_str)
recur = cal.decoded("RRULE")
self.assertIsInstance(recur, icalendar.vRecur)
self.assertEqual(recur.to_ical(),
b'FREQ=WEEKLY;UNTIL=20070619T225959;INTERVAL=1')
self.assertEqual(
recur.to_ical(),
b'FREQ=WEEKLY;UNTIL=20070619T225959;INTERVAL=1'
)
def test_issue_82(self):
"""Issue #82 - vBinary __repr__ called rather than to_ical from
@ -127,12 +132,12 @@ END:VEVENT"""
self.assertEqual(b.to_ical(), b'dGV4dA==')
e = icalendar.Event()
e.add('ATTACH', b)
self.assertEqual(e.to_ical(),
self.assertEqual(
e.to_ical(),
b"BEGIN:VEVENT\r\nATTACH;ENCODING=BASE64;FMTTYPE=text/plain;"
b"VALUE=BINARY:dGV4dA==\r\nEND:VEVENT\r\n"
)
def test_issue_100(self):
"""Issue #100 - Transformed doctests into unittests, Test fixes and
cleanup.
@ -142,7 +147,6 @@ END:VEVENT"""
ical_content = "BEGIN:VEVENT\r\nSUMMARY;LANGUAGE=ru:te\r\nEND:VEVENT"
icalendar.Event.from_ical(ical_content).to_ical()
def test_issue_101(self):
"""Issue #101 - icalender is choking on umlauts in ORGANIZER

Wyświetl plik

@ -1,26 +0,0 @@
from . import unittest
from icalendar import Calendar
import datetime
import os
# An example from the RFC 2445 spec::
class TestGroupScheduled(unittest.TestCase):
def test_group_schedule(self):
directory = os.path.dirname(__file__)
cal = Calendar.from_ical(
open(os.path.join(directory, 'groupscheduled.ics'),'rb').read())
self.assertEqual(str(cal),
"VCALENDAR({'VERSION': '2.0', 'PRODID': '-//RDU Software//NONSGML HandCal//EN'})")
timezones = cal.walk('VTIMEZONE')
self.assertEqual(len(timezones), 1)
tz = timezones[0]
self.assertEqual(str(tz), "VTIMEZONE({'TZID': 'US-Eastern'})")
std = tz.walk('STANDARD')[0]
self.assertEqual(std.decoded('TZOFFSETFROM'), datetime.timedelta(-1, 72000))

Wyświetl plik

@ -1,4 +1,5 @@
# coding: utf-8
import sys
from . import unittest
import doctest
import os
@ -261,22 +262,3 @@ class IcalendarTestCase (unittest.TestCase):
from ..parser import q_join
self.assertEqual(q_join(['Max', 'Moller', 'Rasmussen, Max']),
'Max,Moller,"Rasmussen, Max"')
def load_tests(loader=None, tests=None, pattern=None):
suite = unittest.TestSuite()
suite.addTest(doctest.DocTestSuite(caselessdict))
suite.addTest(doctest.DocTestSuite(parser))
suite.addTest(doctest.DocTestSuite(prop))
suite.addTest(doctest.DocTestSuite(cal))
current_dir = os.path.dirname(__file__)
for docfile in ['example.rst']:
filename = os.path.abspath(os.path.join(current_dir, docfile))
suite.addTest(
doctest.DocFileSuite(
docfile,
optionflags=OPTIONFLAGS,
globs={'__file__': filename}
)
)
return suite

Wyświetl plik

@ -3,14 +3,17 @@ from ..prop import vText
from icalendar import Calendar
import os
#A example with multiple VCALENDAR components::
class TestMultiple(unittest.TestCase):
"""A example with multiple VCALENDAR components"""
def test_multiple(self):
directory = os.path.dirname(__file__)
cals = Calendar.from_ical(
open(os.path.join(directory, 'multiple.ics'),'rb').read(), multiple=True)
open(os.path.join(directory, 'multiple.ics'), 'rb').read(),
multiple=True
)
self.assertEqual(len(cals), 2)
self.assertSequenceEqual([comp.name for comp in cals[0].walk()],
@ -18,5 +21,7 @@ class TestMultiple(unittest.TestCase):
self.assertSequenceEqual([comp.name for comp in cals[1].walk()],
['VCALENDAR', 'VEVENT', 'VEVENT'])
self.assertEqual(cals[0]['prodid'],
vText('-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN'))
self.assertEqual(
cals[0]['prodid'],
vText('-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN')
)

Wyświetl plik

@ -168,7 +168,6 @@ class TestPropertyParams(unittest.TestCase):
'PARAMETER2': ['Value2', 'Value3']})
)
def test_parse_and_access_property_params(self):
"""Parse an ics string and access some property parameters then.
This is a follow-up of a question recieved per email.

Wyświetl plik

@ -2,7 +2,6 @@
import icalendar
import pytz
import datetime
import dateutil.parser
import os
from . import unittest

Wyświetl plik

@ -1,29 +0,0 @@
from . import unittest
from ..prop import vText
from icalendar import Calendar
import os
#A small example::
class TestSmall(unittest.TestCase):
def test_small(self):
directory = os.path.dirname(__file__)
cal = Calendar.from_ical(
open(os.path.join(directory, 'small.ics'),'rb').read())
self.assertEqual(str(cal), "VCALENDAR({'VERSION': '2.0', "
"'METHOD': 'Request', "
"'PRODID': '-//My product//mxm.dk/'})")
self.assertSequenceEqual([comp.name for comp in cal.walk()],
['VCALENDAR', 'VEVENT', 'VEVENT'])
self.assertEqual(str(cal['prodid']), vText('-//My product//mxm.dk/'))
self.assertEqual(str(cal.decoded('prodid')), '-//My product//mxm.dk/')
first_event = cal.walk('vevent')[0]
self.assertEqual(first_event['description'][:75],
u'This is a very long description that will be folded This is a very long des')
self.assertEqual(first_event['summary'], vText('A second event'))

Wyświetl plik

@ -4,6 +4,7 @@ import os
from . import unittest
class TestTime(unittest.TestCase):
def setUp(self):

Wyświetl plik

@ -12,9 +12,14 @@ class TestTimezoned(unittest.TestCase):
def test_create_from_ical(self):
directory = os.path.dirname(__file__)
cal = icalendar.Calendar.from_ical(open(os.path.join(directory, 'timezoned.ics'), 'rb').read())
cal = icalendar.Calendar.from_ical(
open(os.path.join(directory, 'timezoned.ics'), 'rb').read()
)
self.assertEqual(cal['prodid'].to_ical(), b"-//Plone.org//NONSGML plone.app.event//EN")
self.assertEqual(
cal['prodid'].to_ical(),
b"-//Plone.org//NONSGML plone.app.event//EN"
)
timezones = cal.walk('VTIMEZONE')
self.assertEqual(len(timezones), 1)
@ -23,11 +28,19 @@ class TestTimezoned(unittest.TestCase):
self.assertEqual(tz['tzid'].to_ical(), b"Europe/Vienna")
std = tz.walk('STANDARD')[0]
self.assertEqual(std.decoded('TZOFFSETFROM'), datetime.timedelta(0, 7200))
self.assertEqual(
std.decoded('TZOFFSETFROM'),
datetime.timedelta(0, 7200)
)
ev1 = cal.walk('VEVENT')[0]
self.assertEqual(ev1.decoded('DTSTART'), datetime.datetime(2012, 2, 13, 10, 0, 0, tzinfo=pytz.timezone('Europe/Vienna')))
self.assertEqual(ev1.decoded('DTSTAMP'), datetime.datetime(2010, 10, 10, 9, 10, 10, tzinfo=pytz.utc))
self.assertEqual(
ev1.decoded('DTSTART'),
datetime.datetime(2012, 2, 13, 10, 0, 0,
tzinfo=pytz.timezone('Europe/Vienna')))
self.assertEqual(
ev1.decoded('DTSTAMP'),
datetime.datetime(2010, 10, 10, 9, 10, 10, tzinfo=pytz.utc))
def test_create_to_ical(self):
cal = icalendar.Calendar()
@ -63,12 +76,22 @@ class TestTimezoned(unittest.TestCase):
event = icalendar.Event()
tz = pytz.timezone("Europe/Vienna")
event.add('dtstart', datetime.datetime(2012, 2, 13, 10, 00, 00, tzinfo=tz))
event.add('dtend', datetime.datetime(2012, 2, 17, 18, 00, 00, tzinfo=tz))
event.add('dtstamp', datetime.datetime(2010, 10, 10, 10, 10, 10, tzinfo=tz))
event.add('created', datetime.datetime(2010, 10, 10, 10, 10, 10, tzinfo=tz))
event.add(
'dtstart',
datetime.datetime(2012, 2, 13, 10, 00, 00, tzinfo=tz))
event.add(
'dtend',
datetime.datetime(2012, 2, 17, 18, 00, 00, tzinfo=tz))
event.add(
'dtstamp',
datetime.datetime(2010, 10, 10, 10, 10, 10, tzinfo=tz))
event.add(
'created',
datetime.datetime(2010, 10, 10, 10, 10, 10, tzinfo=tz))
event.add('uid', u'123456')
event.add('last-modified', datetime.datetime(2010, 10, 10, 10, 10, 10, tzinfo=tz))
event.add(
'last-modified',
datetime.datetime(2010, 10, 10, 10, 10, 10, tzinfo=tz))
event.add('summary', u'artsprint 2012')
# event.add('rrule', u'FREQ=YEARLY;INTERVAL=1;COUNT=10')
event.add('description', u'sprinting at the artsprint')
@ -85,13 +108,13 @@ class TestTimezoned(unittest.TestCase):
test_out = b'|'.join(cal.to_ical().splitlines())
test_out = test_out.decode('utf-8')
vtimezone_lines = "BEGIN:VTIMEZONE|TZID:Europe/Vienna|X-LIC-LOCATION:"\
+ "Europe/Vienna|BEGIN:STANDARD|DTSTART;VALUE=DATE-TIME:19701025T03"\
+ "0000|RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10|RRULE:FREQ=YEARLY;B"\
+ "YDAY=-1SU;BYMONTH=3|TZNAME:CET|TZOFFSETFROM:+0200|TZOFFSETTO:+01"\
+ "00|END:STANDARD|BEGIN:DAYLIGHT|DTSTART;VALUE=DATE-TIME:19700329T"\
+ "020000|TZNAME:CEST|TZOFFSETFROM:+0100|TZOFFSETTO:+0200|END:DAYLI"\
+ "GHT|END:VTIMEZONE"
vtimezone_lines = "BEGIN:VTIMEZONE|TZID:Europe/Vienna|X-LIC-LOCATION:"
"Europe/Vienna|BEGIN:STANDARD|DTSTART;VALUE=DATE-TIME:19701025T03"
"0000|RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10|RRULE:FREQ=YEARLY;B"
"YDAY=-1SU;BYMONTH=3|TZNAME:CET|TZOFFSETFROM:+0200|TZOFFSETTO:+01"
"00|END:STANDARD|BEGIN:DAYLIGHT|DTSTART;VALUE=DATE-TIME:19700329T"
"020000|TZNAME:CEST|TZOFFSETFROM:+0100|TZOFFSETTO:+0200|END:DAYLI"
"GHT|END:VTIMEZONE"
self.assertTrue(vtimezone_lines in test_out)
test_str = "DTSTART;TZID=Europe/Vienna;VALUE=DATE-TIME:20120213T100000"

Wyświetl plik

@ -17,14 +17,18 @@ class TestCalComponent(unittest.TestCase):
# Every key defines a property.A property can consist of either a
# single item. This can be set with a single value...
c['prodid'] = '-//max m//icalendar.mxm.dk/'
self.assertEqual(c,
Calendar({'PRODID': '-//max m//icalendar.mxm.dk/'}))
self.assertEqual(
c,
Calendar({'PRODID': '-//max m//icalendar.mxm.dk/'})
)
# or with a list
c['ATTENDEE'] = ['Max M', 'Rasmussen']
self.assertEqual(c,
self.assertEqual(
c,
Calendar({'ATTENDEE': ['Max M', 'Rasmussen'],
'PRODID': '-//max m//icalendar.mxm.dk/'}))
'PRODID': '-//max m//icalendar.mxm.dk/'})
)
# if you use the add method you don't have to considder if a value is
# a list or not.
@ -32,9 +36,11 @@ class TestCalComponent(unittest.TestCase):
c.name = 'VEVENT'
c.add('attendee', 'maxm@mxm.dk')
c.add('attendee', 'test@example.dk')
self.assertEqual(c,
self.assertEqual(
c,
Event({'ATTENDEE': [prop.vCalAddress('maxm@mxm.dk'),
prop.vCalAddress('test@example.dk')]}))
prop.vCalAddress('test@example.dk')]})
)
# You can get the values back directly ...
c.add('prodid', '-//my product//')
@ -53,8 +59,10 @@ class TestCalComponent(unittest.TestCase):
c = Component()
c.name = 'VCALENDAR'
c.add('attendee', 'Max M')
self.assertEqual(c.to_ical(),
b'BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n')
self.assertEqual(
c.to_ical(),
b'BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n'
)
# Components can be nested, so You can add a subcompont. Eg a calendar
# holds events.
@ -62,15 +70,19 @@ class TestCalComponent(unittest.TestCase):
e.name = 'VEVENT'
e.add('dtend', '20000102T000000', encode=0)
e.add('dtstart', '20000101T000000', encode=0)
self.assertEqual(e.to_ical(),
self.assertEqual(
e.to_ical(),
b'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n'
+ b'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r'
+ b'\nEND:VEVENT\r\n')
+ b'\nEND:VEVENT\r\n'
)
c.add_component(e)
self.assertEqual(c.subcomponents,
self.assertEqual(
c.subcomponents,
[Event({'DTEND': '20000102T000000', 'DTSTART': '20000101T000000',
'SUMMARY': 'A brief history of time'})])
'SUMMARY': 'A brief history of time'})]
)
# We can walk over nested componentes with the walk method.
self.assertEqual([i.name for i in c.walk()], ['VCALENDAR', 'VEVENT'])
@ -79,57 +91,75 @@ class TestCalComponent(unittest.TestCase):
# them on their name.
self.assertEqual([i.name for i in c.walk('VEVENT')], ['VEVENT'])
self.assertEqual([i['dtstart'] for i in c.walk('VEVENT')],
['20000101T000000'])
self.assertEqual(
[i['dtstart'] for i in c.walk('VEVENT')],
['20000101T000000']
)
# We can enumerate property items recursively with the property_items
# method.
self.assertEqual(c.property_items(),
self.assertEqual(
c.property_items(),
[('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')),
('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'),
('DTSTART', '20000101T000000'),
('SUMMARY', 'A brief history of time'), ('END', b'VEVENT'),
('END', b'VCALENDAR')])
('END', b'VCALENDAR')]
)
# We can also enumerate property items just under the component.
self.assertEqual(c.property_items(recursive=False),
self.assertEqual(
c.property_items(recursive=False),
[('BEGIN', b'VCALENDAR'),
('ATTENDEE', prop.vCalAddress('Max M')),
('END', b'VCALENDAR')])
('END', b'VCALENDAR')]
)
sc = c.subcomponents[0]
self.assertEqual(sc.property_items(recursive=False),
self.assertEqual(
sc.property_items(recursive=False),
[('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'),
('DTSTART', '20000101T000000'),
('SUMMARY', 'A brief history of time'), ('END', b'VEVENT')])
('SUMMARY', 'A brief history of time'), ('END', b'VEVENT')]
)
# Text fields which span multiple mulitple lines require proper
# indenting
c = Calendar()
c['description'] = u'Paragraph one\n\nParagraph two'
self.assertEqual(c.to_ical(),
b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two'
+ b'\r\nEND:VCALENDAR\r\n')
self.assertEqual(
c.to_ical(),
b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two'
+ b'\r\nEND:VCALENDAR\r\n'
)
# INLINE properties have their values on one property line. Note the
# double quoting of the value with a colon in it.
c = Calendar()
c['resources'] = 'Chair, Table, "Room: 42"'
self.assertEqual(c,
Calendar({'RESOURCES': 'Chair, Table, "Room: 42"'}))
self.assertEqual(
c,
Calendar({'RESOURCES': 'Chair, Table, "Room: 42"'})
)
self.assertEqual(c.to_ical(),
self.assertEqual(
c.to_ical(),
b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n'
+ b'END:VCALENDAR\r\n')
+ b'END:VCALENDAR\r\n'
)
# The inline values must be handled by the get_inline() and
# set_inline() methods.
self.assertEqual(c.get_inline('resources', decode=0),
[u'Chair', u'Table', u'Room: 42'])
self.assertEqual(
c.get_inline('resources', decode=0),
[u'Chair', u'Table', u'Room: 42']
)
# These can also be decoded
self.assertEqual(c.get_inline('resources', decode=1),
[b'Chair', b'Table', b'Room: 42'])
self.assertEqual(
c.get_inline('resources', decode=1),
[b'Chair', b'Table', b'Room: 42']
)
# You can set them directly ...
c.set_inline('resources', ['A', 'List', 'of', 'some, recources'],
@ -137,14 +167,18 @@ class TestCalComponent(unittest.TestCase):
self.assertEqual(c['resources'], 'A,List,of,"some, recources"')
# ... and back again
self.assertEqual(c.get_inline('resources', decode=0),
['A', 'List', 'of', 'some, recources'])
self.assertEqual(
c.get_inline('resources', decode=0),
['A', 'List', 'of', 'some, recources']
)
c['freebusy'] = '19970308T160000Z/PT3H,19970308T200000Z/PT1H,'\
+ '19970308T230000Z/19970309T000000Z'
self.assertEqual(c.get_inline('freebusy', decode=0),
self.assertEqual(
c.get_inline('freebusy', decode=0),
['19970308T160000Z/PT3H', '19970308T200000Z/PT1H',
'19970308T230000Z/19970309T000000Z'])
'19970308T230000Z/19970309T000000Z']
)
freebusy = c.get_inline('freebusy', decode=1)
self.assertTrue(isinstance(freebusy[0][0], datetime))
@ -170,7 +204,8 @@ class TestCalComponent(unittest.TestCase):
self.assertTrue(b"CREATED;VALUE=DATE-TIME:20101010T120000Z" in lines)
self.assertTrue(b"DTSTAMP;VALUE=DATE-TIME:20101010T130000Z" in lines)
self.assertTrue(
b"LAST-MODIFIED;VALUE=DATE-TIME:20101010T160000Z" in lines)
b"LAST-MODIFIED;VALUE=DATE-TIME:20101010T160000Z" in lines
)
def test_cal_Component_add_no_reencode(self):
"""Already encoded values should not be re-encoded.
@ -216,8 +251,10 @@ class TestCal(unittest.TestCase):
factory = ComponentFactory()
component = factory['VEVENT']
event = component(dtstart='19700101')
self.assertEqual(event.to_ical(),
b'BEGIN:VEVENT\r\nDTSTART:19700101\r\nEND:VEVENT\r\n')
self.assertEqual(
event.to_ical(),
b'BEGIN:VEVENT\r\nDTSTART:19700101\r\nEND:VEVENT\r\n'
)
self.assertEqual(
factory.get('VCALENDAR', icalendar.cal.Component),
@ -239,12 +276,13 @@ class TestCal(unittest.TestCase):
cal.add_component(event)
self.assertEqual(
cal.subcomponents[0].to_ical(),
b'BEGIN:VEVENT\r\nSUMMARY:Python meeting about calendaring\r\n'\
+ b'DTSTART;VALUE=DATE-TIME:20050404T080000\r\nUID:42\r\n'\
b'BEGIN:VEVENT\r\nSUMMARY:Python meeting about calendaring\r\n'
+ b'DTSTART;VALUE=DATE-TIME:20050404T080000\r\nUID:42\r\n'
+ b'END:VEVENT\r\n')
# Write to disc
import tempfile, os
import tempfile
import os
directory = tempfile.mkdtemp()
open(os.path.join(directory, 'test.ics'), 'wb').write(cal.to_ical())

Wyświetl plik

@ -10,46 +10,60 @@ class TestCaselessdict(unittest.TestCase):
keys = ['DTEND', 'DTSTAMP', 'DTSTART', 'UID', 'SUMMARY', 'LOCATION']
out = canonsort_keys(keys)
self.assertEqual(out,
['DTEND', 'DTSTAMP', 'DTSTART', 'LOCATION', 'SUMMARY', 'UID'])
self.assertEqual(
out,
['DTEND', 'DTSTAMP', 'DTSTART', 'LOCATION', 'SUMMARY', 'UID']
)
out = canonsort_keys(keys, ('SUMMARY', 'DTSTART', 'DTEND', ))
self.assertEqual(out,
['SUMMARY', 'DTSTART', 'DTEND', 'DTSTAMP', 'LOCATION', 'UID'])
self.assertEqual(
out,
['SUMMARY', 'DTSTART', 'DTEND', 'DTSTAMP', 'LOCATION', 'UID']
)
out = canonsort_keys(keys, ('UID', 'DTSTART', 'DTEND', ))
self.assertEqual(out,
['UID', 'DTSTART', 'DTEND', 'DTSTAMP', 'LOCATION', 'SUMMARY'])
out = canonsort_keys(keys,
('UID', 'DTSTART', 'DTEND', 'RRULE', 'EXDATE'))
self.assertEqual(out,
['UID', 'DTSTART', 'DTEND', 'DTSTAMP', 'LOCATION', 'SUMMARY'])
self.assertEqual(
out,
['UID', 'DTSTART', 'DTEND', 'DTSTAMP', 'LOCATION', 'SUMMARY']
)
out = canonsort_keys(
keys,
('UID', 'DTSTART', 'DTEND', 'RRULE', 'EXDATE')
)
self.assertEqual(
out,
['UID', 'DTSTART', 'DTEND', 'DTSTAMP', 'LOCATION', 'SUMMARY']
)
def test_caselessdict_canonsort_items(self):
canonsort_items = icalendar.caselessdict.canonsort_items
d = dict(i=7, c='at', a=3.5, l=(2,3), e=[4,5], n=13, d={'x': 'y'},
d = dict(i=7, c='at', a=3.5, l=(2, 3), e=[4, 5], n=13, d={'x': 'y'},
r=1.0)
out = canonsort_items(d)
self.assertEqual(out,
self.assertEqual(
out,
[('a', 3.5), ('c', 'at'), ('d', {'x': 'y'}), ('e', [4, 5]),
('i', 7), ('l', (2, 3)), ('n', 13), ('r', 1.0)])
('i', 7), ('l', (2, 3)), ('n', 13), ('r', 1.0)]
)
out = canonsort_items(d, ('i', 'c', 'a'))
self.assertTrue(out,
self.assertTrue(
out,
[('i', 7), ('c', 'at'), ('a', 3.5), ('d', {'x': 'y'}),
('e', [4, 5]), ('l', (2, 3)), ('n', 13), ('r', 1.0)])
('e', [4, 5]), ('l', (2, 3)), ('n', 13), ('r', 1.0)]
)
def test_CaselessDict(self):
CaselessDict = icalendar.caselessdict.CaselessDict
ncd = CaselessDict(key1='val1', key2='val2')
self.assertEqual(ncd,
CaselessDict({'KEY2': 'val2', 'KEY1': 'val1'}))
self.assertEqual(
ncd,
CaselessDict({'KEY2': 'val2', 'KEY1': 'val1'})
)
self.assertEqual(ncd['key1'], 'val1')
self.assertEqual(ncd['KEY1'], 'val1')
@ -66,9 +80,9 @@ class TestCaselessdict(unittest.TestCase):
self.assertTrue('key4' in ncd)
del ncd['key4']
self.assertFalse(ncd.has_key('key4'))
self.assertFalse('key4' in ncd)
ncd.update({'key5':'val5', 'KEY6':'val6', 'KEY5':'val7'})
ncd.update({'key5': 'val5', 'KEY6': 'val6', 'KEY5': 'val7'})
self.assertEqual(ncd['key6'], 'val6')
keys = list(ncd.keys())

Wyświetl plik

@ -20,8 +20,10 @@ class TestParserTools(unittest.TestCase):
def test_parser_tools_data_encode(self):
data1 = {u'k1': u'v1', 'k2': 'v2', u'k3': u'v3',
'li1': ['it1', u'it2', {'k4': u'v4', u'k5': 'v5'}, 123]}
data1 = {
u'k1': u'v1', 'k2': 'v2', u'k3': u'v3',
'li1': ['it1', u'it2', {'k4': u'v4', u'k5': 'v5'}, 123]
}
res = {b'k3': b'v3', b'k2': b'v2', b'k1': b'v1',
b'li1': [b'it1', b'it2', {b'k5': b'v5', b'k4': b'v4'}, 123]}
self.assertEqual(data_encode(data1), res)

Wyświetl plik

@ -160,7 +160,10 @@ class TestProp(unittest.TestCase):
self.assertEqual(vDuration(timedelta(11)).to_ical(), b'P11D')
self.assertEqual(vDuration(timedelta(-14)).to_ical(), b'-P14D')
self.assertEqual(vDuration(timedelta(1, 7384)).to_ical(), b'P1DT2H3M4S')
self.assertEqual(
vDuration(timedelta(1, 7384)).to_ical(),
b'P1DT2H3M4S'
)
self.assertEqual(vDuration(timedelta(1, 7380)).to_ical(), b'P1DT2H3M')
self.assertEqual(vDuration(timedelta(1, 7200)).to_ical(), b'P1DT2H')
self.assertEqual(vDuration(timedelta(0, 7200)).to_ical(), b'PT2H')
@ -289,7 +292,10 @@ class TestProp(unittest.TestCase):
r = vRecur.from_ical('FREQ=DAILY;INTERVAL=2;COUNT=10')
self.assertEqual(r,
{'COUNT': [10], 'FREQ': ['DAILY'], 'INTERVAL': [2]})
self.assertEqual(vRecur(r).to_ical(), b'FREQ=DAILY;COUNT=10;INTERVAL=2')
self.assertEqual(
vRecur(r).to_ical(),
b'FREQ=DAILY;COUNT=10;INTERVAL=2'
)
r = vRecur.from_ical('FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=-SU;'
'BYHOUR=8,9;BYMINUTE=30')
@ -301,7 +307,8 @@ class TestProp(unittest.TestCase):
self.assertEqual(
vRecur(r).to_ical(),
b'FREQ=YEARLY;INTERVAL=2;BYMINUTE=30;BYHOUR=8,9;BYDAY=-SU;BYMONTH=1'
b'FREQ=YEARLY;INTERVAL=2;BYMINUTE=30;BYHOUR=8,9;BYDAY=-SU;'
b'BYMONTH=1'
)
# Some examples from the spec

Wyświetl plik

@ -11,10 +11,8 @@ commands =
coverage report --omit=*tests*
coverage html --omit=*tests*
[testenv:py33]
basepython = python3.3
deps =
unittest2py3k
coverage