Explorar o código

celery.db.a805d4bd: This module fixes a bug with pickling and relative imports in Python < 2.6.

The problem is with pickling an e.g. ``exceptions.KeyError`` instance.
As SQLAlchemy has its own ``exceptions`` module, pickle will try to
lookup ``KeyError`` in the wrong module, resulting in this exception::

    cPickle.PicklingError: Can't pickle <type 'exceptions.KeyError'>:
        attribute lookup exceptions.KeyError failed

doing ``import exceptions`` just before the dump in ``sqlalchemy.types``
reveals the source of the bug::

    EXCEPTIONS: <module 'sqlalchemy.exc' from '/var/lib/hudson/jobs/celery/
        workspace/buildenv/lib/python2.5/site-packages/sqlalchemy/exc.pyc'>

Hence the random module name "a805d5bd" is taken to decrease the chances of
a collision.
Ask Solem %!s(int64=15) %!d(string=hai) anos
pai
achega
e3c34268fb
Modificáronse 2 ficheiros con 71 adicións e 1 borrados
  1. 68 0
      celery/db/a805d4bd.py
  2. 3 1
      celery/db/models.py

+ 68 - 0
celery/db/a805d4bd.py

@@ -0,0 +1,68 @@
+"""
+a805d4bd
+This module fixes a bug with pickling and relative imports in Python < 2.6.
+
+The problem is with pickling an e.g. ``exceptions.KeyError`` instance.
+As SQLAlchemy has its own ``exceptions`` module, pickle will try to
+lookup ``KeyError`` in the wrong module, resulting in this exception::
+
+    cPickle.PicklingError: Can't pickle <type 'exceptions.KeyError'>:
+        attribute lookup exceptions.KeyError failed
+
+doing ``import exceptions`` just before the dump in ``sqlalchemy.types``
+reveals the source of the bug::
+
+    EXCEPTIONS: <module 'sqlalchemy.exc' from '/var/lib/hudson/jobs/celery/
+        workspace/buildenv/lib/python2.5/site-packages/sqlalchemy/exc.pyc'>
+
+Hence the random module name "a805d5bd" is taken to decrease the chances of
+a collision.
+
+"""
+from sqlalchemy.types import PickleType as _PickleType
+
+
+class PickleType(_PickleType):
+
+    def bind_processor(self, dialect):
+        impl_processor = self.impl.bind_processor(dialect)
+        dumps = self.pickler.dumps
+        protocol = self.protocol
+        if impl_processor:
+
+            def process(value):
+                if value is not None:
+                    value = dumps(value, protocol)
+                return impl_processor(value)
+
+        else:
+
+            def process(value):
+                if value is not None:
+                    value = dumps(value, protocol)
+                return value
+        return process
+
+    def result_processor(self, dialect, coltype):
+        impl_processor = self.impl.result_processor(dialect, coltype)
+        loads = self.pickler.loads
+        if impl_processor:
+
+            def process(value):
+                value = impl_processor(value)
+                if value is None:
+                    return None
+                return loads(value)
+        else:
+
+            def process(value):
+                if value is None:
+                    return None
+                return loads(value)
+        return process
+
+    def copy_value(self, value):
+        if self.mutable:
+            return self.pickler.loads(self.pickler.dumps(value, self.protocol))
+        else:
+            return value

+ 3 - 1
celery/db/models.py

@@ -1,11 +1,13 @@
 from datetime import datetime
 
 from sqlalchemy import Column, Sequence, ForeignKey
-from sqlalchemy import Integer, String, Text, DateTime, PickleType
+from sqlalchemy import Integer, String, Text, DateTime
 from sqlalchemy.orm import relation
 
 from celery import states
 from celery.db.session import ResultModelBase
+# See docstring of a805d4bd for an explanation for this workaround ;)
+from celery.db.a805d4bd import PickleType