[FIX] google_calendar: rrule crash

Consider the following:
``` python
from datetime import datetime
from dateutil import rrule
import pytz

dt = pytz.UTC.localize(datetime(2016, 9, 2, 15, 42, 43, 205))
rset = rrule.rrulestr('FREQ=WEEKLY;INTERVAL=2;BYDAY=SU,FR,SA', dtstart=dt, forceset=True, tzinfos={})
test = [d for d in rset]
```

This will generate the following error:
```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/dateutil/rrule.py", line 1164, in _iter
    advance_iterator(ritem)
  File "/usr/lib/python2.7/dist-packages/dateutil/rrule.py", line 1091, in __next__
    self.dt = advance_iterator(self.gen)
  File "/usr/lib/python2.7/dist-packages/dateutil/rrule.py", line 649, in _iter
    date = datetime.date.fromordinal(ii.yearordinal+i)
ValueError: year is out of range
```

If such an event is received from Google Calendar, the synchronization
crashes. To avoid this, we enforce a `COUNT` condition if the latter or
`UNTIL` is not explicitly specified. This gives:
``` python
rset = rrule.rrulestr('FREQ=WEEKLY;INTERVAL=2;BYDAY=SU,FR,SA;COUNT=100', dtstart=dt, forceset=True, tzinfos={})
```

Note that this was supposed to be fixed in
https://github.com/odoo/odoo/blob/9dcc32c3041e7ad3549a09c5ed68ee3ef22c7a26/addons/calendar/models/calendar.py#L1287
However, this was working with the old API. The new API and its computed
fields does something different:

1. create the calendar event with the provided `rrule`
2. trigger the inverse method `_inverse_rrule` => `count=100` is added
   to the computed parameters
3. however, doing so won't recompute `rrule` for obvious reasons (it was
   the initial value provided, so we don't recompute it)
4. the crash is met in `_get_recurrent_date_by_event` when using
   `self.rrule`

The fundamental issue is that `_inverse_rrule` is not strictly the
inverse of `_compute_rrule`.

Fixes #25189
opw-1861658
This commit is contained in:
Nicolas Martinelli
2018-08-07 09:02:44 +02:00
committed by Nicolas Martinelli
parent a4454fc7b1
commit b37416376b
+18
View File
@@ -1470,6 +1470,10 @@ class Meeting(models.Model):
@api.multi
def write(self, values):
# FIXME: neverending recurring events
if 'rrule' in values:
values['rrule'] = self._fix_rrule(values)
# compute duration, only if start and stop are modified
if not 'duration' in values and 'start' in values and 'stop' in values:
values['duration'] = self._get_duration(values['start'], values['stop'])
@@ -1538,6 +1542,10 @@ class Meeting(models.Model):
@api.model
def create(self, values):
# FIXME: neverending recurring events
if 'rrule' in values:
values['rrule'] = self._fix_rrule(values)
if not 'user_id' in values: # Else bug with quick_create when we are filter on an other user
values['user_id'] = self.env.user.id
@@ -1742,3 +1750,13 @@ class Meeting(models.Model):
activity_values['user_id'] = values['user_id']
if activity_values.keys():
self.mapped('activity_ids').write(activity_values)
@api.model
def _fix_rrule(self, values):
rule_str = values.get('rrule')
if rule_str:
rule = rrule.rrulestr(rule_str)
if not rule._until and not rule._count:
rule._count = 100
rule_str = str(rule).split('RRULE:')[-1]
return rule_str