[Python-modules-commits] [python-icalendar] 03/13: Import python-icalendar_3.11.7.orig.tar.gz

Christoph Egger christoph at moszumanska.debian.org
Wed Nov 1 15:02:06 UTC 2017


This is an automated email from the git hooks/post-receive script.

christoph pushed a commit to branch master
in repository python-icalendar.

commit d607b6c075dd427884cf0b229003430a92be2805
Author: Christoph Egger <christoph at christoph-egger.org>
Date:   Wed Nov 1 15:39:41 2017 +0100

    Import python-icalendar_3.11.7.orig.tar.gz
---
 CHANGES.rst                                        | 41 ++++++++++++
 PKG-INFO                                           | 76 +++++++++++++++++-----
 README.rst                                         | 33 +++++-----
 setup.cfg                                          |  3 +-
 src/icalendar.egg-info/PKG-INFO                    | 76 +++++++++++++++++-----
 src/icalendar.egg-info/SOURCES.txt                 |  4 +-
 src/icalendar/__init__.py                          |  2 +-
 src/icalendar/cal.py                               | 32 +++++----
 src/icalendar/parser.py                            | 12 +++-
 src/icalendar/prop.py                              |  7 +-
 src/icalendar/tests/apple_xlocation_test.py        | 26 --------
 src/icalendar/tests/test_icalendar.py              | 68 +++++++++++++++++++
 src/icalendar/tests/test_timezoned.py              | 72 +++++++++++++++++---
 src/icalendar/tests/test_unit_cal.py               | 23 +++++++
 src/icalendar/tests/timezone_rdate.ics             | 55 ++++++++++++++++
 src/icalendar/tests/timezone_same_start.ics        | 27 ++++++++
 .../tests/timezone_same_start_and_offset.ics       | 23 +++++++
 tox.ini                                            |  2 +-
 18 files changed, 470 insertions(+), 112 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index 4bc1782..c16cc26 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,6 +1,47 @@
 Changelog
 =========
 
+3.11.7 (2017-08-27)
+-------------------
+
+New features:
+
+- added vUTCOffset.ignore_exceptions to allow surpressing of failed TZOFFSET
+  parsing (for now this ignores the check for offsets > 24h) [geier]
+
+
+3.11.6 (2017-08-04)
+-------------------
+
+Bug fixes:
+
+- Fix VTIMEZONEs including RDATEs #234.  [geier]
+
+
+3.11.5 (2017-07-03)
+-------------------
+
+Bug fixes:
+
+- added an assertion that VTIMEZONE sub-components' DTSTART must be of type
+  DATETIME [geier]
+
+- Fix handling of VTIMEZONEs with subcomponents with the same DTSTARTs and
+  OFFSETs but which are of different types  [geier]
+
+
+3.11.4 (2017-05-10)
+-------------------
+
+Bug fixes:
+
+- Don't break on parameter values which contain equal signs, e.g. base64 encoded
+  binary data [geier]
+
+- Fix handling of VTIMEZONEs with subcomponents with the same DTSTARTs.
+  [geier]
+
+
 3.11.3 (2017-02-15)
 -------------------
 
diff --git a/PKG-INFO b/PKG-INFO
index 937e11b..820481c 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: icalendar
-Version: 3.11.3
+Version: 3.11.7
 Summary: iCalendar parser/generator
 Home-page: https://github.com/collective/icalendar
 Author: Plone Foundation
@@ -15,12 +15,12 @@ Description: ==========================================================
         
         ----
         
-            :Homepage: http://icalendar.readthedocs.org
-            :Code: http://github.com/collective/icalendar
-            :Mailing list: http://github.com/collective/icalendar/issues
-            :Dependencies: `python-dateutil`_ and `pytz`_.
-            :Compatible with: Python 2.6, 2.7 and 3.3+
-            :License: `BSD`_
+        :Homepage: https://icalendar.readthedocs.io
+        :Code: https://github.com/collective/icalendar
+        :Mailing list: https://github.com/collective/icalendar/issues
+        :Dependencies: `python-dateutil`_ and `pytz`_.
+        :Compatible with: Python 2.6, 2.7 and 3.3+
+        :License: `BSD`_
         
         ----
         
@@ -35,7 +35,6 @@ Description: ==========================================================
         - 4.0: API refactoring
         
         
-        
         Changes in version 3.0
         ======================
         
@@ -63,26 +62,26 @@ Description: ==========================================================
         database timezone identifiers. This can be a problem for 'GMT' identifiers,
         which are not defined in the Olson database.
         
-        Instead of our own UTC tzinfo implementation we use pytz UTC tzinfo object now.
+        Instead of our own UTC tzinfo implementation, we use pytz UTC tzinfo object now.
         
         
         About this fork which is not a fork anymore
         ===========================================
         
         The aim of this fork (not fork anymore, read further) was to bring this package
