Projects
Kolab:3.4:Updates
python-icalendar
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 10
View file
python-icalendar.spec
Changed
@@ -3,7 +3,7 @@ %endif Name: python-icalendar -Version: 3.4 +Version: 3.8.2 Release: 1%{?dist} Summary: Parser/generator of iCalendar files following the RFC 2445 @@ -59,6 +59,9 @@ %{python_sitelib}/*.egg-info %changelog +* Thu Aug 21 2014 Thomas Bruederli <bruederli@kolabsys.com> - 3.8.2 +- New upstream version + * Sun Jun 9 2013 Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> - 3.4-1 - New upstream version
View file
debian.changelog
Changed
@@ -1,3 +1,9 @@ +python-icalendar (3.8.2) unstable; urgency=low + + * Imported Upstream version 3.8.2 + + -- Thomas Bruederli (Kolab Systems) <bruederli@kolabsys.com> Thu, 21 Aug 2014 17:01:00 +0200 + python-icalendar (3.4-1) unstable; urgency=low * Imported Upstream version 3.4
View file
icalendar-3.4.tar.gz/.gitignore
Deleted
@@ -1,24 +0,0 @@ -*.pyc -*.pyo -*.swp -*.swo - -.DT_Store -.coverage -.tox/ -bin/ -build/ -coverage-* -dist/ -docs/_build/ -include/ -lib/ -src/icalendar.egg-info/ -.installed.cfg -.project -.pydevproject -.settings/ -develop-eggs/ -eggs/ -parts/ -htmlcov/
View file
icalendar-3.4.tar.gz/.travis.yml
Deleted
@@ -1,12 +0,0 @@ -language: python -python: -# - "2.4" - - "2.5" - - "2.6" - - "2.7" -# - "3.2" -install: - - pip install . --use-mirrors - - pip install unittest2 --use-mirrors -script: - - $HOME/virtualenv/python$TRAVIS_PYTHON_VERSION/bin/unit2 discover icalendar []
View file
icalendar-3.4.tar.gz/bootstrap.py
Deleted
@@ -1,121 +0,0 @@ -############################################################################## -# -# Copyright (c) 2006 Zope Corporation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -"""Bootstrap a buildout-based project - -Simply run this script in a directory containing a buildout.cfg. -The script accepts buildout command-line options, so you can -use the -c option to specify an alternate configuration file. -""" - -import os, shutil, sys, tempfile, urllib2 -from optparse import OptionParser - -tmpeggs = tempfile.mkdtemp() - -is_jython = sys.platform.startswith('java') - -# parsing arguments -parser = OptionParser() -parser.add_option("-v", "--version", dest="version", - help="use a specific zc.buildout version") -parser.add_option("-d", "--distribute", - action="store_true", dest="distribute", default=False, - help="Use Disribute rather than Setuptools.") - -parser.add_option("-c", None, action="store", dest="config_file", - help=("Specify the path to the buildout configuration " - "file to be used.")) - -options, args = parser.parse_args() - -# if -c was provided, we push it back into args for buildout' main function -if options.config_file is not None: - args += ['-c', options.config_file] - -if options.version is not None: - VERSION = '==%s' % options.version -else: - VERSION = '' - -# We decided to always use distribute, make sure this is the default for us -# USE_DISTRIBUTE = options.distribute -USE_DISTRIBUTE = True -args = args + ['bootstrap'] - -to_reload = False -try: - import pkg_resources - if not hasattr(pkg_resources, '_distribute'): - to_reload = True - raise ImportError -except ImportError: - ez = {} - if USE_DISTRIBUTE: - exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py' - ).read() in ez - ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True) - else: - exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' - ).read() in ez - ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) - - if to_reload: - reload(pkg_resources) - else: - import pkg_resources - -if sys.platform == 'win32': - def quote(c): - if ' ' in c: - return '"%s"' % c # work around spawn lamosity on windows - else: - return c -else: - def quote (c): - return c - -cmd = 'from setuptools.command.easy_install import main; main()' -ws = pkg_resources.working_set - -if USE_DISTRIBUTE: - requirement = 'distribute' -else: - requirement = 'setuptools' - -if is_jython: - import subprocess - - assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd', - quote(tmpeggs), 'zc.buildout' + VERSION], - env=dict(os.environ, - PYTHONPATH= - ws.find(pkg_resources.Requirement.parse(requirement)).location - ), - ).wait() == 0 - -else: - assert os.spawnle( - os.P_WAIT, sys.executable, quote (sys.executable), - '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION, - dict(os.environ, - PYTHONPATH= - ws.find(pkg_resources.Requirement.parse(requirement)).location - ), - ) == 0 - -ws.add_entry(tmpeggs) -ws.require('zc.buildout' + VERSION) -import zc.buildout.buildout -zc.buildout.buildout.main(args) -shutil.rmtree(tmpeggs)
View file
icalendar-3.4.tar.gz/buildout.cfg
Deleted
@@ -1,26 +0,0 @@ -[buildout] -develop = . -parts += - test - py - coverage - -[test] -recipe = zc.recipe.testrunner -eggs = - icalendar[test] -defaults = ['--auto-color', '--auto-progress'] - -[py] -recipe = zc.recipe.egg -interpreter = py -eggs = ${test:eggs} -scripts = - -[coverage] -recipe = collective.recipe.template -input = inline: - #!/bin/sh - ./bin/test --coverage ../../coverage -v --auto-progress "$@" -output = ${buildout:directory}/bin/coverage -mode = 755
View file
icalendar-3.4.tar.gz/docs/changelog.rst
Deleted
@@ -1,1 +0,0 @@ -.. include:: ../CHANGES.rst
View file
icalendar-3.4.tar.gz/docs/examples.rst
Deleted
@@ -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.
View file
icalendar-3.4.tar.gz/src/icalendar/tests/example.rst
Deleted
@@ -1,287 +0,0 @@ -iCalendar package -================= - -This package is used for parsing and generating iCalendar files following the -standard in RFC 2445. - -It should be fully compliant, but it is possible to generate and parse invalid -files if you really want to. - -File structure --------------- - -An iCalendar file is a text file (utf-8) with a special format. Basically it -consists of content lines. - -Each content line defines a property that has 3 parts (name, parameters, -values). Parameters are optional. - -A simple content line with only name and value could look like this:: - - BEGIN:VCALENDAR - -A content line with parameters can look like this:: - - ATTENDEE;CN=Max Rasmussen;ROLE=REQ-PARTICIPANT:MAILTO:example@example.com - -And the parts are:: - - Name: ATTENDEE - Params: CN=Max Rasmussen;ROLE=REQ-PARTICIPANT - Value: MAILTO:example@example.com - -Long content lines are usually "folded" to less than 75 character, but the -package takes care of that. - -Overview --------- - -On a higher level iCalendar files consists of components. Components can have -sub components. - -The root component is the VCALENDAR:: - - BEGIN:VCALENDAR - ... vcalendar properties ... - END:VCALENDAR - -The most frequent subcomponent to a VCALENDAR is a VEVENT. They are -nested like this:: - - BEGIN:VCALENDAR - ... vcalendar properties ... - BEGIN:VEVENT - ... vevent properties ... - END:VEVENT - END:VCALENDAR - -Inside the components there are properties with values. The values -have special types. like integer, text, datetime etc. These values are -encoded in a special text format in an iCalendar file. - -There are methods for converting to and from these encodings in the package. - -These are the most important imports:: - - >>> from icalendar import Calendar, Event - -Components ----------- - -Components are like (Case Insensitive) dicts. So if you want to set a property -you do it like this. The calendar is a component:: - - >>> cal = Calendar() - >>> cal['dtstart'] = '20050404T080000' - >>> cal['summary'] = 'Python meeting about calendaring' - >>> for k,v in cal.items(): - ... k,v - (u'DTSTART', '20050404T080000') - (u'SUMMARY', 'Python meeting about calendaring') - -NOTE: the recommended way to add components to the calendar is to use -create the subcomponent and add it via Calendar.add! The example above adds a -string, but not a vText component. - - -You can generate a string for a file with the to_ical() method:: - - >>> cal.to_ical() - 'BEGIN:VCALENDAR\r\nDTSTART:20050404T080000\r\nSUMMARY:Python meeting about calendaring\r\nEND:VCALENDAR\r\n' - -The rendered view is easier to read:: - - BEGIN:VCALENDAR - DTSTART:20050404T080000 - SUMMARY:Python meeting about calendaring - END:VCALENDAR - -So, let's define a function so we can easily display to_ical() output:: - - >>> def display(cal): - ... return cal.to_ical().replace('\r\n', '\n').strip() - -You can set multiple properties like this:: - - >>> cal = Calendar() - >>> cal['attendee'] = ['MAILTO:maxm@mxm.dk','MAILTO:test@example.com'] - >>> print display(cal) - BEGIN:VCALENDAR - ATTENDEE:MAILTO:maxm@mxm.dk - ATTENDEE:MAILTO:test@example.com - END:VCALENDAR - -If you don't want to care about whether a property value is a list or -a single value, just use the add() method. It will automatically -convert the property to a list of values if more than one value is -added. Here is an example:: - - >>> cal = Calendar() - >>> cal.add('attendee', 'MAILTO:maxm@mxm.dk') - >>> cal.add('attendee', 'MAILTO:test@example.com') - >>> print display(cal) - BEGIN:VCALENDAR - ATTENDEE:MAILTO:maxm@mxm.dk - ATTENDEE:MAILTO:test@example.com - END:VCALENDAR - -Note: this version doesn't check for compliance, so you should look in -the RFC 2445 spec for legal properties for each component, or look in -the icalendar/calendar.py file, where it is at least defined for each -component. - -Subcomponents -------------- - -Any component can have subcomponents. Eg. inside a calendar there can -be events. They can be arbitrarily nested. First by making a new -component:: - - >>> event = Event() - >>> event['uid'] = '42' - >>> event['dtstart'] = '20050404T080000' - -And then appending it to a "parent":: - - >>> cal.add_component(event) - >>> print display(cal) - BEGIN:VCALENDAR - ATTENDEE:MAILTO:maxm@mxm.dk - ATTENDEE:MAILTO:test@example.com - BEGIN:VEVENT - DTSTART:20050404T080000 - UID:42 - END:VEVENT - END:VCALENDAR - -Subcomponents are appended to the subcomponents property on the component:: - - >>> cal.subcomponents - [VEVENT({'DTSTART': '20050404T080000', 'UID': '42'})] - -Value types ------------ - -Property values are utf-8 encoded strings. - -This is impractical if you want to use the data for further -computation. Eg. the datetime format looks like this: -'20050404T080000'. But the package makes it simple to Parse and -generate iCalendar formatted strings. - -Basically you can make the add() method do the thinking, or you can do it -yourself. - -To add a datetime value, you can use Pythons built in datetime types, -and the set the encode parameter to true, and it will convert to the -type defined in the spec:: - - >>> from datetime import datetime - >>> cal.add('dtstart', datetime(2005,4,4,8,0,0)) - >>> cal['dtstart'].to_ical() - '20050404T080000' - -If that doesn't work satisfactorily for some reason, you can also do it -manually. - -In 'icalendar.prop', all the iCalendar data types are defined. Each -type has a class that can parse and encode the type. - -So if you want to do it manually:: - - >>> from icalendar import vDatetime - >>> now = datetime(2005,4,4,8,0,0) - >>> vDatetime(now).to_ical() - '20050404T080000' - -So the drill is to initialise the object with a python built in type, -and then call the "to_ical()" method on the object. That will return an -ical encoded string.
View file
icalendar-3.4.tar.gz/src/icalendar/tests/groupscheduled.ics
Deleted
@@ -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
View file
icalendar-3.4.tar.gz/src/icalendar/tests/groupscheduled.rst
Deleted
@@ -1,21 +0,0 @@ -An example from the RFC 2445 spec:: - - >>> from icalendar import Calendar - >>> import os - >>> directory = os.path.dirname(__file__) - >>> cal = Calendar.from_ical( - ... open(os.path.join(directory, 'groupscheduled.ics'),'rb').read()) - >>> cal - VCALENDAR({'VERSION': '2.0', 'PRODID': '-//RDU Software//NONSGML HandCal//EN'}) - - >>> timezones = cal.walk('VTIMEZONE') - >>> len(timezones) - 1 - - >>> tz = timezones[0] - >>> tz - VTIMEZONE({'TZID': 'US-Eastern'}) - - >>> std = tz.walk('STANDARD')[0] - >>> std.decoded('TZOFFSETFROM') - datetime.timedelta(-1, 72000)
View file
icalendar-3.4.tar.gz/src/icalendar/tests/multiple.rst
Deleted
@@ -1,19 +0,0 @@ -A exmaple with multiple VCALENDAR components:: - - >>> from icalendar import Calendar - >>> import os - >>> directory = os.path.dirname(__file__) - >>> cals = Calendar.from_ical( - ... open(os.path.join(directory, 'multiple.ics'),'rb').read(), multiple=True) - - >>> for cal in cals: - ... for component in cal.walk(): - ... component.name - 'VCALENDAR' - 'VEVENT' - 'VCALENDAR' - 'VEVENT' - 'VEVENT' - - >>> cals[0]['prodid'] - vText('-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN')
View file
icalendar-3.4.tar.gz/src/icalendar/tests/recurrence.rst
Deleted
@@ -1,21 +0,0 @@ -Testing recurrence. - - >>> from icalendar import Calendar - >>> import os - >>> directory = os.path.dirname(__file__) - >>> cal = Calendar.from_ical( - ... open(os.path.join(directory, 'recurrence.ics'),'rb').read()) - >>> first_event = cal.walk('vevent')[0] - - >>> first_event['rrule'] - CaselessDict({'COUNT': [100], 'FREQ': ['DAILY']}) - - >>> first_event['exdate'].dts[0].dt - datetime.datetime(1996, 4, 2, 1, 0, tzinfo=<UTC>) - - >>> first_event['exdate'].dts[1].dt - datetime.datetime(1996, 4, 3, 1, 0, tzinfo=<UTC>) - - >>> first_event['exdate'].dts[2].dt - datetime.datetime(1996, 4, 4, 1, 0, tzinfo=<UTC>) -
View file
icalendar-3.4.tar.gz/src/icalendar/tests/small.ics
Deleted
@@ -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
View file
icalendar-3.4.tar.gz/src/icalendar/tests/small.rst
Deleted
@@ -1,30 +0,0 @@ -A small example:: - - >>> from icalendar import Calendar - >>> import os - >>> directory = os.path.dirname(__file__) - >>> cal = Calendar.from_ical( - ... open(os.path.join(directory, 'small.ics'),'rb').read()) - >>> cal - VCALENDAR({'VERSION': '2.0', - 'METHOD': 'Request', - 'PRODID': '-//My product//mxm.dk/'}) - - >>> for component in cal.walk(): - ... component.name - 'VCALENDAR' - 'VEVENT' - 'VEVENT' - - >>> cal['prodid'] - vText('-//My product//mxm.dk/') - - >>> cal.decoded('prodid') - '-//My product//mxm.dk/' - - >>> first_event = cal.walk('vevent')[0] - >>> first_event['description'][:75] - u'This is a very long description that will be folded This is a very long des' - - >>> first_event['summary'] - vText('A second event')
View file
icalendar-3.4.tar.gz/CHANGES.rst -> icalendar-3.8.2.tar.gz/CHANGES.rst
Changed
@@ -2,6 +2,120 @@ Changelog ========= +3.8.2 (2014-07-22) +------------------ + +- Exclude editor backup files from egg distributions. Fixes #144. + [thet] + + +3.8.1 (2014-07-17) +------------------ + +- The representation of CaselessDicts in 3.8 changed the name attribute of + Components and therefore broke the external API. This has been fixed. + [untitaker] + + +3.8 (2014-07-17) +---------------- + +- Allow dots in property names (Needed for vCard compatibility). Refs #143. + [untitaker] + +- Change class representation for CaselessDict objects to always include the + class name or the class' name attribute, if available. Also show + subcomponents for Component objects. + [thet] + +- Don't use data_encode for CaselessDict class representation but use dict's + __repr__ method. + [t-8ch] + +- Handle parameters with multiple values, which is needed for vCard 3.0. + Refs #142. + [t-8ch] + + +3.7 (2014-06-02) +---------------- + +- For components with ``ignore_exceptions`` set to ``True``, mark unparseable + lines as broken instead rising a ``ValueError``. ``VEVENT`` components have + ``ignore_exceptions`` set to ``True`` by default. Ref #131. Fixes #104. + [jkiang13] + +- Make ``python-dateutil`` a soft-dependency. + [boltnev] + +- Add optional ``sorted`` parameter to ``Component.to_ical``. Setting it to + false allows the user to preserve the original property and parameter order. + Ref #136. Fixes #133. + [untitaker] + +- Fix tests for latest ``pytz``. Don't set ``tzinfo`` directly on datetime + objects, but use pytz's ``localize`` function. Ref #138. + [untitaker, thet] + +- Remove incorrect use of __all__. We don't encourage using ``from package + import *`` imports. Fixes #129. + [eric-wieser] + + +3.6.2 (2014-04-05) +------------------ + +- Pep8 and cleanup. + [lasudry] + +3.6.1 (2014-01-13) +------------------ + +- Open text files referenced by setup.py as utf-8, no matter what the locale + settings are set to. Fixes #122. + [sochotnicky] + +- Add tox.ini to source tarball, which simplifies testing for in distributions. + [sochotnicky] + + +3.6 (2014-01-06) +---------------- + +- Python3 (3.3+) + Python 2 (2.6+) support [geier] + +- Made sure to_ical() always returns bytes [geier] + +- Support adding lists to a component property, which value already was a list + and remove the Component.set method, which was only used by the add method. + [thet] + +- Remove ability to add property parameters via a value's params attribute when + adding via cal.add (that was only possible for custom value objects and makes + up a strange API), but support a parameter attribute on cal.add's method + signature to pass a dictionary with property parameter key/value pairs. + Fixes #116. + [thet] + +- Backport some of Regebro's changes from his regebro-refactor branch. + [thet] + +- Raise explicit error on another malformed content line case. + [hajdbo] + +- Correctly parse datetime component property values with timezone information + when parsed from ical strings. + [untitaker] + + +3.5 (2013-07-03) +---------------- + +- Let to_unicode be more graceful for non-unicode strings, as like CMFPlone's + safe_unicode does it. + [thet] + + 3.4 (2013-04-24) ----------------
View file
icalendar-3.4.tar.gz/MANIFEST.in -> icalendar-3.8.2.tar.gz/MANIFEST.in
Changed
@@ -1,4 +1,4 @@ -include *.rst +include *.rst tox.ini graft docs recursive-include src/icalendar * -recursive-exclude src/icalendar *.pyc +recursive-exclude src/icalendar *.pyc *~
View file
icalendar-3.4.tar.gz/PKG-INFO -> icalendar-3.8.2.tar.gz/PKG-INFO
Changed
@@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: icalendar -Version: 3.4 +Version: 3.8.2 Summary: iCalendar parser/generator Home-page: https://github.com/collective/icalendar Author: Plone Foundation @@ -19,12 +19,23 @@ :Code: http://github.com/collective/icalendar :Mailing list: http://github.com/collective/icalendar/issues :Dependencies: `setuptools`_ and since version 3.0 we depend on `pytz`_. - :Compatible with: Python 2.6 and 2.7 + :Compatible with: Python 2.6, 2.7 and 3.3+ :License: `BSD`_ ---- + .. image:: https://travis-ci.org/collective/icalendar.svg?branch=master + :target: https://travis-ci.org/collective/icalendar + + + Roadmap + ======= + + - 4.0: API refactoring + + + Changes in version 3.0 ====================== @@ -55,21 +66,6 @@ Instead of the own UTC tzinfo implementation we use pytz UTC tzinfo object now. - Roadmap - ======= - - 1) Internally Unicode will be used exclusively. - - 2) On API Functions, accept or return Unicode or en/decoded strings. - - 3) This will make the 3.4 Release. - - 4) API change: API calls also only accept/return Unicode. - - 5) This will make the 4.0 release. - - - About this fork which is not a fork anymore =========================================== @@ -95,21 +91,136 @@ Output from coverage test:: - Name Stmts Miss Cover - ---------------------------------------------------------------------------------- - .tox/py27/lib/python2.7/site-packages/icalendar/__init__ 6 0 100% - .tox/py27/lib/python2.7/site-packages/icalendar/cal 223 8 96% - .tox/py27/lib/python2.7/site-packages/icalendar/caselessdict 55 2 96% - .tox/py27/lib/python2.7/site-packages/icalendar/parser 181 18 90% - .tox/py27/lib/python2.7/site-packages/icalendar/parser_tools 19 0 100% - .tox/py27/lib/python2.7/site-packages/icalendar/prop 521 59 89% - .tox/py27/lib/python2.7/site-packages/icalendar/tools 12 0 100% - ---------------------------------------------------------------------------------- - TOTAL 1017 87 91% + Name Stmts Miss Cover + ------------------------------------------------ + src/icalendar/__init__ 4 0 100% + src/icalendar/cal 243 7 97% + src/icalendar/caselessdict 66 7 89% + src/icalendar/compat 1 0 100% + src/icalendar/parser 192 6 97% + src/icalendar/parser_tools 20 0 100% + src/icalendar/prop 536 64 88% + src/icalendar/tools 16 0 100% + ------------------------------------------------ + TOTAL 1078 84 92% Changelog ========= + 3.8.2 (2014-07-22) + ------------------ + + - Exclude editor backup files from egg distributions. Fixes #144. + [thet] + + + 3.8.1 (2014-07-17) + ------------------ + + - The representation of CaselessDicts in 3.8 changed the name attribute of + Components and therefore broke the external API. This has been fixed. + [untitaker] + + + 3.8 (2014-07-17) + ---------------- + + - Allow dots in property names (Needed for vCard compatibility). Refs #143. + [untitaker] + + - Change class representation for CaselessDict objects to always include the + class name or the class' name attribute, if available. Also show + subcomponents for Component objects. + [thet] + + - Don't use data_encode for CaselessDict class representation but use dict's + __repr__ method. + [t-8ch] + + - Handle parameters with multiple values, which is needed for vCard 3.0. + Refs #142. + [t-8ch] + + + 3.7 (2014-06-02) + ---------------- + + - For components with ``ignore_exceptions`` set to ``True``, mark unparseable + lines as broken instead rising a ``ValueError``. ``VEVENT`` components have + ``ignore_exceptions`` set to ``True`` by default. Ref #131. Fixes #104. + [jkiang13] + + - Make ``python-dateutil`` a soft-dependency. + [boltnev] + + - Add optional ``sorted`` parameter to ``Component.to_ical``. Setting it to + false allows the user to preserve the original property and parameter order. + Ref #136. Fixes #133. + [untitaker] + + - Fix tests for latest ``pytz``. Don't set ``tzinfo`` directly on datetime + objects, but use pytz's ``localize`` function. Ref #138. + [untitaker, thet] + + - Remove incorrect use of __all__. We don't encourage using ``from package + import *`` imports. Fixes #129. + [eric-wieser] + + + 3.6.2 (2014-04-05) + ------------------ + + - Pep8 and cleanup. + [lasudry] + + 3.6.1 (2014-01-13) + ------------------ + + - Open text files referenced by setup.py as utf-8, no matter what the locale + settings are set to. Fixes #122. + [sochotnicky] + + - Add tox.ini to source tarball, which simplifies testing for in distributions. + [sochotnicky] + + + 3.6 (2014-01-06) + ---------------- + + - Python3 (3.3+) + Python 2 (2.6+) support [geier] + + - Made sure to_ical() always returns bytes [geier] + + - Support adding lists to a component property, which value already was a list + and remove the Component.set method, which was only used by the add method. + [thet] + + - Remove ability to add property parameters via a value's params attribute when + adding via cal.add (that was only possible for custom value objects and makes + up a strange API), but support a parameter attribute on cal.add's method + signature to pass a dictionary with property parameter key/value pairs. + Fixes #116. + [thet] + + - Backport some of Regebro's changes from his regebro-refactor branch. + [thet] + + - Raise explicit error on another malformed content line case. + [hajdbo] + + - Correctly parse datetime component property values with timezone information + when parsed from ical strings. + [untitaker] + + + 3.5 (2013-07-03) + ---------------- + + - Let to_unicode be more graceful for non-unicode strings, as like CMFPlone's + safe_unicode does it. + [thet] + +
View file
icalendar-3.4.tar.gz/README.rst -> icalendar-3.8.2.tar.gz/README.rst
Changed
@@ -11,12 +11,23 @@ :Code: http://github.com/collective/icalendar :Mailing list: http://github.com/collective/icalendar/issues :Dependencies: `setuptools`_ and since version 3.0 we depend on `pytz`_. - :Compatible with: Python 2.6 and 2.7 + :Compatible with: Python 2.6, 2.7 and 3.3+ :License: `BSD`_ ---- +.. image:: https://travis-ci.org/collective/icalendar.svg?branch=master + :target: https://travis-ci.org/collective/icalendar + + +Roadmap +======= + +- 4.0: API refactoring + + + Changes in version 3.0 ====================== @@ -47,21 +58,6 @@ Instead of the own UTC tzinfo implementation we use pytz UTC tzinfo object now. -Roadmap -======= - -1) Internally Unicode will be used exclusively. - -2) On API Functions, accept or return Unicode or en/decoded strings. - -3) This will make the 3.4 Release. - -4) API change: API calls also only accept/return Unicode. - -5) This will make the 4.0 release. - - - About this fork which is not a fork anymore =========================================== @@ -87,14 +83,15 @@ Output from coverage test:: - Name Stmts Miss Cover - ---------------------------------------------------------------------------------- - .tox/py27/lib/python2.7/site-packages/icalendar/__init__ 6 0 100% - .tox/py27/lib/python2.7/site-packages/icalendar/cal 223 8 96% - .tox/py27/lib/python2.7/site-packages/icalendar/caselessdict 55 2 96% - .tox/py27/lib/python2.7/site-packages/icalendar/parser 181 18 90% - .tox/py27/lib/python2.7/site-packages/icalendar/parser_tools 19 0 100% - .tox/py27/lib/python2.7/site-packages/icalendar/prop 521 59 89% - .tox/py27/lib/python2.7/site-packages/icalendar/tools 12 0 100% - ---------------------------------------------------------------------------------- - TOTAL 1017 87 91% + Name Stmts Miss Cover + ------------------------------------------------ + src/icalendar/__init__ 4 0 100% + src/icalendar/cal 243 7 97% + src/icalendar/caselessdict 66 7 89% + src/icalendar/compat 1 0 100% + src/icalendar/parser 192 6 97% + src/icalendar/parser_tools 20 0 100% + src/icalendar/prop 536 64 88% + src/icalendar/tools 16 0 100% + ------------------------------------------------ + TOTAL 1078 84 92%
View file
icalendar-3.4.tar.gz/docs/credits.rst -> icalendar-3.8.2.tar.gz/docs/credits.rst
Changed
@@ -7,6 +7,7 @@ - Andrey Nikolaev <nikolaeff@gmail.com> - Barak Michener <me@barakmich.com> - Christophe de Vienne <cdevienne@gmail.com> +- Christian Geier <contact@lostpackets.de> - Dai MIKURUBE <dmikurube@acm.org> - Dan Stovall <dbstovall@gmail.com> - Eric Hanchrow <erich@cozi.com> @@ -29,7 +30,10 @@ - Ronan Dunklau <ronan@dunklau.fr> - Sidnei da Silva <sidnei@enfoldsystems.com> - Stanislav Ochotnicky <sochotnicky@redhat.com> +- Stefan Schwarzer <sschwarzer@sschwarzer.net> - Victor Varvaryuk <victor.varvariuc@gmail.com> - Wichert Akkerman <wichert@wiggy.net> - spanktar <spanky@kapanka.com> - tgecho <tgecho@gmail.com> +- Markus Unterwaditzer <markus@unterwaditzer.net> +- Thomas Weißschuh <thomas@t-8ch.de>
View file
icalendar-3.4.tar.gz/docs/index.rst -> icalendar-3.8.2.tar.gz/docs/index.rst
Changed
@@ -9,8 +9,7 @@ about install - examples + usage RFC 5545 <rfc5545/index> - changelog credits license
View file
icalendar-3.8.2.tar.gz/docs/usage.rst
Added
@@ -0,0 +1,324 @@ +iCalendar package +================= + +This package is used for parsing and generating iCalendar files following the +standard in RFC 2445. + +It should be fully compliant, but it is possible to generate and parse invalid +files if you really want to. + + +File structure +-------------- + +An iCalendar file is a text file (utf-8) with a special format. Basically it +consists of content lines. + +Each content line defines a property that has 3 parts (name, parameters, +values). Parameters are optional. + +A simple content line with only name and value could look like this:: + + BEGIN:VCALENDAR + +A content line with parameters can look like this:: + + ATTENDEE;CN=Max Rasmussen;ROLE=REQ-PARTICIPANT:MAILTO:example@example.com + +And the parts are:: + + Name: ATTENDEE + Params: CN=Max Rasmussen;ROLE=REQ-PARTICIPANT + Value: MAILTO:example@example.com + +Long content lines are usually "folded" to less than 75 character, but the +package takes care of that. + + +Overview +-------- + +On a higher level iCalendar files consists of components. Components can have +sub components. + +The root component is the VCALENDAR:: + + BEGIN:VCALENDAR + ... vcalendar properties ... + END:VCALENDAR + +The most frequent subcomponent to a VCALENDAR is a VEVENT. They are +nested like this:: + + BEGIN:VCALENDAR + ... vcalendar properties ... + BEGIN:VEVENT + ... vevent properties ... + END:VEVENT + END:VCALENDAR + +Inside the components there are properties with values. The values +have special types. like integer, text, datetime etc. These values are +encoded in a special text format in an iCalendar file. + +There are methods for converting to and from these encodings in the package. + +These are the most important imports:: + + >>> from icalendar import Calendar, Event + + +Components +---------- + +Components are like (Case Insensitive) dicts. So if you want to set a property +you do it like this. The calendar is a component:: + + >>> cal = Calendar() + >>> cal['dtstart'] = '20050404T080000' + >>> cal['summary'] = 'Python meeting about calendaring' + >>> for k,v in cal.items(): + ... k,v + (u'DTSTART', '20050404T080000') + (u'SUMMARY', 'Python meeting about calendaring') + +NOTE: the recommended way to add components to the calendar is to use +create the subcomponent and add it via Calendar.add! The example above adds a +string, but not a vText component. + + +You can generate a string for a file with the to_ical() method:: + + >>> cal.to_ical() + 'BEGIN:VCALENDAR\r\nDTSTART:20050404T080000\r\nSUMMARY:Python meeting about calendaring\r\nEND:VCALENDAR\r\n' + +The rendered view is easier to read:: + + BEGIN:VCALENDAR + DTSTART:20050404T080000 + SUMMARY:Python meeting about calendaring + END:VCALENDAR + +So, let's define a function so we can easily display to_ical() output:: + + >>> def display(cal): + ... return cal.to_ical().replace('\r\n', '\n').strip() + +You can set multiple properties like this:: + + >>> cal = Calendar() + >>> cal['attendee'] = ['MAILTO:maxm@mxm.dk','MAILTO:test@example.com'] + >>> print display(cal) + BEGIN:VCALENDAR + ATTENDEE:MAILTO:maxm@mxm.dk + ATTENDEE:MAILTO:test@example.com + END:VCALENDAR + +If you don't want to care about whether a property value is a list or +a single value, just use the add() method. It will automatically +convert the property to a list of values if more than one value is +added. Here is an example:: + + >>> cal = Calendar() + >>> cal.add('attendee', 'MAILTO:maxm@mxm.dk') + >>> cal.add('attendee', 'MAILTO:test@example.com') + >>> print display(cal) + BEGIN:VCALENDAR + ATTENDEE:MAILTO:maxm@mxm.dk + ATTENDEE:MAILTO:test@example.com + END:VCALENDAR + +Note: this version doesn't check for compliance, so you should look in +the RFC 2445 spec for legal properties for each component, or look in +the icalendar/calendar.py file, where it is at least defined for each +component. + + +Subcomponents +------------- + +Any component can have subcomponents. Eg. inside a calendar there can +be events. They can be arbitrarily nested. First by making a new +component:: + + >>> event = Event() + >>> event['uid'] = '42' + >>> event['dtstart'] = '20050404T080000' + +And then appending it to a "parent":: + + >>> cal.add_component(event) + >>> print display(cal) + BEGIN:VCALENDAR + ATTENDEE:MAILTO:maxm@mxm.dk + ATTENDEE:MAILTO:test@example.com + BEGIN:VEVENT + DTSTART:20050404T080000 + UID:42 + END:VEVENT + END:VCALENDAR + +Subcomponents are appended to the subcomponents property on the component:: + + >>> cal.subcomponents + [VEVENT({'DTSTART': '20050404T080000', 'UID': '42'})] + + +Value types +----------- + +Property values are utf-8 encoded strings. + +This is impractical if you want to use the data for further +computation. Eg. the datetime format looks like this: +'20050404T080000'. But the package makes it simple to Parse and +generate iCalendar formatted strings. + +Basically you can make the add() method do the thinking, or you can do it +yourself. + +To add a datetime value, you can use Pythons built in datetime types, +and the set the encode parameter to true, and it will convert to the +type defined in the spec:: + + >>> from datetime import datetime + >>> cal.add('dtstart', datetime(2005,4,4,8,0,0)) + >>> cal['dtstart'].to_ical() + '20050404T080000' + +If that doesn't work satisfactorily for some reason, you can also do it +manually. + +In 'icalendar.prop', all the iCalendar data types are defined. Each +type has a class that can parse and encode the type. + +So if you want to do it manually:: + + >>> from icalendar import vDatetime + >>> now = datetime(2005,4,4,8,0,0) + >>> vDatetime(now).to_ical()
View file
icalendar-3.4.tar.gz/setup.py -> icalendar-3.8.2.tar.gz/setup.py
Changed
@@ -1,11 +1,29 @@ +import codecs import setuptools +import sys -version = '3.4' + +version = '3.8.2' shortdesc = 'iCalendar parser/generator' -longdesc = open('README.rst').read() -longdesc += open('CHANGES.rst').read() -longdesc += open('LICENSE.rst').read() -tests_require = ['unittest2'] +longdesc = codecs.open('README.rst', encoding='utf-8').read() +longdesc += codecs.open('CHANGES.rst', encoding='utf-8').read() +longdesc += codecs.open('LICENSE.rst', encoding='utf-8').read() + + +tests_require = [ + 'python-dateutil', +] +install_requires = [ + 'setuptools', + 'pytz' +] + +if sys.version_info[:2] == (2, 6): + # Python unittest2 only needed for Python 2.6 + tests_require.append('unittest2') + # OrderedDict was added in 2.7 + install_requires.append('ordereddict') + setuptools.setup( name='icalendar', @@ -15,24 +33,26 @@ classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', + "Programming Language :: Python", + "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.3", 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', - ], + ], keywords='calendar calendaring ical icalendar event todo journal ' 'recurring', author='Plone Foundation', - author_email='plone-developers@lists.sourceforge.net', + author_email='plone-developers@lists.sourceforge.net', url='https://github.com/collective/icalendar', license='BSD', packages=setuptools.find_packages('src'), package_dir={'': 'src'}, include_package_data=True, zip_safe=False, - install_requires=[ - 'setuptools', - 'python-dateutil', - 'pytz', - ], + install_requires=install_requires, extras_require={ 'test': tests_require - }) + } +)
View file
icalendar-3.4.tar.gz/src/icalendar.egg-info/PKG-INFO -> icalendar-3.8.2.tar.gz/src/icalendar.egg-info/PKG-INFO
Changed
@@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: icalendar -Version: 3.4 +Version: 3.8.2 Summary: iCalendar parser/generator Home-page: https://github.com/collective/icalendar Author: Plone Foundation @@ -19,12 +19,23 @@ :Code: http://github.com/collective/icalendar :Mailing list: http://github.com/collective/icalendar/issues :Dependencies: `setuptools`_ and since version 3.0 we depend on `pytz`_. - :Compatible with: Python 2.6 and 2.7 + :Compatible with: Python 2.6, 2.7 and 3.3+ :License: `BSD`_ ---- + .. image:: https://travis-ci.org/collective/icalendar.svg?branch=master + :target: https://travis-ci.org/collective/icalendar + + + Roadmap + ======= + + - 4.0: API refactoring + + + Changes in version 3.0 ====================== @@ -55,21 +66,6 @@ Instead of the own UTC tzinfo implementation we use pytz UTC tzinfo object now. - Roadmap - ======= - - 1) Internally Unicode will be used exclusively. - - 2) On API Functions, accept or return Unicode or en/decoded strings. - - 3) This will make the 3.4 Release. - - 4) API change: API calls also only accept/return Unicode. - - 5) This will make the 4.0 release. - - - About this fork which is not a fork anymore =========================================== @@ -95,21 +91,136 @@ Output from coverage test:: - Name Stmts Miss Cover - ---------------------------------------------------------------------------------- - .tox/py27/lib/python2.7/site-packages/icalendar/__init__ 6 0 100% - .tox/py27/lib/python2.7/site-packages/icalendar/cal 223 8 96% - .tox/py27/lib/python2.7/site-packages/icalendar/caselessdict 55 2 96% - .tox/py27/lib/python2.7/site-packages/icalendar/parser 181 18 90% - .tox/py27/lib/python2.7/site-packages/icalendar/parser_tools 19 0 100% - .tox/py27/lib/python2.7/site-packages/icalendar/prop 521 59 89% - .tox/py27/lib/python2.7/site-packages/icalendar/tools 12 0 100% - ---------------------------------------------------------------------------------- - TOTAL 1017 87 91% + Name Stmts Miss Cover + ------------------------------------------------ + src/icalendar/__init__ 4 0 100% + src/icalendar/cal 243 7 97% + src/icalendar/caselessdict 66 7 89% + src/icalendar/compat 1 0 100% + src/icalendar/parser 192 6 97% + src/icalendar/parser_tools 20 0 100% + src/icalendar/prop 536 64 88% + src/icalendar/tools 16 0 100% + ------------------------------------------------ + TOTAL 1078 84 92% Changelog ========= + 3.8.2 (2014-07-22) + ------------------ + + - Exclude editor backup files from egg distributions. Fixes #144. + [thet] + + + 3.8.1 (2014-07-17) + ------------------ + + - The representation of CaselessDicts in 3.8 changed the name attribute of + Components and therefore broke the external API. This has been fixed. + [untitaker] + + + 3.8 (2014-07-17) + ---------------- + + - Allow dots in property names (Needed for vCard compatibility). Refs #143. + [untitaker] + + - Change class representation for CaselessDict objects to always include the + class name or the class' name attribute, if available. Also show + subcomponents for Component objects. + [thet] + + - Don't use data_encode for CaselessDict class representation but use dict's + __repr__ method. + [t-8ch] + + - Handle parameters with multiple values, which is needed for vCard 3.0. + Refs #142. + [t-8ch] + + + 3.7 (2014-06-02) + ---------------- + + - For components with ``ignore_exceptions`` set to ``True``, mark unparseable + lines as broken instead rising a ``ValueError``. ``VEVENT`` components have + ``ignore_exceptions`` set to ``True`` by default. Ref #131. Fixes #104. + [jkiang13] + + - Make ``python-dateutil`` a soft-dependency. + [boltnev] + + - Add optional ``sorted`` parameter to ``Component.to_ical``. Setting it to + false allows the user to preserve the original property and parameter order. + Ref #136. Fixes #133. + [untitaker] + + - Fix tests for latest ``pytz``. Don't set ``tzinfo`` directly on datetime + objects, but use pytz's ``localize`` function. Ref #138. + [untitaker, thet] + + - Remove incorrect use of __all__. We don't encourage using ``from package + import *`` imports. Fixes #129. + [eric-wieser] + + + 3.6.2 (2014-04-05) + ------------------ + + - Pep8 and cleanup. + [lasudry] + + 3.6.1 (2014-01-13) + ------------------ + + - Open text files referenced by setup.py as utf-8, no matter what the locale + settings are set to. Fixes #122. + [sochotnicky] + + - Add tox.ini to source tarball, which simplifies testing for in distributions. + [sochotnicky] + + + 3.6 (2014-01-06) + ---------------- + + - Python3 (3.3+) + Python 2 (2.6+) support [geier] + + - Made sure to_ical() always returns bytes [geier] + + - Support adding lists to a component property, which value already was a list + and remove the Component.set method, which was only used by the add method. + [thet] + + - Remove ability to add property parameters via a value's params attribute when + adding via cal.add (that was only possible for custom value objects and makes + up a strange API), but support a parameter attribute on cal.add's method + signature to pass a dictionary with property parameter key/value pairs. + Fixes #116. + [thet] + + - Backport some of Regebro's changes from his regebro-refactor branch. + [thet] + + - Raise explicit error on another malformed content line case. + [hajdbo] + + - Correctly parse datetime component property values with timezone information + when parsed from ical strings. + [untitaker] + + + 3.5 (2013-07-03) + ---------------- + + - Let to_unicode be more graceful for non-unicode strings, as like CMFPlone's + safe_unicode does it. + [thet] + +
View file
icalendar-3.4.tar.gz/src/icalendar.egg-info/SOURCES.txt -> icalendar-3.8.2.tar.gz/src/icalendar.egg-info/SOURCES.txt
Changed
@@ -1,30 +1,26 @@ -.gitignore -.travis.yml CHANGES.rst CONTRIBUTING.rst LICENSE.rst MANIFEST.in README.rst TODO.rst -bootstrap.py -buildout.cfg setup.py tox.ini docs/Makefile docs/about.rst -docs/changelog.rst docs/conf.py docs/credits.rst -docs/examples.rst docs/index.rst docs/install.rst docs/license.rst +docs/usage.rst docs/_themes/icalendar/layout.html docs/_themes/icalendar/theme.conf docs/_themes/icalendar/static/icalendar.css src/icalendar/__init__.py src/icalendar/cal.py src/icalendar/caselessdict.py +src/icalendar/compat.py src/icalendar/parser.py src/icalendar/parser_tools.py src/icalendar/prop.py @@ -36,21 +32,17 @@ src/icalendar.egg-info/requires.txt src/icalendar.egg-info/top_level.txt src/icalendar/tests/__init__.py -src/icalendar/tests/case_meetup.ics src/icalendar/tests/encoding.ics -src/icalendar/tests/example.rst -src/icalendar/tests/groupscheduled.ics -src/icalendar/tests/groupscheduled.rst +src/icalendar/tests/issue_112_missing_tzinfo_on_exdate.ics +src/icalendar/tests/issue_53_parsing_failure.ics src/icalendar/tests/multiple.ics -src/icalendar/tests/multiple.rst src/icalendar/tests/recurrence.ics -src/icalendar/tests/recurrence.rst -src/icalendar/tests/small.ics -src/icalendar/tests/small.rst src/icalendar/tests/test_encoding.py src/icalendar/tests/test_fixed_issues.py src/icalendar/tests/test_icalendar.py +src/icalendar/tests/test_multiple.py src/icalendar/tests/test_property_params.py +src/icalendar/tests/test_recurrence.py src/icalendar/tests/test_time.py src/icalendar/tests/test_timezoned.py src/icalendar/tests/test_unit_cal.py
View file
icalendar-3.4.tar.gz/src/icalendar.egg-info/requires.txt -> icalendar-3.8.2.tar.gz/src/icalendar.egg-info/requires.txt
Changed
@@ -1,6 +1,5 @@ setuptools -python-dateutil pytz [test] -unittest2 \ No newline at end of file +python-dateutil \ No newline at end of file
View file
icalendar-3.4.tar.gz/src/icalendar/__init__.py -> icalendar-3.8.2.tar.gz/src/icalendar/__init__.py
Changed
@@ -1,7 +1,4 @@ -from __future__ import absolute_import - - -from .cal import ( +from icalendar.cal import ( Calendar, Event, Todo, @@ -14,7 +11,7 @@ ComponentFactory, ) # Property Data Value Types -from .prop import ( +from icalendar.prop import ( vBinary, vBoolean, vCalAddress, @@ -36,27 +33,14 @@ TypesFactory, ) # useful tzinfo subclasses -from .prop import ( +from icalendar.prop import ( FixedOffset, LocalTimezone, ) # Parameters and helper methods for splitting and joining string with escaped # chars. -from .parser import ( +from icalendar.parser import ( Parameters, q_split, q_join, ) - - -__all__ = [ - Calendar, Event, Todo, Journal, - FreeBusy, Alarm, ComponentFactory, - Timezone, TimezoneStandard, TimezoneDaylight, - vBinary, vBoolean, vCalAddress, vDatetime, vDate, - vDDDTypes, vDuration, vFloat, vInt, vPeriod, - vWeekday, vFrequency, vRecur, vText, vTime, vUri, - vGeo, vUTCOffset, TypesFactory, - FixedOffset, LocalTimezone, - Parameters, q_split, q_join, -]
View file
icalendar-3.4.tar.gz/src/icalendar/cal.py -> icalendar-3.8.2.tar.gz/src/icalendar/cal.py
Changed
@@ -3,23 +3,19 @@ files according to rfc2445. These are the defined components. - """ -from __future__ import absolute_import -import pytz from datetime import datetime -from .parser_tools import data_encode -from .caselessdict import CaselessDict -from .parser import ( - Contentlines, - Contentline, - Parameters, - q_split, - q_join, -) -from .prop import TypesFactory -from .prop import vText, vDDDLists -from .parser_tools import DEFAULT_ENCODING +from icalendar.caselessdict import CaselessDict +from icalendar.parser import Contentline +from icalendar.parser import Contentlines +from icalendar.parser import Parameters +from icalendar.parser import q_join +from icalendar.parser import q_split +from icalendar.parser_tools import DEFAULT_ENCODING +from icalendar.prop import TypesFactory +from icalendar.prop import vText, vDDDLists + +import pytz ###################################### @@ -28,13 +24,12 @@ 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): """Set keys to upper for initial dict. """ - CaselessDict.__init__(self, *args, **kwargs) + super(ComponentFactory, self).__init__(*args, **kwargs) self['VEVENT'] = Event self['VTODO'] = Todo self['VJOURNAL'] = Journal @@ -48,9 +43,11 @@ # These Properties have multiple property values inlined in one propertyline # seperated by comma. Use CaselessDict as simple caseless set. -INLINE = CaselessDict( - [(cat, 1) for cat in ('CATEGORIES', 'RESOURCES', 'FREEBUSY')] -) +INLINE = CaselessDict({ + 'CATEGORIES': 1, + 'RESOURCES': 1, + 'FREEBUSY': 1, +}) _marker = [] @@ -59,15 +56,15 @@ """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 = None # should 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 +73,12 @@ def __init__(self, *args, **kwargs): """Set keys to upper for initial dict. - """ - CaselessDict.__init__(self, *args, **kwargs) + super(Component, self).__init__(*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,38 +90,67 @@ # """ # return name in not_compliant - ############################# # handling of property values - def _encode(self, name, value, cond=1): - """Conditional convertion of values. + def _encode(self, name, value, parameters=None, encode=1): + """Encode values to icalendar property values. + + :param name: Name of the property. + :type name: string + + :param value: Value of the property. Either of a basic Python type of + any of the icalendar's own property types. + :type value: Python native type or icalendar property type. + :param parameters: Property parameter dictionary for the value. Only + available, if encode is set to True. + :type parameters: Dictionary + + :param encode: True, if the value should be encoded to one of + icalendar's own property types (Fallback is "vText") + or False, if not. + :type encode: Boolean + + :returns: icalendar property value """ - if not cond: + if not encode: return value - if type(value) in types_factory.all_types: + if isinstance(value, types_factory.all_types): # Don't encode already encoded values. return value klass = types_factory.for_property(name) obj = klass(value) - if hasattr(value, 'params') and len(value.params.keys()) > 0: - # TODO: How can a python native value have params? - obj.params = value.params + if parameters: + if isinstance(parameters, dict): + params = Parameters() + for key, item in parameters.items(): + params[key] = item + parameters = params + assert isinstance(parameters, Parameters) + obj.params = parameters return obj - def set(self, name, value, encode=1): - if encode and isinstance(value, list) \ - and name.lower() not in ['rdate', 'exdate']: - # Individually convert each value to an ical type except rdate and - # exdate, where lists of dates might be passed to vDDDLists. - self[name] = [self._encode(name, v, encode) for v in value] - else: - self[name] = self._encode(name, value, encode) - - def add(self, name, value, encode=1): + def add(self, name, value, parameters=None, encode=1): """Add a property. + :param name: Name of the property. + :type name: string + + :param value: Value of the property. Either of a basic Python type of + any of the icalendar's own property types. + :type value: Python native type or icalendar property type. + + :param parameters: Property parameter dictionary for the value. Only + available, if encode is set to True. + :type parameters: Dictionary + + :param encode: True, if the value should be encoded to one of + icalendar's own property types (Fallback is "vText") + or False, if not. + :type encode: Boolean + + :returns: None """ if isinstance(value, datetime) and\ name.lower() in ('dtstamp', 'created', 'last-modified'): @@ -135,20 +161,31 @@ # assume UTC for naive datetime instances value = pytz.utc.localize(value) - # If property already exists, append it. Otherwise create and set it. + # encode value + if encode and isinstance(value, list) \ + and name.lower() not in ['rdate', 'exdate']: + # Individually convert each value to an ical type except rdate and
View file
icalendar-3.4.tar.gz/src/icalendar/caselessdict.py -> icalendar-3.8.2.tar.gz/src/icalendar/caselessdict.py
Changed
@@ -1,12 +1,16 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import -from .parser_tools import to_unicode, data_encode +from icalendar.compat import iteritems +from icalendar.parser_tools import to_unicode + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict 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,90 +20,91 @@ 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)] -class CaselessDict(dict): +class CaselessDict(OrderedDict): """A dictionary that isn't case sensitive, and only uses strings as keys. Values retain their case. - """ def __init__(self, *args, **kwargs): """Set keys to upper for initial dict. """ - dict.__init__(self, *args, **kwargs) + super(CaselessDict, self).__init__(*args, **kwargs) for key, value in self.items(): key_upper = to_unicode(key).upper() if key != key_upper: - dict.__delitem__(self, key) + super(CaselessDict, self).__delitem__(key) self[key_upper] = value def __getitem__(self, key): key = to_unicode(key) - return dict.__getitem__(self, key.upper()) + return super(CaselessDict, self).__getitem__(key.upper()) def __setitem__(self, key, value): key = to_unicode(key) - dict.__setitem__(self, key.upper(), value) + super(CaselessDict, self).__setitem__(key.upper(), value) def __delitem__(self, key): key = to_unicode(key) - dict.__delitem__(self, key.upper()) + super(CaselessDict, self).__delitem__(key.upper()) def __contains__(self, key): key = to_unicode(key) - return dict.__contains__(self, key.upper()) + return super(CaselessDict, self).__contains__(key.upper()) def get(self, key, default=None): key = to_unicode(key) - return dict.get(self, key.upper(), default) + return super(CaselessDict, self).get(key.upper(), default) def setdefault(self, key, value=None): key = to_unicode(key) - return dict.setdefault(self, key.upper(), value) + return super(CaselessDict, self).setdefault(key.upper(), value) def pop(self, key, default=None): key = to_unicode(key) - return dict.pop(self, key.upper(), default) + return super(CaselessDict, self).pop(key.upper(), default) def popitem(self): - return dict.popitem(self) + return super(CaselessDict, self).popitem() def has_key(self, key): key = to_unicode(key) - return dict.__contains__(self, key.upper()) + return super(CaselessDict, self).__contains__(key.upper()) - def update(self, indict): - """ - Multiple keys where key1.upper() == key2.upper() will be lost. - """ - for key, value in indict.iteritems(): - self[key] = value + def update(self, *args, **kwargs): + # Multiple keys where key1.upper() == key2.upper() will be lost. + mappings = list(args) + [kwargs] + for mapping in mappings: + if hasattr(mapping, 'items'): + mapping = iteritems(mapping) + for key, value in mapping: + self[key] = value def copy(self): - return CaselessDict(dict.copy(self)) + return type(self)(super(CaselessDict, self).copy()) def __repr__(self): - return 'CaselessDict(%s)' % data_encode(self) + return '%s(%s)' % (type(self).__name__, dict(self)) + + def __eq__(self, other): + return self is other or dict(self.items()) == dict(other.items()) # A list of keys that must appear first in sorted_keys and sorted_items; # must be uppercase. 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)
View file
icalendar-3.8.2.tar.gz/src/icalendar/compat.py
Added
@@ -0,0 +1,11 @@ +import sys + + +if sys.version_info[0] == 2: # pragma: no cover + unicode_type = unicode + bytes_type = str + iteritems = lambda d, *args, **kwargs: iter(d.iteritems(*args, **kwargs)) +else: # pragma: no cover + unicode_type = str + bytes_type = bytes + iteritems = lambda d, *args, **kwargs: iter(d.items(*args, **kwargs))
View file
icalendar-3.4.tar.gz/src/icalendar/parser.py -> icalendar-3.8.2.tar.gz/src/icalendar/parser.py
Changed
@@ -6,23 +6,21 @@ It is stupid in the sense that it treats the content purely as strings. No type conversion is attempted. """ -from __future__ import absolute_import +from icalendar import compat +from icalendar.caselessdict import CaselessDict +from icalendar.parser_tools import DEFAULT_ENCODING +from icalendar.parser_tools import SEQUENCE_TYPES +from icalendar.parser_tools import to_unicode + import re -from .caselessdict import CaselessDict -from .parser_tools import ( - DEFAULT_ENCODING, - SEQUENCE_TYPES, - to_unicode, - data_encode -) def escape_char(text): """Format value according to iCalendar TEXT escaping rules. """ - assert isinstance(text, basestring) + assert isinstance(text, (compat.unicode_type, compat.bytes_type)) # NOTE: ORDER MATTERS! - return text.replace('\N', '\n')\ + return text.replace(r'\N', '\n')\ .replace('\\', '\\\\')\ .replace(';', r'\;')\ .replace(',', r'\,')\ @@ -31,14 +29,22 @@ def unescape_char(text): - assert isinstance(text, basestring) + assert isinstance(text, (compat.unicode_type, compat.bytes_type)) # NOTE: ORDER MATTERS! - return text.replace(r'\N', r'\n')\ - .replace(r'\r\n', '\n')\ - .replace(r'\n', '\n')\ - .replace(r'\,', ',')\ - .replace(r'\;', ';')\ - .replace('\\\\', '\\') + if isinstance(text, compat.unicode_type): + return text.replace(u'\\N', u'\\n')\ + .replace(u'\r\n', u'\n')\ + .replace(u'\\n', u'\n')\ + .replace(u'\\,', u',')\ + .replace(u'\\;', u';')\ + .replace(u'\\\\', u'\\') + elif isinstance(text, compat.bytes_type): + return text.replace(b'\N', b'\n')\ + .replace(b'\r\n', b'\n')\ + .replace(b'\n', b'\n')\ + .replace(b'\,', b',')\ + .replace(b'\;', b';')\ + .replace(b'\\\\', b'\\') def tzid_from_dt(dt): @@ -63,7 +69,7 @@ immediately followed by a single linear white-space character (i.e., SPACE or HTAB). """ - assert isinstance(line, unicode) + assert isinstance(line, compat.unicode_type) assert u'\n' not in line ret_line = u'' @@ -91,10 +97,15 @@ # Could be improved -NAME = re.compile('[\w-]+') + +# [\w-] because of the iCalendar RFC +# \. because of the vCard RFC +NAME = re.compile('[\w\.-]+') + UNSAFE_CHAR = re.compile('[\x00-\x08\x0a-\x1f\x7F",:;]') QUNSAFE_CHAR = re.compile('[\x00-\x08\x0a-\x1f\x7F"]') -FOLD = re.compile('(\r?\n)+[ \t]') +FOLD = re.compile(b'(\r?\n)+[ \t]') +uFOLD = re.compile(u'(\r?\n)+[ \t]') NEWLINE = re.compile(r'\r?\n') @@ -154,15 +165,13 @@ 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() @@ -185,24 +194,24 @@ # def decoded(self, name): # "returns a decoded value, or list of same" - def __repr__(self): - return 'Parameters(%s)' % data_encode(self) - - def to_ical(self): + def to_ical(self, sorted=True): result = [] - items = self.items() - items.sort() # To make doctests work + items = list(self.items()) + if sorted: + items.sort() + for key, value in items: value = param_value(value) - if isinstance(value, unicode): + if isinstance(value, compat.unicode_type): value = value.encode(DEFAULT_ENCODING) # CaselessDict keys are always unicode - result.append('%s=%s' % (key.upper().encode('utf-8'), value)) - return ';'.join(result) + key = key.upper().encode(DEFAULT_ENCODING) + result.append(key + b'=' + value) + return b';'.join(result) @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() @@ -243,18 +252,24 @@ .replace(r'\;', '%3B').replace(r'\\', '%5C') -def unsescape_string(val): +def unescape_string(val): return val.replace('%2C', ',').replace('%3A', ':')\ .replace('%3B', ';').replace('%5C', '\\') +def unescape_list_or_string(val): + if isinstance(val, list): + return [unescape_string(s) for s in val] + else: + return unescape_string(val) + + ######################################### # parsing and generation of content lines -class Contentline(unicode): +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) @@ -265,7 +280,7 @@ return self @classmethod - def from_parts(cls, name, params, values): + def from_parts(cls, name, params, values, sorted=True): """Turn a parts into a content line. """ assert isinstance(params, Parameters) @@ -281,7 +296,7 @@ name = to_unicode(name) values = to_unicode(values) if params: - params = to_unicode(params.to_ical()) + params = to_unicode(params.to_ical(sorted=sorted)) return cls(u'%s;%s:%s' % (name, params, values)) return cls(u'%s:%s' % (name, values)) @@ -301,23 +316,25 @@ value_split = i if ch == '"': in_quotes = not in_quotes - name = unsescape_string(st[:name_split]) + name = unescape_string(st[:name_split]) if not name: raise ValueError('Key name is required') validate_token(name) - if name_split + 1 == value_split: + if not name_split or name_split + 1 == value_split:
View file
icalendar-3.4.tar.gz/src/icalendar/parser_tools.py -> icalendar-3.8.2.tar.gz/src/icalendar/parser_tools.py
Changed
@@ -1,3 +1,6 @@ +from icalendar import compat + + SEQUENCE_TYPES = (list, tuple) DEFAULT_ENCODING = 'utf-8' @@ -5,14 +8,14 @@ def to_unicode(value, encoding='utf-8'): """Converts a value to unicode, even if it is already a unicode string. """ - if isinstance(value, unicode): + if isinstance(value, compat.unicode_type): return value - elif isinstance(value, str): + elif isinstance(value, compat.bytes_type): try: - return value.decode(encoding) + value = value.decode(encoding) except UnicodeDecodeError: - return value.decode('utf-8', 'replace') - raise AssertionError('A str/unicode expected.') + value = value.decode('utf-8', 'replace') + return value def data_encode(data, encoding=DEFAULT_ENCODING): @@ -20,10 +23,10 @@ Currently unicode strings, dicts and lists are supported. """ # http://stackoverflow.com/questions/1254454/fastest-way-to-convert-a-dicts-keys-values-from-unicode-to-str - if isinstance(data, unicode): + if isinstance(data, compat.unicode_type): return data.encode(encoding) elif isinstance(data, dict): - return dict(map(data_encode, data.iteritems())) + return dict(map(data_encode, compat.iteritems(data))) elif isinstance(data, list) or isinstance(data, tuple): return list(map(data_encode, data)) else:
View file
icalendar-3.4.tar.gz/src/icalendar/prop.py -> icalendar-3.8.2.tar.gz/src/icalendar/prop.py
Changed
@@ -34,29 +34,34 @@ These types are mainly used for parsing and file generation. But you can set them directly. - """ -from __future__ import absolute_import -import re -import pytz +from datetime import date +from datetime import datetime +from datetime import time +from datetime import timedelta +from datetime import tzinfo + +try: + from dateutil.tz import tzutc +except ImportError: + tzutc = None + +from icalendar import compat +from icalendar.caselessdict import CaselessDict +from icalendar.parser import Parameters +from icalendar.parser import escape_char +from icalendar.parser import tzid_from_dt +from icalendar.parser import unescape_char +from icalendar.parser_tools import DEFAULT_ENCODING +from icalendar.parser_tools import SEQUENCE_TYPES +from icalendar.parser_tools import to_unicode + +import base64 import binascii +import pytz +import re import time as _time -from datetime import ( - datetime, - timedelta, - time, - date, - tzinfo, -) -from dateutil.tz import tzutc -from .parser_tools import SEQUENCE_TYPES, DEFAULT_ENCODING, to_unicode -from .caselessdict import CaselessDict -from .parser import ( - Parameters, - escape_char, - unescape_char, - tzid_from_dt, -) + DATE_PART = r'(\d+)D' TIME_PART = r'T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?' @@ -128,32 +133,30 @@ class vBinary(object): """Binary property values are base 64 encoded. - """ def __init__(self, obj): - self.obj = obj + self.obj = to_unicode(obj) self.params = Parameters(encoding='BASE64', value="BINARY") def __repr__(self): return "vBinary('%s')" % self.to_ical() def to_ical(self): - return binascii.b2a_base64(self.obj)[:-1] + return binascii.b2a_base64(self.obj.encode('utf-8'))[:-1] @staticmethod def from_ical(ical): try: - return ical.decode('base-64') + return base64.b64decode(ical) except UnicodeError: raise ValueError('Not valid base 64 encoding.') class vBoolean(int): """Returns specific string according to state. - """ - BOOL_MAP = CaselessDict(true=True, false=False) + BOOL_MAP = CaselessDict({'true': True, 'false': False}) def __new__(cls, *args, **kwargs): self = super(vBoolean, cls).__new__(cls, *args, **kwargs) @@ -162,8 +165,8 @@ def to_ical(self): if self: - return 'TRUE' - return 'FALSE' + return b'TRUE' + return b'FALSE' @classmethod def from_ical(cls, ical): @@ -173,9 +176,8 @@ raise ValueError("Expected 'TRUE' or 'FALSE'. Got %s" % ical) -class vCalAddress(unicode): +class vCalAddress(compat.unicode_type): """This just returns an unquoted string. - """ def __new__(cls, value, encoding=DEFAULT_ENCODING): value = to_unicode(value, encoding=encoding) @@ -196,7 +198,6 @@ class vFloat(float): """Just a float. - """ def __new__(cls, *args, **kwargs): self = super(vFloat, cls).__new__(cls, *args, **kwargs) @@ -204,7 +205,7 @@ return self def to_ical(self): - return str(self) + return compat.unicode_type(self).encode('utf-8') @classmethod def from_ical(cls, ical): @@ -216,7 +217,6 @@ class vInt(int): """Just an int. - """ def __new__(cls, *args, **kwargs): self = super(vInt, cls).__new__(cls, *args, **kwargs) @@ -224,7 +224,7 @@ return self def to_ical(self): - return str(self) + return compat.unicode_type(self).encode('utf-8') @classmethod def from_ical(cls, ical): @@ -236,7 +236,6 @@ class vDDDLists(object): """A list of vDDDTypes values. - """ def __init__(self, dt_list): if not hasattr(dt_list, '__iter__'): @@ -256,7 +255,7 @@ def to_ical(self): dts_ical = (dt.to_ical() for dt in self.dts) - return ",".join(dts_ical) + return b",".join(dts_ical) @staticmethod def from_ical(ical, timezone=None): @@ -271,10 +270,9 @@ """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): + if not isinstance(dt, (datetime, date, timedelta, time)): raise ValueError('You must use datetime, date, timedelta or time') if isinstance(dt, datetime): self.params = Parameters(dict(value='DATE-TIME')) @@ -284,9 +282,10 @@ 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): + if tzinfo is not pytz.utc and\ + (tzutc is None or not isinstance(tzinfo, tzutc)): # set the timezone as a parameter to the property tzid = tzid_from_dt(dt) if tzid: @@ -324,7 +323,6 @@ class vDate(object): """Render and generates iCalendar date format. - """ def __init__(self, dt): if not isinstance(dt, date): @@ -333,7 +331,8 @@ self.params = Parameters(dict(value='DATE'))
View file
icalendar-3.4.tar.gz/src/icalendar/tests/__init__.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/__init__.py
Changed
@@ -2,3 +2,4 @@ import unittest if not hasattr(unittest.TestCase, 'assertIsNotNone'): import unittest2 as unittest +unittest # pep 8
View file
icalendar-3.8.2.tar.gz/src/icalendar/tests/issue_112_missing_tzinfo_on_exdate.ics
Added
@@ -0,0 +1,48 @@ +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:PUBLISH +X-WR-CALNAME:Market East +X-WR-TIMEZONE:America/New_York +X-WR-CALDESC: +BEGIN:VTIMEZONE +TZID:America/New_York +X-LIC-LOCATION:America/New_York +BEGIN:DAYLIGHT +TZOFFSETFROM:-0500 +TZOFFSETTO:-0400 +TZNAME:EDT +DTSTART:19700308T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:-0400 +TZOFFSETTO:-0500 +TZNAME:EST +DTSTART:19701101T020000 +RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU +END:STANDARD +END:VTIMEZONE + +BEGIN:VEVENT +DTSTART;TZID=America/New_York:20130907T120000 +DTEND;TZID=America/New_York:20130907T170000 +RRULE:FREQ=WEEKLY;BYDAY=FR,SA;UNTIL=20131025T035959Z +EXDATE;TZID=America/New_York:20131012T120000 +EXDATE;TZID=America/New_York:20131011T120000 +DTSTAMP:20131021T025552Z +UID:ak30b02u7858q1oo6ji9dm4mgg@google.com +CREATED:20130903T181453Z +DESCRIPTION:The Fieldhouse and Hard Rock Cafe are working with PhillyRising + to provide live entertainment on Friday and Saturday afternoons throughout + the Summer. +LAST-MODIFIED:20131015T210927Z +LOCATION:12th and Market Streets (weather permitting) +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Market East Live! +TRANSP:OPAQUE +END:VEVENT + +END:VCALENDAR
View file
icalendar-3.8.2.tar.gz/src/icalendar/tests/issue_53_parsing_failure.ics
Changed
(renamed from src/icalendar/tests/case_meetup.ics)
View file
icalendar-3.4.tar.gz/src/icalendar/tests/recurrence.ics -> icalendar-3.8.2.tar.gz/src/icalendar/tests/recurrence.ics
Changed
@@ -9,4 +9,16 @@ EXDATE:19960402T010000Z,19960403T010000Z,19960404T010000Z SUMMARY:A recurring event with exdates END:VEVENT +BEGIN:VEVENT +DTSTART;TZID=Europe/Vienna:20120327T100000 +DTEND;TZID=Europe/Vienna:20120327T180000 +RRULE:FREQ=WEEKLY;UNTIL=20120703T080000Z;BYDAY=TU +EXDATE;TZID=Europe/Vienna:20120529T100000 +EXDATE;TZID=Europe/Vienna:20120403T100000 +EXDATE;TZID=Europe/Vienna:20120410T100000 +EXDATE;TZID=Europe/Vienna:20120501T100000 +EXDATE;TZID=Europe/Vienna:20120417T100000 +DTSTAMP:20130716T120638Z +SUMMARY:A Recurring event with multiple exdates, one per line. +END:VEVENT END:VCALENDAR
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_encoding.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_encoding.py
Changed
@@ -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): @@ -15,18 +14,20 @@ data = open(os.path.join(directory, 'encoding.ics'), 'rb').read() cal = icalendar.Calendar.from_ical(data) - self.assertEqual(cal['prodid'].to_ical(), - "-//Plönë.org//NONSGML plone.app.event//EN") - self.assertEqual(cal['X-WR-CALDESC'].to_ical(), - "test non ascii: äöü ÄÖÜ €") + self.assertEqual(cal['prodid'].to_ical().decode('utf-8'), + u"-//Plönë.org//NONSGML plone.app.event//EN") + self.assertEqual(cal['X-WR-CALDESC'].to_ical().decode('utf-8'), + u"test non ascii: äöü ÄÖÜ €") event = cal.walk('VEVENT')[0] - self.assertEqual(event['SUMMARY'].to_ical(), - 'Non-ASCII Test: ÄÖÜ äöü €') - self.assertEqual(event['DESCRIPTION'].to_ical(), - 'icalendar should be able to handle non-ascii: €äüöÄÜÖ.') - self.assertEqual(event['LOCATION'].to_ical(), - 'Tribstrül') + 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['LOCATION'].to_ical().decode('utf-8'), + u'Tribstrül') def test_create_to_ical(self): cal = icalendar.Calendar() @@ -38,28 +39,42 @@ 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', + pytz.utc.localize(datetime.datetime(2010, 10, 10, 10, 0, 0)) + ) + event.add( + 'dtend', + pytz.utc.localize(datetime.datetime(2010, 10, 10, 12, 0, 0)) + ) + event.add( + 'created', + pytz.utc.localize(datetime.datetime(2010, 10, 10, 0, 0, 0)) + ) 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) ical_lines = cal.to_ical().splitlines() - cmp = 'PRODID:-//Pl\xc3\xb6n\xc3\xab.org//NONSGML plone.app.event//EN' + cmp = b'PRODID:-//Pl\xc3\xb6n\xc3\xab.org//NONSGML plone.app.event//EN' self.assertTrue(cmp in ical_lines) 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", + pytz.utc.localize(datetime.datetime(2010, 10, 10, 0, 0, 0)) + ) event.add("summary", u"åäö") out = event.to_ical() - summary = "SUMMARY:åäö" + 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 @@ event.add(u'DESCRIPTION', u'äöüßÄÖÜ') cal.add_component(event) c = cal.to_ical() - self.assertEqual(c, - 'BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nDESCRIPTION:'\ - + '\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x9f\xc3\x84\xc3\x96\xc3\x9c\r\n'\ - + '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' + )
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_fixed_issues.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_fixed_issues.py
Changed
@@ -1,33 +1,34 @@ # -*- coding: utf-8 -*- -from . import unittest -import icalendar +from icalendar.parser_tools import to_unicode +from icalendar.tests import unittest + import datetime +import icalendar import os 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 """ directory = os.path.dirname(__file__) - ics = open(os.path.join(directory, 'case_meetup.ics'), 'rb') + ics = open(os.path.join(directory, 'issue_53_parsing_failure.ics'), + 'rb') cal = icalendar.Calendar.from_ical(ics.read()) ics.close() event = cal.walk('VEVENT')[0] desc = event.get('DESCRIPTION') - self.assertTrue('July 12 at 6:30 PM' in desc.to_ical()) + self.assertTrue(b'July 12 at 6:30 PM' in desc.to_ical()) timezones = cal.walk('VTIMEZONE') self.assertEqual(len(timezones), 1) tz = timezones[0] - self.assertEqual(tz['tzid'].to_ical(), "America/New_York") - + 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 @@ -45,12 +46,14 @@ END:VTIMEZONE""" tz = icalendar.Timezone.from_ical(ical_str) - self.assertEqual(tz.to_ical(), - 'BEGIN:VTIMEZONE\r\nTZID:America/Los Angeles\r\nBEGIN:STANDARD\r\n' - 'DTSTART:18831118T120702\r\nRDATE:18831118T120702\r\nTZNAME:PST' - '\r\nTZOFFSETFROM:-075258\r\nTZOFFSETTO:-0800\r\nEND:STANDARD\r\n' - 'END:VTIMEZONE\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\n' + b'END:STANDARD\r\n' + b'END:VTIMEZONE\r\n') def test_issue_58(self): """Issue #58 - TZID on UTC DATE-TIMEs @@ -64,11 +67,12 @@ event = icalendar.Event() dt = pytz.utc.localize(datetime.datetime(2012, 7, 16, 0, 0, 0)) event.add('dtstart', dt) - self.assertEqual(event.to_ical(), - "BEGIN:VEVENT\r\n" - "DTSTART;VALUE=DATE-TIME:20120716T000000Z\r\n" - "END:VEVENT\r\n") - + self.assertEqual( + event.to_ical(), + b"BEGIN:VEVENT\r\n" + b"DTSTART;VALUE=DATE-TIME:20120716T000000Z\r\n" + b"END:VEVENT\r\n" + ) def test_issue_64(self): """Issue #64 - Event.to_ical() fails for unicode strings @@ -79,17 +83,21 @@ event = icalendar.Event() event.add("dtstart", datetime.datetime(2012, 9, 3, 0, 0, 0)) event.add("summary", u"abcdef") - self.assertEqual(event.to_ical(), - "BEGIN:VEVENT\r\nSUMMARY:abcdef\r\nDTSTART;VALUE=DATE-TIME:" - "20120903T000000\r\nEND:VEVENT\r\n") + self.assertEqual( + event.to_ical(), + b"BEGIN:VEVENT\r\nSUMMARY:abcdef\r\nDTSTART;VALUE=DATE-TIME:" + 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(), - "BEGIN:VEVENT\r\nSUMMARY:\xc3\xa5\xc3\xa4\xc3\xb6\r\n" - "DTSTART;VALUE=DATE-TIME:20120903T000000\r\nEND:VEVENT\r\n") + 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" + ) def test_issue_70(self): """Issue #70 - e.decode("RRULE") causes Attribute Error @@ -111,10 +119,10 @@ cal = icalendar.Calendar.from_ical(ical_str) recur = cal.decoded("RRULE") self.assertIsInstance(recur, icalendar.vRecur) - self.assertEqual(recur.to_ical(), - u'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 @@ -124,15 +132,15 @@ b = icalendar.vBinary('text') b.params['FMTTYPE'] = 'text/plain' - self.assertEqual(b.to_ical(), 'dGV4dA==') + self.assertEqual(b.to_ical(), b'dGV4dA==') e = icalendar.Event() e.add('ATTACH', b) - self.assertEqual(e.to_ical(), - "BEGIN:VEVENT\r\nATTACH;ENCODING=BASE64;FMTTYPE=text/plain;" - "VALUE=BINARY:dGV4dA==\r\nEND:VEVENT\r\n" + 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 +150,6 @@ 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 @@ -172,3 +179,140 @@ cal = icalendar.Calendar.from_ical(ical_str) org_cn = cal.walk('VEVENT')[0]['ORGANIZER'].params['CN'] self.assertEqual(org_cn, u'acme, ädmin') + + def test_issue_104__ignore_exceptions(self): + """ + Issue #104 - line parsing error in a VEVENT + (which has ignore_exceptions). Should mark the event broken + but not raise an exception. + https://github.com/collective/icalendar/issues/104 + """ + ical_str = """ +BEGIN:VEVENT +DTSTART:20140401T000000Z +DTEND:20140401T010000Z +DTSTAMP:20140401T000000Z +SUMMARY:Broken Eevnt +CLASS:PUBLIC +STATUS:CONFIRMED +TRANSP:OPAQUE +X +END:VEVENT""" + event = icalendar.Calendar.from_ical(ical_str) + self.assertTrue(isinstance(event, icalendar.Event)) + self.assertTrue(event.is_broken) + + def test_issue_104__no_ignore_exceptions(self): + """ + Issue #104 - line parsing error in a VCALENDAR + (which doesn't have ignore_exceptions). Should raise an exception. + """ + ical_str = """BEGIN:VCALENDAR +VERSION:2.0 +METHOD:PUBLISH +BEGIN:VEVENT +DTSTART:20140401T000000Z +DTEND:20140401T010000Z +DTSTAMP:20140401T000000Z +SUMMARY:Broken Eevnt +CLASS:PUBLIC +STATUS:CONFIRMED +TRANSP:OPAQUE +END:VEVENT +X +END:VCALENDAR""" + with self.assertRaises(ValueError):
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_icalendar.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_icalendar.py
Changed
@@ -1,15 +1,5 @@ # coding: utf-8 -from . import unittest -import doctest -import os -from .. import ( - cal, - caselessdict, - parser, - prop, -) - -OPTIONFLAGS = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS +from icalendar.tests import unittest class IcalendarTestCase (unittest.TestCase): @@ -20,9 +10,9 @@ c.append(Contentline(''.join('123456789 ' * 10))) self.assertEqual( c.to_ical(), - 'BEGIN:VEVENT\r\n123456789 123456789 123456789 123456789 ' - '123456789 123456789 123456789 1234\r\n 56789 123456789 ' - '123456789 \r\n' + b'BEGIN:VEVENT\r\n123456789 123456789 123456789 123456789 ' + b'123456789 123456789 123456789 1234\r\n 56789 123456789 ' + b'123456789 \r\n' ) # from doctests @@ -45,15 +35,15 @@ self.assertEqual( Contentline('Si meliora dies, ut vina, poemata reddit').to_ical(), - 'Si meliora dies, ut vina, poemata reddit' + b'Si meliora dies, ut vina, poemata reddit' ) # A long line gets folded c = Contentline(''.join(['123456789 '] * 10)).to_ical() self.assertEqual( c, - ('123456789 123456789 123456789 123456789 123456789 123456789 ' - '123456789 1234\r\n 56789 123456789 123456789 ') + (b'123456789 123456789 123456789 123456789 123456789 123456789 ' + b'123456789 1234\r\n 56789 123456789 123456789 ') ) # A folded line gets unfolded @@ -70,22 +60,24 @@ # N or a LATIN CAPITAL LETTER N, that is "\n" or "\N". # Newlines are not allwoed in content lines - self.assertRaises(AssertionError, Contentline, '1234\r\n\r\n1234') + self.assertRaises(AssertionError, Contentline, b'1234\r\n\r\n1234') self.assertEqual( Contentline('1234\\n\\n1234').to_ical(), - '1234\\n\\n1234' + b'1234\\n\\n1234' ) # We do not fold within a UTF-8 character - c = Contentline('This line has a UTF-8 character where it should be ' - 'folded. Make sure it g\xc3\xabts folded before that ' - 'character.') - self.assertIn('\xc3\xab', c.to_ical()) + c = Contentline(b'This line has a UTF-8 character where it should be ' + b'folded. Make sure it g\xc3\xabts folded before that ' + b'character.') + + self.assertIn(b'\xc3\xab', c.to_ical()) # Another test of the above - c = Contentline('x' * 73 + '\xc3\xab' + '\\n ' + 'y' * 10) - self.assertEqual(c.to_ical().count('\xc3'), 1) + c = Contentline(b'x' * 73 + b'\xc3\xab' + b'\\n ' + b'y' * 10) + + self.assertEqual(c.to_ical().count(b'\xc3'), 1) # Don't fail if we fold a line that is exactly X times 74 characters # long @@ -112,7 +104,7 @@ 'MAILTO:maxm@example.com') ) self.assertEqual( - c.to_ical(), + c.to_ical().decode('utf-8'), 'ATTENDEE;CN=Max Rasmussen;ROLE=REQ-PARTICIPANT:' 'MAILTO:maxm@example.com' ) @@ -162,8 +154,8 @@ self.assertEqual(name, 'ATTENDEE') self.assertEqual(vals, 'MAILTO:maxm@example.com') self.assertEqual( - params.items(), - [('ROLE', 'REQ-PARTICIPANT'), ('CN', 'Max Rasmussen')] + sorted(params.items()), + sorted([('ROLE', 'REQ-PARTICIPANT'), ('CN', 'Max Rasmussen')]) ) # And the traditional failure @@ -226,8 +218,12 @@ u'Vestibulum conval\r\n lis imperdiet dui posuere.') ) + # I don't really get this test + # at least just but bytes in there + # porting it to "run" under python 2 & 3 makes it not much better with self.assertRaises(AssertionError): - foldline('привет', limit=3) + foldline(u'привет'.encode('utf-8'), limit=3) + self.assertEqual(foldline(u'foobar', limit=4), u'foo\r\n bar') self.assertEqual( foldline(u'Lorem ipsum dolor sit amet, consectetur adipiscing elit' @@ -255,23 +251,3 @@ 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', 'groupscheduled.rst', - 'small.rst', 'multiple.rst', 'recurrence.rst']: - filename = os.path.abspath(os.path.join(current_dir, docfile)) - suite.addTest( - doctest.DocFileSuite( - docfile, - optionflags=OPTIONFLAGS, - globs={'__file__': filename} - ) - ) - return suite
View file
icalendar-3.8.2.tar.gz/src/icalendar/tests/test_multiple.py
Added
@@ -0,0 +1,28 @@ +from icalendar import Calendar +from icalendar.prop import vText +from icalendar.tests import unittest + +import os + + +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 + ) + + self.assertEqual(len(cals), 2) + self.assertSequenceEqual([comp.name for comp in cals[0].walk()], + ['VCALENDAR', 'VEVENT']) + 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') + )
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_property_params.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_property_params.py
Changed
@@ -1,8 +1,12 @@ # coding: utf-8 +from icalendar import Calendar +from icalendar import Event +from icalendar import Parameters +from icalendar import vCalAddress +from icalendar.tests import unittest -from . import unittest - -from .. import vCalAddress, Calendar, Event, Parameters +import icalendar +import re class TestPropertyParams(unittest.TestCase): @@ -17,8 +21,8 @@ ical.add('organizer', cal_address) ical_str = Calendar.to_ical(ical) - exp_str = """BEGIN:VCALENDAR\r\nORGANIZER;CN="Doe, John":"""\ - """mailto:john.doe@example.org\r\nEND:VCALENDAR\r\n""" + exp_str = b"""BEGIN:VCALENDAR\r\nORGANIZER;CN="Doe, John":"""\ + b"""mailto:john.doe@example.org\r\nEND:VCALENDAR\r\n""" self.assertEqual(ical_str, exp_str) @@ -33,23 +37,25 @@ vevent = Event() vevent['ORGANIZER'] = cal_address self.assertEqual( - vevent.to_ical(), - 'BEGIN:VEVENT\r\n' - 'ORGANIZER;CN="Джон Доу":mailto:john.doe@example.org\r\n' - 'END:VEVENT\r\n' + vevent.to_ical().decode('utf-8'), + u'BEGIN:VEVENT\r\n' + u'ORGANIZER;CN="Джон Доу":mailto:john.doe@example.org\r\n' + u'END:VEVENT\r\n' ) - self.assertEqual(vevent['ORGANIZER'].params['CN'], 'Джон Доу') + + self.assertEqual(vevent['ORGANIZER'].params['CN'], + 'Джон Доу') def test_quoting(self): # not double-quoted - self._test_quoting(u"Aramis", 'Aramis') + self._test_quoting(u"Aramis", u'Aramis') # if a space is present - enclose in double quotes - self._test_quoting(u"Aramis Alameda", '"Aramis Alameda"') + self._test_quoting(u"Aramis Alameda", u'"Aramis Alameda"') # a single quote in parameter value - double quote the value - self._test_quoting("Aramis d'Alameda", '"Aramis d\'Alameda"') + self._test_quoting(u"Aramis d'Alameda", u'"Aramis d\'Alameda"') # double quote is replaced with single quote - self._test_quoting("Aramis d\"Alameda", '"Aramis d\'Alameda"') - self._test_quoting(u"Арамис д'Аламеда", '"Арамис д\'Аламеда"') + self._test_quoting(u"Aramis d\"Alameda", u'"Aramis d\'Alameda"') + self._test_quoting(u"Арамис д'Аламеда", u'"Арамис д\'Аламеда"') def _test_quoting(self, cn_param, cn_quoted): """ @@ -62,16 +68,16 @@ vevent.add('ATTENDEE', attendee) self.assertEqual( vevent.to_ical(), - 'BEGIN:VEVENT\r\nATTENDEE;CN=%s:test@mail.com\r\nEND:VEVENT\r\n' - % cn_quoted + b'BEGIN:VEVENT\r\nATTENDEE;CN=' + cn_quoted.encode('utf-8') + + b':test@mail.com\r\nEND:VEVENT\r\n' ) def test_escaping(self): # verify that escaped non safe chars are decoded correctly - NON_SAFE_CHARS = ur',\;:' + NON_SAFE_CHARS = u',\\;:' for char in NON_SAFE_CHARS: - cn_escaped = ur"Society\%s 2014" % char - cn_decoded = ur"Society%s 2014" % char + cn_escaped = u"Society\\%s 2014" % char + cn_decoded = u"Society%s 2014" % char vevent = Event.from_ical( u'BEGIN:VEVENT\r\n' u'ORGANIZER;CN=%s:that\r\n' @@ -90,18 +96,18 @@ r'that, that; %th%%at%\ that:' ) self.assertEqual( - vevent['ORGANIZER'].to_ical(), - r'это, то; that\ %th%%at%:' + vevent['ORGANIZER'].to_ical().decode('utf-8'), + u'это, то; that\\ %th%%at%:' ) def test_parameters_class(self): # Simple parameter:value pair p = Parameters(parameter1='Value1') - self.assertEqual(p.to_ical(), 'PARAMETER1=Value1') + self.assertEqual(p.to_ical(), b'PARAMETER1=Value1') # keys are converted to upper - self.assertEqual(p.keys(), ['PARAMETER1']) + self.assertEqual(list(p.keys()), ['PARAMETER1']) # Parameters are case insensitive self.assertEqual(p['parameter1'], 'Value1') @@ -109,22 +115,22 @@ # Parameter with list of values must be seperated by comma p = Parameters({'parameter1': ['Value1', 'Value2']}) - self.assertEqual(p.to_ical(), 'PARAMETER1=Value1,Value2') + self.assertEqual(p.to_ical(), b'PARAMETER1=Value1,Value2') # Multiple parameters must be seperated by a semicolon p = Parameters({'RSVP': 'TRUE', 'ROLE': 'REQ-PARTICIPANT'}) - self.assertEqual(p.to_ical(), 'ROLE=REQ-PARTICIPANT;RSVP=TRUE') + self.assertEqual(p.to_ical(), b'ROLE=REQ-PARTICIPANT;RSVP=TRUE') # Parameter values containing ',;:' must be double quoted p = Parameters({'ALTREP': 'http://www.wiz.org'}) - self.assertEqual(p.to_ical(), 'ALTREP="http://www.wiz.org"') + self.assertEqual(p.to_ical(), b'ALTREP="http://www.wiz.org"') # list items must be quoted seperately p = Parameters({'MEMBER': ['MAILTO:projectA@host.com', 'MAILTO:projectB@host.com']}) self.assertEqual( p.to_ical(), - 'MEMBER="MAILTO:projectA@host.com","MAILTO:projectB@host.com"' + b'MEMBER="MAILTO:projectA@host.com","MAILTO:projectB@host.com"' ) # Now the whole sheebang @@ -133,8 +139,8 @@ 'ALTREP': ['http://www.wiz.org', 'value4']}) self.assertEqual( p.to_ical(), - ('ALTREP="http://www.wiz.org",value4;PARAMETER1=Value1;' - 'PARAMETER2=Value2,Value3') + (b'ALTREP="http://www.wiz.org",value4;PARAMETER1=Value1;' + b'PARAMETER2=Value2,Value3') ) # We can also parse parameter strings @@ -164,3 +170,47 @@ 'ALTREP': ['http://www.wiz.org', 'value4'], '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. + + """ + ics = """BEGIN:VCALENDAR +VERSION:2.0 +PRODID://RESEARCH IN MOTION//BIS 3.0 +METHOD:REQUEST +BEGIN:VEVENT +SEQUENCE:2 +X-RIM-REVISION:0 +SUMMARY:Test meeting from BB +X-MICROSOFT-CDO-ALLDAYEVENT:TRUE +CLASS:PUBLIC +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="RembrandXS":MAILTO:rembrand@xs4all.nl +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="RembrandDX":MAILTO:rembrand@daxlab.com +ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="RembrandSB":MAILTO:rembspam@xs4all.nl +UID:XRIMCAL-628059586-522954492-9750559 +DTSTART;VALUE=DATE:20120814 +DTEND;VALUE=DATE:20120815 +DESCRIPTION:Test meeting from BB +DTSTAMP:20120813T151458Z +ORGANIZER:mailto:rembrand@daxlab.com +END:VEVENT +END:VCALENDAR""" + + cal = icalendar.Calendar.from_ical(ics) + event = cal.walk("VEVENT")[0] + event['attendee'][0] + self.assertEqual(event['attendee'][0].to_ical(), + b'MAILTO:rembrand@xs4all.nl') + self.assertEqual(event['attendee'][0].params.to_ical(), + b'CN=RembrandXS;PARTSTAT=NEEDS-ACTION;RSVP=TRUE') + self.assertEqual(event['attendee'][0].params['cn'], u'RembrandXS') + + def test_repr(self): + """Test correct class representation. + """ + it = Parameters(parameter1='Value1') + self.assertTrue( + re.match("Parameters\({u?'PARAMETER1': 'Value1'}\)", str(it)) + )
View file
icalendar-3.8.2.tar.gz/src/icalendar/tests/test_recurrence.py
Added
@@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +from icalendar.caselessdict import CaselessDict +from icalendar.tests import unittest + +import datetime +import icalendar +import os +import pytz + + +class TestRecurrence(unittest.TestCase): + + def setUp(self): + directory = os.path.dirname(__file__) + self.cal = icalendar.Calendar.from_ical( + open(os.path.join(directory, 'recurrence.ics'), 'rb').read() + ) + + def test_recurrence_exdates_one_line(self): + first_event = self.cal.walk('vevent')[0] + + self.assertIsInstance(first_event, CaselessDict) + self.assertEqual( + first_event['rrule'], {'COUNT': [100], 'FREQ': ['DAILY']} + ) + + self.assertEqual( + first_event['exdate'].to_ical(), + b'19960402T010000Z,19960403T010000Z,19960404T010000Z' + ) + + self.assertEqual( + first_event['exdate'].dts[0].dt, + pytz.utc.localize(datetime.datetime(1996, 4, 2, 1, 0)) + ) + + self.assertEqual( + first_event['exdate'].dts[1].dt, + pytz.utc.localize(datetime.datetime(1996, 4, 3, 1, 0)) + ) + + self.assertEqual( + first_event['exdate'].dts[2].dt, + pytz.utc.localize(datetime.datetime(1996, 4, 4, 1, 0)) + ) + + def test_recurrence_exdates_multiple_lines(self): + event = self.cal.walk('vevent')[1] + + exdate = event['exdate'] + + # TODO: DOCUMENT BETTER! + # In this case we have multiple EXDATE definitions, one per line. + # Icalendar makes a list out of this instead of zipping it into one + # vDDDLists object. Actually, this feels correct for me, as it also + # allows to define different timezones per exdate line - but client + # code has to handle this as list and not blindly expecting to be able + # to call event['EXDATE'].to_ical() on it: + self.assertEqual(isinstance(exdate, list), True) # multiple EXDATE + self.assertEqual(exdate[0].to_ical(), b'20120529T100000') + + # TODO: test for embedded timezone information!
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_time.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_time.py
Changed
@@ -1,8 +1,9 @@ -import icalendar +from icalendar.tests import unittest + import datetime +import icalendar import os -from . import unittest class TestTime(unittest.TestCase): @@ -24,5 +25,5 @@ def test_create_to_ical(self): cal = icalendar.Calendar() cal.add('X-SOMETIME', datetime.time(17, 20, 10)) - self.assertTrue('X-SOMETIME;VALUE=TIME:172010' in + self.assertTrue(b'X-SOMETIME;VALUE=TIME:172010' in cal.to_ical().splitlines())
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_timezoned.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_timezoned.py
Changed
@@ -1,33 +1,51 @@ # -*- coding: utf-8 -*- -import icalendar -import pytz +from icalendar.tests import unittest + import datetime import dateutil.parser +import icalendar import os - -from . import unittest +import pytz 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(), "-//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) tz = timezones[0] - self.assertEqual(tz['tzid'].to_ical(), "Europe/Vienna") + 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, 02, 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'), + pytz.timezone('Europe/Vienna').localize( + datetime.datetime(2012, 2, 13, 10, 0, 0) + ) + ) + self.assertEqual( + ev1.decoded('DTSTAMP'), + pytz.utc.localize( + datetime.datetime(2010, 10, 10, 9, 10, 10) + ) + ) def test_create_to_ical(self): cal = icalendar.Calendar() @@ -63,12 +81,22 @@ event = icalendar.Event() tz = pytz.timezone("Europe/Vienna") - event.add('dtstart', datetime.datetime(2012, 02, 13, 10, 00, 00, tzinfo=tz)) - event.add('dtend', datetime.datetime(2012, 02, 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', + tz.localize(datetime.datetime(2012, 2, 13, 10, 00, 00))) + event.add( + 'dtend', + tz.localize(datetime.datetime(2012, 2, 17, 18, 00, 00))) + event.add( + 'dtstamp', + tz.localize(datetime.datetime(2010, 10, 10, 10, 10, 10))) + event.add( + 'created', + tz.localize(datetime.datetime(2010, 10, 10, 10, 10, 10))) event.add('uid', u'123456') - event.add('last-modified', datetime.datetime(2010, 10, 10, 10, 10, 10, tzinfo=tz)) + event.add( + 'last-modified', + tz.localize(datetime.datetime(2010, 10, 10, 10, 10, 10))) event.add('summary', u'artsprint 2012') # event.add('rrule', u'FREQ=YEARLY;INTERVAL=1;COUNT=10') event.add('description', u'sprinting at the artsprint') @@ -82,15 +110,16 @@ event.add('url', u'http://plone.org') cal.add_component(event) - test_out = '|'.join(cal.to_ical().splitlines()) + 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" @@ -98,13 +127,12 @@ self.assertTrue("ATTENDEE:sepp" in test_out) # ical standard expects DTSTAMP and CREATED in UTC - self.assertTrue("DTSTAMP;VALUE=DATE-TIME:20101010T091010Z" in test_out) - self.assertTrue("CREATED;VALUE=DATE-TIME:20101010T091010Z" in test_out) + self.assertTrue("DTSTAMP;VALUE=DATE-TIME:20101010T081010Z" in test_out) + self.assertTrue("CREATED;VALUE=DATE-TIME:20101010T081010Z" in test_out) def test_tzinfo_dateutil(self): # Test for issues #77, #63 # references: #73,7430b66862346fe3a6a100ab25e35a8711446717 - date = dateutil.parser.parse('2012-08-30T22:41:00Z') date2 = dateutil.parser.parse('2012-08-30T22:41:00 +02:00') self.assertTrue(date.tzinfo.__module__ == 'dateutil.tz') @@ -112,6 +140,6 @@ # make sure, it's parsed properly and doesn't throw an error self.assertTrue(icalendar.vDDDTypes(date).to_ical() - == '20120830T224100Z') + == b'20120830T224100Z') self.assertTrue(icalendar.vDDDTypes(date2).to_ical() - == '20120830T224100') + == b'20120830T224100')
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_unit_cal.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_unit_cal.py
Changed
@@ -1,7 +1,10 @@ -from . import unittest +from datetime import datetime +from datetime import timedelta +from icalendar.tests import unittest + import icalendar -from datetime import datetime, timedelta import pytz +import re class TestCalComponent(unittest.TestCase): @@ -17,44 +20,73 @@ # 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/'}) + ) + + ### ADD MULTIPLE VALUES TO A PROPERTY # if you use the add method you don't have to considder if a value is # a list or not. c = Component() c.name = 'VEVENT' + + # add multiple values at once + c.add('attendee', + ['test@test.com', 'test2@test.com']) + + # or add one per line c.add('attendee', 'maxm@mxm.dk') c.add('attendee', 'test@example.dk') - self.assertEqual(c, - Event({'ATTENDEE': [prop.vCalAddress('maxm@mxm.dk'), - prop.vCalAddress('test@example.dk')]})) + + # add again multiple values at once to very concatenaton of lists + c.add('attendee', + ['test3@test.com', 'test4@test.com']) + + self.assertEqual( + c, + Event({'ATTENDEE': [ + prop.vCalAddress('test@test.com'), + prop.vCalAddress('test2@test.com'), + prop.vCalAddress('maxm@mxm.dk'), + prop.vCalAddress('test@example.dk'), + prop.vCalAddress('test3@test.com'), + prop.vCalAddress('test4@test.com') + ]}) + ) + + ### # You can get the values back directly ... c.add('prodid', '-//my product//') self.assertEqual(c['prodid'], prop.vText(u'-//my product//')) # ... or decoded to a python type - self.assertEqual(c.decoded('prodid'), '-//my product//') + self.assertEqual(c.decoded('prodid'), b'-//my product//') # With default values for non existing properties self.assertEqual(c.decoded('version', 'No Version'), 'No Version') c.add('rdate', [datetime(2013, 3, 28), datetime(2013, 3, 27)]) - self.assertEqual(type(c.decoded('rdate')), prop.vDDDLists) + self.assertTrue(isinstance(c.decoded('rdate'), prop.vDDDLists)) # The component can render itself in the RFC 2445 format. c = Component() c.name = 'VCALENDAR' c.add('attendee', 'Max M') - self.assertEqual(c.to_ical(), - '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 +94,19 @@ e.name = 'VEVENT' e.add('dtend', '20000102T000000', encode=0) e.add('dtstart', '20000101T000000', encode=0) - self.assertEqual(e.to_ical(), - 'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n' - + 'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r' - + '\nEND:VEVENT\r\n') + 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' + ) 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 +115,75 @@ # 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(), - [('BEGIN', 'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), - ('BEGIN', 'VEVENT'), ('DTEND', '20000102T000000'), + 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', 'VEVENT'), - ('END', 'VCALENDAR')]) + ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT'), + ('END', b'VCALENDAR')] + ) # We can also enumerate property items just under the component. - self.assertEqual(c.property_items(recursive=False), - [('BEGIN', 'VCALENDAR'), + self.assertEqual( + c.property_items(recursive=False), + [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), - ('END', 'VCALENDAR')]) + ('END', b'VCALENDAR')] + ) sc = c.subcomponents[0] - self.assertEqual(sc.property_items(recursive=False), - [('BEGIN', 'VEVENT'), ('DTEND', '20000102T000000'), + self.assertEqual( + sc.property_items(recursive=False), + [('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('DTSTART', '20000101T000000'), - ('SUMMARY', 'A brief history of time'), ('END', '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(), - 'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two' - + '\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(), - 'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' - + 'END:VCALENDAR\r\n')
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_unit_caselessdict.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_unit_caselessdict.py
Changed
@@ -1,4 +1,5 @@ -from . import unittest +from icalendar.tests import unittest + import icalendar @@ -10,46 +11,60 @@ 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,11 +81,10 @@ 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 = ncd.keys() - keys.sort() + keys = sorted(ncd.keys()) self.assertEqual(keys, ['KEY1', 'KEY2', 'KEY3', 'KEY5', 'KEY6'])
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_unit_parser_tools.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_unit_parser_tools.py
Changed
@@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- -from . import unittest -from ..parser_tools import to_unicode -from ..parser_tools import data_encode +from icalendar.parser_tools import data_encode +from icalendar.parser_tools import to_unicode +from icalendar.tests import unittest class TestParserTools(unittest.TestCase): @@ -11,19 +11,19 @@ self.assertEqual(to_unicode('spam'), u'spam') self.assertEqual(to_unicode(u'spam'), u'spam') self.assertEqual(to_unicode(u'spam'.encode('utf-8')), u'spam') - self.assertEqual(to_unicode('\xc6\xb5'), u'\u01b5') + self.assertEqual(to_unicode(b'\xc6\xb5'), u'\u01b5') self.assertEqual(to_unicode(u'\xc6\xb5'.encode('iso-8859-1')), u'\u01b5') - self.assertEqual(to_unicode('\xc6\xb5', encoding='ascii'), u'\u01b5') - with self.assertRaises(AssertionError): - to_unicode(1) - with self.assertRaises(AssertionError): - to_unicode(None) + self.assertEqual(to_unicode(b'\xc6\xb5', encoding='ascii'), u'\u01b5') + self.assertEqual(to_unicode(1), 1) + self.assertEqual(to_unicode(None), None) 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]} - res = {'k3': 'v3', 'k2': 'v2', 'k1': 'v1', - 'li1': ['it1', 'it2', {'k5': 'v5', 'k4': 'v4'}, 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)
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_unit_prop.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_unit_prop.py
Changed
@@ -1,5 +1,10 @@ -from datetime import datetime, date, timedelta, time -from . import unittest +# -*- coding: utf-8 -*- +from datetime import date +from datetime import datetime +from datetime import time +from datetime import timedelta +from icalendar.parser import Parameters +from icalendar.tests import unittest import pytz @@ -9,33 +14,33 @@ def test_prop_vBinary(self): from ..prop import vBinary - txt = 'This is gibberish' - txt_ical = 'VGhpcyBpcyBnaWJiZXJpc2g=' + txt = b'This is gibberish' + txt_ical = b'VGhpcyBpcyBnaWJiZXJpc2g=' self.assertEqual(vBinary(txt).to_ical(), txt_ical) self.assertEqual(vBinary.from_ical(txt_ical), txt) # The roundtrip test - txt = 'Binary data \x13 \x56' - txt_ical = 'QmluYXJ5IGRhdGEgEyBW' + txt = b'Binary data \x13 \x56' + txt_ical = b'QmluYXJ5IGRhdGEgEyBW' self.assertEqual(vBinary(txt).to_ical(), txt_ical) self.assertEqual(vBinary.from_ical(txt_ical), txt) + self.assertIsInstance(vBinary('txt').params, Parameters) self.assertEqual( - str(vBinary('txt').params), - "Parameters({'VALUE': 'BINARY', 'ENCODING': 'BASE64'})" + vBinary('txt').params, {'VALUE': 'BINARY', 'ENCODING': 'BASE64'} ) # Long data should not have line breaks, as that would interfere - txt = 'a' * 99 - txt_ical = 'YWFh' * 33 + txt = b'a' * 99 + txt_ical = b'YWFh' * 33 self.assertEqual(vBinary(txt).to_ical(), txt_ical) self.assertEqual(vBinary.from_ical(txt_ical), txt) def test_prop_vBoolean(self): from ..prop import vBoolean - self.assertEqual(vBoolean(True).to_ical(), 'TRUE') - self.assertEqual(vBoolean(0).to_ical(), 'FALSE') + self.assertEqual(vBoolean(True).to_ical(), b'TRUE') + self.assertEqual(vBoolean(0).to_ical(), b'FALSE') # The roundtrip test self.assertEqual(vBoolean.from_ical(vBoolean(True).to_ical()), True) @@ -43,23 +48,24 @@ def test_prop_vCalAddress(self): from ..prop import vCalAddress - txt = 'MAILTO:maxm@mxm.dk' + txt = b'MAILTO:maxm@mxm.dk' a = vCalAddress(txt) a.params['cn'] = 'Max M' self.assertEqual(a.to_ical(), txt) - self.assertEqual(str(a.params), "Parameters({'CN': 'Max M'})") + self.assertIsInstance(a.params, Parameters) + self.assertEqual(a.params, {'CN': 'Max M'}) self.assertEqual(vCalAddress.from_ical(txt), 'MAILTO:maxm@mxm.dk') def test_prop_vFloat(self): from ..prop import vFloat - self.assertEqual(vFloat(1.0).to_ical(), '1.0') + self.assertEqual(vFloat(1.0).to_ical(), b'1.0') self.assertEqual(vFloat.from_ical('42'), 42.0) - self.assertEqual(vFloat(42).to_ical(), '42.0') + self.assertEqual(vFloat(42).to_ical(), b'42.0') def test_prop_vInt(self): from ..prop import vInt - self.assertEqual(vInt(42).to_ical(), '42') + self.assertEqual(vInt(42).to_ical(), b'42') self.assertEqual(vInt.from_ical('13'), 13) self.assertRaises(ValueError, vInt.from_ical, '1s3') @@ -79,13 +85,13 @@ self.assertEqual(str(dt_list[2]), '1996-04-04 01:00:00+00:00') dt_list = vDDDLists([]) - self.assertEqual(dt_list.to_ical(), '') + self.assertEqual(dt_list.to_ical(), b'') dt_list = vDDDLists([datetime(2000, 1, 1)]) - self.assertEqual(dt_list.to_ical(), '20000101T000000') + self.assertEqual(dt_list.to_ical(), b'20000101T000000') dt_list = vDDDLists([datetime(2000, 1, 1), datetime(2000, 11, 11)]) - self.assertEqual(dt_list.to_ical(), '20000101T000000,20001111T000000') + self.assertEqual(dt_list.to_ical(), b'20000101T000000,20001111T000000') def test_prop_vDDDTypes(self): from ..prop import vDDDTypes @@ -94,7 +100,7 @@ datetime)) self.assertEqual(vDDDTypes.from_ical('20010101T123000Z'), - datetime(2001, 1, 1, 12, 30, tzinfo=pytz.utc)) + pytz.utc.localize(datetime(2001, 1, 1, 12, 30))) self.assertTrue(isinstance(vDDDTypes.from_ical('20010101'), date)) @@ -108,8 +114,8 @@ def test_prop_vDate(self): from ..prop import vDate - self.assertEqual(vDate(date(2001, 1, 1)).to_ical(), '20010101') - self.assertEqual(vDate(date(1899, 1, 1)).to_ical(), '18990101') + self.assertEqual(vDate(date(2001, 1, 1)).to_ical(), b'20010101') + self.assertEqual(vDate(date(1899, 1, 1)).to_ical(), b'18990101') self.assertEqual(vDate.from_ical('20010102'), date(2001, 1, 2)) @@ -119,16 +125,16 @@ from ..prop import vDatetime dt = datetime(2001, 1, 1, 12, 30, 0) - self.assertEqual(vDatetime(dt).to_ical(), '20010101T123000') + self.assertEqual(vDatetime(dt).to_ical(), b'20010101T123000') self.assertEqual(vDatetime.from_ical('20000101T120000'), datetime(2000, 1, 1, 12, 0)) - dutc = datetime(2001, 1, 1, 12, 30, 0, tzinfo=pytz.utc) - self.assertEqual(vDatetime(dutc).to_ical(), '20010101T123000Z') + dutc = pytz.utc.localize(datetime(2001, 1, 1, 12, 30, 0)) + self.assertEqual(vDatetime(dutc).to_ical(), b'20010101T123000Z') - dutc = datetime(1899, 1, 1, 12, 30, 0, tzinfo=pytz.utc) - self.assertEqual(vDatetime(dutc).to_ical(), '18990101T123000Z') + dutc = pytz.utc.localize(datetime(1899, 1, 1, 12, 30, 0)) + self.assertEqual(vDatetime(dutc).to_ical(), b'18990101T123000Z') self.assertEqual(vDatetime.from_ical('20010101T000000'), datetime(2001, 1, 1, 0, 0)) @@ -136,7 +142,7 @@ self.assertRaises(ValueError, vDatetime.from_ical, '20010101T000000A') utc = vDatetime.from_ical('20010101T000000Z') - self.assertEqual(vDatetime(utc).to_ical(), '20010101T000000Z') + self.assertEqual(vDatetime(utc).to_ical(), b'20010101T000000Z') # 1 minute before transition to DST dat = vDatetime.from_ical('20120311T015959', 'America/Denver') @@ -149,26 +155,29 @@ '20120311030000 -0600') dat = vDatetime.from_ical('20101010T000000', 'Europe/Vienna') - self.assertEqual(vDatetime(dat).to_ical(), '20101010T000000') + self.assertEqual(vDatetime(dat).to_ical(), b'20101010T000000') def test_prop_vDuration(self): from ..prop import vDuration - self.assertEqual(vDuration(timedelta(11)).to_ical(), 'P11D') - self.assertEqual(vDuration(timedelta(-14)).to_ical(), '-P14D') - self.assertEqual(vDuration(timedelta(1, 7384)).to_ical(), 'P1DT2H3M4S') - self.assertEqual(vDuration(timedelta(1, 7380)).to_ical(), 'P1DT2H3M') - self.assertEqual(vDuration(timedelta(1, 7200)).to_ical(), 'P1DT2H') - self.assertEqual(vDuration(timedelta(0, 7200)).to_ical(), 'PT2H') - self.assertEqual(vDuration(timedelta(0, 7384)).to_ical(), 'PT2H3M4S') - self.assertEqual(vDuration(timedelta(0, 184)).to_ical(), 'PT3M4S') - self.assertEqual(vDuration(timedelta(0, 22)).to_ical(), 'PT22S') - self.assertEqual(vDuration(timedelta(0, 3622)).to_ical(), 'PT1H0M22S') + 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, 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') + self.assertEqual(vDuration(timedelta(0, 7384)).to_ical(), b'PT2H3M4S') + self.assertEqual(vDuration(timedelta(0, 184)).to_ical(), b'PT3M4S') + self.assertEqual(vDuration(timedelta(0, 22)).to_ical(), b'PT22S') + self.assertEqual(vDuration(timedelta(0, 3622)).to_ical(), b'PT1H0M22S') self.assertEqual(vDuration(timedelta(days=1, hours=5)).to_ical(), - 'P1DT5H') - self.assertEqual(vDuration(timedelta(hours=-5)).to_ical(), '-PT5H') + b'P1DT5H') + self.assertEqual(vDuration(timedelta(hours=-5)).to_ical(), b'-PT5H') self.assertEqual(vDuration(timedelta(days=-1, hours=-5)).to_ical(), - '-P1DT5H') + b'-P1DT5H') # How does the parsing work? self.assertEqual(vDuration.from_ical('PT1H0M22S'), timedelta(0, 3622)) @@ -185,10 +194,10 @@
View file
icalendar-3.4.tar.gz/src/icalendar/tests/test_unit_tools.py -> icalendar-3.8.2.tar.gz/src/icalendar/tests/test_unit_tools.py
Changed
@@ -1,4 +1,4 @@ -from . import unittest +from icalendar.tests import unittest from icalendar.tools import UIDGenerator @@ -9,19 +9,20 @@ # Automatic semi-random uid g = UIDGenerator() uid = g.uid() + txt = uid.to_ical() length = 15 + 1 + 16 + 1 + 11 self.assertTrue(len(txt) == length) - self.assertTrue('@example.com' in txt) + self.assertTrue(b'@example.com' in txt) # You should at least insert your own hostname to be more compliant uid = g.uid('Example.ORG') txt = uid.to_ical() self.assertTrue(len(txt) == length) - self.assertTrue('@Example.ORG' in txt) + self.assertTrue(b'@Example.ORG' in txt) # You can also insert a path or similar uid = g.uid('Example.ORG', '/path/to/content') txt = uid.to_ical() self.assertTrue(len(txt) == length) - self.assertTrue('-/path/to/content@Example.ORG' in txt) + self.assertTrue(b'-/path/to/content@Example.ORG' in txt)
View file
icalendar-3.4.tar.gz/src/icalendar/tools.py -> icalendar-3.8.2.tar.gz/src/icalendar/tools.py
Changed
@@ -1,14 +1,11 @@ -from __future__ import absolute_import -import random -from string import ( - ascii_letters, - digits, -) from datetime import datetime -from .prop import ( - vText, - vDatetime, -) +from icalendar.parser_tools import to_unicode +from icalendar.prop import vDatetime +from icalendar.prop import vText +from string import ascii_letters +from string import digits + +import random class UIDGenerator(object): @@ -28,7 +25,9 @@ Like: 20050105T225746Z-HKtJMqUgdO0jDUwm@example.com """ + host_name = to_unicode(host_name) unique = unique or self.rnd_string() - return vText('%s-%s@%s' % (vDatetime(datetime.today()).to_ical(), + today = to_unicode(vDatetime(datetime.today()).to_ical()) + return vText('%s-%s@%s' % (today, unique, host_name))
View file
icalendar-3.4.tar.gz/tox.ini -> icalendar-3.8.2.tar.gz/tox.ini
Changed
@@ -1,12 +1,13 @@ +# to run for a specific environment, use ``tox -e ENVNAME`` [tox] -envlist = py26,py27 +envlist = py26,py27,py33 [testenv] deps = - icalendar [test] + pytest coverage + icalendar [test] commands = - coverage erase - coverage run --source=icalendar --omit=*tests* {envbindir}/unit2 discover icalendar [] - coverage report --omit=*tests* - coverage html --omit=*tests* + coverage run --source=src/icalendar --omit=*/tests/* --module pytest src/icalendar + coverage report + coverage html
View file
python-icalendar.dsc
Changed
@@ -2,7 +2,7 @@ Source: python-icalendar Binary: python-icalendar Architecture: all -Version: 3.4-1 +Version: 3.8.2 Maintainer: Paul Klos <kolab@klos2day.nl> Homepage: http://codespeak.net/icalendar/ Standards-Version: 3.9.3 @@ -10,5 +10,5 @@ Package-List: python-icalendar deb python optional Files: - 00000000000000000000000000000000 0 python-icalendar-3.4.tar.gz - 00000000000000000000000000000000 0 python-icalendar-3.4.debian.tar.gz + 00000000000000000000000000000000 0 python-icalendar-3.8.2.tar.gz + 00000000000000000000000000000000 0 python-icalendar-3.8.2.debian.tar.gz
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.