From 72e75a90c38815de97c789f2eca248af7a8c17f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Sun, 3 Apr 2016 19:00:44 +0300 Subject: [PATCH] Implemented __getstate__ and __setstate__ for trigger classes (fixes #121) --- apscheduler/triggers/cron/__init__.py | 24 ++++++++++++++++++++++++ apscheduler/triggers/date.py | 18 ++++++++++++++++++ apscheduler/triggers/interval.py | 26 ++++++++++++++++++++++++++ docs/versionhistory.rst | 6 ++++++ 4 files changed, 74 insertions(+) diff --git a/apscheduler/triggers/cron/__init__.py b/apscheduler/triggers/cron/__init__.py index 33899e432..4cced4100 100644 --- a/apscheduler/triggers/cron/__init__.py +++ b/apscheduler/triggers/cron/__init__.py @@ -168,6 +168,30 @@ def get_next_fire_time(self, previous_fire_time, now): if fieldnum >= 0: return next_date + def __getstate__(self): + return { + 'version': 1, + 'timezone': self.timezone, + 'start_date': self.start_date, + 'end_date': self.end_date, + 'fields': self.fields + } + + def __setstate__(self, state): + # This is for compatibility with APScheduler 3.0.x + if isinstance(state, tuple): + state = state[1] + + if state.get('version', 1) > 1: + raise ValueError( + 'Got serialized data for version %s of %s, but only version 1 can be handled' % + (state['version'], self.__class__.__name__)) + + self.timezone = state['timezone'] + self.start_date = state['start_date'] + self.end_date = state['end_date'] + self.fields = state['fields'] + def __str__(self): options = ["%s='%s'" % (f.name, f) for f in self.fields if not f.is_default] return 'cron[%s]' % (', '.join(options)) diff --git a/apscheduler/triggers/date.py b/apscheduler/triggers/date.py index b6bb6cea4..c8a26ddd5 100644 --- a/apscheduler/triggers/date.py +++ b/apscheduler/triggers/date.py @@ -23,6 +23,24 @@ def __init__(self, run_date=None, timezone=None): def get_next_fire_time(self, previous_fire_time, now): return self.run_date if previous_fire_time is None else None + def __getstate__(self): + return { + 'version': 1, + 'run_date': self.run_date + } + + def __setstate__(self, state): + # This is for compatibility with APScheduler 3.0.x + if isinstance(state, tuple): + state = state[1] + + if state.get('version', 1) > 1: + raise ValueError( + 'Got serialized data for version %s of %s, but only version 1 can be handled' % + (state['version'], self.__class__.__name__)) + + self.run_date = state['run_date'] + def __str__(self): return 'date[%s]' % datetime_repr(self.run_date) diff --git a/apscheduler/triggers/interval.py b/apscheduler/triggers/interval.py index 2a0934431..d8700b286 100644 --- a/apscheduler/triggers/interval.py +++ b/apscheduler/triggers/interval.py @@ -1,6 +1,7 @@ from datetime import timedelta, datetime from math import ceil +import six from tzlocal import get_localzone from apscheduler.triggers.base import BaseTrigger @@ -59,6 +60,31 @@ def get_next_fire_time(self, previous_fire_time, now): if not self.end_date or next_fire_time <= self.end_date: return self.timezone.normalize(next_fire_time) + def __getstate__(self): + return { + 'version': 1, + 'timezone': self.timezone, + 'start_date': self.start_date, + 'end_date': self.end_date, + 'interval': self.interval + } + + def __setstate__(self, state): + # This is for compatibility with APScheduler 3.0.x + if isinstance(state, tuple): + state = state[1] + + if state.get('version', 1) > 1: + raise ValueError( + 'Got serialized data for version %s of %s, but only version 1 can be handled' % + (state['version'], self.__class__.__name__)) + + self.timezone = state['timezone'] + self.start_date = state['start_date'] + self.end_date = state['end_date'] + self.interval = state['interval'] + self.interval_length = timedelta_seconds(self.interval) + def __str__(self): return 'interval[%s]' % str(self.interval) diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst index 892cb857f..7e5cf9079 100644 --- a/docs/versionhistory.rst +++ b/docs/versionhistory.rst @@ -4,6 +4,12 @@ Version history To find out how to migrate your application from a previous version of APScheduler, see the :doc:`migration section `. +3.1.1 +----- + +* Fixed pickling problems with persistent jobs when upgrading from 3.0.x + + 3.1.0 -----