[Python-modules-team] Bug#909368: python-vobject: diff for NMU version 0.9.6.1-0.1

Jonas Smedegaard dr at jones.dk
Sat Sep 22 17:04:36 BST 2018


Package: python-vobject
Version: 0.9.5-2
Severity: normal
Tags: patch  pending

[Replace XX with correct value]

Dear maintainer,

I've prepared an NMU for python-vobject (versioned as 0.9.6.1-0.1) and
took the liberty of uploading it straight to unstable (since Jelmer
Vernooij permits that at https://wiki.debian.org/LowThresholdNmu).

I prepared the NMU in a clone of the Debian git tree, and can share that
if you permit me write access to simply do a "git push".  Otherwise
please use the included patch, as I am not familiar with other schemes
of exchanging git material.

Regards.

 - Jonas

diff -Nru python-vobject-0.9.5/debian/changelog python-vobject-0.9.6.1/debian/changelog
--- python-vobject-0.9.5/debian/changelog	2018-06-02 20:20:50.000000000 +0200
+++ python-vobject-0.9.6.1/debian/changelog	2018-09-22 17:52:42.000000000 +0200
@@ -1,3 +1,23 @@
+python-vobject (0.9.6.1-0.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+
+  [ Jelmer Vernooij ]
+  * Remove Jonas from uploaders.
+
+  [ Ondřej Nový ]
+  * d/changelog: Remove trailing whitespaces
+
+  [ Jonas Smedegaard ]
+  * New upstream version 0.9.6.1
+    Closes: Bug#907718, #908499.
+    Thanks to Paul Gevers and Adrian Bunk.
+  * Fix drop patch to treat untils as floating:
+    Bogusly double-applied since 0.9.2-1.
+  * Unfuzz patch to not install ics diff.
+
+ -- Jonas Smedegaard <dr at jones.dk>  Sat, 22 Sep 2018 17:52:42 +0200
+
 python-vobject (0.9.5-2) unstable; urgency=medium
 
   * Change maintainer to Debian Python Modules Team. Closes: #899678
@@ -187,7 +207,7 @@
 
 python-vobject (0.5.0-1) unstable; urgency=low
 
-  * New upstream version 
+  * New upstream version
 
  -- Guido Guenther <agx at sigxcpu.org>  Wed, 16 Jan 2008 11:45:55 +0100
 
@@ -203,7 +223,7 @@
 
 python-vobject (0.4.8-1) unstable; urgency=low
 
-  * New Upstream Version (Closes: #421894) 
+  * New Upstream Version (Closes: #421894)
   * remove_ics_diff.patch: don't install /usr/bin/ics_diff
 
  -- Guido Guenther <agx at sigxcpu.org>  Mon, 18 Jun 2007 18:30:30 +0200
@@ -238,7 +258,7 @@
 
 python-vobject (0.0.svn155-2) unstable; urgency=low
 
-  * build depend on python-dateutil so the testuite can run properly. 
+  * build depend on python-dateutil so the testuite can run properly.
     (Closes: #389385)
 
  -- Guido Guenther <agx at sigxcpu.org>  Mon, 25 Sep 2006 15:49:10 +0200
@@ -269,4 +289,3 @@
       http://trac.macosforge.org/projects/calendarserver/browser/CalendarServer/trunk/patches/vObject/icalendar.patch
 
  -- Guido Guenther <agx at sigxcpu.org>  Wed,  6 Sep 2006 11:04:33 +0200
-
diff -Nru python-vobject-0.9.5/debian/control python-vobject-0.9.6.1/debian/control
--- python-vobject-0.9.5/debian/control	2018-06-02 20:20:50.000000000 +0200
+++ python-vobject-0.9.6.1/debian/control	2018-09-20 13:58:18.000000000 +0200
@@ -2,8 +2,7 @@
 Section: python
 Priority: optional
 Maintainer: Debian Python Modules Team <python-modules-team at lists.alioth.debian.org>
-Uploaders: Guido Günther <agx at sigxcpu.org>, Jelmer Vernooij <jelmer at debian.org>,
- Jonas Smedegaard <dr at jones.dk>
+Uploaders: Guido Günther <agx at sigxcpu.org>, Jelmer Vernooij <jelmer at debian.org>
 Build-Depends: debhelper, dh-python,
  python,
  python-dateutil,
diff -Nru python-vobject-0.9.5/debian/copyright python-vobject-0.9.6.1/debian/copyright
--- python-vobject-0.9.5/debian/copyright	2018-06-02 20:20:50.000000000 +0200
+++ python-vobject-0.9.6.1/debian/copyright	2018-09-20 13:58:18.000000000 +0200
@@ -65,4 +65,3 @@
  * originally written at the National Center for Supercomputing Applications,
  * University of Illinois, Urbana-Champaign.
  */
-
diff -Nru python-vobject-0.9.5/debian/patches/Don-t-install-ics_diff.patch python-vobject-0.9.6.1/debian/patches/Don-t-install-ics_diff.patch
--- python-vobject-0.9.5/debian/patches/Don-t-install-ics_diff.patch	2018-06-02 20:20:50.000000000 +0200
+++ python-vobject-0.9.6.1/debian/patches/Don-t-install-ics_diff.patch	2018-09-22 17:30:28.000000000 +0200
@@ -8,9 +8,9 @@
 
 --- a/setup.py
 +++ b/setup.py
-@@ -43,12 +43,6 @@
+@@ -38,12 +38,6 @@
        url = "http://eventable.github.io/vobject/",
-       download_url = 'https://github.com/eventable/vobject/tarball/0.9.5',
+       download_url = 'https://github.com/eventable/vobject/tarball/0.9.6.1',
        bugtrack_url = "https://github.com/eventable/vobject/issues",
 -      entry_points = {
 -            'console_scripts': [
diff -Nru python-vobject-0.9.5/debian/patches/series python-vobject-0.9.6.1/debian/patches/series
--- python-vobject-0.9.5/debian/patches/series	2018-06-02 20:20:50.000000000 +0200
+++ python-vobject-0.9.6.1/debian/patches/series	2018-09-22 17:49:13.000000000 +0200
@@ -1,2 +1 @@
 Don-t-install-ics_diff.patch
-Treat-untils-as-floating.patch
diff -Nru python-vobject-0.9.5/debian/patches/Treat-untils-as-floating.patch python-vobject-0.9.6.1/debian/patches/Treat-untils-as-floating.patch
--- python-vobject-0.9.5/debian/patches/Treat-untils-as-floating.patch	2018-06-02 20:20:50.000000000 +0200
+++ python-vobject-0.9.6.1/debian/patches/Treat-untils-as-floating.patch	1970-01-01 01:00:00.000000000 +0100
@@ -1,29 +0,0 @@
-From: Morgen Sagen <sagen at apple.com>
-Date: Mon, 4 Jan 2010 20:27:01 +0100
-Subject: Treat untils as floating
-
----
- vobject/icalendar.py | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
---- a/vobject/icalendar.py
-+++ b/vobject/icalendar.py
-@@ -489,6 +489,18 @@
-                         if dtstart.tzinfo is None:
-                             until = until.replace(tzinfo=None)
- 
-+                        # RFC2445 actually states that UNTIL must be a UTC value. Whilst the
-+                        # changes above work OK, one problem case is if DTSTART is floating but
-+                        # UNTIL is properly specified as UTC (or with a TZID). In that case dateutil
-+                        # will fail datetime comparisons. There is no easy solution to this as
-+                        # there is no obvious timezone (at this point) to do proper floating time
-+                        # offset compisons. The best we can do is treat the UNTIL value as floating.
-+                        # This could mean incorrect determination of the last instance. The better
-+                        # solution here is to encourage clients to use COUNT rather than UNTIL
-+                        # when DTSTART is floating.
-+                        if dtstart.tzinfo is None:
-+                            until = until.replace(tzinfo=None)
-+
-                         rule._until = until
- 
-                     # add the rrule or exrule to the rruleset
diff -Nru python-vobject-0.9.5/docs/index.html python-vobject-0.9.6.1/docs/index.html
--- python-vobject-0.9.5/docs/index.html	2017-06-29 20:55:55.000000000 +0200
+++ python-vobject-0.9.6.1/docs/index.html	2018-07-18 20:28:54.000000000 +0200
@@ -337,6 +337,30 @@
 <a id="release-history" class="anchor" href="#release-history" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Release History</h1>
 
 <h3>
+<a id="7-july-2018" class="anchor" href="#7-july-2018" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>7 July 2018</h3>
+
+<p><strong>vobject 0.9.6</strong> released (<a href="https://github.com/eventable/vobject/releases/tag/0.9.6">view</a>).</p>
+
+<p>To install, use <code>pip install vobject</code>, or download the archive and untar, run python setup.py install. Tests can be run via python setup.py test. <a href="https://pypi.org/project/python-dateutil/">dateutil</a> and <a href="https://pypi.org/project/six">six</a> are required. Python 2.7 or higher is required.</p>
+
+<h5>
+<a id="release-notes" class="anchor" href="#release-notes" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Release Notes</h5>
+
+<ul>
+<li>  Correctly order calendar properties before calendar components</li>
+<li>  Correctly serialize timestamp values (i.e. `REV`)</li>
+<li>  Pass correct formatting string to logger</li>
+<li>  RRULE: Fix floating UNTIL with dateutil > 2.6.1</li>
+<li>  Encode params if necessary in serialization</li>
+<li>  Ignore escaped semi-colons in UNTIL value</li>
+<li>  RRULE: Fix VTODO without DTSTART</li>
+<li>  Fixed regexp for VCF Version 2.1</li>
+<li>  repr() changed for datetime.timedelta in python 3.7</li>
+</ul>
+
+<hr>
+
+<h3>
 <a id="29-june-2017" class="anchor" href="#29-june-2017" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>29 June 2017</h3>
 
 <p><strong>vobject 0.9.5</strong> released (<a href="https://github.com/eventable/vobject/releases/tag/0.9.5">view</a>).</p>
diff -Nru python-vobject-0.9.5/.gitignore python-vobject-0.9.6.1/.gitignore
--- python-vobject-0.9.5/.gitignore	2017-06-29 20:55:55.000000000 +0200
+++ python-vobject-0.9.6.1/.gitignore	2018-07-18 20:28:54.000000000 +0200
@@ -7,3 +7,4 @@
 vobject.egg-info/**/*
 venv/**/*
 .idea/*
+*.sublime-*
diff -Nru python-vobject-0.9.5/setup.py python-vobject-0.9.6.1/setup.py
--- python-vobject-0.9.5/setup.py	2017-06-29 20:55:55.000000000 +0200
+++ python-vobject-0.9.6.1/setup.py	2018-07-18 20:28:54.000000000 +0200
@@ -15,13 +15,8 @@
 
 Recent changes
 --------------
-   - Make ics_diff.py work with Python 3
-   - Huge changes to text encoding for Python 2/3 compatibility
-   - Autogenerate DTSTAMP if not provided
-   - Fix getrruleset() for Python 3 and in the case that addRDate=True
-   - Update vCard property validation to match specifications
-   - Handle offset-naive and offset-aware datetimes in recurrence rules
-   - Improved documentation for multi-value properties
+    - Revert too-strict serialization of timestamp values - broke too many other
+       implementations
 
 For older changes, see
    - http://eventable.github.io/vobject/#release-history or
@@ -33,7 +28,7 @@
 doclines = (__doc__ or '').splitlines()
 
 setup(name = "vobject",
-      version = "0.9.5",
+      version = "0.9.6.1",
       author = "Jeffrey Harris",
       author_email = "jeffrey at osafoundation.org",
       maintainer = "Sameen Karim",
@@ -41,7 +36,7 @@
       license = "Apache",
       zip_safe = True,
       url = "http://eventable.github.io/vobject/",
-      download_url = 'https://github.com/eventable/vobject/tarball/0.9.5',
+      download_url = 'https://github.com/eventable/vobject/tarball/0.9.6.1',
       bugtrack_url = "https://github.com/eventable/vobject/issues",
       entry_points = {
             'console_scripts': [
diff -Nru python-vobject-0.9.5/test_files/simple_2_0_test.ics python-vobject-0.9.6.1/test_files/simple_2_0_test.ics
--- python-vobject-0.9.5/test_files/simple_2_0_test.ics	2017-06-29 20:55:55.000000000 +0200
+++ python-vobject-0.9.6.1/test_files/simple_2_0_test.ics	2018-07-18 20:28:54.000000000 +0200
@@ -4,6 +4,7 @@
 BEGIN:VEVENT
 UID:Not very random UID
 DTSTART:20060509T000000
+ATTENDEE;CN=Fröhlich:mailto:froelich at example.com
 CREATED:20060101T180000Z
 DESCRIPTION:Test event
 DTSTAMP:20170626T000000Z
diff -Nru python-vobject-0.9.5/tests.py python-vobject-0.9.6.1/tests.py
--- python-vobject-0.9.5/tests.py	2017-06-29 20:55:55.000000000 +0200
+++ python-vobject-0.9.6.1/tests.py	2018-07-18 20:28:54.000000000 +0200
@@ -68,6 +68,9 @@
         cal.vevent.add('uid').value = "Not very random UID"
         cal.vevent.add('dtstamp').value = datetime.datetime(2017, 6, 26, 0, tzinfo=tzutc())
 
+        cal.vevent.add('attendee').value = 'mailto:froelich at example.com'
+        cal.vevent.attendee.params['CN'] = ['Fröhlich']
+
         # Note we're normalizing line endings, because no one got time for that.
         self.assertEqual(
             cal.serialize().replace('\r\n', '\n'),
@@ -253,7 +256,7 @@
         )
         self.assertEqual(
             str(parseRDate(textLineToContentLine("RDATE;VALUE=PERIOD:19960403T020000Z/19960403T040000Z,19960404T010000Z/PT3H"))),
-            "<RDATE{'VALUE': ['PERIOD']}[(datetime.datetime(1996, 4, 3, 2, 0, tzinfo=tzutc()), datetime.datetime(1996, 4, 3, 4, 0, tzinfo=tzutc())), (datetime.datetime(1996, 4, 4, 1, 0, tzinfo=tzutc()), datetime.timedelta(0, 10800))]>"
+            "<RDATE{'VALUE': ['PERIOD']}[(datetime.datetime(1996, 4, 3, 2, 0, tzinfo=tzutc()), datetime.datetime(1996, 4, 3, 4, 0, tzinfo=tzutc())), (datetime.datetime(1996, 4, 4, 1, 0, tzinfo=tzutc()), " + ("datetime.timedelta(0, 10800)" if sys.version_info < (3,7) else "datetime.timedelta(seconds=10800)") + ")]>"
         )
 
     def test_periodBehavior(self):
diff -Nru python-vobject-0.9.5/vobject/base.py python-vobject-0.9.6.1/vobject/base.py
--- python-vobject-0.9.5/vobject/base.py	2017-06-29 20:55:55.000000000 +0200
+++ python-vobject-0.9.6.1/vobject/base.py	2018-07-18 20:28:54.000000000 +0200
@@ -69,7 +69,7 @@
 logger = logging.getLogger(__name__)
 if not logging.getLogger().handlers:
     handler = logging.StreamHandler()
-    formatter = logging.Formatter('{name} {levelname} {message}')
+    formatter = logging.Formatter('%(name)s %(levelname)s %(message)s')
     handler.setFormatter(formatter)
     logger.addHandler(handler)
 logger.setLevel(logging.ERROR)  # Log errors
@@ -774,7 +774,7 @@
 # get a full content line, break it up into group, name, parameters, and value
 patterns['line'] = r"""
 ^ ((?P<group> {name!s})\.)?(?P<name> {name!s}) # name group
-  (?P<params> (?: {param!s} )* )               # params group (may be empty)
+  (?P<params> ;?(?: {param!s} )* )               # params group (may be empty)
 : (?P<value> .* )$                             # value group
 """.format(**patterns)
 
@@ -1022,10 +1022,13 @@
         keys = sorted(obj.params.keys())
         for key in keys:
             paramstr = ','.join(dquoteEscape(p) for p in obj.params[key])
-            s.write(";{0}={1}".format(key, paramstr))
+            try:
+                s.write(";{0}={1}".format(key, paramstr))
+            except (UnicodeDecodeError, UnicodeEncodeError):
+                s.write(";{0}={1}".format(key, paramstr.encode('utf-8')))
         try:
             s.write(":{0}".format(obj.value))
-        except (UnicodeDecodeError, UnicodeEncodeError) as e:
+        except (UnicodeDecodeError, UnicodeEncodeError):
             s.write(":{0}".format(obj.value.encode('utf-8')))
         if obj.behavior and not startedEncoded:
             obj.behavior.decode(obj)
diff -Nru python-vobject-0.9.5/vobject/icalendar.py python-vobject-0.9.6.1/vobject/icalendar.py
--- python-vobject-0.9.5/vobject/icalendar.py	2017-06-29 20:55:55.000000000 +0200
+++ python-vobject-0.9.6.1/vobject/icalendar.py	2018-07-18 20:28:54.000000000 +0200
@@ -2,7 +2,6 @@
 
 from __future__ import print_function
 
-import codecs
 import datetime
 import logging
 import random  # for generating a UID
@@ -32,7 +31,7 @@
 from . import behavior
 from .base import (VObjectError, NativeError, ValidateError, ParseError,
                    Component, ContentLine, logger, registerBehavior,
-                   backslashEscape, foldOneLine, str_)
+                   backslashEscape, foldOneLine)
 
 
 # ------------------------------- Constants ------------------------------------
@@ -415,7 +414,21 @@
                 if addfunc is None:
                     addfunc = getattr(rruleset, name)
 
-                dtstart = self.dtstart.value
+                try:
+                    dtstart = self.dtstart.value
+                except (AttributeError, KeyError):
+                    # Special for VTODO - try DUE property instead
+                    try:
+                        if self.name == "VTODO":
+                            dtstart = self.due.value
+                        else:
+                            # if there's no dtstart, just return None
+                            logging.error('failed to get dtstart with VTODO')
+                            return None
+                    except (AttributeError, KeyError):
+                        # if there's no due, just return None
+                        logging.error('failed to find DUE at all.')
+                        return None
 
                 if name in DATENAMES:
                     if type(line.value[0]) == datetime.datetime:
@@ -427,31 +440,22 @@
                         # ignore RDATEs with PERIOD values for now
                         pass
                 elif name in RULENAMES:
-                    try:
-                        dtstart = self.dtstart.value
-                    except (AttributeError, KeyError):
-                        # Special for VTODO - try DUE property instead
-                        try:
-                            if self.name == "VTODO":
-                                dtstart = self.due.value
-                            else:
-                                # if there's no dtstart, just return None
-                                logging.error('failed to get dtstart with VTODO')
-                                return None
-                        except (AttributeError, KeyError):
-                            # if there's no due, just return None
-                            logging.error('failed to find DUE at all.')
-                            return None
-
                     # a Ruby iCalendar library escapes semi-colons in rrules,
                     # so also remove any backslashes
                     value = line.value.replace('\\', '')
-                    rule = rrule.rrulestr(
-                        value, dtstart=dtstart,
-                        # If dtstart has no time zone, `until`
-                        # shouldn't get one, either:
-                        ignoretz=isinstance(dtstart, datetime.date))
-                    until = rule._until
+                    # If dtstart has no time zone, `until`
+                    # shouldn't get one, either:
+                    ignoretz = (not isinstance(dtstart, datetime.datetime) or
+                                dtstart.tzinfo is None)
+                    try:
+                        until = rrule.rrulestr(value, ignoretz=ignoretz)._until
+                    except ValueError:
+                        # WORKAROUND: dateutil<=2.7.2 doesn't set the time zone
+                        # of dtstart
+                        if ignoretz:
+                            raise
+                        utc_now = datetime.datetime.now(datetime.timezone.utc)
+                        until = rrule.rrulestr(value, dtstart=utc_now)._until
 
                     if until is not None and isinstance(dtstart,
                                                         datetime.datetime) and \
@@ -459,7 +463,7 @@
                         # dateutil converts the UNTIL date to a datetime,
                         # check to see if the UNTIL parameter value was a date
                         vals = dict(pair.split('=') for pair in
-                                    line.value.upper().split(';'))
+                                    value.upper().split(';'))
                         if len(vals.get('UNTIL', '')) == 8:
                             until = datetime.datetime.combine(until.date(),
                                                               dtstart.time())
@@ -489,7 +493,12 @@
                         if dtstart.tzinfo is None:
                             until = until.replace(tzinfo=None)
 
-                        rule._until = until
+                    value_without_until = ';'.join(
+                        pair for pair in value.split(';')
+                        if pair.split('=')[0].upper() != 'UNTIL')
+                    rule = rrule.rrulestr(value_without_until,
+                                          dtstart=dtstart, ignoretz=ignoretz)
+                    rule._until = until
 
                     # add the rrule or exrule to the rruleset
                     addfunc(rule)
@@ -974,6 +983,65 @@
             tzid = toUnicode(tzid)
             if tzid != u'UTC' and tzid not in oldtzids:
                 obj.add(TimezoneComponent(tzinfo=getTzid(tzid)))
+
+    @classmethod
+    def serialize(cls, obj, buf, lineLength, validate=True):
+        """
+        Set implicit parameters, do encoding, return unicode string.
+
+        If validate is True, raise VObjectError if the line doesn't validate
+        after implicit parameters are generated.
+
+        Default is to call base.defaultSerialize.
+
+        """
+
+        cls.generateImplicitParameters(obj)
+        if validate:
+            cls.validate(obj, raiseException=True)
+        if obj.isNative:
+            transformed = obj.transformFromNative()
+            undoTransform = True
+        else:
+            transformed = obj
+            undoTransform = False
+        out = None
+        outbuf = buf or six.StringIO()
+        if obj.group is None:
+            groupString = ''
+        else:
+            groupString = obj.group + '.'
+        if obj.useBegin:
+            foldOneLine(outbuf, "{0}BEGIN:{1}".format(groupString, obj.name),
+                        lineLength)
+
+        try:
+            first_props = [s for s in cls.sortFirst if s in obj.contents \
+                                    and not isinstance(obj.contents[s][0], Component)]
+            first_components = [s for s in cls.sortFirst if s in obj.contents \
+                                    and isinstance(obj.contents[s][0], Component)]
+        except Exception:
+            first_props = first_components = []
+            # first_components = []
+
+        prop_keys = sorted(list(k for k in obj.contents.keys() if k not in first_props \
+                                         and not isinstance(obj.contents[k][0], Component)))
+        comp_keys = sorted(list(k for k in obj.contents.keys() if k not in first_components \
+                                        and isinstance(obj.contents[k][0], Component)))
+
+        sorted_keys = first_props + prop_keys + first_components + comp_keys
+        children = [o for k in sorted_keys for o in obj.contents[k]]
+
+        for child in children:
+            # validate is recursive, we only need to validate once
+            child.serialize(outbuf, lineLength, validate=False)
+        if obj.useBegin:
+            foldOneLine(outbuf, "{0}END:{1}".format(groupString, obj.name),
+                        lineLength)
+        out = buf or outbuf.getvalue()
+        if undoTransform:
+            obj.transformToNative()
+        return out
 registerBehavior(VCalendar2_0)
 
 



More information about the Python-modules-team mailing list