-        up to date with latest icalendar `RFC`_ specification as part of
-        `plone.app.event`_ project which goal is to bring recurrent events to `Plone`_.
+        up to date with latest icalendar `RFC`_ specification, as part of the
+        `plone.app.event`_ project whose goal is to bring recurrent events to `Plone`_.
         
-        After some thoughts we (Plone developers involved with `plone.app.event`_) send
-        a suggestion to icalendar-dev at codespeak.net to take over maintaining of
+        After some thoughts we (Plone developers involved with `plone.app.event`_) sent
+        a suggestion to icalendar-dev at codespeak.net to take over maintenance of
         `icalendar`_. Nobody objected and since version 2.2 we are back to development.
         
-        .. _`icalendar`: http://pypi.python.org/pypi/icalendar
-        .. _`plone.app.event`: http://github.com/plone/plone.app.event
-        .. _`Plone`: http://plone.org
+        .. _`icalendar`: https://pypi.python.org/pypi/icalendar
+        .. _`plone.app.event`: https://github.com/plone/plone.app.event
+        .. _`Plone`: https://plone.org
         .. _`python-dateutil`: https://github.com/dateutil/dateutil/
-        .. _`pytz`: http://pypi.python.org/pypi/pytz
-        .. _`RFC`: http://www.ietf.org/rfc/rfc5545.txt
+        .. _`pytz`: https://pypi.python.org/pypi/pytz
+        .. _`RFC`: https://www.ietf.org/rfc/rfc5545.txt
         .. _`BSD`: https://github.com/collective/icalendar/issues/2
         
         
@@ -108,6 +107,47 @@ Description: ==========================================================
         Changelog
         =========
         
+        3.11.7 (2017-08-27)
+        -------------------
+        
+        New features:
+        
+        - added vUTCOffset.ignore_exceptions to allow surpressing of failed TZOFFSET
+          parsing (for now this ignores the check for offsets > 24h) [geier]
+        
+        
+        3.11.6 (2017-08-04)
+        -------------------
+        
+        Bug fixes:
+        
+        - Fix VTIMEZONEs including RDATEs #234.  [geier]
+        
+        
+        3.11.5 (2017-07-03)
+        -------------------
+        
+        Bug fixes:
+        
+        - added an assertion that VTIMEZONE sub-components' DTSTART must be of type
+          DATETIME [geier]
+        
+        - Fix handling of VTIMEZONEs with subcomponents with the same DTSTARTs and
+          OFFSETs but which are of different types  [geier]
+        
+        
+        3.11.4 (2017-05-10)
+        -------------------
+        
+        Bug fixes:
+        
+        - Don't break on parameter values which contain equal signs, e.g. base64 encoded
+          binary data [geier]
+        
+        - Fix handling of VTIMEZONEs with subcomponents with the same DTSTARTs.
+          [geier]
+        
+        
         3.11.3 (2017-02-15)
         -------------------
         
diff --git a/README.rst b/README.rst
index b0531d5..90ba236 100644
--- a/README.rst
+++ b/README.rst
@@ -7,12 +7,12 @@ with Python.
 
 ----
 
-    :Homepage: http://icalendar.readthedocs.org
-    :Code: http://github.com/collective/icalendar
-    :Mailing list: http://github.com/collective/icalendar/issues
-    :Dependencies: `python-dateutil`_ and `pytz`_.
-    :Compatible with: Python 2.6, 2.7 and 3.3+
-    :License: `BSD`_
+:Homepage: https://icalendar.readthedocs.io
+:Code: https://github.com/collective/icalendar
+:Mailing list: https://github.com/collective/icalendar/issues
+:Dependencies: `python-dateutil`_ and `pytz`_.
+:Compatible with: Python 2.6, 2.7 and 3.3+
+:License: `BSD`_
 
 ----
 
@@ -27,7 +27,6 @@ Roadmap
 - 4.0: API refactoring
 
 
-
 Changes in version 3.0
 ======================
 
@@ -55,26 +54,26 @@ instances. The timezone identifiers must be valid pytz respectively Olson
 database timezone identifiers. This can be a problem for 'GMT' identifiers,
 which are not defined in the Olson database.
 
-Instead of our own UTC tzinfo implementation we use pytz UTC tzinfo object now.
+Instead of our own UTC tzinfo implementation, we use pytz UTC tzinfo object now.
 
 
 About this fork which is not a fork anymore
 ===========================================
 
 The aim of this fork (not fork anymore, read further) was to bring this package
-up to date with latest icalendar `RFC`_ specification as part of
-`plone.app.event`_ project which goal is to bring recurrent events to `Plone`_.
+up to date with latest icalendar `RFC`_ specification, as part of the
+`plone.app.event`_ project whose goal is to bring recurrent events to `Plone`_.
 
-After some thoughts we (Plone developers involved with `plone.app.event`_) send
-a suggestion to icalendar-dev at codespeak.net to take over maintaining of
+After some thoughts we (Plone developers involved with `plone.app.event`_) sent
+a suggestion to icalendar-dev at codespeak.net to take over maintenance of
 `icalendar`_. Nobody objected and since version 2.2 we are back to development.
 
