Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decorator @task_with_respect_to_language for using tasks with respect of current site's languages #21

Closed
ramusus opened this issue Oct 26, 2010 · 9 comments

Comments

@ramusus
Copy link
Contributor

ramusus commented Oct 26, 2010

What do you think about add this to repo?
Created by recommendations from here http://celeryq.org/docs/django-celery/faq.html#generating-a-template-in-a-task-doesn-t-seem-to-respect-my-i18n-settings

from django.utils import translation
from celery.decorators import task
from django.utils.functional import wraps
def task_with_respect_to_language(func):
    '''
    Decorator for tasks with respect to site's current language.
    You can use in tasks.py this decorator @task_respect_to_language instead of default @task
    Be sure that task method have kwargs argument:

        @task_respect_to_language
        def my_task(...., **kwargs):
            pass

    You can call this task this way:

        from django.utils import translation
        tasks.my_task.delay(...., language=translation.get_language())
    '''
    def wrapper(*args, **kwargs):
        language = kwargs.pop('language', None)
        prev_language = translation.get_language()
        language and translation.activate(language)
        try:
            return func(*args, **kwargs)
        finally:
            translation.activate(prev_language)

    wrapper.__doc__ = func.__doc__
    wrapper.__name__ = func.__name__
    wrapper.__module__ = func.__module__
    return wraps(func)(task(wrapper))
@ask
Copy link
Contributor

ask commented Oct 29, 2010

It is certainly useful, but the implementation is maybe a little to specific.
For one if there was more than one such task_with_* decorator, it wouldn't be possible to use more than one for the same task.

It would be much more useful like this:

from celery.decorators import task
from djcelery.decorators import respects_language

@task
@respects_language
def my_task(**kwargs):
    pass

and then I think it would be much better as a contextmanager:

@task
 def my_task(x, y, language=None):
     with respect_to_language(language):
         pass

@ramusus
Copy link
Contributor Author

ramusus commented Oct 30, 2010

Thanks for recommendations. I modify code with respect to them. And add small test for 'with' statement
Diff file here:

diff --git a/djcelery/decorators.py b/djcelery/decorators.py
new file mode 100644
index 0000000..c303bb8
--- /dev/null
+++ b/djcelery/decorators.py
@@ -0,0 +1,55 @@
+from django.utils import translation
+from django.utils.functional import wraps
+
+def respects_language(func):
+    '''
+    Decorator for tasks with respect to site's current language.
+    You can use in tasks.py this decorator @task_respect_to_language instead of default @task
+    Be sure that task method have kwargs argument:
+
+        @task
+        @respects_language
+        def my_task(**kwargs):
+            pass
+
+    You can call this task this way:
+
+        from django.utils import translation
+        tasks.my_task.delay(language=translation.get_language())
+    '''
+    def wrapper(*args, **kwargs):
+        language = kwargs.pop('language', None)
+        prev_language = translation.get_language()
+        language and translation.activate(language)
+        try:
+            return func(*args, **kwargs)
+        finally:
+            translation.activate(prev_language)
+
+    wrapper.__doc__ = func.__doc__
+    wrapper.__name__ = func.__name__
+    wrapper.__module__ = func.__module__
+    return wraps(func)(wrapper)
+
+class respect_to_language:
+    '''
+    Class for 'with' statement.
+    You can use it inside task methods definition this way:
+
+        @task
+        def my_task(language=None):
+            with respect_to_language(language):
+                pass
+    '''
+    language = None
+    language_prev = None
+
+    def __init__(self, language):
+        self.language = language
+
+    def __enter__(self):
+        self.language_prev = translation.get_language()
+        self.language and translation.activate(self.language)
+
+    def __exit__(self, type, value, traceback):
+        translation.activate(self.language_prev)
\ No newline at end of file
diff --git a/djcelery/tests/__init__.py b/djcelery/tests/__init__.py
index e69de29..8b5dc7b 100644
--- a/djcelery/tests/__init__.py
+++ b/djcelery/tests/__init__.py
@@ -0,0 +1,10 @@
+'''
+>>> from djcelery.decorators import respect_to_language
+>>> from django.utils import translation
+>>> language = translation.get_language()
+>>> with respect_to_language('ru'):
+...     translation.get_language()
+'ru'
+>>> language == translation.get_language()
+True
+'''
\ No newline at end of file

@ask
Copy link
Contributor

ask commented Nov 18, 2010

Thanks! Sorry for the late reply, seems I missed this for some time. Lots of stuff going on at the same time :(

The documentation seems to be out of date, could you update that, and also document the purpose of respect_for_language (so it makes more sense if you do help(respect_to_language) or pydoc celery.decorators.respect_to_language.

Thanks in advance!

@ramusus
Copy link
Contributor Author

ramusus commented Nov 18, 2010

I updated patch and published it here http://dpaste.com/276957/

@ramusus
Copy link
Contributor Author

ramusus commented Nov 18, 2010

Shit, I closed it by mistake... Can you reopen it or... maybe apply my patch ? :-)

@ask
Copy link
Contributor

ask commented Nov 24, 2010

It doesn't seem like I can reopen it :(

But could you fork the project and make a pull request instead? That is a lot easier to work with, and for me to merge it and maintain author info.
See http://help.github.com/forking/

@ramusus
Copy link
Contributor Author

ramusus commented Nov 29, 2010

I see a little problem with it. Now I use your branch "release20-maint" for working with r13315 revision of Django. Can you suggest to me, what branch is better to patch. I can not use "master" and in this way I prefer "release20-maint". But may be it's not good for you and purposes of creating this branch. What do you think about it?

@ask
Copy link
Contributor

ask commented Nov 29, 2010

You can work on either one; release21-maint or master. I will do the merging necessary afterwards :)

@ramusus
Copy link
Contributor Author

ramusus commented Nov 29, 2010

I have done this - https://github.com/ask/django-celery/pull/31
Merge, please with release21-maint if it's the same with release20-maint.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants