Browse Source

Fix KeyError when starting celery beat (#3481)

The shelve module does not accept byte literals as keys on Py3, and
does not accept unicode literals as keys on Py2, so instead the
"informal" string is used for both.

There is a description about informal strings here:
https://docs.python.org/3/library/stdtypes.html#str
Alli 8 years ago
parent
commit
d87f9db737
3 changed files with 20 additions and 19 deletions
  1. 1 0
      CONTRIBUTORS.txt
  2. 13 13
      celery/beat.py
  3. 6 6
      t/unit/app/test_beat.py

+ 1 - 0
CONTRIBUTORS.txt

@@ -218,3 +218,4 @@ Adriano Martins de Jesus, 2016/06/22
 Kevin Richardson, 2016/06/29
 Andrew Stewart, 2016/07/04
 Xin Li, 2016/08/03
+Alli Witheford, 2016/09/29

+ 13 - 13
celery/beat.py

@@ -433,55 +433,55 @@ class PersistentScheduler(Scheduler):
 
         for _ in (1, 2):
             try:
-                self._store[b'entries']
+                self._store[str(b'entries')]
             except KeyError:
                 # new schedule db
                 try:
-                    self._store[b'entries'] = {}
+                    self._store[str(b'entries')] = {}
                 except KeyError as exc:
                     self._store = self._destroy_open_corrupted_schedule(exc)
                     continue
             else:
-                if b'__version__' not in self._store:
+                if str(b'__version__') not in self._store:
                     warning('DB Reset: Account for new __version__ field')
                     self._store.clear()   # remove schedule at 2.2.2 upgrade.
-                elif b'tz' not in self._store:
+                elif str(b'tz') not in self._store:
                     warning('DB Reset: Account for new tz field')
                     self._store.clear()   # remove schedule at 3.0.8 upgrade
-                elif b'utc_enabled' not in self._store:
+                elif str(b'utc_enabled') not in self._store:
                     warning('DB Reset: Account for new utc_enabled field')
                     self._store.clear()   # remove schedule at 3.0.9 upgrade
             break
 
         tz = self.app.conf.timezone
-        stored_tz = self._store.get(b'tz')
+        stored_tz = self._store.get(str(b'tz'))
         if stored_tz is not None and stored_tz != tz:
             warning('Reset: Timezone changed from %r to %r', stored_tz, tz)
             self._store.clear()   # Timezone changed, reset db!
         utc = self.app.conf.enable_utc
-        stored_utc = self._store.get(b'utc_enabled')
+        stored_utc = self._store.get(str(b'utc_enabled'))
         if stored_utc is not None and stored_utc != utc:
             choices = {True: 'enabled', False: 'disabled'}
             warning('Reset: UTC changed from %s to %s',
                     choices[stored_utc], choices[utc])
             self._store.clear()   # UTC setting changed, reset db!
-        entries = self._store.setdefault(b'entries', {})
+        entries = self._store.setdefault(str(b'entries'), {})
         self.merge_inplace(self.app.conf.beat_schedule)
         self.install_default_entries(self.schedule)
         self._store.update({
-            b'__version__': __version__,
-            b'tz': tz,
-            b'utc_enabled': utc,
+            str(b'__version__'): __version__,
+            str(b'tz'): tz,
+            str(b'utc_enabled'): utc,
         })
         self.sync()
         debug('Current schedule:\n' + '\n'.join(
             repr(entry) for entry in values(entries)))
 
     def get_schedule(self):
-        return self._store[b'entries']
+        return self._store[str(b'entries')]
 
     def set_schedule(self, schedule):
-        self._store[b'entries'] = schedule
+        self._store[str(b'entries')] = schedule
     schedule = property(get_schedule, set_schedule)
 
     def sync(self):

+ 6 - 6
t/unit/app/test_beat.py

@@ -398,17 +398,17 @@ class test_PersistentScheduler:
         s.setup_schedule()
         s._remove_db.assert_called_with()
 
-        s._store = {b'__version__': 1}
+        s._store = {str(b'__version__'): 1}
         s.setup_schedule()
 
         s._store.clear = Mock()
         op = s.persistence.open = Mock()
         op.return_value = s._store
-        s._store[b'tz'] = 'FUNKY'
+        s._store[str(b'tz')] = 'FUNKY'
         s.setup_schedule()
         op.assert_called_with(s.schedule_filename, writeback=True)
         s._store.clear.assert_called_with()
-        s._store[b'utc_enabled'] = False
+        s._store[str(b'utc_enabled')] = False
         s._store.clear = Mock()
         s.setup_schedule()
         s._store.clear.assert_called_with()
@@ -417,10 +417,10 @@ class test_PersistentScheduler:
         s = create_persistent_scheduler()[0](
             schedule_filename='schedule', app=self.app,
         )
-        s._store = {b'entries': {}}
+        s._store = {str(b'entries'): {}}
         s.schedule = {'foo': 'bar'}
         assert s.schedule == {'foo': 'bar'}
-        assert s._store[b'entries'] == s.schedule
+        assert s._store[str(b'entries')] == s.schedule
 
 
 class test_Service:
@@ -439,7 +439,7 @@ class test_Service:
         assert isinstance(schedule, dict)
         assert isinstance(s.scheduler, beat.Scheduler)
         scheduled = list(schedule.keys())
-        for task_name in keys(sh[b'entries']):
+        for task_name in keys(sh[str(b'entries')]):
             assert task_name in scheduled
 
         s.sync()