-.. _`icalendar`: http://pypi.python.org/pypi/icalendar
-.. _`plone.app.event`: http://github.com/plone/plone.app.event
-.. _`Plone`: http://plone.org
+.. _`icalendar`: https://pypi.python.org/pypi/icalendar
+.. _`plone.app.event`: https://github.com/plone/plone.app.event
+.. _`Plone`: https://plone.org
 .. _`python-dateutil`: https://github.com/dateutil/dateutil/
-.. _`pytz`: http://pypi.python.org/pypi/pytz
-.. _`RFC`: http://www.ietf.org/rfc/rfc5545.txt
+.. _`pytz`: https://pypi.python.org/pypi/pytz
+.. _`RFC`: https://www.ietf.org/rfc/rfc5545.txt
 .. _`BSD`: https://github.com/collective/icalendar/issues/2
 
 
diff --git a/setup.cfg b/setup.cfg
index 8f0a823..a1f002e 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -8,7 +8,7 @@ ignore =
 python-file-with-version = src/icalendar/__init__.py
 create-wheel = yes
 
-[wheel]
+[bdist_wheel]
 universal = 1
 
 [tool:pytest]
@@ -17,5 +17,4 @@ norecursedirs = .* env* docs *.egg src/icalendar/tests/hypothesis
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
diff --git a/src/icalendar.egg-info/PKG-INFO b/src/icalendar.egg-info/PKG-INFO
index 937e11b..820481c 100644
--- a/src/icalendar.egg-info/PKG-INFO
+++ b/src/icalendar.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: icalendar
-Version: 3.11.3
+Version: 3.11.7
 Summary: iCalendar parser/generator
 Home-page: https://github.com/collective/icalendar
 Author: Plone Foundation
@@ -15,12 +15,12 @@ Description: ==========================================================
         
         ----
         
-            :Homepage: http://icalendar.readthedocs.org
-            :Code: http://github.com/collective/icalendar
-            :Mailing list: http://github.com/collective/icalendar/issues
-            :Dependencies: `python-dateutil`_ and `pytz`_.
-            :Compatible with: Python 2.6, 2.7 and 3.3+
-            :License: `BSD`_
+        :Homepage: https://icalendar.readthedocs.io
+        :Code: https://github.com/collective/icalendar
+        :Mailing list: https://github.com/collective/icalendar/issues
+        :Dependencies: `python-dateutil`_ and `pytz`_.
+        :Compatible with: Python 2.6, 2.7 and 3.3+
+        :License: `BSD`_
         
         ----
         
@@ -35,7 +35,6 @@ Description: ==========================================================
         - 4.0: API refactoring
         
         
-        
         Changes in version 3.0
         ======================
         
@@ -63,26 +62,26 @@ Description: ==========================================================
         database timezone identifiers. This can be a problem for 'GMT' identifiers,
         which are not defined in the Olson database.
         
-        Instead of our own UTC tzinfo implementation we use pytz UTC tzinfo object now.
+        Instead of our own UTC tzinfo implementation, we use pytz UTC tzinfo object now.
         
         
         About this fork which is not a fork anymore
         ===========================================
         
         The aim of this fork (not fork anymore, read further) was to bring this package
-        up to date with latest icalendar `RFC`_ specification as part of
-        `plone.app.event`_ project which goal is to bring recurrent events to `Plone`_.
+        up to date with latest icalendar `RFC`_ specification, as part of the
+        `plone.app.event`_ project whose goal is to bring recurrent events to `Plone`_.
         
-        After some thoughts we (Plone developers involved with `plone.app.event`_) send
-        a suggestion to icalendar-dev at codespeak.net to take over maintaining of
+        After some thoughts we (Plone developers involved with `plone.app.event`_) sent
+        a suggestion to icalendar-dev at codespeak.net to take over maintenance of
         `icalendar`_. Nobody objected and since version 2.2 we are back to development.
         
-        .. _`icalendar`: http://pypi.python.org/pypi/icalendar
-        .. _`plone.app.event`: http://github.com/plone/plone.app.event
-        .. _`Plone`: http://plone.org
+        .. _`icalendar`: https://pypi.python.org/pypi/icalendar
+        .. _`plone.app.event`: https://github.com/plone/plone.app.event
+        .. _`Plone`: https://plone.org
         .. _`python-dateutil`: https://github.com/dateutil/dateutil/
-        .. _`pytz`: http://pypi.python.org/pypi/pytz
-        .. _`RFC`: http://www.ietf.org/rfc/rfc5545.txt
+        .. _`pytz`: https://pypi.python.org/pypi/pytz
+        .. _`RFC`: https://www.ietf.org/rfc/rfc5545.txt
         .. _`BSD`: https://github.com/collective/icalendar/issues/2
         
         
@@ -108,6 +107,47 @@ Description: ==========================================================
         Changelog
         =========
         
