Skip to content

Commit

Permalink
Merge branch 'master' of github.com:ask/django-celery
Browse files Browse the repository at this point in the history
Conflicts:
	Changelog
	djcelery/tests/runners.py
  • Loading branch information
ask committed Oct 28, 2011
2 parents 2bbb4fa + b072bec commit a5ffee6
Show file tree
Hide file tree
Showing 22 changed files with 375 additions and 88 deletions.
2 changes: 2 additions & 0 deletions AUTHORS
Expand Up @@ -40,3 +40,5 @@ Ordered by date of first contribution:
WoLpH <Rick@Fawo.nl>
Darjus Loktevic <darjus@amazon.com>
Greg Taylor <gtaylor@duointeractive.com>
Ionel Maries Cristian <ionel.mc@gmail.com>
Jonas Haag <jonas@lophus.org>
32 changes: 26 additions & 6 deletions Changelog
Expand Up @@ -10,24 +10,44 @@
2.4.0
=====
:release-date: 2011-10-29 04:00 P.M BST
:by: Ask Solem

.. _240-important:

Important Notes
---------------

This release adds south_ migrations, which well assist users in automatically
This release adds `South`_ migrations, which well assist users in automatically
updating their database schemas with each django-celery release.

.. _south: http://pypi.python.org/pypi/South/
.. _`South`: http://pypi.python.org/pypi/South/

.. _240-news:

News
----

* Now depends on Celery 2.4.0 or higher.

* South migrations have been added. Migration 0001 is a snapshot from the
last release, 2.3.3. For those who do not use south, no action is required.
south users will want to read the upgrading instructions in the
following section.
* South migrations have been added.

Migration 0001 is a snapshot from the previous stable release (2.3.3).
For those who do not use South, no action is required.
South users will want to read the :ref:`240-upgrade-south` section
below.

Contributed by Greg Taylor.

* Test runner now compatible with Django 1.4.

Test runners are now classes instead of functions,
so you have to change the ``TEST_RUNNER`` setting to read::

TEST_RUNNER = "djcelery.contrib.test_runner.CeleryTestSuiteRunner"

Contributed by Jonas Haag.

.. _240-upgrade_south:

Upgrading for south users
-------------------------
Expand Down
4 changes: 2 additions & 2 deletions FAQ
Expand Up @@ -63,7 +63,7 @@ To use this test runner, add the following to your ``settings.py``:

.. code-block:: python

TEST_RUNNER = "djcelery.tests.runners.run_tests",
TEST_RUNNER = "djcelery.tests.runners.CeleryTestSuiteRunner",
TEST_APPS = (
"app1",
"app2",
Expand All @@ -76,6 +76,6 @@ Or, if you just want to skip the celery tests:
.. code-block:: python

INSTALLED_APPS = (.....)
TEST_RUNNER = "djcelery.tests.runners.run_tests",
TEST_RUNNER = "djcelery.tests.runners.CeleryTestSuiteRunner",
TEST_APPS = filter(lambda k: k != "celery", INSTALLED_APPS)

3 changes: 3 additions & 0 deletions contrib/release/removepyc.sh
@@ -0,0 +1,3 @@
#!/bin/bash
(cd "${1:-.}";
find . -name "*.pyc" | xargs rm -- 2>/dev/null) || echo "ok"
3 changes: 1 addition & 2 deletions djcelery/admin.py
Expand Up @@ -49,7 +49,7 @@ def colored_state(task):
return """<b><span style="color: %s;">%s</span></b>""" % (color, state)


@display_field(_("state"), "last_timestamp")
@display_field(_("state"), "last_heartbeat")
def node_state(node):
state = node.is_alive() and "ONLINE" or "OFFLINE"
color = NODE_STATE_COLORS[state]
Expand Down Expand Up @@ -171,7 +171,6 @@ def rate_limit_tasks(self, request, queryset):
"object_name": force_unicode(opts.verbose_name),
"action_checkbox_name": helpers.ACTION_CHECKBOX_NAME,
"opts": opts,
"root_path": self.admin_site.root_path,
"app_label": app_label,
}

Expand Down
14 changes: 7 additions & 7 deletions djcelery/contrib/test_runner.py
@@ -1,23 +1,23 @@
from __future__ import absolute_import

from django.conf import settings
from django.test.simple import run_tests as run_tests_orig
from django.test.simple import DjangoTestSuiteRunner

USAGE = """\
Custom test runner to allow testing of celery delayed tasks.
"""


def run_tests(test_labels, *args, **kwargs):
class CeleryTestSuiteRunner(DjangoTestSuiteRunner):
"""Django test runner allowing testing of celery delayed tasks.
All tasks are run locally, not in a worker.
To use this runner set ``settings.TEST_RUNNER``::
TEST_RUNNER = "celery.contrib.test_runner.run_tests"
TEST_RUNNER = "celery.contrib.test_runner.CeleryTestSuiteRunner"
"""
settings.CELERY_ALWAYS_EAGER = True
settings.CELERY_EAGER_PROPAGATES_EXCEPTIONS = True # Issue #75
return run_tests_orig(test_labels, *args, **kwargs)
def setup_test_environment(self, **kwargs):
super(CeleryTestSuiteRunner, self).setup_test_environment(**kwargs)
settings.CELERY_ALWAYS_EAGER = True
settings.CELERY_EAGER_PROPAGATES_EXCEPTIONS = True # Issue #75
8 changes: 6 additions & 2 deletions djcelery/loaders.py
Expand Up @@ -86,13 +86,17 @@ def on_worker_init(self):
warnings.warn("Using settings.DEBUG leads to a memory leak, never "
"use this setting in production environments!")

