Browse Source

Remove Python 2.5 specific hacks

Ask Solem 12 years ago
parent
commit
9d95af8772

+ 1 - 2
celery/app/builtins.py

@@ -285,8 +285,7 @@ def add_chord_task(app):
                                        propagate=propagate,
                                        result=results)
             # - call the header group, returning the GroupResult.
-            # XXX Python 2.5 doesn't allow kwargs after star-args.
-            return header(*partial_args, **{'task_id': group_id})
+            return header(*partial_args, task_id=group_id)
 
         def _prepare_member(self, task, body, group_id):
             opts = task.options

+ 1 - 2
celery/apps/worker.py

@@ -44,9 +44,8 @@ logger = get_logger(__name__)
 
 def active_thread_count():
     from threading import enumerate
-    # must use .getName on Python 2.5
     return sum(1 for t in enumerate()
-        if not t.getName().startswith('Dummy-'))
+        if not t.name.startswith('Dummy-'))
 
 
 def safe_say(msg):

+ 0 - 71
celery/backends/database/a805d4bd.py

@@ -1,71 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    celery.backends.database.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 :exc:`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 __future__ import absolute_import
-
-from sqlalchemy.types import PickleType as _PickleType
-
-
-class PickleType(_PickleType):  # pragma: no cover
-
-    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):  # noqa
-                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 not None:
-                    return loads(value)
-        else:
-
-            def process(value):  # noqa
-                if value is not 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

+ 0 - 50
celery/backends/database/dfd042c7.py

@@ -1,50 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    celery.backends.database.dfd042c7
-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-    SQLAlchemy 0.5.8 version of :mod:`~celery.backends.database.a805d4bd`,
-    see the docstring of that module for an explanation of why we need
-    this workaround.
-
-"""
-from __future__ import absolute_import
-
-from sqlalchemy.types import PickleType as _PickleType
-from sqlalchemy import util
-
-
-class PickleType(_PickleType):  # pragma: no cover
-
-    def process_bind_param(self, value, dialect):
-        dumps = self.pickler.dumps
-        protocol = self.protocol
-        if value is not None:
-            return dumps(value, protocol)
-
-    def process_result_value(self, value, dialect):
-        loads = self.pickler.loads
-        if value is not None:
-            return loads(str(value))
-
-    def copy_value(self, value):
-        if self.mutable:
-            return self.pickler.loads(self.pickler.dumps(value, self.protocol))
-        else:
-            return value
-
-    def compare_values(self, x, y):
-        if self.comparator:
-            return self.comparator(x, y)
-        elif self.mutable and not hasattr(x, '__eq__') and x is not None:
-            util.warn_deprecated(
-                    'Objects stored with PickleType when mutable=True '
-                    'must implement __eq__() for reliable comparison.')
-            a = self.pickler.dumps(x, self.protocol)
-            b = self.pickler.dumps(y, self.protocol)
-            return a == b
-        else:
-            return x == y
-
-    def is_mutable(self):
-        return self.mutable

+ 1 - 6
celery/backends/database/models.py

@@ -11,17 +11,12 @@ from __future__ import absolute_import
 from datetime import datetime
 
 import sqlalchemy as sa
+from sqlalchemy.types import PickleType
 
 from celery import states
 
 from .session import ResultModelBase
 
-# See docstring of a805d4bd for an explanation for this workaround ;)
-if sa.__version__.startswith('0.5'):
-    from .dfd042c7 import PickleType
-else:
-    from .a805d4bd import PickleType  # noqa
-
 
 class Task(ResultModelBase):
     """Task result/status."""

+ 2 - 1
celery/beat.py

@@ -15,6 +15,8 @@ import shelve
 import sys
 import traceback
 
+from threading import Event, Thread
+
 from billiard import Process, ensure_multiprocessing
 from kombu.utils import reprcall
 from kombu.utils.functional import maybe_promise
@@ -27,7 +29,6 @@ from .app import app_or_default
 from .schedules import maybe_schedule, crontab
 from .utils import cached_property
 from .utils.imports import instantiate
-from .utils.threads import Event, Thread
 from .utils.timeutils import humanize_seconds
 from .utils.log import get_logger
 

+ 4 - 7
celery/bin/celery.py

@@ -519,10 +519,9 @@ class _RemoteControl(Command):
         except AttributeError:
             handler = self.call
 
-        # XXX Python 2.5 does not support X(*args, foo=1)
-        kwargs = {"timeout": timeout, "destination": destination,
-                  "callback": self.say_remote_command_reply}
-        replies = handler(method, *args[1:], **kwargs)
+        replies = handler(method, *args[1:], timeout=timeout,
+                          destination=destination,
+                          callback=self.say_remote_command_reply)
         if not replies:
             raise Error('No nodes replied within time constraint.',
                         status=EX_UNAVAILABLE)
@@ -602,9 +601,7 @@ class control(_RemoteControl):
     }
 
     def call(self, method, *args, **options):
-        # XXX Python 2.5 doesn't support X(*args, reply=True, **kwargs)
-        return getattr(self.app.control, method)(
-                *args, **dict(options, retry=True))
+        return getattr(self.app.control, method)(*args, retry=True, **options)
 
     def pool_grow(self, method, n=1, **kwargs):
         """[N=1]"""

+ 2 - 6
celery/platforms.py

@@ -599,12 +599,8 @@ else:
                 '%s:%s' % (progname, current_process().name), info=info)
 
 
-def shellsplit(s, posix=True):
-    # posix= option to shlex.split first available in Python 2.6+
-    lexer = shlex.shlex(s, posix=not IS_WINDOWS)
-    lexer.whitespace_split = True
-    lexer.commenters = ''
-    return list(lexer)
+def shellsplit(s):
+    return shlex.split(s, posix=not IS_WINDOWS)
 
 
 @contextmanager

+ 0 - 10
celery/task/trace.py

@@ -225,16 +225,6 @@ def build_tracer(name, task, loader=None, hostname=None, store_errors=True,
                         for errback in task_request.errbacks or []]
                 except BaseException as exc:
                     raise
-                except:  # pragma: no cover
-                    # For Python2.5 where raising strings are still allowed
-                    # (but deprecated)
-                    if propagate:
-                        raise
-                    I = Info(FAILURE, None)
-                    state, retval = I.state, I.retval
-                    R = I.handle_error_state(task, eager=eager)
-                    [subtask(errback).apply_async((uuid, ))
-                        for errback in task_request.errbacks or []]
                 else:
                     # callback tasks must be applied before the result is
                     # stored, so that result.children is populated.

+ 0 - 17
celery/tests/backends/test_database.py

@@ -49,23 +49,6 @@ class test_DatabaseBackend(Case):
             with self.assertRaises(ImproperlyConfigured):
                 _sqlalchemy_installed()
 
-    def test_pickle_hack_for_sqla_05(self):
-        import sqlalchemy as sa
-        from celery.backends.database import session
-        prev_base = session.ResultModelBase
-        prev_ver, sa.__version__ = sa.__version__, '0.5.0'
-        prev_models = sys.modules.pop('celery.backends.database.models', None)
-        try:
-            from sqlalchemy.ext.declarative import declarative_base
-            session.ResultModelBase = declarative_base()
-            from celery.backends.database.dfd042c7 import PickleType as Type1
-            from celery.backends.database.models import PickleType as Type2
-            self.assertIs(Type1, Type2)
-        finally:
-            sys.modules['celery.backends.database.models'] = prev_models
-            sa.__version__ = prev_ver
-            session.ResultModelBase = prev_base
-
     def test_missing_dburi_raises_ImproperlyConfigured(self):
         conf = app_or_default().conf
         prev, conf.CELERY_RESULT_DBURI = conf.CELERY_RESULT_DBURI, None

+ 3 - 6
celery/tests/bin/test_celeryd.py

@@ -587,12 +587,9 @@ class test_signal_handlers(AppCase):
     @skip_if_pypy
     @skip_if_jython
     def test_worker_cry_handler(self, stderr):
-        if sys.version_info > (2, 5):
-            handlers = self.psig(cd.install_cry_handler)
-            self.assertIsNone(handlers['SIGUSR1']('SIGUSR1', object()))
-            self.assertTrue(stderr.write.called)
-        else:
-            raise SkipTest('Needs Python 2.5 or later')
+        handlers = self.psig(cd.install_cry_handler)
+        self.assertIsNone(handlers['SIGUSR1']('SIGUSR1', object()))
+        self.assertTrue(stderr.write.called)
 
     @disable_stdouts
     def test_worker_term_handler_only_stop_MainProcess(self):

+ 0 - 4
celery/tests/utilities/test_local.py

@@ -74,8 +74,6 @@ class test_Proxy(Case):
         self.assertEqual(unicode(x), 'REPR')
 
     def test_dir(self):
-        if sys.version_info < (2, 6):
-            raise SkipTest('Not relevant for Py2.5')
 
         class X(object):
 
@@ -93,8 +91,6 @@ class test_Proxy(Case):
         self.assertListEqual(dir(y), [])
 
     def test_getsetdel_attr(self):
-        if sys.version_info < (2, 6):
-            raise SkipTest('Not relevant for Py2.5')
 
         class X(object):
             a = 1

+ 1 - 1
celery/tests/worker/test_worker.py

@@ -4,6 +4,7 @@ import socket
 
 from collections import deque
 from datetime import datetime, timedelta
+from threading import Event
 from Queue import Empty
 
 from billiard.exceptions import WorkerLostError
@@ -28,7 +29,6 @@ from celery.worker.consumer import BlockingConsumer
 from celery.worker.consumer import QoS, RUN, PREFETCH_COUNT_MAX, CLOSE
 from celery.utils.serialization import pickle
 from celery.utils.timer2 import Timer
-from celery.utils.threads import Event
 
 from celery.tests.utils import AppCase, Case
 

+ 0 - 3
celery/utils/functional.py

@@ -260,6 +260,3 @@ class _regen(UserList, list):
     @cached_property
     def data(self):
         return list(self.__it)
-
-    def __iter__(self):  # needed for Python 2.5
-        return iter(self.data)

+ 4 - 26
celery/utils/serialization.py

@@ -12,42 +12,20 @@ import inspect
 import sys
 import types
 
-import pickle as pypickle
 try:
-    import cPickle as cpickle
+    import cPickle as pickle
 except ImportError:
-    cpickle = None  # noqa
+    import pickle
 
 from .encoding import safe_repr
 
 
-if sys.version_info < (2, 6):  # pragma: no cover
-    # cPickle is broken in Python <= 2.6.
-    # It unsafely and incorrectly uses relative instead of absolute imports,
-    # so e.g.:
-    #       exceptions.KeyError
-    # becomes:
-    #       celery.exceptions.KeyError
-    #
-    # Your best choice is to upgrade to Python 2.6,
-    # as while the pure pickle version has worse performance,
-    # it is the only safe option for older Python versions.
-    pickle = pypickle
-else:
-    pickle = cpickle or pypickle
-
 #: List of base classes we probably don't want to reduce to.
 unwanted_base_classes = (StandardError, Exception, BaseException, object)
 
-if sys.version_info < (2, 5):  # pragma: no cover
-
-    # Prior to Python 2.5, Exception was an old-style class
-    def subclass_exception(name, parent, unused):
-        return types.ClassType(name, (parent,), {})
-else:
 
-    def subclass_exception(name, parent, module):  # noqa
-        return type(name, (parent,), {'__module__': module})
+def subclass_exception(name, parent, module):  # noqa
+    return type(name, (parent,), {'__module__': module})
 
 
 def find_nearest_pickleable_exception(exc):

+ 3 - 24
celery/utils/threads.py

@@ -15,38 +15,17 @@ import traceback
 
 from kombu.syn import detect_environment
 
-_Thread = threading.Thread
-_Event = threading._Event
-
 active_count = (getattr(threading, 'active_count', None) or
                 threading.activeCount)
 USE_PURE_LOCALS = os.environ.get("USE_PURE_LOCALS")
 
 
-class Event(_Event):
-
-    if not hasattr(_Event, 'is_set'):     # pragma: no cover
-        is_set = _Event.isSet
-
-
-class Thread(_Thread):
-
-    if not hasattr(_Thread, 'is_alive'):  # pragma: no cover
-        is_alive = _Thread.isAlive
-
-    if not hasattr(_Thread, 'daemon'):    # pragma: no cover
-        daemon = property(_Thread.isDaemon, _Thread.setDaemon)
-
-    if not hasattr(_Thread, 'name'):      # pragma: no cover
-        name = property(_Thread.getName, _Thread.setName)
-
-
-class bgThread(Thread):
+class bgThread(threading.Thread):
 
     def __init__(self, name=None, **kwargs):
         super(bgThread, self).__init__()
-        self._is_shutdown = Event()
-        self._is_stopped = Event()
+        self._is_shutdown = threading.Event()
+        self._is_stopped = threading.Event()
         self.daemon = True
         self.name = name or self.__class__.__name__
 

+ 1 - 1
celery/worker/__init__.py

@@ -19,6 +19,7 @@ import time
 import traceback
 
 from functools import partial
+from threading import Event
 
 from billiard import forking_enable
 from billiard.exceptions import WorkerLostError
@@ -34,7 +35,6 @@ from celery.task import trace
 from celery.utils.functional import noop
 from celery.utils.imports import qualname, reload_from_cwd
 from celery.utils.log import get_logger
-from celery.utils.threads import Event
 from celery.utils.timer2 import Schedule
 
 from . import bootsteps

+ 2 - 1
celery/worker/autoreload.py

@@ -15,13 +15,14 @@ import sys
 import time
 
 from collections import defaultdict
+from threading import Event
 
 from kombu.utils import eventio
 
 from celery.platforms import ignore_EBADF
 from celery.utils.imports import module_file
 from celery.utils.log import get_logger
-from celery.utils.threads import bgThread, Event
+from celery.utils.threads import bgThread
 
 from .bootsteps import StartStopComponent
 

+ 0 - 2
extra/release/doc4allmods

@@ -13,8 +13,6 @@ SKIP_FILES="celery.__compat__.rst
             celery.local.rst
             celery.app.base.rst
             celery.apps.rst
-            celery.backends.database.a805d4bd.rst
-            celery.backends.database.dfd042c7.rst
             celery.canvas.rst
             celery.utils.encoding.rst"