+        3.11.7 (2017-08-27)
+        -------------------
+        
+        New features:
+        
+        - added vUTCOffset.ignore_exceptions to allow surpressing of failed TZOFFSET
+          parsing (for now this ignores the check for offsets > 24h) [geier]
+        
+        
+        3.11.6 (2017-08-04)
+        -------------------
+        
+        Bug fixes:
+        
+        - Fix VTIMEZONEs including RDATEs #234.  [geier]
+        
+        
+        3.11.5 (2017-07-03)
+        -------------------
+        
+        Bug fixes:
+        
+        - added an assertion that VTIMEZONE sub-components' DTSTART must be of type
+          DATETIME [geier]
+        
+        - Fix handling of VTIMEZONEs with subcomponents with the same DTSTARTs and
+          OFFSETs but which are of different types  [geier]
+        
+        
+        3.11.4 (2017-05-10)
+        -------------------
+        
+        Bug fixes:
+        
+        - Don't break on parameter values which contain equal signs, e.g. base64 encoded
+          binary data [geier]
+        
+        - Fix handling of VTIMEZONEs with subcomponents with the same DTSTARTs.
+          [geier]
+        
+        
         3.11.3 (2017-02-15)
         -------------------
         
diff --git a/src/icalendar.egg-info/SOURCES.txt b/src/icalendar.egg-info/SOURCES.txt
index 462ff3f..2f66a38 100644
--- a/src/icalendar.egg-info/SOURCES.txt
+++ b/src/icalendar.egg-info/SOURCES.txt
@@ -33,7 +33,6 @@ src/icalendar.egg-info/requires.txt
 src/icalendar.egg-info/top_level.txt
 src/icalendar/tests/__init__.py
 src/icalendar/tests/america_new_york.ics
-src/icalendar/tests/apple_xlocation_test.py
 src/icalendar/tests/encoding.ics
 src/icalendar/tests/issue_112_missing_tzinfo_on_exdate.ics
 src/icalendar/tests/issue_53_parsing_failure.ics
@@ -54,6 +53,9 @@ src/icalendar/tests/test_unit_parser_tools.py
 src/icalendar/tests/test_unit_prop.py
 src/icalendar/tests/test_unit_tools.py
 src/icalendar/tests/time.ics
+src/icalendar/tests/timezone_rdate.ics
+src/icalendar/tests/timezone_same_start.ics
+src/icalendar/tests/timezone_same_start_and_offset.ics
 src/icalendar/tests/timezoned.ics
 src/icalendar/tests/x_location.ics
 src/icalendar/tests/hypothesis/test_fuzzing.py
\ No newline at end of file
diff --git a/src/icalendar/__init__.py b/src/icalendar/__init__.py
index 2bcea75..f7f715e 100644
--- a/src/icalendar/__init__.py
+++ b/src/icalendar/__init__.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-__version__ = '3.11.3'
+__version__ = '3.11.7'
 
 from icalendar.cal import (
     Calendar,
diff --git a/src/icalendar/cal.py b/src/icalendar/cal.py
index 9ace041..ad7a25d 100644
--- a/src/icalendar/cal.py
+++ b/src/icalendar/cal.py
@@ -517,19 +517,11 @@ class Timezone(Component):
     singletons = ('TZID', 'LAST-MODIFIED', 'TZURL',)
 
     @staticmethod
-    def _extract_offsets(component, zone):
+    def _extract_offsets(component, tzname):
         """extract offsets and transition times from a VTIMEZONE component
         :param component: a STANDARD or DAYLIGHT component
-        :param zone: the name of the zone, used for constructing a TZNAME if
-                     this component has none
+        :param tzname: the name of the zone
         """
-        try:
-            tzname = str(component['TZNAME'])
-        except KeyError:
-            tzname = '{0}_{1}'.format(
-                zone,
-                component['DTSTART'].to_ical().decode('utf-8')
-            )
         offsetfrom = component['TZOFFSETFROM'].td
         offsetto = component['TZOFFSETTO'].td
         dtstart = component['DTSTART'].dt
@@ -551,7 +543,7 @@ class Timezone(Component):
                 # pytz.timezones don't know any transition dates after 2038
                 # either
                 rrule._until = datetime(2038, 12, 31)
-            elif rrule._until.tzinfo:
+            elif 'UNTIL' in component['RRULE'] and rrule._until.tzinfo:
                 rrule._until = rrule._until.replace(tzinfo=None)
             transtimes = rrule
         # or rdates
@@ -580,18 +572,29 @@ class Timezone(Component):
         zone = str(self['TZID'])
         transitions = []
         dst = {}
+        tznames = set()
         for component in self.walk():
             if type(component) == Timezone:
                 continue
+            assert isinstance(component['DTSTART'].dt, datetime), (
+                "VTIMEZONEs sub-components' DTSTART must be of type datetime, not date"
+            )
             try:
                 tzname = str(component['TZNAME'])
             except KeyError:
-                tzname = '{0}_{1}'.format(
+                tzname = '{0}_{1}_{2}_{3}'.format(
                     zone,
-                    component['DTSTART'].to_ical().decode('utf-8')
+                    component['DTSTART'].to_ical().decode('utf-8'),
+                    component['TZOFFSETFROM'].to_ical(),  # for whatever reason this is str/unicode
+                    component['TZOFFSETTO'].to_ical(),  # for whatever reason this is str/unicode
                 )
+                # TODO better way of making sure tznames are unique
+                while tzname in tznames:
+                    tzname += '_1'
+                tznames.add(tzname)
+
             dst[tzname], component_transitions = self._extract_offsets(
-                component, zone
+                component, tzname
             )
             transitions.extend(component_transitions)
 
@@ -622,6 +625,7 @@ class Timezone(Component):
                         if not dst[transitions[index][3]]:  # [3] is the name
                             dst_offset = osto - transitions[index][2]  # [2] is osto  # noqa
                             break
+            assert dst_offset is not False
             transition_info.append((osto, dst_offset, name))
 
         cls = type(zone, (DstTzInfo,), {
diff --git a/src/icalendar/parser.py b/src/icalendar/parser.py
index 4a5fc13..87587ad 100644
--- a/src/icalendar/parser.py
+++ b/src/icalendar/parser.py
@@ -149,13 +149,17 @@ def dquote(val):
 
 
 # parsing helper
-def q_split(st, sep=','):
+def q_split(st, sep=',', maxsplit=-1):
     """Splits a string on char, taking double (q)uotes into considderation.
     """
+    if maxsplit == 0:
+        return [st]
+
     result = []
     cursor = 0
     length = len(st)
     inquote = 0
+    splits = 0
     for i in range(length):
         ch = st[i]
         if ch == '"':
@@ -163,8 +167,10 @@ def q_split(st, sep=','):
         if not inquote and ch == sep:
             result.append(st[cursor:i])
             cursor = i + 1
-        if i + 1 == length:
+            splits += 1
+        if i + 1 == length or splits == maxsplit:
             result.append(st[cursor:])
+            break
     return result
 
 
@@ -227,7 +233,7 @@ class Parameters(CaselessDict):
         result = cls()
         for param in q_split(st, ';'):
             try:
-                key, val = q_split(param, '=')
+                key, val = q_split(param, '=', maxsplit=1)
                 validate_token(key)
                 # Property parameter values that are not in quoted
                 # strings are case insensitive.
diff --git a/src/icalendar/prop.py b/src/icalendar/prop.py
index f084e84..5c705c2 100644
--- a/src/icalendar/prop.py
+++ b/src/icalendar/prop.py
@@ -792,6 +792,11 @@ class vUTCOffset(object):
     """Renders itself as a utc offset.
     """
 
+    ignore_exceptions = False   # if True, and we cannot parse this
+                                # component, we will silently ignore
+                                # it, rather than let the exception
+                                # propagate upwards
+
     def __init__(self, td):
         if not isinstance(td, timedelta):
             raise ValueError('Offset value MUST be a timedelta instance')
@@ -831,7 +836,7 @@ class vUTCOffset(object):
             offset = timedelta(hours=hours, minutes=minutes, seconds=seconds)
         except:
             raise ValueError('Expected utc offset, got: %s' % ical)
-        if offset >= timedelta(hours=24):
+        if not cls.ignore_exceptions and offset >= timedelta(hours=24):
             raise ValueError(
                 'Offset must be less than 24 hours, was %s' % ical)
         if sign == '-':
diff --git a/src/icalendar/tests/apple_xlocation_test.py b/src/icalendar/tests/apple_xlocation_test.py
deleted file mode 100644
index 12c0abb..0000000
--- a/src/icalendar/tests/apple_xlocation_test.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-from icalendar.tests import unittest
-
-import datetime
-import icalendar
-import os
-import pytz
-
-class TestEncoding(unittest.TestCase):
-
-    def test_apple_xlocation(self):
-        """
-        Test if error messages are encode properly.
-        """
-        try:
-            directory = os.path.dirname(__file__)
-            with open(os.path.join(directory, 'x_location.ics'), 'rb') as fp:
-                data = fp.read()
-            cal = icalendar.Calendar.from_ical(data)
-            for event in cal.walk('vevent'):
-                self.assertEqual(len(event.errors), 1, 'Got too many errors')
-                error = event.errors[0][1]
-                self.assertTrue(error.startswith(u'Content line could not be parsed into parts'))
-
-        except UnicodeEncodeError as e:
-            self.fail("There is something wrong with encoding in the collected error messages")
diff --git a/src/icalendar/tests/test_icalendar.py b/src/icalendar/tests/test_icalendar.py
index 333a632..47343e7 100644
--- a/src/icalendar/tests/test_icalendar.py
+++ b/src/icalendar/tests/test_icalendar.py
@@ -1,4 +1,8 @@
 # -*- coding: utf-8 -*-
+import icalendar
+import os
+import textwrap
+
 from icalendar.tests import unittest
 
 
@@ -207,6 +211,30 @@ class IcalendarTestCase (unittest.TestCase):
             ('key', Parameters({'PARAM': 'pValue'}), 'value')
         )
 
+        contains_base64 = (
+            'X-APPLE-STRUCTURED-LOCATION;'
+            'VALUE=URI;X-ADDRESS="Kaiserliche Hofburg, 1010 Wien";'
+            'X-APPLE-MAPKIT-HANDLE=CAESxQEZgr3QZXJyZWljaA==;'
+            'X-APPLE-RADIUS=328.7978217977285;X-APPLE-REFERENCEFRAME=1;'
+            'X-TITLE=Heldenplatz:geo:48.206686,16.363235'
+        ).encode('utf-8')
+
+        self.assertEqual(
+            Contentline(contains_base64, strict=True).parts(),
+            ('X-APPLE-STRUCTURED-LOCATION',
+             Parameters({
+                 'X-APPLE-RADIUS': '328.7978217977285',
+                 'X-ADDRESS': 'Kaiserliche Hofburg, 1010 Wien',
+                 'X-APPLE-REFERENCEFRAME': '1',
+                 'X-TITLE': u'HELDENPLATZ',
+                 'X-APPLE-MAPKIT-HANDLE':
+                 'CAESXQEZGR3QZXJYZWLJAA==',
+                 'VALUE': 'URI',
+             }),
+             'geo:48.206686,16.363235'
+             )
+        )
+
     def test_fold_line(self):
         from ..parser import foldline
 
@@ -247,7 +275,47 @@ class IcalendarTestCase (unittest.TestCase):
         self.assertEqual(q_split('Max,Moller,"Rasmussen, Max"'),
                          ['Max', 'Moller', '"Rasmussen, Max"'])
 
+    def test_q_split_bin(self):
+        from ..parser import q_split
+        for s in ('X-SOMETHING=ABCDE==', ',,,'):
+            for maxsplit in range(-1, 3):
+                self.assertEqual(q_split(s, '=', maxsplit=maxsplit),
+                                 s.split('=', maxsplit))
+
     def test_q_join(self):
         from ..parser import q_join
         self.assertEqual(q_join(['Max', 'Moller', 'Rasmussen, Max']),
                          'Max,Moller,"Rasmussen, Max"')
+
+
+class TestEncoding(unittest.TestCase):
+
+    def test_broken_property(self):
+        """
+        Test if error messages are encode properly.
+        """
+        broken_ical = textwrap.dedent("""
+            BEGIN:VCALENDAR
+            BEGIN:VEVENT
+            SUMMARY:An Event with too many semicolons
+            DTSTART;;VALUE=DATE-TIME:20140409T093000
+            UID:abc
+            END:VEVENT
+            END:VCALENDAR
+            """)
+        cal = icalendar.Calendar.from_ical(broken_ical)
+        for event in cal.walk('vevent'):
+            self.assertEqual(len(event.errors), 1, 'Not the right amount of errors.')
+            error = event.errors[0][1]
+            self.assertTrue(error.startswith(u'Content line could not be parsed into parts'))
+
+    def test_apple_xlocation(self):
+        """
+        Test if we support base64 encoded binary data in parameter values.
+        """
+        directory = os.path.dirname(__file__)
+        with open(os.path.join(directory, 'x_location.ics'), 'rb') as fp:
+            data = fp.read()
+        cal = icalendar.Calendar.from_ical(data)
+        for event in cal.walk('vevent'):
+            self.assertEqual(len(event.errors), 0, 'Got too many errors')
diff --git a/src/icalendar/tests/test_timezoned.py b/src/icalendar/tests/test_timezoned.py
index a24402b..068c116 100644
--- a/src/icalendar/tests/test_timezoned.py
+++ b/src/icalendar/tests/test_timezoned.py
@@ -266,39 +266,39 @@ class TestTimezoneCreation(unittest.TestCase):
             [(
                 datetime.timedelta(0, 43200),
                 datetime.timedelta(0),
-                'custom_Pacific/Fiji_19151026T000000'
+                'custom_Pacific/Fiji_19151026T000000_+115544_+1200'
             )] +
             3 * [(
                 datetime.timedelta(0, 46800),
                 datetime.timedelta(0, 3600),
-                'custom_Pacific/Fiji_19981101T020000'
+                'custom_Pacific/Fiji_19981101T020000_+1200_+1300'
             ), (
                 datetime.timedelta(0, 43200),
                 datetime.timedelta(0),
-                'custom_Pacific/Fiji_19990228T030000')
+                'custom_Pacific/Fiji_19990228T030000_+1300_+1200')
             ] +
             3 * [(
                 datetime.timedelta(0, 46800),
                 datetime.timedelta(0, 3600),
-                'custom_Pacific/Fiji_20101024T020000'
+                'custom_Pacific/Fiji_20101024T020000_+1200_+1300'
             ), (
                 datetime.timedelta(0, 43200),
                 datetime.timedelta(0),
-                'custom_Pacific/Fiji_19990228T030000'
+                'custom_Pacific/Fiji_19990228T030000_+1300_+1200'
             )] +
             25 * [(
                 datetime.timedelta(0, 46800),
                 datetime.timedelta(0, 3600),
-                'custom_Pacific/Fiji_20101024T020000'
+                'custom_Pacific/Fiji_20101024T020000_+1200_+1300'
             ), (
                 datetime.timedelta(0, 43200),
                 datetime.timedelta(0),
-                'custom_Pacific/Fiji_20140119T020000'
+                'custom_Pacific/Fiji_20140119T020000_+1300_+1200'
             )] +
             [(
                 datetime.timedelta(0, 46800),
                 datetime.timedelta(0, 3600),
-                'custom_Pacific/Fiji_20101024T020000'
+                'custom_Pacific/Fiji_20101024T020000_+1200_+1300'
             )]
         )
 
@@ -306,7 +306,7 @@ class TestTimezoneCreation(unittest.TestCase):
             (
                 datetime.timedelta(0, 46800),
                 datetime.timedelta(0, 3600),
-                'custom_Pacific/Fiji_19981101T020000'
+                'custom_Pacific/Fiji_19981101T020000_+1200_+1300'
             ),
             tz._tzinfos.keys()
         )
