[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:
committed by
Nicolas Martinelli
parent
a4454fc7b1
commit
b37416376b
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user