# the parent process may have established these,
# so need to close them.
self.close_database()
self.close_cache()
self.import_default_modules()
autodiscover()

def on_worker_process_init(self):
# the parent process may have established these,
# so need to close them.
self.close_database()
self.close_cache()

def mail_admins(self, subject, body, fail_silently=False, **kwargs):
return mail_admins(subject, body, fail_silently=fail_silently)

Expand Down
8 changes: 7 additions & 1 deletion djcelery/managers.py
Expand Up @@ -89,6 +89,12 @@ def connection_for_read(self):
return connections[self.db]
return connection

def current_engine(self):
try:
return settings.DATABASES[self.db]["ENGINE"]
except AttributeError:
return settings.DATABASE_ENGINE


class ResultManager(ExtendedManager):

Expand Down Expand Up @@ -156,7 +162,7 @@ def store_result(self, task_id, result, status, traceback=None):
"traceback": traceback})

def warn_if_repeatable_read(self):
if settings.DATABASE_ENGINE.lower() == "mysql":
if "mysql" in self.current_engine().lower():
cursor = self.connection_for_read().cursor()
if cursor.execute("SELECT @@tx_isolation"):
isolation = cursor.fetchone()[0]
Expand Down
21 changes: 0 additions & 21 deletions djcelery/tests/runners.py

This file was deleted.

2 changes: 1 addition & 1 deletion docs/cookbook/unit-testing.rst
Expand Up @@ -34,7 +34,7 @@ To enable the test runner, set the following settings:

.. code-block:: python
TEST_RUNNER = 'djcelery.contrib.test_runner.run_tests'
TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner'
Then we can put the tests in a ``tests.py`` somewhere:

Expand Down
Empty file.
Empty file.
62 changes: 62 additions & 0 deletions examples/clickcounter/clickmuncher/actors.py
@@ -0,0 +1,62 @@
from collections import defaultdict

import cl

from celery import current_app as celery
from celery.utils.timer2 import apply_interval


from clickmuncher import models


class Clicks(cl.Actor):
default_routing_key = "Clicks"

class state:
model = models.Click
clicks = defaultdict(lambda: 0)

def increment(self, url, clicks=1):
self.clicks[url] += clicks

def flush(self):
print("FLUSH!!!")
print("STATE: %r" % (self.clicks, ))
for url, clicks in self.clicks.iteritems():
self.model.objects.increment_clicks(url, clicks)
self.clicks.clear()

def __init__(self, connection=None, *args, **kwargs):
if not connection:
connection = celery.broker_connection()
super(Clicks, self).__init__(connection, *args, **kwargs)

def increment(self, url, clicks=1):
self.cast("increment", {"url": url, "clicks": clicks})


class Agent(cl.Agent):
actors = [Clicks()]
flush_every = 5

def __init__(self, connection=None, *args, **kwargs):
if not connection:
connection = celery.broker_connection()
self.clicks = Clicks()
self.actors = [self.clicks]
self.timers = []
super(Agent, self).__init__(connection, *args, **kwargs)

def on_consume_ready(self, *args, **kwargs):
print("INSTALLING TIMER")
self.timers.append(apply_interval(self.flush_every * 1000,
self.clicks.state.flush))

def stop(self):
for entry in self.timers:
entry.cancel()
super(Agent, self).stop()


if __name__ == "__main__":
Agent().run_from_commandline()
27 changes: 27 additions & 0 deletions examples/clickcounter/clickmuncher/models.py
@@ -0,0 +1,27 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from djcelery.managers import ExtendedManager


class ClickManager(ExtendedManager):

def increment_clicks(self, url, increment=1):
"""Increment the click count for an URL."""
obj, created = self.get_or_create(url=url,
defaults={"clicks": increment})
if not created:
obj.clicks += increment
obj.save()

return obj.clicks


class Click(models.Model):
url = models.URLField(_(u"URL"), verify_exists=False, unique=True)
clicks = models.PositiveIntegerField(_(u"clicks"), default=0)

objects = ClickManager()

class Meta:
verbose_name = _(u"click")
verbose_name_plural = _(u"clicks")
14 changes: 14 additions & 0 deletions examples/clickcounter/manage.py
@@ -0,0 +1,14 @@
#!/usr/bin/env python
from django.core.management import execute_manager
import imp
try:
imp.find_module('settings') # Assumed to be in the same directory.
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
sys.exit(1)

import settings

if __name__ == "__main__":
execute_manager(settings)

0 comments on commit a5ffee6

Please sign in to comment.