@@ -314,7 +314,59 @@ class TestTimezoneCreation(unittest.TestCase):
             (
                 datetime.timedelta(0, 43200),
                 datetime.timedelta(0),
-                'custom_Pacific/Fiji_19990228T030000'
+                'custom_Pacific/Fiji_19990228T030000_+1300_+1200'
             ),
             tz._tzinfos.keys()
         )
+
+    def test_same_start_date(self):
+        """testing if we can handle VTIMEZONEs whose different components
+        have the same start DTIMEs."""
+        directory = os.path.dirname(__file__)
+        with open(os.path.join(directory, 'timezone_same_start.ics'), 'rb') as fp:
+            data = fp.read()
+        cal = icalendar.Calendar.from_ical(data)
+        d = cal.subcomponents[1]['DTSTART'].dt
+        self.assertEqual(d.strftime('%c'), 'Fri Feb 24 12:00:00 2017')
+
+    def test_same_start_date_and_offset(self):
+        """testing if we can handle VTIMEZONEs whose different components
+        have the same DTSTARTs, TZOFFSETFROM, and TZOFFSETTO."""
+        directory = os.path.dirname(__file__)
+        with open(os.path.join(directory, 'timezone_same_start_and_offset.ics'), 'rb') as fp:
+            data = fp.read()
+        cal = icalendar.Calendar.from_ical(data)
+        d = cal.subcomponents[1]['DTSTART'].dt
+        self.assertEqual(d.strftime('%c'), 'Fri Feb 24 12:00:00 2017')
+
+    def test_rdate(self):
+        """testing if we can handle VTIMEZONEs who only have an RDATE, not RRULE
+        """
+        directory = os.path.dirname(__file__)
+        with open(os.path.join(directory, 'timezone_rdate.ics'), 'rb') as fp:
+            data = fp.read()
+        cal = icalendar.Calendar.from_ical(data)
+        vevent = cal.walk('VEVENT')[0]
+        tz = vevent['DTSTART'].dt.tzinfo
+        self.assertEqual(str(tz), 'posix/Europe/Vaduz')
+        self.assertEqual(
+            tz._utc_transition_times[:6],
+            [
+                datetime.datetime(1901, 12, 13, 20, 45, 38),
+                datetime.datetime(1941, 5, 5, 0, 0, 0),
+                datetime.datetime(1941, 10, 6, 0, 0, 0),
+                datetime.datetime(1942, 5, 4, 0, 0, 0),
+                datetime.datetime(1942, 10, 5, 0, 0, 0),
+                datetime.datetime(1981, 3, 29, 1, 0),
+            ])
+        self.assertEqual(
+            tz._transition_info[:6],
+            [
+                (datetime.timedelta(0, 3600), datetime.timedelta(0), 'CET'),
+                (datetime.timedelta(0, 7200), datetime.timedelta(0, 3600), 'CEST'),
+                (datetime.timedelta(0, 3600), datetime.timedelta(0), 'CET'),
+                (datetime.timedelta(0, 7200), datetime.timedelta(0, 3600), 'CEST'),
+                (datetime.timedelta(0, 3600), datetime.timedelta(0), 'CET'),
+                (datetime.timedelta(0, 7200), datetime.timedelta(0, 3600), 'CEST'),
+            ]
+        )
diff --git a/src/icalendar/tests/test_unit_cal.py b/src/icalendar/tests/test_unit_cal.py
index 0cda117..1082ce7 100644
--- a/src/icalendar/tests/test_unit_cal.py
+++ b/src/icalendar/tests/test_unit_cal.py
@@ -430,3 +430,26 @@ class TestCal(unittest.TestCase):
                 for e in icalendar.cal.Calendar.from_ical(s).walk('VEVENT')],
             [[], [('EXDATE', "Expected datetime, date, or time, got: ''")]]
         )
