Jelajahi Sumber

Fix couchdb keys (#4166)

* Fix couchdb keys problem on Python 3. Addresses code review in #3861.

* isort.

* fix build failure.
Omer Katz 7 tahun lalu
induk
melakukan
7e87cb1dbf
2 mengubah file dengan 35 tambahan dan 3 penghapusan
  1. 2 0
      celery/backends/couchdb.py
  2. 33 3
      t/unit/backends/test_couchdb.py

+ 2 - 0
celery/backends/couchdb.py

@@ -2,6 +2,7 @@
 """CouchDB result store backend."""
 from __future__ import absolute_import, unicode_literals
 
+from kombu.utils.encoding import bytes_to_str
 from kombu.utils.url import _parse_url
 
 from celery.exceptions import ImproperlyConfigured
@@ -86,6 +87,7 @@ class CouchBackend(KeyValueStoreBackend):
             return None
 
     def set(self, key, value):
+        key = bytes_to_str(key)
         data = {'_id': key, 'value': value}
         try:
             self.connection.save(data)

+ 33 - 3
t/unit/backends/test_couchdb.py

@@ -43,16 +43,46 @@ class test_CouchBackend:
 
         CouchBackend.get should return  and take two params
         db conn to couchdb is mocked.
-        TODO Should test on key not exists
-
         """
         x = CouchBackend(app=self.app)
         x._connection = Mock()
         get = x._connection.get = MagicMock()
-        # should return None
         assert x.get('1f3fab') == get.return_value['value']
         x._connection.get.assert_called_once_with('1f3fab')
 
+    def test_get_non_existent_key(self):
+        x = CouchBackend(app=self.app)
+        x._connection = Mock()
+        get = x._connection.get = MagicMock()
+        get.side_effect = pycouchdb.exceptions.NotFound
+        assert x.get('1f3fab') is None
+        x._connection.get.assert_called_once_with('1f3fab')
+
+    @pytest.mark.parametrize("key", ['1f3fab', b'1f3fab'])
+    def test_set(self, key):
+        x = CouchBackend(app=self.app)
+        x._connection = Mock()
+
+        x.set(key, 'value')
+
+        x._connection.save.assert_called_once_with({'_id': '1f3fab',
+                                                    'value': 'value'})
+
+    @pytest.mark.parametrize("key", ['1f3fab', b'1f3fab'])
+    def test_set_with_conflict(self, key):
+        x = CouchBackend(app=self.app)
+        x._connection = Mock()
+        x._connection.save.side_effect = (pycouchdb.exceptions.Conflict, None)
+        get = x._connection.get = MagicMock()
+
+        x.set(key, 'value')
+
+        x._connection.get.assert_called_once_with('1f3fab')
+        x._connection.get('1f3fab').__setitem__.assert_called_once_with(
+            'value', 'value')
+        x._connection.save.assert_called_with(get('1f3fab'))
+        assert x._connection.save.call_count == 2
+
     def test_delete(self):
         """test_delete