a805d4bd.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. # -*- coding: utf-8 -*-
  2. """
  3. celery.backends.database.a805d4bd
  4. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  5. This module fixes a bug with pickling and relative imports in Python < 2.6.
  6. The problem is with pickling an e.g. `exceptions.KeyError` instance.
  7. As SQLAlchemy has its own `exceptions` module, pickle will try to
  8. lookup :exc:`KeyError` in the wrong module, resulting in this exception::
  9. cPickle.PicklingError: Can't pickle <type 'exceptions.KeyError'>:
  10. attribute lookup exceptions.KeyError failed
  11. doing `import exceptions` just before the dump in `sqlalchemy.types`
  12. reveals the source of the bug::
  13. EXCEPTIONS: <module 'sqlalchemy.exc' from '/var/lib/hudson/jobs/celery/
  14. workspace/buildenv/lib/python2.5/site-packages/sqlalchemy/exc.pyc'>
  15. Hence the random module name 'a805d5bd' is taken to decrease the chances of
  16. a collision.
  17. """
  18. from __future__ import absolute_import
  19. from sqlalchemy.types import PickleType as _PickleType
  20. class PickleType(_PickleType): # pragma: no cover
  21. def bind_processor(self, dialect):
  22. impl_processor = self.impl.bind_processor(dialect)
  23. dumps = self.pickler.dumps
  24. protocol = self.protocol
  25. if impl_processor:
  26. def process(value):
  27. if value is not None:
  28. value = dumps(value, protocol)
  29. return impl_processor(value)
  30. else:
  31. def process(value): # noqa
  32. if value is not None:
  33. value = dumps(value, protocol)
  34. return value
  35. return process
  36. def result_processor(self, dialect, coltype):
  37. impl_processor = self.impl.result_processor(dialect, coltype)
  38. loads = self.pickler.loads
  39. if impl_processor:
  40. def process(value):
  41. value = impl_processor(value)
  42. if value is not None:
  43. return loads(value)
  44. else:
  45. def process(value): # noqa
  46. if value is not None:
  47. return loads(value)
  48. return process
  49. def copy_value(self, value):
  50. if self.mutable:
  51. return self.pickler.loads(self.pickler.dumps(value, self.protocol))
  52. else:
  53. return value