+
+    def test_cal_strict_parsing(self):
+        cal_str = b'\r\n'.join(
+            [
+                b'BEGIN:VCALENDAR',
+                b'BEGIN:VTIMEZONE',
+                b'TZID:Europe/Prague',
+                b'BEGIN:STANDARD',
+                b'DTSTART:18500101T000000',
+                b'TZNAME:PMT',
+                b'TZOFFSETFROM:+5744',
+                b'TZOFFSETTO:+5744',
+                b'END:STANDARD',
+                b'END:VTIMEZONE',
+                b'END:VCALENDAR',
+                b'',
+            ]
+        )
+
+        self.assertRaises(ValueError, icalendar.Calendar.from_ical, cal_str)
+        icalendar.vUTCOffset.ignore_exceptions = True
+        self.assertEqual(icalendar.Calendar.from_ical(cal_str).to_ical(), cal_str)
+        icalendar.vUTCOffset.ignore_exceptions = False
diff --git a/src/icalendar/tests/timezone_rdate.ics b/src/icalendar/tests/timezone_rdate.ics
new file mode 100644
index 0000000..5a4f7a9
--- /dev/null
+++ b/src/icalendar/tests/timezone_rdate.ics
@@ -0,0 +1,55 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:posix/Europe/Vaduz
+BEGIN:STANDARD
+TZNAME:CET
+TZOFFSETFROM:+002946
+TZOFFSETTO:+0100
+DTSTART:19011213T211538
+RDATE;VALUE=DATE-TIME:19011213T211538
+END:STANDARD
+BEGIN:DAYLIGHT
+TZNAME:CEST
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+DTSTART:19810329T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+BEGIN:DAYLIGHT
+TZNAME:CEST
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+DTSTART:19410505T010000
+RDATE;VALUE=DATE-TIME:19410505T010000
+RDATE;VALUE=DATE-TIME:19420504T010000
+END:DAYLIGHT
+BEGIN:STANDARD
+TZNAME:CET
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+DTSTART:19810927T030000
+RRULE:FREQ=YEARLY;COUNT=15;BYDAY=-1SU;BYMONTH=9
+END:STANDARD
+BEGIN:STANDARD
+TZNAME:CET
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+DTSTART:19961027T030000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+BEGIN:STANDARD
+TZNAME:CET
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+DTSTART:19411006T020000
+RDATE;VALUE=DATE-TIME:19411006T020000
+RDATE;VALUE=DATE-TIME:19421005T020000
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+UID:123
+DTSTART;TZID=posix/Europe/Vaduz:20120213T100000
+SUMMARY=testevent
+END:VEVENT
+END:VCALENDAR
diff --git a/src/icalendar/tests/timezone_same_start.ics b/src/icalendar/tests/timezone_same_start.ics
new file mode 100644
index 0000000..a221ae3
--- /dev/null
+++ b/src/icalendar/tests/timezone_same_start.ics
@@ -0,0 +1,27 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:Microsoft Exchange Server 2010
+METHOD:REQUEST
+BEGIN:VTIMEZONE
+TZID:Pacific Standard Time
+BEGIN:STANDARD
+DTSTART:16010101T020000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0800
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3
+TZOFFSETFROM:-0800
+TZOFFSETTO:-0700
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+SUMMARY;LANGUAGE=en-US:Test 4
+DTSTART;TZID="Pacific Standard Time":20170224T120000
+DTEND;TZID="Pacific Standard Time":20170224T123000
+DTSTAMP:20170224T180431Z
+UID:040000008200E00074C5B7101A82E0080000000090E19664858ED20100000000000000
+END:VEVENT
+END:VCALENDAR
diff --git a/src/icalendar/tests/timezone_same_start_and_offset.ics b/src/icalendar/tests/timezone_same_start_and_offset.ics
new file mode 100644
index 0000000..0ec7ba0
--- /dev/null
+++ b/src/icalendar/tests/timezone_same_start_and_offset.ics
@@ -0,0 +1,23 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:Microsoft Exchange Server 2010
+BEGIN:VTIMEZONE
+TZID:Tokyo Standard Time
+BEGIN:STANDARD
+DTSTART:16010101T000000
+TZOFFSETFROM:+0900
+TZOFFSETTO:+0900
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T000000
+TZOFFSETFROM:+0900
+TZOFFSETTO:+0900
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTART;TZID="Tokyo Standard Time":20170224T120000
+DTEND;TZID="Tokyo Standard Time":20170224T123000
+UID:blafoobar
+SUMMARY:this is an event
+END:VEVENT
+END:VCALENDARD
diff --git a/tox.ini b/tox.ini
index 6743126..82ea668 100644
--- a/tox.ini
+++ b/tox.ini
@@ -7,7 +7,7 @@ deps =
     pytest
     coverage
     py{27,33,34,35,36}: hypothesis>=3.0
... 5 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-icalendar.git



More information about the Python-modules-commits mailing list