pax_global_header00006660000000000000000000000064133725756370014534gustar00rootroot0000000000000052 comment=5f832bfb8fca3dd89706b220b4e0fa50011a3853 django-celery-results-1.0.4/000077500000000000000000000000001337257563700157605ustar00rootroot00000000000000django-celery-results-1.0.4/.bumpversion.cfg000066400000000000000000000005451337257563700210740ustar00rootroot00000000000000[bumpversion] current_version = 1.0.4 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)(?P[a-z]+)? serialize = {major}.{minor}.{patch}{releaselevel} {major}.{minor}.{patch} [bumpversion:file:django_celery_results/__init__.py] [bumpversion:file:docs/includes/introduction.txt] [bumpversion:file:README.rst] django-celery-results-1.0.4/.cookiecutterrc000066400000000000000000000016721337257563700210140ustar00rootroot00000000000000# This file exists so you can easily regenerate your project. # # `cookiepatcher` is a convenient shim around `cookiecutter` # for regenerating projects (it will generate a .cookiecutterrc # automatically for any template). To use it: # # pip install cookiepatcher # cookiepatcher gh:ionelmc/cookiecutter-pylibrary project-path # # See: # https://pypi.python.org/pypi/cookiecutter # # Alternatively, you can run: # # cookiecutter --overwrite-if-exists --config-file=project-path/.cookiecutterrc gh:ionelmc/cookiecutter-pylibrary default_context: email: 'ask@celeryproject.org' full_name: 'Ask Solem' github_username: 'celery' project_name: 'django-celery-results' project_short_description: 'Celery result backends using Django' project_slug: 'django-celery-results' version: '1.0.0' year: '2016' django-celery-results-1.0.4/.coveragerc000066400000000000000000000002251337257563700201000ustar00rootroot00000000000000[run] branch = 1 cover_pylib = 0 include = *django_celery_results/* omit = t/* [report] omit = */python?.?/* */site-packages/* */pypy/* django-celery-results-1.0.4/.editorconfig000066400000000000000000000003151337257563700204340ustar00rootroot00000000000000# http://editorconfig.org root = true [*] indent_style = space indent_size = 4 trim_trailing_whitespace = true insert_final_newline = true charset = utf-8 end_of_line = lf [Makefile] indent_style = tab django-celery-results-1.0.4/.gitignore000066400000000000000000000004461337257563700177540ustar00rootroot00000000000000.DS_Store *.pyc *$py.class *~ .*.sw[pon] dist/ *.egg-info *.egg *.egg/ build/ .build/ _build/ pip-log.txt .directory erl_crash.dump *.db Documentation/ .tox/ .ropeproject/ .project .pydevproject .idea/ .coverage celery/tests/cover/ .ve* cover/ .vagrant/ *.sqlite3 .cache/ htmlcov/ coverage.xml django-celery-results-1.0.4/.travis.yml000066400000000000000000000016111337257563700200700ustar00rootroot00000000000000language: python sudo: false cache: pip python: - '3.6' os: - linux env: global: PYTHONUNBUFFERED=yes matrix: # - TOXENV=3.7-django2.0 # - TOXENV=3.7-django1.11 - TOXENV=flake8 - TOXENV=flakeplus - TOXENV=apicheck - TOXENV=pydocstyle - TOXENV=cov matrix: include: - python: 2.7 env: TOXENV=2.7-django1.11 - python: 3.4 env: TOXENV=3.4-django2.0 - python: 3.4 env: TOXENV=3.4-django1.11 - python: 3.5 env: TOXENV=3.5-django2.0 - python: 3.5 env: TOXENV=3.5-django1.11 - python: 3.6 env: TOXENV=3.6-django2.0 - python: 3.6 env: TOXENV=3.6-django1.11 - python: pypy env: TOXENV=pypy-django1.11 install: travis_retry pip install -U tox | cat script: tox -v -- -v after_success: - .tox/$TRAVIS_PYTHON_VERSION/bin/coverage xml - .tox/$TRAVIS_PYTHON_VERSION/bin/codecov -e TOXENV django-celery-results-1.0.4/AUTHORS000066400000000000000000000060151337257563700170320ustar00rootroot00000000000000========= AUTHORS ========= :order: sorted Aaron Ross Adam Endicott Alex Stapleton Alvaro Vega Andrew Frankel Andrew Watts Andrii Kostenko Anton Novosyolov Ask Solem Augusto Becciu Ben Firshman Brad Jasper Brett Gibson Brian Rosner Charlie DeTar Christopher Grebs Dan LaMotte Darjus Loktevic David Fischer David Ziegler Diego Andres Sanabria Martin Dmitriy Krasilnikov Donald Stufft Eldon Stegall Eugene Nagornyi Felix Berger Glenn Washburn Gnrhxni Greg Taylor Grégoire Cachet Hari Idan Zalzberg Ionel Maries Cristian Jannis Leidel Jason Baker Jay States Jeff Balogh Jeff Fischer Jeffrey Hu Jens Alm Jerzy Kozera Jesper Noehr John Andrews John Watson Jonas Haag Jonatan Heyman Josh Drake José Moreira Jude Nagurney Justin Quick Keith Perkins Kirill Panshin Mark Hellewell Mark Lavin Mark Stover Maxim Bodyansky Michael Elsdoerfer Michael van Tellingen Mikhail Korobov Olivier Tabone Patrick Altman Piotr Bulinski Piotr Sikora Reza Lotun Rockallite Wulf Roger Barnes Roman Imankulov Rune Halvorsen Sam Cooke Scott Rubin Sean Creeley Serj Zavadsky Simon Charette Spencer Ellinor Theo Spears Timo Sugliani Vincent Driessen Vitaly Babiy Vladislav Poluhin Weipin Xia Wes Turner Wes Winham Williams Mendez WoLpH dongweiming zeez django-celery-results-1.0.4/Changelog000066400000000000000000000024101337257563700175670ustar00rootroot00000000000000.. _changelog: ================ Change history ================ .. _version-1.0.4: 1.0.4 ===== :release-date: 2018-11-12 19:00 p.m. UTC+2:00 :release-by: Omer Katz 1.0.3 is broken. Use 1.0.4 - Revert renaming label as it is a breaking change. .. _version-1.0.3: 1.0.3 ===== :release-date: 2018-11-12 18:00 p.m. UTC+2:00 :release-by: Omer Katz - Revert renaming label as it is a breaking change. .. _version-1.0.2: 1.0.2 ===== :release-date: 2018-11-12 18:00 p.m. UTC+2:00 :release-by: Omer Katz - Store task name, args, kwargs as part of the task results in database. Contributed by :github_user: `wardal`. - Admin screen changes - task name filter, search on task_name, task_id, status. Contributed by :github_user: `jaylynch`. - Added default_app_config. - Added missing migration. - Fix MySQL max length issue. - Drop support for Django<1.11. .. _version-1.0.1: 1.0.1 ===== :release-date: 2016-11-07 02:00 p.m. PST :release-by: Ask Solem - Migrations were not being installed as part of the distribution (Issue #4). - Now includes simple task result admin interface. Contributed by :github_user:`zeezdev`. - Now depends on Celery 4.0.0. .. _version-1.0.0: 1.0.0 ===== :release-date: 2016-09-08 03:19 p.m. PDT :release-by: Ask Solem - Initial release django-celery-results-1.0.4/LICENSE000066400000000000000000000051101337257563700167620ustar00rootroot00000000000000Copyright (c) 2015-2016 Ask Solem. All Rights Reserved. Copyright (c) 2012-2014 GoPivotal, Inc. All Rights Reserved. Copyright (c) 2009-2012 Ask Solem. All Rights Reserved. django-celery-results is licensed under The BSD License (3 Clause, also known as the new BSD license). The license is an OSI approved Open Source license and is GPL-compatible(1). The license text can also be found here: http://www.opensource.org/licenses/BSD-3-Clause License ======= Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Ask Solem nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ask Solem OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Documentation License ===================== The documentation portion of django-celery-results (the rendered contents of the "docs" directory of a software distribution or checkout) is supplied under the "Creative Commons Attribution-ShareAlike 4.0 International" (CC BY-SA 4.0) License as described by http://creativecommons.org/licenses/by-sa/4.0/ Footnotes ========= (1) A GPL-compatible license makes it possible to combine django-celery-results with other software that is released under the GPL, it does not mean that we're distributing django-celery-results under the GPL license. The BSD license, unlike the GPL, let you distribute a modified version without making your changes open source. django-celery-results-1.0.4/MANIFEST.in000066400000000000000000000006301337257563700175150ustar00rootroot00000000000000include Changelog include LICENSE include README.rst include MANIFEST.in include setup.cfg include setup.py include manage.py recursive-include docs * recursive-include extra/* recursive-include examples * recursive-include requirements *.txt *.rst recursive-include t *.py recursive-include django_celery_results *.py recursive-exclude * __pycache__ recursive-exclude * *.py[co] recursive-exclude * .*.sw* django-celery-results-1.0.4/Makefile000066400000000000000000000073251337257563700174270ustar00rootroot00000000000000PROJ=django_celery_results PGPIDENT="Celery Security Team" PYTHON=python PYTEST=py.test GIT=git TOX=tox ICONV=iconv FLAKE8=flake8 FLAKEPLUS=flakeplus PYDOCSTYLE=pydocstyle SPHINX2RST=sphinx2rst TESTDIR=t SPHINX_DIR=docs/ SPHINX_BUILDDIR="${SPHINX_DIR}/_build" README=README.rst README_SRC="docs/templates/readme.txt" CONTRIBUTING=CONTRIBUTING.rst CONTRIBUTING_SRC="docs/contributing.rst" SPHINX_HTMLDIR="${SPHINX_BUILDDIR}/html" DOCUMENTATION=Documentation FLAKEPLUSTARGET=2.7 all: help help: @echo "docs - Build documentation." @echo "test-all - Run tests for all supported python versions." @echo "distcheck ---------- - Check distribution for problems." @echo " test - Run unittests using current python." @echo " lint ------------ - Check codebase for problems." @echo " apicheck - Check API reference coverage." @echo " configcheck - Check configuration reference coverage." @echo " readmecheck - Check README.rst encoding." @echo " contribcheck - Check CONTRIBUTING.rst encoding" @echo " flakes -------- - Check code for syntax and style errors." @echo " flakecheck - Run flake8 on the source code." @echo " flakepluscheck - Run flakeplus on the source code." @echo " pep257check - Run pydocstyle on the source code." @echo "readme - Regenerate README.rst file." @echo "contrib - Regenerate CONTRIBUTING.rst file" @echo "clean-dist --------- - Clean all distribution build artifacts." @echo " clean-git-force - Remove all uncomitted files." @echo " clean ------------ - Non-destructive clean" @echo " clean-pyc - Remove .pyc/__pycache__ files" @echo " clean-docs - Remove documentation build artifacts." @echo " clean-build - Remove setup artifacts." @echo "bump - Bump patch version number." @echo "bump-minor - Bump minor version number." @echo "bump-major - Bump major version number." @echo "release - Make PyPI release." clean: clean-docs clean-pyc clean-build clean-dist: clean clean-git-force bump: bumpversion patch bump-minor: bumpversion minor bump-major: bumpversion major release: python setup.py register sdist bdist_wheel upload --sign --identity="$(PGPIDENT)" Documentation: (cd "$(SPHINX_DIR)"; $(MAKE) html) mv "$(SPHINX_HTMLDIR)" $(DOCUMENTATION) docs: Documentation clean-docs: -rm -rf "$(SPHINX_BUILDDIR)" lint: flakecheck apicheck configcheck readmecheck apicheck: (cd "$(SPHINX_DIR)"; $(MAKE) apicheck) configcheck: true flakecheck: $(FLAKE8) "$(PROJ)" "$(TESTDIR)" flakediag: -$(MAKE) flakecheck pep257check: $(PYDOCSTYLE) "$(PROJ)" flakepluscheck: $(FLAKEPLUS) --$(FLAKEPLUSTARGET) "$(PROJ)" "$(TESTDIR)" flakeplusdiag: -$(MAKE) flakepluscheck flakes: flakediag flakeplusdiag pep257check clean-readme: -rm -f $(README) readmecheck: $(ICONV) -f ascii -t ascii $(README) >/dev/null $(README): $(SPHINX2RST) "$(README_SRC)" --ascii > $@ readme: clean-readme $(README) readmecheck clean-contrib: -rm -f "$(CONTRIBUTING)" $(CONTRIBUTING): $(SPHINX2RST) "$(CONTRIBUTING_SRC)" > $@ contrib: clean-contrib $(CONTRIBUTING) clean-pyc: -find . -type f -a \( -name "*.pyc" -o -name "*$$py.class" \) | xargs rm -find . -type d -name "__pycache__" | xargs rm -r removepyc: clean-pyc clean-build: rm -rf build/ dist/ .eggs/ *.egg-info/ .tox/ .coverage cover/ clean-git: $(GIT) clean -xdn clean-git-force: $(GIT) clean -xdf test-all: clean-pyc $(TOX) test: $(PYTHON) setup.py test cov: covbuild (cd $(TESTDIR); py.test -x --cov=django_celery_results --cov-report=html) build: $(PYTHON) setup.py sdist bdist_wheel distcheck: lint test clean dist: readme contrib clean-dist build django-celery-results-1.0.4/README.rst000066400000000000000000000075461337257563700174630ustar00rootroot00000000000000===================================================================== Celery Result Backends using the Django ORM/Cache framework. ===================================================================== |build-status| |coverage| |license| |wheel| |pyversion| |pyimp| :Version: 1.0.4 :Web: http://django-celery-results.readthedocs.io/ :Download: http://pypi.python.org/pypi/django-celery-results :Source: http://github.com/celery/django-celery-results :Keywords: django, celery, database, results About ===== This extension enables you to store Celery task results using the Django ORM. It defines a single model (``django_celery_results.models.TaskResult``) used to store task results, and you can query this database table like any other Django model. Installing ========== The installation instructions for this extension is available from the `Celery documentation`_: http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html#django-celery-results-using-the-django-orm-cache-as-a-result-backend .. _`Celery documentation`: http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html#django-celery-results-using-the-django-orm-cache-as-a-result-backend .. _installation: Installation ============ You can install django-celery-results either via the Python Package Index (PyPI) or from source. To install using `pip`,:: $ pip install -U django-celery-results .. _installing-from-source: Downloading and installing from source -------------------------------------- Download the latest version of django-celery-results from http://pypi.python.org/pypi/django-celery-results You can install it by doing the following,:: $ tar xvfz django-celery-results-0.0.0.tar.gz $ cd django-celery-results-0.0.0 $ python setup.py build # python setup.py install The last command must be executed as a privileged user if you are not currently using a virtualenv. .. _installing-from-git: Using the development version ----------------------------- With pip ~~~~~~~~ You can install the latest snapshot of django-celery-results using the following pip command:: $ pip install https://github.com/celery/django-celery-results/zipball/master#egg=django-celery-results Issues with mysql ----------------- If you want to run ``django-celery-results`` with MySQL, you might run into some issues. One such issue is when you try to run ``python manage.py migrate django_celery_results``, you might get the following error:: django.db.utils.OperationalError: (1071, 'Specified key was too long; max key length is 767 bytes') To get around this issue, you can set:: DJANGO_CELERY_RESULTS_TASK_ID_MAX_LENGTH=191 (or any other value if any other db other than MySQL is causing similar issues.) max_length of **191** seems to work for MySQL. .. |build-status| image:: https://secure.travis-ci.org/celery/django-celery-results.svg?branch=master :alt: Build status :target: https://travis-ci.org/celery/django-celery-results .. |coverage| image:: https://codecov.io/github/celery/django-celery-results/coverage.svg?branch=master :target: https://codecov.io/github/celery/django-celery-results?branch=master .. |license| image:: https://img.shields.io/pypi/l/django-celery-results.svg :alt: BSD License :target: https://opensource.org/licenses/BSD-3-Clause .. |wheel| image:: https://img.shields.io/pypi/wheel/django-celery-results.svg :alt: django-celery-results can be installed via wheel :target: http://pypi.python.org/pypi/django-celery-results/ .. |pyversion| image:: https://img.shields.io/pypi/pyversions/django-celery-results.svg :alt: Supported Python versions. :target: http://pypi.python.org/pypi/django-celery-results/ .. |pyimp| image:: https://img.shields.io/pypi/implementation/django-celery-results.svg :alt: Support Python implementations. :target: http://pypi.python.org/pypi/django-celery-results/ django-celery-results-1.0.4/appveyor.yml000066400000000000000000000024511337257563700203520ustar00rootroot00000000000000environment: global: # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the # /E:ON and /V:ON options are not enabled in the batch script intepreter # See: http://stackoverflow.com/a/13751649/163740 WITH_COMPILER: "cmd /E:ON /V:ON /C .\\extra\\appveyor\\run_with_compiler.cmd" matrix: # Pre-installed Python versions, which Appveyor may upgrade to # a later point release. # See: http://www.appveyor.com/docs/installed-software#python - PYTHON: "C:\\Python27" PYTHON_VERSION: "2.7.x" PYTHON_ARCH: "32" - PYTHON: "C:\\Python34" PYTHON_VERSION: "3.4.x" PYTHON_ARCH: "32" - PYTHON: "C:\\Python27-x64" PYTHON_VERSION: "2.7.x" PYTHON_ARCH: "64" WINDOWS_SDK_VERSION: "v7.0" - PYTHON: "C:\\Python34-x64" PYTHON_VERSION: "3.4.x" PYTHON_ARCH: "64" WINDOWS_SDK_VERSION: "v7.1" init: - "ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH%" install: - "powershell extra\\appveyor\\install.ps1" - "%PYTHON%/Scripts/pip.exe install -U setuptools" build: off test_script: - "%WITH_COMPILER% %PYTHON%/python setup.py test" after_test: - "%WITH_COMPILER% %PYTHON%/python setup.py bdist_wheel" artifacts: - path: dist\* #on_success: # - TODO: upload the content of dist/*.whl to a public wheelhouse django-celery-results-1.0.4/django_celery_results/000077500000000000000000000000001337257563700223465ustar00rootroot00000000000000django-celery-results-1.0.4/django_celery_results/__init__.py000066400000000000000000000017331337257563700244630ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Celery result backends for Django.""" # :copyright: (c) 2016, Ask Solem. # All rights reserved. # :license: BSD (3 Clause), see LICENSE for more details. from __future__ import absolute_import, unicode_literals import re from collections import namedtuple __version__ = '1.0.4' __author__ = 'Ask Solem' __contact__ = 'ask@celeryproject.org' __homepage__ = 'https://github.com/celery/django-celery-results' __docformat__ = 'restructuredtext' # -eof meta- version_info_t = namedtuple('version_info_t', ( 'major', 'minor', 'micro', 'releaselevel', 'serial', )) # bumpversion can only search for {current_version} # so we have to parse the version here. _temp = re.match( r'(\d+)\.(\d+).(\d+)(.+)?', __version__).groups() VERSION = version_info = version_info_t( int(_temp[0]), int(_temp[1]), int(_temp[2]), _temp[3] or '', '') del(_temp) del(re) __all__ = [] default_app_config = 'django_celery_results.apps.CeleryResultConfig' django-celery-results-1.0.4/django_celery_results/admin.py000066400000000000000000000033151337257563700240120ustar00rootroot00000000000000"""Result Task Admin interface.""" from __future__ import absolute_import, unicode_literals from django.contrib import admin from django.conf import settings try: ALLOW_EDITS = settings.DJANGO_CELERY_RESULTS['ALLOW_EDITS'] except (AttributeError, KeyError) as e: ALLOW_EDITS = True pass from .models import TaskResult class TaskResultAdmin(admin.ModelAdmin): """Admin-interface for results of tasks.""" model = TaskResult date_hierarchy = 'date_done' list_display = ('task_id', 'task_name', 'date_done', 'status') list_filter = ('status', 'date_done', 'task_name',) readonly_fields = ('date_done', 'result', 'hidden', 'meta') search_fields = ('task_name', 'task_id', 'status') fieldsets = ( (None, { 'fields': ( 'task_id', 'task_name', 'status', 'content_type', 'content_encoding', ), 'classes': ('extrapretty', 'wide') }), ('Parameters', { 'fields': ( 'task_args', 'task_kwargs', ), 'classes': ('extrapretty', 'wide') }), ('Result', { 'fields': ( 'result', 'date_done', 'traceback', 'hidden', 'meta', ), 'classes': ('extrapretty', 'wide') }), ) def get_readonly_fields(self, request, obj=None): if ALLOW_EDITS: return self.readonly_fields else: return list(set( [field.name for field in self.opts.local_fields] )) admin.site.register(TaskResult, TaskResultAdmin) django-celery-results-1.0.4/django_celery_results/apps.py000066400000000000000000000006601337257563700236650ustar00rootroot00000000000000"""Application configuration.""" from __future__ import absolute_import, unicode_literals from django.apps import AppConfig from django.utils.translation import ugettext_lazy as _ __all__ = ['CeleryResultConfig'] class CeleryResultConfig(AppConfig): """Default configuration for the django_celery_results app.""" name = 'django_celery_results' label = 'django_celery_results' verbose_name = _('Celery Results') django-celery-results-1.0.4/django_celery_results/backends/000077500000000000000000000000001337257563700241205ustar00rootroot00000000000000django-celery-results-1.0.4/django_celery_results/backends/__init__.py000066400000000000000000000002571337257563700262350ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals from .cache import CacheBackend from .database import DatabaseBackend __all__ = ['CacheBackend', 'DatabaseBackend'] django-celery-results-1.0.4/django_celery_results/backends/cache.py000066400000000000000000000020121337257563700255300ustar00rootroot00000000000000"""Celery cache backend using the Django Cache Framework.""" from __future__ import absolute_import, unicode_literals from django.core.cache import cache as default_cache, caches from celery.backends.base import KeyValueStoreBackend class CacheBackend(KeyValueStoreBackend): """Backend using the Django cache framework to store task metadata.""" def __init__(self, *args, **kwargs): super(CacheBackend, self).__init__(*args, **kwargs) # Must make sure backend doesn't convert exceptions to dict. self.serializer = 'pickle' def get(self, key): return self.cache_backend.get(key) def set(self, key, value): self.cache_backend.set(key, value, self.expires) def delete(self, key): self.cache_backend.delete(key) def encode(self, data): return data def decode(self, data): return data @property def cache_backend(self): backend = self.app.conf.cache_backend return caches[backend] if backend else default_cache django-celery-results-1.0.4/django_celery_results/backends/database.py000066400000000000000000000046031337257563700262410ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals from celery.backends.base import BaseDictBackend from celery.utils.serialization import b64encode, b64decode from ..models import TaskResult class DatabaseBackend(BaseDictBackend): """The Django database backend, using models to store task state.""" TaskModel = TaskResult subpolling_interval = 0.5 def _store_result(self, task_id, result, status, traceback=None, request=None): """Store return value and status of an executed task.""" content_type, content_encoding, result = self.encode_content(result) _, _, meta = self.encode_content({ 'children': self.current_task_children(request), }) task_name = getattr(request, 'task', None) if request else None task_args = getattr(request, 'args', None) if request else None task_kwargs = getattr(request, 'kwargs', None) if request else None self.TaskModel._default_manager.store_result( content_type, content_encoding, task_id, result, status, traceback=traceback, meta=meta, task_name=task_name, task_args=task_args, task_kwargs=task_kwargs, ) return result def _get_task_meta_for(self, task_id): """Get task metadata for a task by id.""" obj = self.TaskModel._default_manager.get_task(task_id) res = obj.as_dict() meta = self.decode_content(obj, res.pop('meta', None)) or {} res.update(meta, result=self.decode_content(obj, res.get('result'))) return self.meta_from_decoded(res) def encode_content(self, data): content_type, content_encoding, content = self._encode(data) if content_encoding == 'binary': content = b64encode(content) return content_type, content_encoding, content def decode_content(self, obj, content): if content: if obj.content_encoding == 'binary': content = b64decode(content) return self.decode(content) def _forget(self, task_id): try: self.TaskModel._default_manager.get(task_id=task_id).delete() except self.TaskModel.DoesNotExist: pass def cleanup(self): """Delete expired metadata.""" self.TaskModel._default_manager.delete_expired(self.expires) django-celery-results-1.0.4/django_celery_results/managers.py000066400000000000000000000135461337257563700245260ustar00rootroot00000000000000"""Model managers.""" from __future__ import absolute_import, unicode_literals import warnings from functools import wraps from itertools import count from django.db import connections, router, transaction from django.db import models from django.conf import settings from celery.five import items from .utils import now try: from celery.utils.time import maybe_timedelta except ImportError: # pragma: no cover from celery.utils.timeutils import maybe_timedelta # noqa W_ISOLATION_REP = """ Polling results with transaction isolation level 'repeatable-read' within the same transaction may give outdated results. Be sure to commit the transaction for each poll iteration. """ class TxIsolationWarning(UserWarning): """Warning emitted if the transaction isolation level is suboptimal.""" def transaction_retry(max_retries=1): """Decorate a function to retry database operations. For functions doing database operations, adding retrying if the operation fails. Keyword Arguments: max_retries (int): Maximum number of retries. Default one retry. """ def _outer(fun): @wraps(fun) def _inner(*args, **kwargs): _max_retries = kwargs.pop('exception_retry_count', max_retries) for retries in count(0): try: return fun(*args, **kwargs) except Exception: # pragma: no cover # Depending on the database backend used we can experience # various exceptions. E.g. psycopg2 raises an exception # if some operation breaks the transaction, so saving # the task result won't be possible until we rollback # the transaction. if retries >= _max_retries: raise return _inner return _outer class TaskResultManager(models.Manager): """Manager for :class:`celery.models.TaskResult` models.""" _last_id = None def get_task(self, task_id): """Get result for task by ``task_id``. Keyword Arguments: exception_retry_count (int): How many times to retry by transaction rollback on exception. This could happen in a race condition if another worker is trying to create the same task. The default is to retry once. """ try: return self.get(task_id=task_id) except self.model.DoesNotExist: if self._last_id == task_id: self.warn_if_repeatable_read() self._last_id = task_id return self.model(task_id=task_id) @transaction_retry(max_retries=2) def store_result(self, content_type, content_encoding, task_id, result, status, traceback=None, meta=None, task_name=None, task_args=None, task_kwargs=None): """Store the result and status of a task. Arguments: content_type (str): Mime-type of result and meta content. content_encoding (str): Type of encoding (e.g. binary/utf-8). task_id (str): Id of task. task_name (str): Celery task name. task_args (str): Task arguments. task_kwargs (str): Task kwargs. result (str): The serialized return value of the task, or an exception instance raised by the task. status (str): Task status. See :mod:`celery.states` for a list of possible status values. Keyword Arguments: traceback (str): The traceback string taken at the point of exception (only passed if the task failed). meta (str): Serialized result meta data (this contains e.g. children). exception_retry_count (int): How many times to retry by transaction rollback on exception. This could happen in a race condition if another worker is trying to create the same task. The default is to retry twice. """ fields = { 'status': status, 'result': result, 'traceback': traceback, 'meta': meta, 'content_encoding': content_encoding, 'content_type': content_type, 'task_name': task_name, 'task_args': task_args, 'task_kwargs': task_kwargs, } obj, created = self.get_or_create(task_id=task_id, defaults=fields) if not created: for k, v in items(fields): setattr(obj, k, v) obj.save() return obj def warn_if_repeatable_read(self): if 'mysql' in self.current_engine().lower(): cursor = self.connection_for_read().cursor() if cursor.execute('SELECT @@tx_isolation'): isolation = cursor.fetchone()[0] if isolation == 'REPEATABLE-READ': warnings.warn(TxIsolationWarning(W_ISOLATION_REP.strip())) def connection_for_write(self): return connections[router.db_for_write(self.model)] def connection_for_read(self): return connections[self.db] def current_engine(self): try: return settings.DATABASES[self.db]['ENGINE'] except AttributeError: return settings.DATABASE_ENGINE def get_all_expired(self, expires): """Get all expired task results.""" return self.filter(date_done__lt=now() - maybe_timedelta(expires)) def delete_expired(self, expires): """Delete all expired results.""" meta = self.model._meta with transaction.atomic(): self.get_all_expired(expires).update(hidden=True) cursor = self.connection_for_write().cursor() cursor.execute( 'DELETE FROM {0.db_table} WHERE hidden=%s'.format(meta), (True, ), ) django-celery-results-1.0.4/django_celery_results/migrations/000077500000000000000000000000001337257563700245225ustar00rootroot00000000000000django-celery-results-1.0.4/django_celery_results/migrations/0001_initial.py000066400000000000000000000051531337257563700271710ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals from django.conf import settings from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ migrations.CreateModel( name='TaskResult', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('task_id', models.CharField( max_length=getattr( settings, 'DJANGO_CELERY_RESULTS_TASK_ID_MAX_LENGTH', 255 ), unique=True, verbose_name='task id' )), ('status', models.CharField(choices=[('FAILURE', 'FAILURE'), ('PENDING', 'PENDING'), ('RECEIVED', 'RECEIVED'), ('RETRY', 'RETRY'), ('REVOKED', 'REVOKED'), ('STARTED', 'STARTED'), ('SUCCESS', 'SUCCESS')], default='PENDING', max_length=50, verbose_name='state')), ('content_type', models.CharField( max_length=128, verbose_name='content type')), ('content_encoding', models.CharField( max_length=64, verbose_name='content encoding')), ('result', models.TextField(default=None, editable=False, null=True)), ('date_done', models.DateTimeField( auto_now=True, verbose_name='done at')), ('traceback', models.TextField( blank=True, null=True, verbose_name='traceback')), ('hidden', models.BooleanField( db_index=True, default=False, editable=False)), ('meta', models.TextField(default=None, editable=False, null=True)), ], options={ 'verbose_name': 'task result', 'verbose_name_plural': 'task results', }, ), ] django-celery-results-1.0.4/django_celery_results/migrations/0002_add_task_name_args_kwargs.py000066400000000000000000000016711337257563700327060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Generated by Django 1.9.1 on 2017-10-26 16:06 from __future__ import absolute_import, unicode_literals from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ('django_celery_results', '0001_initial'), ] operations = [ migrations.AddField( model_name='taskresult', name='task_args', field=models.TextField(null=True, verbose_name='task arguments'), ), migrations.AddField( model_name='taskresult', name='task_kwargs', field=models.TextField(null=True, verbose_name='task kwargs'), ), migrations.AddField( model_name='taskresult', name='task_name', field=models.CharField(max_length=255, null=True, verbose_name='task name' ), ), ] django-celery-results-1.0.4/django_celery_results/migrations/0003_auto_20181106_1101.py000066400000000000000000000011131337257563700301260ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Generated by Django 2.1 on 2018-11-06 11:01 from __future__ import absolute_import, unicode_literals from django.db import migrations class Migration(migrations.Migration): dependencies = [ ('django_celery_results', '0002_add_task_name_args_kwargs'), ] operations = [ migrations.AlterModelOptions( name='taskresult', options={ 'ordering': ['-date_done'], 'verbose_name': 'task result', 'verbose_name_plural': 'task results' }, ), ] django-celery-results-1.0.4/django_celery_results/migrations/__init__.py000066400000000000000000000000001337257563700266210ustar00rootroot00000000000000django-celery-results-1.0.4/django_celery_results/models.py000066400000000000000000000044201337257563700242030ustar00rootroot00000000000000"""Database models.""" from __future__ import absolute_import, unicode_literals from django.conf import settings from django.db import models from django.utils.translation import ugettext_lazy as _ from celery import states from celery.five import python_2_unicode_compatible from . import managers ALL_STATES = sorted(states.ALL_STATES) TASK_STATE_CHOICES = sorted(zip(ALL_STATES, ALL_STATES)) @python_2_unicode_compatible class TaskResult(models.Model): """Task result/status.""" task_id = models.CharField( _('task id'), max_length=getattr( settings, 'DJANGO_CELERY_RESULTS_TASK_ID_MAX_LENGTH', 255 ), unique=True ) task_name = models.CharField(_('task name'), null=True, max_length=255) task_args = models.TextField(_('task arguments'), null=True) task_kwargs = models.TextField(_('task kwargs'), null=True) status = models.CharField(_('state'), max_length=50, default=states.PENDING, choices=TASK_STATE_CHOICES ) content_type = models.CharField(_('content type'), max_length=128) content_encoding = models.CharField(_('content encoding'), max_length=64) result = models.TextField(null=True, default=None, editable=False) date_done = models.DateTimeField(_('done at'), auto_now=True) traceback = models.TextField(_('traceback'), blank=True, null=True) hidden = models.BooleanField(editable=False, default=False, db_index=True) meta = models.TextField(null=True, default=None, editable=False) objects = managers.TaskResultManager() class Meta: """Table information.""" ordering = ['-date_done'] verbose_name = _('task result') verbose_name_plural = _('task results') def as_dict(self): return { 'task_id': self.task_id, 'task_name': self.task_name, 'task_args': self.task_args, 'task_kwargs': self.task_kwargs, 'status': self.status, 'result': self.result, 'date_done': self.date_done, 'traceback': self.traceback, 'meta': self.meta, } def __str__(self): return ''.format(self) django-celery-results-1.0.4/django_celery_results/utils.py000066400000000000000000000010261337257563700240570ustar00rootroot00000000000000"""Utilities.""" # -- XXX This module must not use translation as that causes # -- a recursive loader import! from __future__ import absolute_import, unicode_literals from django.conf import settings from django.utils import timezone # see Issue celery/django-celery#222 now_localtime = getattr(timezone, 'template_localtime', timezone.localtime) def now(): """Return the current date and time.""" if getattr(settings, 'USE_TZ', False): return now_localtime(timezone.now()) else: return timezone.now() django-celery-results-1.0.4/docs/000077500000000000000000000000001337257563700167105ustar00rootroot00000000000000django-celery-results-1.0.4/docs/Makefile000066400000000000000000000202511337257563700203500ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " applehelp to make an Apple Help Book" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " epub3 to make an epub3" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" @echo " coverage to run coverage check of the documentation (if enabled)" @echo " apicheck to verify that all modules are present in autodoc" @echo " configcheck to verify that all modules are present in autodoc" @echo " spelling to run a spell checker on the documentation" .PHONY: clean clean: rm -rf $(BUILDDIR)/* .PHONY: html html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." .PHONY: dirhtml dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." .PHONY: singlehtml singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." .PHONY: pickle pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." .PHONY: json json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." .PHONY: htmlhelp htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." .PHONY: qthelp qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PROJ.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PROJ.qhc" .PHONY: applehelp applehelp: $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp @echo @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." @echo "N.B. You won't be able to view it unless you put it in" \ "~/Library/Documentation/Help or install it in your application" \ "bundle." .PHONY: devhelp devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/PROJ" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PROJ" @echo "# devhelp" .PHONY: epub epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." .PHONY: epub3 epub3: $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 @echo @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." .PHONY: latex latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." .PHONY: latexpdf latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." .PHONY: latexpdfja latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." .PHONY: text text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." .PHONY: man man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." .PHONY: texinfo texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." .PHONY: info info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." .PHONY: gettext gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." .PHONY: changes changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." .PHONY: linkcheck linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." .PHONY: doctest doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." .PHONY: coverage coverage: $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage @echo "Testing of coverage in the sources finished, look at the " \ "results in $(BUILDDIR)/coverage/python.txt." .PHONY: apicheck apicheck: $(SPHINXBUILD) -b apicheck $(ALLSPHINXOPTS) $(BUILDDIR)/apicheck .PHONY: configcheck configcheck: $(SPHINXBUILD) -b configcheck $(ALLSPHINXOPTS) $(BUILDDIR)/configcheck .PHONY: spelling spelling: SPELLCHECK=1 $(SPHINXBUILD) -b spelling $(ALLSPHINXOPTS) $(BUILDDIR)/spelling .PHONY: xml xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." .PHONY: pseudoxml pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." django-celery-results-1.0.4/docs/_static/000077500000000000000000000000001337257563700203365ustar00rootroot00000000000000django-celery-results-1.0.4/docs/_static/.keep000066400000000000000000000000001337257563700212510ustar00rootroot00000000000000django-celery-results-1.0.4/docs/_templates/000077500000000000000000000000001337257563700210455ustar00rootroot00000000000000django-celery-results-1.0.4/docs/_templates/.keep000066400000000000000000000000001337257563700217600ustar00rootroot00000000000000django-celery-results-1.0.4/docs/changelog.rst000066400000000000000000000000321337257563700213640ustar00rootroot00000000000000.. include:: ../Changelog django-celery-results-1.0.4/docs/conf.py000066400000000000000000000016661337257563700202200ustar00rootroot00000000000000# -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals import os from sphinx_celery import conf globals().update(conf.build_config( 'django_celery_results', __file__, project='django_celery_results', # version_dev='2.0', # version_stable='1.4', canonical_url='http://django-celery-results.readthedocs.io', webdomain='', github_project='celery/django-celery-results', copyright='2009-2016', django_settings='proj.settings', include_intersphinx={'python', 'sphinx', 'django', 'celery'}, path_additions=[os.path.join(os.pardir, 't')], extra_extensions=['sphinx.ext.napoleon'], html_logo='images/logo.png', html_favicon='images/favicon.ico', html_prepend_sidebars=[], apicheck_ignore_modules=[ 'django_celery_results', 'django_celery_results.apps', 'django_celery_results.admin', r'django_celery_results.migrations.*', ], )) django-celery-results-1.0.4/docs/copyright.rst000066400000000000000000000017121337257563700214530ustar00rootroot00000000000000Copyright ========= *django-celery-results User Manual* by Ask Solem .. |copy| unicode:: U+000A9 .. COPYRIGHT SIGN Copyright |copy| 2016, Ask Solem All rights reserved. This material may be copied or distributed only subject to the terms and conditions set forth in the `Creative Commons Attribution-ShareAlike 4.0 International` `_ license. You may share and adapt the material, even for commercial purposes, but you must give the original author credit. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same license or a license compatible to this one. .. note:: While the django-celery-results *documentation* is offered under the Creative Commons *Attribution-ShareAlike 4.0 International* license the django-celery-results *software* is offered under the `BSD License (3 Clause) `_ django-celery-results-1.0.4/docs/glossary.rst000066400000000000000000000001431337257563700213030ustar00rootroot00000000000000.. _glossary: Glossary ======== .. glossary:: :sorted: term Description of term django-celery-results-1.0.4/docs/images/000077500000000000000000000000001337257563700201555ustar00rootroot00000000000000django-celery-results-1.0.4/docs/images/favicon.ico000066400000000000000000000064441337257563700223060ustar00rootroot00000000000000‰PNG  IHDR szzôÿiCCPICC Profile8TÍOA-Ëbñ""6Æl1)4¼ƒ …FA£$z$lŒ ¿µí7`ãzûþþ¿¶Æ1d€ÀÄåœ!—ÏÔÉ:5¸5´wO›:âzÆi¦˜ âc l,2œµqÌâŒdú#>(¥â"ⶬÏ^ða;«5'ˆF¨" ¬iZÎ+*ñ¥û÷¶’ZqãÂÞ¤›Ñ Ž'±ËÓþQÃX‡Ð\qäâÄQÅLŽ8öq-›ºjó·§Êƒ‡ó_ym1ä)° ÉÔv Ú<«øVü,nˆÅgâ§?Ô¨ðK"¾øÌ³_ö9ØÝ ÷g±8 Œ¢Wi+¶Ú4˜E¾¾ç,¬ÕÜq®“KrÝ\Ü%î2×ËÅpvr|œñøÓ|ßÉ0ìî„?…¾üÆ÷œ€ìÛ«ÿ‰E|i‡¬Uó)kuÕòø“̘ìRõ•õYªЦÐ%Šç…>KDHjrG› ©ª`¹ ƒÐ*Éu{óì븕±Þ²@˪g3¯\ü‚ÿðšg›¬¼0Žœõla¼S‡,“+´êÜï@à5€‘?ÓeÏš¢øæ¼¯Õ¶ð~4<ع_«}R«í 1 LÂ'YfIDATX ½WKl\WþîcžöØãÔNÇm“ª„&TIP¨J „¡ªRP»B,Úª v,€R%V,*+VTB ‚„x…g- Ð¥UÄNb9~df)à¤@dÀÊ® b]S,$Cá À6Å?I·Ç×>°(‡†IJ€>2wa½‰,c¦“¼¸0hO!è$1U,v‡CƪÉ)×@@Ý…§àâG¦t…œX">—¬ÓËÕ`uµù¤âX´‘ŽoõãXM?Gpóžõ,£ÒyŠþp`ãÀæÝM4· Ô‚êõzZu.7Õc&°À–XI—Ó@žg$áɈ¤séžKj.J¼g mÊx§Ö¥<(ªÛýþ>˜®Jf[Ê,ãT©@Ã5½-ç²jÐÀƒáób‹SoöÓbå—\zI`ÉY̽ü"çURÒÐ1ÉËâ§!+^è‰ÔZfEŠ­ì¬¼$†W€†mÃQß‹´BR1iu§,áeãe[˜Öì•Òó8<½óFü]F½¬Þ¸Œ—c&íôŠk¯àó\}&»àd¬Tð¤DTá²îÁg²˜zÒK ¬¸jb2a'Éd¬~¼”È’4d6˘¾>|’YvÔ‡ÉG{º,'ö ÖôØ'Àþ¾G:®!¥•|İX–œ»fLòó’ñ ¡Ó¶÷€ž´¯ï“˜¨¢YQ†á‹W€u P»<4U)¯÷ÚKç2z¥÷" lçÝ0[ WÁ“Sû¾¶™c$ÊFáøP  Áz!o´F”ô^@RA̵hÙÊÂÔ24StX©ï²hUlpKFš¦~;¶A,Ä„1›ÖûÀ,P#ÉŸ½–Á”K©t? ›¸³Ñ§a-²å[«aX‹Q(&÷…tâêßîbîha‹¡ÒÂ#'xù¼`7?Í®…@¦YeȈÞóãèzEI¦¦š¸ÍMefv7Ö®áµ_uñðc‡9Qs¸èõ¶Ö¬^¹ƒëooá­K·ðÄ3gqæ£Óèõ7 D›TÔä7”Þ1#`‰!ïõe|u&T"*fVNÎãµ?ÿ33!ºÝ9üöâë¸ôÊ<¦; ìRln 8MtçZ˜áuêñ^þñXzðƒˆÚ’DÇ4I/%™ÚŽÍQ³¢Xiˆ¥¿K.¦¶ïnãØ©{äþzyr=6ö—ÙªÆl¥û8ºRgFX¿½…¸èâ³O<ŽZ›ÒxUÜKF óA{?‹W€Íc£hâs'ãdÆKôFo~ú>:ÜÁßÿr;ë;”´ RÏ ¦yhY\8ŽÅ¥.Ï`öHem€udܘPɯK0ö#9X<“Gì­ mie8˜ÕC@×òwpâKxàÜYdCJ™ûw7¬¸Á³d› 즛Xëíðà’2Œ5BœÙïšjRìœJ¡N(¶¹ŒÖuíÅb«<ÐÆ¡ýýÚÍ+¨7´[6·yzç;Ç£U>à.Çl—ÌÚ²Cžì£¨aÏ•‘P?#´N0ÛYLÝ^¾Ö˜ãa4ŽÚúS¦ÕJwû'Äã™–ý(ª#M*ÎqƒYì ¢;?ྩ›<Õ>!PÕnÕLµ$NzXÓ³F²k}èsýßOχ﷿`”ݧ|#«[OÍ>‹…ÌïªêøfÀcÚ DH‹5ÃàNuéÕïuΫ#Y’Ô®Û=û™êÙ¨^Þ_•Aé·zýuÓÆlæÅ†]}Ù¯ךô;n%š‚±W(§>¬ŠðÊ? ¾ììðýx¨ì úßW ü?r›HIEND®B`‚django-celery-results-1.0.4/docs/images/logo.png000066400000000000000000000632121337257563700216270ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËiCCPICC Profilex…TßkÓPþÚe°á‹:g >h‘ndStCœ¶kWºÍZê6·!H›¦m\šÆ$í~°Ù‹o:Åwñ>ù Ùƒo{’ Æaø¬ˆ"Lö"³ž›4M'S¹÷»ßùî9'çä^ ùqZÓ/USOÅÂüÄäßò^C+ühM‹†J&G@Ó²yï³óÆltîoß«þcÕš• ð ¾”5Ä"áY i\ÔtàÖ‰ï15ÂÍLsX§ g8ocáŒ#–f45@š ÂÅB:K¸@8˜iàó ØÎä'&©’.‹<«ER/ådE² öðsƒò_°¨”é›­çmšNÑ|ŠÞ9}pŒæÕÁ?_½A¸pX6ã£5~BÍ$®&½çîti˜íeš—Y)%$¼bT®3liæ ‰šæÓíôP’°Ÿ4¿43YóãíP•ë1ÅõöKFôº½×Û‘“ã5>§)Ö@þ½÷õrŠåy’ðë´Õô[’:VÛÛäͦ#ÃÄwQ?HB‚Žd(à‘B ašcĪøL"J¤ÒitTy²8Ö;(“–íGxÉ_¸^õ[²¸öàûžÝ%׎¼…Å·£ØQíµéº²šua¥£ná7¹å›m« QþŠå±H^eÊO‚Q×u6æS—üu Ï2”î%vX º¬ð^ø*l O…—¿ÔÈÎÞ­Ë€q,>«žSÍÆì%ÒLÒëd¸¿ŠõBÆù1CZ¾$MœŠ9òÚP 'w‚ëæâ\/מ»Ì]áú¹­.r#ŽÂõE|!ð¾3¾>_·oˆa§Û¾Ódë£1Zë»Ó‘º¢±z”Û'ö=Žª²±¾±~V+´¢cjJ³tO%mN—ó“ï„ |ˆ®-‰«bWO+ o™ ^— I¯HÙ.°;í¶SÖ]æi_s9ó*péýÃë.7U^ÀÑs. 3uä °|^,ëÛ<ž·€‘;Ûc­=maº‹>V«Ût.[»«ÕŸÏªÕÝçä x£ü©# Ö¡_2 pHYs  šœ IDATxí½ néYß÷öÞ}»û®sçΦÑ,ÍH#ÍhA ÂaYl±(»›*ÇqÀ$¸’ؘpˆSÁ’”q‚1•ì  %V!$!‰Ñ®Ñhf_ï¾ô½½wç÷û?çí¾3÷~W,&U.ôvß9ç]žýyÞå¼ç|cÛÛÛíËé/¯Æÿò²þeΕÀ— à/¹Lþyù#ýya|¹ýŸ]tá®>üOmQøµ±v_Ûþå¶õç%àÏÎú—[ûö±ñvgÛn?ÖTÇŸÊ Æþ4õQþ8õ·.=y\9 \,”ÿÿÎÕ÷æÅè.§£‹Ë_|þ'2€x=-ÅÆù §_Éçk^ÿ7Ýuý¡›ONNc_Âð³yõìPcÛnC/†Cþ8y6ì#–‹Ïw`¼ðĪ—ÇUõ¾Tù ¡ý)®.B:>>Ö¶v®/æñòðÆ¢Â^'Ðã ’rÚnøb[ß\Ý~æøÇîýõ?þ,™àóT´z±¾È»bú’p±Eqþî7ó?ümïü«÷¼þõw¶ƒGæÚÜÌž611Ù¶· Jbá³³Ú;º¥\޽À\ºêw)¥°Â*m ÉÀX]•2òØ.a 5…¾ bÃÅy»ÅÛ”WÉåË/®Y罞\õ4äy0òB”t#C?ùýº·èÇ‚Rß‘‡íšn¨°œo)ßßLó@´º¶ÒN]n÷~âóíWý7>öá_½ÿç{,¿Xw^_.]Ñ:€±«ÇÚ¹öÏ~ê§ÿþ÷ã7½©Í¬´Ó«G7Ï­œjë[k0,Ç¥V‰4iý¦0ÀéäD ‡Š)êÙN»)o)&µîÝbÄ¢¢K¾2¸jOŒ¶ÞÆ×ÍïÂJÉP ¹IE›¦ó2­@Úë'ú©<ÅKšR«e·¥ÒdnZÐ^#ÂËÅï9H;§©³¹µcðÊ|Ë4qnPЏZk›EŸ¢“6ë6xߤž¸Lõíu¡ivr¶-Ìîoûg¯žØ^n¿ñkoÿåþ3?׿Ûº}t{©ëЗK# €†–mGùGÚ/ýß?óOßõò»o=zâ ÛÇN£ßWIãmzj*a®+\Kš´¬~ñQò»âeÒ²‰‰l¯§Æñx¯ÔÔÄ­¶Û&Âñ:õw<ÅNRŽý WE(9Û+á(ˆ6:9ʰã–iBJ¶U`F…­áX®2Cÿ8øÈ¦ù¶—g†ÄUÖmŠf N:̳MHç xµ9ŽclmrBÚ¤Îç¡-ÕáùX_þ…¡œ= Zøò³±¹Æq«]µïðæ-‡î{ð³ÇÆÿÃü/ÞÛžoß5At$/úúÒ°ìçßó+?ù}7ßµoýS|ŒX?56=9=¹„òe$A*I&&øŠH––¯ì;#“(ØTÖN›´-oµÞÊT!ŒëiêwG‘ÂTX~YøuŸ5Y.=Ö©º¥íO¨¥Pê´i;NËJè¥PK¥¢h*(¶'.XF3Îqck£`Sg ØQÞ +k{ì#FÂ%ø„ïµü‚)4Wy–›Ýi4kŸ«Âøúöë^öÆÇ>{vêÝßöÿÕöéí¿Œ‘Pî'Ä‹õ' Ôß·ÿøOþíï»ñ• [Ÿxø£“[ÓQ¾Œl1øTh›››ùÈz„¯@cùÑ=_‚U •J…p#íëÆâ=ip¨[a[a€|00z8Õ3»b‚Ÿ/ì¹!UÏTÉ Vü^ó±Üsõ,,ák Ö“/ËýÔ¹‹†ÐŸüj³±¾Yxœ–‡`«üÀ5¢)³D1C’ÆD®Åm‰Ê7?´õê¡…J¶¯ˆ â‘¿ôó7ÅXl|{vìÞ?6yÃ+ölýãÿÞï£î·Cƒº,O äݯK €ŠZË&‡¹·¼ëU?òÖoxYûâÓŸÛÛšÓ;dN‹‹ ‚RQ–9Xƒê”P¥\¦¼¶ÜóëV 2I§®¾±­Ç¿ò„-ƒ‚AÁÞPÌê.z¤HªÚ†¦m¤ NO“½õöj¡Idâ±DÙg@K^7•þhù€_ *VØÒçÑD••g–‡~ÚÎuÛ‡*ÚF°½eð €$MÊe}c3Ç.# Ö$+£ÃÚÞœ{àéÏoÕ;^ÞÞò®;D]:-4i]_Šõ…éÝ;“­·}Ý×ßý†•±³íÌÙ%Àïö{i0^vR¸Q2ÈEU­×~&âU€âîŒ×Ѿ;^‚8dSôLÔÎöŸy0Ûáp]øË#…j¹¸loŠr…A{£åÊ·çùPW¦‘ôIu´oÆÛÄÝÒ$­5Ö’áŸ8=Ú´GAi×.4B½u‚.OÞL‘€$ò1G:ÅÑiT¥\¹èx‘¯uÁ8ʤ¡s£‡ÎpêôÒÄòö™öö¿òš7PýmÂj»ºÍ¥_—À»{ÑÁöu·Ü½·:w|s¼M €1*„вäª^ÌIˆ„mè õð*S~Ê y 3‚T0´ÞÀÈxÆ(ÃöÔÛ¤«Q¶0q£,é!wÈ«ò]XÂ4¯”îÀ®ãWÞÖ“V°ø­« 1Pv!k ´` ¸4ª?\#©WòPy[œË?€ø.•§Ñ ;òàhD'i•Fò"? 'õî¡óoÞmF3¤€“ Ú3(#ÆÐÆ&Û©ó'6oE‡ ]ZsG·^ é’¥à_fyË{Ã;nºkva¼]X]¯ª©Å) 1z0™'Q5WWƒ•’_caÛè5^PÁÖïE™“á3 †Y2²I_ªÒ‘—É‚ÏêÔÃÞÀIK§™UJ裱ÂÈ9¨*:ÁY•ípQp€˜2Ë«vûÛâWΔ”òоiJ½®+6üÛ:*µø‚=‚¼ð¯£Øž5¥Äï5z¼)0dк†¯¡¾p’§HÒVÞv®WVÖÚâât{Ã=7ÝQÐj’om'Y)P[›Û·ï~-}uŒ #y?žWx…A˜°OÛ G@Ú¤¿êIf"2œ® Þ0èQåÄÚe( –7Z^I±¨\=Kc€T™%[…¤ý0…Ò8,B´m{Ãs®Â‰j÷t Ï®1Qźé7¡C+"ȹ¼)l*úµÆ ¡U¢Nð—Ñ„–Þe/‹ŠœFùŠ@ &'šŒœ†~N4}ĭׇډ×ùÊZ ˜"CÎ9å'Ùœ´‹õõrÞýû÷í'sNŽJÇB©tIò§‘×Ì6ž·±¾Ê‹!”Á\7ÄQ&T’É)ºŠð:ŠºÓº& •1 Œ‚0'oi“**©$®r,1»„Yp7Q´I 3žé±Ó5´±­ÉÚãóeEY­ýF¹WΠ øN^€W´‘øÍ3íâ—> ùe^…5˜åQˆ°!1Oá Ôxâ'/¼°è$ j•o=£¨†R<’ç¶Q®ÝÔSŒæk7Þ*Àv\¾ŸæsÏ Ò( ¹ÆÂ·H€ ‚Kù„o v’"RªK”i(Çñ–È@å8±nÂðÀ(H†£åL•87œŠÁS·ÉàWÅØÞ¤P*yîG¥ÑÂHž–Y‘ëUÁ:–QàB¯n†ØCdmm¤ÛQíåQ Ê¢0:LÑ~Uªy†ö²ËPEQÖfE$œA”À·QTäþYÏÅ¡r:j_òW¸Q–`}ót’š:‚0p3çb#" !û¹$4ÄjÅNàĂ㲟Dدõ.ƒ¬VF! ²¥'I!q/‘z*·`gOÆøóÝGi«©©›´p§eou>â—FOOS¦¢…ONà9WƒP¬9Þ¦R¿ ¦F)ôÞɳ\øl y¬jz.¼ô"îºÆœÖ)“·Îh`”áfÝ#áP‚Ø.R纎%o)Nhà‚i^8·Ë r·ì86Á¯ö›²ÊXAÂp£°d¤ .M£ @TÀ1†@ÈÀ\1¡‚‹á g1BÀ£ã} ‘›´Qá–k©”°§¸o¡4ö˜%š± cn~¶¼j±MO·= ³¹ž™¦ÜðÜX„Y£íf[ÛXåö+K­tá^ƒöœp½I·aíý5GnÅu‰>üF(ï½ÿÿŒµÒ&hà©xê¤h2øG‚ÒaB²à*µ”®nìJ0NŒ]akÔq7CÅÒHÐóã1k€WFAsN•˜rÂ0R)«çÚéˆ(pñ•*Á”žfL›(Þö&aœ† ÎâÓ¶Æ”ÆÇ1š…ùE®fÚÑgε/|æÁöÙ?z¢=ð…§Ú}÷=ÔÎ<»XÚ¯—½úºväšýíÆ[·ëo¸ªÝpÓÕíšë÷µÃ×ìk{÷-´¹=Åv[ÛÄa3@FÐŒ´cö´„c• ïÁò)£ˆí˜c+¯v)/¥š©#VŒŽzΛjëÈ¿©¤ÀHÎdLJ¬¯,*?q*T£G§Fëñ§Õ ¿F<ÅŠ%Ð.dp­yy± Î ¤cxd)V†!|»}º’Ö¬ÇIM}À¦6m`j †»òËú1$ë(™íɨa~ž3Ûþ±ö›¿ú©öoÿõïµ¥£¥ð=×·¶wq¾:‚qk’1Ëæºc—bZÒ›’€»¾¶•éÙ&½²²ÞέoOÝ÷Lûðo u†Ã‘—îo¯~Í-í寸¾ÝöÊkÛKn9ÔŽ\·¿Íƒk|RïÛhË+Ëm}›‘ø€‘GÑ(åÍð ÿ*Ö1ƒJI>"‘ù®r€hŠÜ7éâ” /Q¸ò6z8÷˜ƒ]4Ĩ[ø(£M˜W0‘yØ(bœ¡[„ãP.«1Ž¢· ïˆS":CⵋÃi„*7fm1ˆqG˜ (êƒÂÕOd·oï><þ|{Ï¿ú@û—?]Zºá•‹íú›ö…EØ4¢”õu”1C»Y`jÍü#¦Ð¹º¶Ù¦èƦQ”ÓZêÏϵÅñŶ¸²Ý¦o¦&ù~ÖYQ¹¿ý‘O¶ßþµOvêÛk¾òæv×ëniwÅÍíÖWÁ öb‹C,//·6jxÃLçØäþƘ3Zo5”ƒìî,oK©Ï$$ÖœŒ±”ë0Ö‚ PlxèÑ6åø%!`Ñ lsUðS𢯑 ²%¨Fü¥D O$P¦(u .È x­®'­¹ææŒðÜ8°Äi<½ ]í3*DùäÇr1x½WêYA¶í[ÜÛ>þÁGÚõ¿ÐN>u¡ÝúÚ«ðpM‚cl½Mчs3 bð|„=—MM×®Ë*‚î8ž?37ÞÐQ Ü‘îËò2>µ…q°¶ŠÒ …áEŸ™i·`å–šU,Ÿ_oO<ûhûôÿòh禽ý]wµ{¾êŽöª×ÝØn¼õP;¸w±­­­¶•Õ mcl Óä®!±•‡rh©Œ»rÊkaÛ––ê󭳫 #Šeʲdn¹™|8-cenæÒHHèE9Ø„‰#@µPJ$"F öNÈ¡ݦ?‡:·žm†hírx'ëäöm긓jší‡“ôóû´÷ý_Ô~ôïýR;ò²=íŽ{®Æ{ë®áì•ÌfFE4šÁ›7·ð~ Á Û™™²¹Ádr–î„2…6K”Èš;¸6ô&Y‡ ’8\_TSwyi=d–ˆ1·÷P»ê0Æö»¿ýÙö»ïuk^koùúW´·}ëÛë‰×ßpˆè¹Õί°³¹ŒÒW#Ì!:K´Ä³U*§ÙyG4NÝ …Y“ N.ƒEÙé`¹,ëé˜ÑQšy-LÍæòi¤€*-üE9lQŸÖ©h±Ûß:ʹƒ Ç:FtŸ¾È£†•¾ÉÂSÙNÍÀíwù¼09>Õöí;ÐÞûo>ÙþñüR{Ùë·É -Í¡x›Î-¢xŒf¯µo™Gñ(î<^:˹1Ä¥[£ÍžY§…ãméíg§ ™u ò'Pè,i·ïžÃ(&g kÇN'¨Kë4ekkЋa9vÐKÓ^~÷ÁD«åóíÞÏßÏ8âþÈïÛ¾÷Íí¯¼ë5íŽWÞÐö´å‰³íÂ…%â;ÓTp% €‡hA¨NR‰Lbsü¨ÐK~œ+Û"×£r/ÁK—©@F¤‘ b³¬Jà Âá¤BIÌ•ÐêóÇÈ–£L‚Á–Ý…{ÿTÐ Ÿ¤N1a$©UÅb,–jø¥þ8÷³f@‘ì÷÷µýæƒ(ÿÿl·¿ñ0›‘6ÚÞmG²Å;,2ܯÓG.ÌMeöaèžió À€®5®÷,L·)à_X^o ÎÞý5m\g,°¸ošñƒ@Êf1Šù Á?¦{æ§Ãë<vÏÆÞ7‚âFÙê2Qe­f(+«(ÍiòžívÓKµÍkÙ ]¿ò ˜Ï›¾îŽö×þúÚÝoº©í½ê`[:{2÷YTŸÞiÐcÀP|ñdÊ”—³ %æB˜ÇŒò=碶ˆü¡Á<õ¢Ž´d/ÜQi¤Äkâ<:qH¹eަh¤¯<ÙЙ%I*¸še%Û$pÒGº£18È´ÜOºFÛÁÈQcqÏþöèOµü®Ÿm7ÝͽŒ©Í6M7<=;Ö¦0ÆÙyz~pOWAG±Gj‡ (Íð~þìFÛ¿Ž5B´«e¸×Âj²XuöÜJÛ»w&Ôuøs0¶¸·VO³vp€þ~·^[Õ÷ÛÂ>”ok(tŽîcr ±ÉÝÌÌœæHD€ð)ò]‹ˆ¤ˆRÛÌo{ã!46Þ>ùù/¶þÎÛËﺮ½ó;_×¾æ]·Óî‡>G\ïÏ=CšÌ eÌYŒY+¯·®]…Ëé¶Ä`)S¦®ÕH³Î¥nÔ¾ú•ʤG•$¡žòŒü!HË”á̃]ˆ§"€Gë$3aJ‹õRB¨³¡…Ó/1cH Nvìj¦ò|Џ»¾:ÞþÅO¿¿5t?¿wªMãY³{ì!ŠL êÎÍ£ŽNçfŒP(û PÙzòÂÓë Î00:¬^÷àÍD¬eËh3‹Rí2ÒrqþÂáž±Ÿu Áh2O»Ò ÊÞÌ<èYÐ(çézf|rÛEãœYÀH‰ÖÙ_m/½ñ`{ům~ö™öài‹ÓWÇ!d ‹IÊ6òF˜ Ê^ˆ†£ð”+ˆØÄu¨RtÙPäêBú †0 ´WC—O# …Y§q†èMõTÛíLÜ„™%ìÏãi _AÞ'é_ l;­S¡z±¾Eúv¢K‚Äýûæ»ÂŒbq~w²?vjÇX5\ :ø\ÃL;xpŒ5¢ÄTàa–¹¯ LïœGñ®½‹ˆèøaƒ†fTÒTfŒp/]`„œžÁηö­ýëÛòæqè½€«· 0TJ–4 d¨#9äæ˜IdzŠòç蟲äcªÐ_å¶·F©p™/sd à‚¤ôб>³\òfùÔ* sqGój½¬N¢´Né1Ĺέ‚b”Éõ6žãúþÔä$ kþÀ}­aj9Þ•Zc$¼¸8ËÖôŽ'#|Ë ùz²¡}ß¾9H˜nüñ#¹QsŽiøs§”1¦8|h_{ò±§ÛçŸmíðÐC´§Ž·v뵇+ˆR§g«pàð¢ 2h¼ß»o&Š_ç Ùè0;;!X@bMÀzëÐ{~ÉÉT[Ø;×òÉöÍïúºvÛ×¶'O}4Ó½ÍuV Q°’Q]™ëcà.ï:m5);˺’7C©tó\*æ<]pnŒ…nysÌ(aÄN'—¤‘`¿++ÍÌnÀÕ6—1˪5ÈÇu¥‚¼æQb‚‹%Ôˆ6ß !—åe lÂåäÔl;{b½ÝûñûÛ­7ímô¥20M˜Ãs×ðH]5b//ß‹âõB#€iïœ`oÀ“O=ßžfDÿö;ßÖ¾òµ_ßn{Ù­íúë¯ÃøœŠB‚F€'OŸj'Oœj§—N´'Ÿx¦=ôǶçN=Üž9û™öáŸgD×Ú›_Š1N!âLµC‡fXÓÎ^8Q÷†PFò…DP´ë.+é2éX\DÎ]ž:,$YMU”žm+Œ¡´Wê¾ø0ÒâÑâ €‚¯[vQ–¹JÃ`œ&Ñ0æ‚lر3¨Ê†Dºia‚1Áø´dÈðx{ö©“­Ýh£S>úP•¶Bߺ€!ú–ί&ìk L;&X[kŸøÂj{ÿÿöSíÐísOü*pVñ4=Ü.œti¯’Þ§±kçbÐçVžnÏŸñ”µ…q6‰Ìl 3W·—Ý}M{Õë¿¶}Ë·~Cûá?Üf|ñû¿ÿ±öÁ{ßß<ýh[`qx~;rä t­¶³gWÚ…s·¯zç«ÛkßðòöÜÉOEvÛðO…ÿ®§’‡ßÞvW6Ub Í‘/kÄëFìX¡W {Cõ¡²¥þ›2y™4ÒÒ—ÄQ@ûö/¡Ç“†@vnªg ¶ÉÐÎZK,Ó6*ŠáC?Z§7y%Vè éLÏœ>ßYñseájßÁC³mœ¥^GùÞ¸™ãÜØwni…Õ¾Ù ÀÖV'Ûo~úñö?ÿ'?ÚnáñýOý¿ Aóøú»y"iº™íÁ¤ôcŒàĹdÖÛ{P¾£pæ ü–ÚÉ3À¡}Œ®gæPÛ¿pC{í›^ÚÞô–»Ú|ê{Úç?÷PûÐÇþ€Èð‹í7~ç‘vÓKì&îhûü‰öÏ~诵‰=KíôÉc𩱩xy—„¢A…©Ð_ ÞM‘ؤáê”Êή#¢·mºPÅ[œ E9´Ë|4És©Q!­#o°07kTZ(€@‰cī³óVÙAHT*òAT–…¥Š¥RÇ©#²©¤l IDAT¸¦Àr.pŽ=դ硆)nÞô)—Û¼ö1ºžÄð\pLJ¼ÛçȆ{û¯=|u{Û×¾¶=sæ3‚…¿µÅ=_x©mmråTtˆRm–+<·P—wÉ–:k¦Œ¶ÇVÚ™u—[z¼=A×83u XĸówÏ[ÿNûžçþFûä§>ÝÞ÷›ïmÿög«í½…»ƒoe{þôÕ\ œ@¬/•ç˜ÈgÕ©Ø¥)až iŠCJçT[Í|H«gt¾¡ý V}2ëáÄ—¦‘Ë”#B)3+Ài’)1nάùl”®SßsÍ#_Cº§NÕ²˜$, '™úUM'™³må¼Cß,ì8¬XY]CñôÏ´[Y©2|â8Gˆu½||¡=øèãíwÿͶçÀF{òäsÀ–JŒ YwŒ9UÏy¤o 9rÀ•:\ɾo?19°b¸Æ5D o1[#ïéãGÛÓ'>ÓöLl‡omoÿ†»x&ïMío~ûw·cÇŸƒ™3íÄsÏc” rP‰ÀqàgŠl!Å$Q%Îe·ëS îpä¥úÈú€¼Jl‡I×u3%—ÿi%Œ> #p‘d„©‚ù(‰m—(=•b(O³„òìë ô›¼v½Câ­“q€aP¶vµxiwiÕ>†€á^/÷z£kip•Îü=ÜÜqAfùÖs T©ê¹ÛH¹I›åýhH:Iº¡Åå# @ŠU´¢ôÛ‹R‘Xs¼kðþx=rÕ0$À›:ÊP8.äÈ”¤g¸eé86î ͺâÑC˜.(vUºÙ(ß›9†Êy*Ïà@p†U¶g¿ÍLs“gûBúAX‡á–â pm?„ÿb/«q"WÆ¥<)d¯¥=¼µ¨Sçt_œ;&²RîÞqô$…|XÌ×sŒž=õ±ÆSpƒškí]˜Âã¿ ªµ¢-dÚ¦Ëßz‰æC£í«ÛÚBÆ©AÔÑÙÞt…4ÒD(0#³;{âÑ UE’ôf0 ‹CˆLèM.… +R!OÚ”ÿ‡2q³Ä1†å«<”:ÃMv¼ëÊÚæþYZZÍ€ ëܱ 3ÕKˆ7dw:"t ÒhdPY;Ê.e”q'ÊaŒâNè‡Ç®0)Î 'BC¡ K1ŒS`•#œm»\;àJÅ©œÂ}œWÔÀlS Lm+ò©E1’‹ÃuÕdàåvw&£™ô)o#«ù‰´)½ü—ŽNb2q4¤8©t)ÐèdAÈQá–À”Ö±±fÀxsÈ~là)L ¾>,ƒ,.9Ÿ'ßÅ냜lïK­ªL¶­ØB,Y £úw”š‡\«~Ú¡vpQq×H€Êµû+„ìô]•J# ÀËÊ*;a6–Ùt1(ÈÒ¹¹;«zƒ°3JB*Åc}Бþ,\J†1ÀÁ£Äm`(SñŒ´„ªtŸát#†+Žd8÷ùYùó|9;yØš…òõPgn9 }rŸ.G!+wéRÄds´½xl—Ä…SÝÜpÇLw!°êõ²2páQe'hÐ äuÌŒ6JqÖë3 ìâ¤GÚ̃œ%-4.ùЊ¬l¼ Õu€”|#—|QεƒÐŒAJ1*gQ[Û+íèæR;ÏbÚ¨4Òέ¬¶§>ÑV×­Â(Fá3Ó³Ù-³É`Ðî 0‰˜k£‹=²(°f<‡àñ†Þ Ðh’'€€žºÀÈÑ1út߾޹Ä}wïù»ðã~ag:˜óË«™û; 0” ‡Ð0…j¨*ývÍë|Ìsuœ'’V¦ÙóÈbÙ¨4ÒìW¼ùQ„ œž1&X[7ìâ-gžÏÒhêº.ÎcÕ“,*4oÊó ˜/ùé2¡È$½#x„¯ Êýz>‹à\_ïZåÚY€ëv nÔt·ãƒeV óÞàk\¥­¦QGè~|P°˜ø7Êy¢à»ç…_ðÉ Œri6÷ˆf]yTù]qn’­÷!ô—‰,´µMiÅ7€³ Áá™Jk®s¿Y‘@”A9…9Æ0ƾ´5ãù HÉ\Y«û fºÁrŠ7\OO³gá,`³É*¡u:sûw{X T8«ÌìÄá,ÀAnóöÚ*9&Š ôÎôrÊû8ã?!Ç\<¯¿’E2^f|@•Ý-kr%ÿixu Ÿd)sËÊ Ù£ 爇VÈ7D+ÃR°]‚ 1Ú€û•‘øÍÊÞIà/Î"Ä Õš\ªðPǹΧšgû©è¤"k^æk¤(¤êCK`ÕB3_Õ¥VÖýµnßó+QRì!–Pˆñ¼n%K Ä*—h i.謲9ó\ÞıÍ7>#°%nõîç6°ÓÁìú·† pΜ¥+`ÿþœ[°±³ók'=VyS!Á¦‚QðF"9C2Ob«Þnu»Û8Ýíä§+RžWœ!™º‡ [¯­é2\£B)DåjŒ¥4 9W§ÊÒ¨ãgÛÆð0zw‰^ú4®H[røguQFZ»£‹FAå$õ'_b®`½Qì‚‹€¢hÝ?Ȭc¿4ô©°-‹¥#Œ~ÑPeQgh'bÀ°á’îÆz®._`ÞÏÞ{ŸÆÉ½žÓ·ßGNlYÏÀ<¼·ÙM°%‡#y% Oàæí[l»&ˆs‹Å#£²¿ø¢x°¦û’p7ÐA~?/§QM™µØØ:*­”SÊ­ä@Äy싟{X+ ˆ •—§ˆog=ðºWXž™H=½Ti¤Õ“ã”ù¯ò8%+u#\2廸ç$)‘O§ 5U¥8x‡såÜS …‹ žû1òfÕŠü9…Üà57yfxžïÎW..û5Ú€P4YEp¨KdÆT’áÆ ÑEØäG¹ä]ÌŒM½N:ôS ËnC¸ÁçC·ÂÖs³ÇÇnüèÞ\ek¸#}o[#€k 3¬±HÈ¢IÑFahªÁ_y‡Jµ_’4 hay¥õK¡½Ë†å’¨œä^<ÖÑ’‰axGø*7áYÑüÂYÓ¹^/†X]Â*££eá¼øDxävÙ*këçcEÙÊ«1õ‹æ:»ü÷H(à,`6sP§2ƒ ÔàÀd¦# ké2hŠr¦Õ[?ŒDkCItà¤"LFW÷ì»XÊf ˜÷ö\`½[Ã}VïÂRM= ZÇ]ÁÜ8RE ±E˜Àó¨§K¯´¿4H„Bå£q¤Žç/à­èô±páØVö¬34,j`çÜ|×㬜¡¡pÛ6¼p„rå¼Öº RL35¬îœÔXh R¢³!ù_ÅVøåÓH°¡cˆî5e¹¥|1<íHk‰y„ó^[Ï’°ÿuAÈG¿\W…ý(bÉ9À_‚Êk*§ Jz¥@$M!*ti·ÌÇÉ-èü«(ùÉ8 c ®0c‘Ô9/ÞÍî%ñXêÄ™8ZS üÁ@¬_‘² GùÅQ .4À³mæ%è¤x´@:wñSå²i¤XÛæ!ó; ãÚó„Àqx‚*ª6]à]ÀÂÑ{ÊÓcñi¯àØg@#g”q>ïS5*C/÷¸ÂÚö4w}ÄûÿN U¼÷éø2'Å[=“ž8ŒÄ+;ôÉt‹Û‘3èwøëÆ!í–=—âŸlÊJNa»ñDNÀÚi+ íàPT”ýÂQr0åç°2Ɉ .ùñ#/GÏâ4rŸI¸Ò`]³Ì·÷#†*)½Ü×hpd‹E9ý J˜7‚D×ýa±[]Md™’DÛyæ1†T°Z‰w>]]‡¦duñ(»‚Qö2ï¼7å{Hz/Àª V|oëM¼®`1hã¯+Daúéø»À*"™?y K#•…˜ŸœáZƒ^ø'¿ 9‚¦®ŠíÞ jÿwG6´•gá/ùØÞ:ý˜”­4éåŽp4 ’Äv¡+ŒŸJU®ñø°¤»|Àšé Jw:¸ÊâÏä8ø³Ë0Zp:0lD‘ÖºÅZ¡I襪\ûû¢Iì -i ±+Ë<ù-a—Bé¢úÖIû0(-ÅpõÕàtÇ/–’øÁ¥l#7š kD©[8ŒA"ˆGz¤¼§:·~¡/×9¯KO½î £ `¨—9pÄ$0oJ@¥-©U„ÃVÍüU‰Q?J¦²uÈÀ †Ð¥õ‰å]XÒ*Áî@V¹zН±ž÷ü]ðõqޤ£ÆîbH»0 *Ý&áKlz|êhÐ ­m®Ã—žôq!>ï:F ]9€‘¾ê „,\¾9¥ÕriˆÌâ!FÈ`NËÄg½r¨ŽG@6V¹þ¥AüËr (y¦2—5€¶¨h®u”¿ðM6 Â\]ú5ÚÄ×KCØ h}@‰GÝU)\"•¨úì¨LzŠíõâÀ‰M‘—|„<Œòæ Gúà›c?‚ûÜ¢WÀÁ•KÀŽdO døà ;0ÉT¡žXyÕŸÕ,“4#BuKR©7âaWØ6OÑjX¾øzò”¢àÿ\TžxJ¹^+·l¬áb8äµL# þ‚-Í ~ò#7óD¶“Š6²SWax¡ìÔyáIWñ sûÕ[!í Ùÿ„!êBÏaY¯*'“ö^»cº5›_,fs¨ÆÄê iX®Úú8–»€U˜³_ò´ÄÊ ]/€òÜú¾Öc ÃA5 ÔK‹p¿³´<žÂ-¡ƒ*Q˸Düxõëë([~T~)¶”­—é¥Ðο‚Pàé6c&ݨ…6x¦uDl/Mˆ=OÈE©”M†ÙC™ã¯à'KºM1ÊͯäeÛiYp÷ïH Τ³Â¶gz¤Âµ]y×Ê©ø©V”%R}©„ºrz¿+­ÖOÆGpKe$Há ¹·n•©£Ã@u:<ÛéÁ­¸º¼…•x ½*Wü{Œ!HÍ/?‘Õ×\IÉHntÚQ k„]aM#p`(Q+£=Ô†‰ºÖJèT€`ÁãŽÐÈœ( #Ó0”í,@ÅK¼á]ؾÏBÖvGëns•Ч†ÜÚ(¹ÃR0Þ- ÓzÒëŠ èò‹' S:ýXÇ´³¯ß×Å I8åeeìvÙ¾I…ŠS8]Q"•Oo¦%¸ö\ÓðXã[ øØ#¡bêÇ2‚2Ló•s` x{è×lêQç_6‘®daÕR€&•¯`Ó¿ÉzqXUÉP½„Ui;‰¹8yU!Ú+%0ÇëìTñâYbÀ×ïøõ1€»…¢ B®?¸@ÔÜJÒP«¯-å{î K)ÌNA±Sa]:¥-†™zå­ÂS±6²¾°bÄÔ©Y„íë6l‡+ ay;‰œ$dÓ¦pH¤ ÁÇGãÎV.Úôz5®û 3ëÇO"jp”Ã({Ç'âwjµ")Q¶Ns}¹¯+@œÁš£óÁ3d"›A€&h£Šù±\ %¸¬X•õy Öº¶/(ÂÓ¼0ÌÀåó¾¶Ý!3<)ä”P£Ðpœ*Vt 0 èÝ“pœDÈ +]$ØAeS>€oê22/ Açg9*ä‡ô£0? ÊÀ±žp㜘enEÆêÅåP.]â‘FÑ\§Ó£åzø§Mo_r‹QR(.q«›Rþ€_ØWÞFÑ+¥+@Hë04x‰HM*¶÷o2£Õv$ܘ -“È> Ìší…“Oέ+`•…€Ig€†ðdb†1€ŒúÂHÿø½ Ìi#(h?âí²¾B)mÞ@ª®lð¬¾ÐϹBìÊ‚˜¤B2Ð vyÅ“õK‘À¶,3ù BôYƒu¹~d’mf‘‡FR‹uê¼ ÿàlò¡ð¬']ŸrRé‘¿0"¾ÒA/¯hg!Õ¯FŽ´ ŸÚÙôñ$’ÇY‰M(-AI_/wU‹•:>]ˆ!˜úZ¢©÷Á€"|­Ù_Ôª(Q€-™Yôñgä :Èu Ðߤ!ø^~_ £Á¬1=t%PaùÑû<êùy¸Et$VÊ.cÍ5Äȃ´jLxCÚœÐ:À,0…¼]¶êDå˧$TÄ·ÝY)MžËøEB¢b¯m‚‹ e—&Ú[n=ej—õí󻲩•pXOÃð—Ø"[ ;¼â P=_6‰Wd.$ Ê¿\ƒÌT°+D)fSªh›Üháakî ñtCR¡¼]C¯6¬:ôè˜ ïýgYxÅkL.9hš¦kh¬š^Ý\(胤„/’…Ž Åk¹Çj[†®àë–¯|•’¬ɨv%ŸàÊÒNþ5ÀoA.™)åSòÞ:T”¿u•SIKX7=i±©xÐjK×m´µ‚ÔŒJ#  70 HˆÖ«0$V$‚¤ Š°"F&9KêS/ì»M)·*ÀTlšFV‘ߣï,@C±+У4„©i|¾¶}¸à¬ÀQ¾Ñ¡VK¸Ò«áÙ>p¡:чlC³)¦,~è-£¥-4ô{ý 9F ŒN³íÒÈÿ@¿ãΰõ ~I ŒQH5#RK^NŸ5ÂN³ø*zt€…_‡‚fð™¬ùs-Ï5’‚I™V€òMY·°ÁÒh´XB,üu^ éMa6„”7)T‰/”uôÁ;:œÄ‹3¨c”–«ò2ˆ © ýò¡ ¥%!›“Dóàl‚WÜiÑòêöìœo.f|²Úüôó³ÜùF~"n‰é*¯l±^ÉEœ]FAƒ6ñˆWº"G.}Q¸­Ì—”ŽÕdÌ}é†ÒÖ²4N][J# @oÕ#LeédNä|PAÁH`Å2f GÒZãÚÙØH‘HC& ÌŸ¢Élƒ«þVÜé‹qùsqþÆŸ/ˆ2ˆíÂ9"{4WÖŒ×ÙßîýØCí¿ûL güZ^T‘ýÿJ ä#® Œêš"™-1$#–4É–ï/^]³ÿjçx>QqNE}kÙ44OA‹¿e°ÝN<»Ü¾øÉ'ÚÇ?ðh{àüä "üÉ_z'U~ jIç gƒÌ‚³#vdJý(’:޵2+Sš!¶„ü¨ZÃ…\«æC)×Ü]ÍUñÈÙåÒH0Ô¤ˆ­pgHVR¢W{T¨nÕª†u“g%Û);…©a˜×C¬°%6Æ`%~Â8¾nßùvüsüxÓaC¸„ñ[€üpä̰'PèÐÞ{þ>ð ‘oâñÏ=|º}âo_û-·2PtiEä;tÀ‰tûÞ¾Þ+9 R^òfpNT|uþþtûª \wkº¿U8Kˆg)‰Ÿ=¹Ö¾ðñgÛg?úLûÐû’Ä6ÃS½äöíÉNQv¢½ñ?¸Ž­¾ÞÅ›Cna6Ä9 ©ÈIùT”)¹vCž²¢fõŒ8åûŠ~yq•¥¬+9óð9K»ØQi¤ˆM¤*Ïé^æñäí„`Æãa †"zÌã?}µˆÐÉ—È^_b2"ß°6É/ŽKVû¯âgÞÏ «{®ïd?sýuúù9~‚ÅÕ=g*ÞB¼ o Ÿæ÷ n|Õ¾öóÿ݇ÚËî<Ü®»e;ÉoLM͵1~¨y‚ŸŸS€ÛLJÐéu¨¿ b—#>’6Zî \ŠöÌÔÖ*¶õü“Ú“?ßøôsü¾ñÃZZÒ5·,ð ¢.Z±lÍÂÞ0×~÷W¾Øî~Ëu¬dòŽ#žoç—Du_Ÿ›nGYÒZå—–wK ;k l;é ­”éxÛÈǃəòWù8HjËéåÓh áÆ6OÚxŸ¡tvÀC×,…{V£ÛPocâÜíÓ½­3Ø AsL@Í0ï áu1Çð ÛÑ>ŠJW°ˆÿî4å'ãQ–÷ œ 6ÙKÈú?3Ûþ÷Ÿú`ûŸx;°´¥3K,+ó䆦GÔÀJo«ðª7;• yp3Š¿ñgøu•ÑA³3'×Û1~ÏèÑŽ·ûïEñŸz6´øuäæ…¬E8¦ÉJF6ůˆj¬{çfÛcŸ?ÕúÔñv×ÛŽ°í΂!3@-‡/¼ ÒEI‡"æ«¢Au«FEäÝúæIwxH?$O#C_dL£ h“ºfˆq Q"Úf@Ã(—1(`‰rÞkh•h‡®¡’ï6&_%Â04Ë5Ü»üàá…»êHߟ]E¹:†³€,ùRêÔÐßv(KÇL Çã„Á½fÛÑçNµŸú¡_oßóC_Õn»ë0‘#V;ˆ5Z™ºQº®Ec*Ïåæeúê3'–Û±gηg=ÝyèùöùóÃCZ`ÆqÝmü¬÷Fä)º+Ç®Ð=‹îi€Í€ZÙwíTûý÷=ØnÿŠÃéÊ67ÝÐVŠò;ä’§ü*·ŠžvM“jôS©ºÐ«˜c‰†#I†9ÈÇNP§‘F€MJ黀3hGy¦X:G‰¬q€Š*‚ºp%ÁsS–Œíø³¾+q2á¹–>Îoœ¿°Ü®ºöêvíWÁ¡ÒÛÂ<À¯†ªìúÝ@¢}o]É`ПsÁÛ\ÎÊä>²·-^mÿý¿½æ-7%ü^wÓ¾¶pÀ'ŠˆiLXú{È­Ÿå÷O]Æpζçž<ÛžøâÙvòy^?ÞAéš[3­÷§sœþ" Êú$ËÓ¾‹ÇÇ×U€û“JNåoÿ¡yfÏÑ]<ß^yÏÕü õr Ljc¨ÖˆLÊ/B2=MÖðe„(Ù&z’k·ìX šçZ=ÔàQ}éõ|ò–Wœ×Ð0"4Ó+d€&|úûwu Vª°š!¨H4Až}¹Œh­…õt+ˆò/º%ŸöâÁ{&Æù1Æ¥óíÈSí5o¼µ½ï½kw¾öªšÐçºMÌ_èÝ2C#CÖ–ËȳIé‘á9 㥯ši÷ßÿXûô‡“Фù«|ëÈ^î n¢t~Ëõ2éª÷´n߇‚)D›zC”¬âO°ê¨r-´[ñgl'ˆ$ƒÑÎ1€m|Œ­¢ FpýTûÈoüq»ýµ×ÐmíA†,co^`ÔŽ<…K[DýJ¥.z¸8j‰3Τ’‘…2¯vÞùSÎGºˆ §éÃ2Î^œF€Þ™_Á¨€ÀñV.´Þ K”²ê °ŒãA¾Êi¾<7ϤÅʸ kZ¸Œ®n\hwÝó’ö¾ó1ê²ùƒ÷¸à´Ï{âTùÚÒÞ$ÂÀÐk×ô oÉ»?@¥—^};6q¸ðûør·xGn«ùÉ÷ µÐ¬M«ì6×ÒëžDúۿôò¨HžÁ£â¥Å©è´¿Zêkcå 8vYå ÝÏA~†ö¾=Ûù܉vëk÷1#X&º@T]’2—òsÀmÔ6ÊæuïJ(2V¹ é8|i [É3 H{å#×>:Áe’f<"©(E `ªÅy®@–¨Õ‰‹õR^a°!!±8²žÂQ€ýXá’—Nn´“§N¶[_Åoô½â†væÌ9|¾€¹>]?a?«° Q|Ê|“x•¥+€+…¯ÒƧ — p€6ÉšÍì/œ²ÛÀø­Èôßþ(“}ŠƒÈ|XXšà# û†á@O3Ý”w9šb%Ò² ŸF ßi¨Ò³‰•è0A™³Ê¿pT ?0Ö>üþπ˦råcTt@¬mÐC H£qÀé@Øè3M] oË>žœšê®Ò¢"w¢u=G<5>Áˆ®½v_û̇žn?p:}¹E ®•Mä¦Òà«<˜3p& §<±D=»S7„¸„ÑóbXÔQÒèÙ¨4Òl‡Ê¢|•à@)EJfYnB%„k†z¶ó¡‘04SÖ8j¹z¯ðzèµ¾FPïâYoÏ}¦½æ­7µ¯zǫډ3Ì ¹)µB¿o¿«<7T+`‡cGä–k$²k?\IoÅŒQ¸£õÞ©ríËÍ·ÔÊõV=Þ_GÕÃ8–×â“ÖU=X/†‘I^4<#U§EXŽ3”]" ÓM”Lïý¥ÅX©Ä0-WN;róBé"ÏrŒRlÉ*ÁÕeÚÑTWü/¿z Üè$h/û5ÒPdŽ$¹2!r.1¦ÐÚÁL¤çY¹¢B)YC¨6²¹ŒË !Õ°Üâí€ðìÙÓíÜêñö]ç«Ûɇ¨Ç Ô·„¹õË®§àù"H‹ïñ§i‹×´öãÿë÷¶?~ª­q£/ý1ôôÝB [® ê©*ÕP,J/…G2v@¡>Š­‘Äh˜ŒÊvé×È!õ…«‹®5¦}9Ædÿ.>œƒ$:0ByH?o€w*Íñ Û%~Rþs_äw8ÑÞt÷ëÚ?ùÙïo?òß SÁ#™5¹¡Ä¥Z•,Í&²ô<ÝF ¬üSæ–÷¾Ÿ+< å¨ìÌÒ ”¯…:b”dÁeR“—ѯ CºB¢ø8€Žhe™¨ªVÙ(!Í2àhH¹ŠsK™†.±:¥ aÛ¾×/\ÅãM<ñP{Å=¯iÿÙO¼»ýô?|O{ùƒ!¶ɮ`va"×Q 0U’ÉÝBþì¬ÞšnAø#T&™ì»gæ1 ¹<&pÔ`\~öþ‚I#¦G_E3Ϫ¤^ŸUIíVγ…·UŽ3ýâÃGÛÚ“,½bº}ç7¿½½é«_Ñ^zûÁ¶Â»}ö¾vôè1žrZ7ÅAû8ÜÙUªL²*2FP]E„òÒ±ÔO G¦TŠ€H‘u²èñ¤äÒ¯‘ ÊŒŽäUš‘ÃëÜ_ žKÎ.1«|½]¯wŠ©wåî#0½3)LËö:8&:ð«¥Û,b:ª=ò)„ÀBæ7}ó=íu÷¼œ™Ìõmñª©¶´zº=øôg™áœ z¬¦›#n h»×Ñ2QÊ#¤òå‰ *Û¼äÞi5М*~šºq*Cœ38ëwX\½84ÛT?nÈöÎ\)Ç|Ï»åõü!â|¼>©èÚ!²ú5!Jà„vjÄ à°Vôì>ð*¼dëÄñöÐØ}í­ïze»êÈßn?ùþv~j½½ê–#,±\ŒÀ]Ë·Oª}¾h5„9¢ƒÊÞ-«`;Ÿ.RÙâÛd—û 0qž‡NzYº @CÐxW¸§¯ÁŒOl´çž9ÖŽ=¢E<ý%Óí+ï¾§}Åß»½ÝöÊëÛÞC¼¼ŠG•Nž=Ö}èéŒi\Lsäûÿëuö¥T Dz~ård n“çV²¼®u>¼ˆTŽÈy‰´ê¦¾zK•+~4€´ P pÔ¾Bä0P‰7CD7«:BMD ¶Öêø/‡Y>a„| “IëÈ”×»Æ!S¶AX"Fp'Om÷qg펯xuûç¿øÃY$úåŸÿ=î·¶vÛÔÁ¬vyßÀ±„û õŽ”‘ËÇznî"2b7Ôk ÐAc¦”Ó5÷&o$—ÎuÏæèB4ÓÇùÝ!§ù}â6ÜxÛ;_Ù¾å›nl·Ýñ’vÃ-WµÅƒ(]?§Îžh_xüYÞdvšÈäϹðR x¨5ûjÇP%+e¬LÊ(2à<²å˜žŸb«¸žïíøDGºKi´­ípG¦jjHÔQ¶WJW0{Ž]«Ë#Èv@L5>®ÒUD–vÂUÝéãF -§¸ú5ÎM·ÔåÕ>ˆÑÈ8bPa:ë'N´Ï¬~¼ÝxÃ-í»à­í«ßñêö_ÿlû½~ ?Nð]}„»W‚žš6λ‚ÈTÏ-Ìß)ýËç ýeˆÝÁ,ã k癧϶1ˆÎû¬á3|Hw¼áêöê;ïh·¾ì†ö’[®n×Üp í;į–c8k›+íôÙçÛãã%Ög1ÀóÌÙõnyæã_¼¾<>Ò _zü˜TÒ gMUà·Kò:•rPΦ܇áÔö‚Ùq$N:®Ô¡Ü6»‘æ/øº‚T=QjµãÌcÝÌ pµÐD•.!µç½ˆ²\µ|tð¡ lÛ[??âÄ1‘C#¼@ðu˺ì©Ã ½}»uv«=øƒ¨ýϵ—Þpsû?ô¶ö®ï¼§=ôùgÚÃ>Ùþøá§ÚÇÿèa4r»¿K²»„sI>ÊÇ´Ï™œ%„ûLÛÊo»ýšöú»¯o×\sU;rÍ¡vÝKrci_[Ü?ßöpblJZVÚÙó§Û£Gmgðò~œb•_Ws›º‹cñt§c‰aų£Dø—?Îå=BÁLå¶§Ý KN#/«ä d¸À”ÕÈœ–u¹Gé”Ç`@¡ƒ9»Rm"à Cø^Jè¤ Ë•´Nú.ʬ§‚£L¼¸R)ÛüšŽ@\¬To(Ëõšâ|Œ]41Z¿úíþI[üöq\þôéSüžà>¶‚ÝÐ^óµ×¶7¼ýfFôx.¿#´Îö±cÏÉàð¯–?sr)ø:å›dßü>~ª†ûÞÿßw`1L¦ÙuT«ƒÐá­n¬0áNá…“íñ'Nµ¥ ü¢ Ï,¬Ó?d ‹²ö†R–G"^œ î]Z”à4 åçµenøÃ0v$ , ò­¾Ztü ñ¸OAEwõÀ‹WFa ñG}`ƒ»ŸWJ£ ú­ÐÀ“AêÞ/®¥öRn½x=G=½Bx‘ÈÁiˆ£vapÎQâ³+Xñ£OEÅáJ<¬ nlòÊ á†àbËž¹ù¶¸°—M¢ (sO»ùÚEÞ ^¿5œ1'ü‹ nck~¸¯€å¬1Æ8³¼ÔÖxíÌòò…ܬY#ßš×­À^æàƒr¤'¯h‘híô‹ƒKRÿÎû¼Ž“ì:‹ Óp™è'}Ô1U—hT *ìlÌÍu5Õ±Äç3–_ü)g+xz™¯Ñ@eiƒBNÓàÝe…T £ixRH¦#Ô¨~]B åeLj’ñC‚…Ø]Á™.`#‚F°‰ò01žÎaEÙÂy:íÌ„ár±ž“[·às³HŒ¸¼·Q8ô¬Rž†àºF<:yÑbŒYškô^Ï(¨8ÐQÛíp¥[Øs+–cn‘“[Š(^30&¯¸—¿Ÿx-nË5šJà¡ ^E×:eÒâ\ ¿¸hÏ 3KÆð9ˆ¹À]æ{´€XFHœ Œ6HØÚZƒ !x1V8ƺxÑ­Uk‚Ë× ÄZ+XseXjBGC³«8ɨÇҭ˵uT|ò€“¢Â§°2Šr¹0b'Ï,ÃzªÓ0ñ{?Ü­Z&ñVx4t~…(Únx–‘vðShUy O”©Ä ‡Âð·Z5Ì áÒ<(¢ÐÉ“¼)C{§]9©¿å ·ËO 2 ×è¼ ÕV2ùêŸê6h–qÙ‘Y9HÝ…LÃ}•«½(Ó¶0JWĶ%jôW»‰½,­#r‰W¸ý(B¯e ç ^#èý–BTP•/2E\p"2¼ÁR`0š(¢p„±Ð G•Sž%Q£ð—€l¢@¥Mz°íM9|hœ–gÏð! —<ù‰‚h”ææy2x£ž/Žt•…ÖŠ…ßÙîèÍ“ÖÐÂ×àLâ·œ³:æ;‹JnÚUûjçJ#mÓXŽ'êÑ«hã‹Ò.C&„HÉêúÊö¹´e4w80Wƒ ª›T3…Ó0Ò°+=Ó´9†6*KÅp͆z“-#,´ªRÄ•üQ %TT(Î׮ଫ@"<8ª3;<(3ô—·Y¥…Žj¯`Ã._e´Õ¦ðWγ]cÎmç+κâO@yŽE,Ïú=¸Ó™E§4ìº4„°…³"§çÀ!_X¾FOGïÜÔ¾µµmw¸®îBàjH/0l·s}f{™E­û×—±²q§B50±’Á"ÔmYšv­ÏsAT*OÊ5Y%ˆ¡ÄëÀ,¸zµ)u:Lká^«°\;Þ ~¯Ý!ã§’Þo›‚8=·}>”…î¡¶¥ó¢ÁR5i§½°üÚ=À·*Š;£ü¡±y¶·.àZŠžÊÓ°‹Q¯õReî°ã()ú…7Ðþ}Wf•_/ÒgêiÁ Oà›dzËn-Ÿn÷Sg¹ý7Ñmg7X/ÜWT^8¹õÑ¥ãÓwñº3ãÛ,¾l0ºÞf‹Ø|ð+m$­N"Í/"Š seå\`÷Ëô>Xfíö*­X WÀz¦L™‘Á'e‚É6Ž”•u0G¶ôq´~2Ó üz†uêÚ¶f¨ü‚2ä[eêM…¯ã¯Z*9‘N%>tK?)‚¾¸TjåU~®ƒŸü* @ùW©iÓqxQƒmùO¡^‘S”,Û—ì©<Ï5pgÊÏ»ŒbnZŸ~vû¶>hƒn r}_jïqŒÌªéÒ™\ýÌÁ‡ö^7wÛä$Ûئ?Æþ8‚©_\°a"ûëõB”Àˆ;a Õ8!Õ”i’üxjßßÇ >•Sžk©‚‘Ÿ°–6~•’#¢­fãâˆÒâÙœ;å+üÀ<²‚T¼Ý Šp€g¢ãç<±„B¤ð¥ÂÿÒkE‰ê·ÿÂË~ D|–E±f„$ù*Ü¡&xœ¥„¿¥Š¤EÇßÛs¬(Q‘VX ‹ÁWXw‹V @cÄ&&×éù'ÆÏ<3õЙ³Ï~ÄvmÐm·¯K ‚¶Ç¾gÁ®nOœ~zó÷_»ðcûo<ÆÍ˜½ yãÎS*’q’©ÐЇ:Wwñ%CA®A¶t„«25­±—T¢Ì”e;pá,O¡h(SˆÀÐ;…ͽ]"Gy—¢,/Q1–'ò× `e}J¥øxvB3ýµØFèÂTõÂ,ó„A øƒtâ׸‹nñ—Ò… ªxføž©º£ åÀ}´×ƒ·Ù¢fR‘ÂÏù@Ÿ°” ç<4+K’p„7»ÀÝË'®n§ŸÛüÅUt©NiW•R³¾ìï/º2¥êÝm|ï'Û͇ù¹›ß¼öÕSó§6—NíË$ÞõåŒâ‘ƒkéç"V5Ân-f˜Wž]Ó±è¹ÖsQȲâ³héFC³0¨§FКÁ CYïÐynØ¢ž¬ø·£LÊL Úˆ‘º MxÒAJˆ@®øŠaªñóç¿ÉëÂE%Îí†,ªA™y¹ OW¹õ½Î`üq$ñDñ ›*Li*Ç(Å:õ­BQ¦VxÉr5»Œ%`þà™Íõ¥|tú÷OœzþûϾ®=ª÷S¿{H—5ËÜøM7µésÓ³o=xhßÏÜøºõWL-œÝZ]šåf ®8ÄY¹£¢þÓÿ£lš¨$#%äRHñà¹a,d…kave1ÖÀ¸ÊPì=¨A_„Ó¦!š OÔ”LÊ $â‘fØÏ­¹„Ž åñ"*L€_CQ¨Ýˆ¤¹f%vY*Ó¤±ÐÒ7èM½>ËîÐ&Öç«*)ç(YÊ.Æ Æû"1Ô¡M"|ïøñÆñ”š˜ÞØš[Xn«çöŽ?õééûO?ñƒ‹kzì1ñøeÒ• @´·¿¥Í99ó¶=‹ûÿÑ5/ߺgñšó(€Û >ȃWã¼-*o†Ë\3H„GÒXø¢,â¤+!GÔUF×ìÍ·ßcŒÁ#:F-ÙN/XB…Û0|OÕÓ8"­(Caš,ÓüÆÇ|οÂváVશî|ÂOia7G—âS¼0%±¨$éÖõ¾«|€åMüÖ_Æ$(OÔy ˜wÈ»0í<Ú…WÝòÎgÙƒGåÇÇý‘DZå™rŽ=ùÂÏSHŸšf 8¹Ò­4îIDATïL}v¾=÷ÀøÇ.œ;÷ßn¼ðÁãÎ[”¹Ó,†KÓH°*Œ‹uâ–×·ù£'ÛÝ Ó¿÷ÐõSïÜ{ÝæÕóXŸññ+CSÔÁÛ¨„eør$0\«¢«–%Iº‚EÑ–¾Ä;x¾Ì+´ÞМ\êºMMÃÒãJ¸¥Â^áØ{C{*Öàpž;—HS˜c(Ç8sse~ï9¨pͨªøàªJ•þ2Ú¡%j ­˜ ÍÁ/½ÖS¶bÂÜT&繎,¤Ã.²Ž;Ê·~äUükÁÍÛU6ÖØszªyfâ艧×ÿŸ¥µ“¿põÁö™G>Ñ|øq¤òÅsEH%ð5mâð±Ã³mùصl yÃôä¯ZÜ7yçÜâøõìŠYÔà‹\‰«A‰ÀŒ~1”:\\­7+ÅXÒsªuA† ²ðbœ¨ü$6•ËAö97?×ÖÝ¡~À“æu.<7jHG™Ÿ”t<ÅWä[q庲z… â ²F^¼¸ùµpÐj y{cmìÜʹ­§/œÙ¸oeãÔ°ãíÚÜág>¶Ò>peå‹üK@*WcwÞÙ&—gÛÜù¥vÍ­G¸…~ZânÙ¬/ÈÐì2MNÕMÜÈ+%\¬‰*ºä»,мnWÖÅ º'Y¨/Z¿çõHÒ¯)™¬{I=ò:.Ëxt |x4ISY'U¾CïÀ§!õ:°ª~é·m^TçbYØ@¹vüVW®‹{&VX78ÁéŽónªççÚɹ•¶|ß}Ù E€èž „˧?‘ØÐMc_ó5mü±vÓäùcM.ΘX=j’èØË«Ö—¿ÿB%@°=3`ãÜÊ©ÍùÃ7mÜÔÛøÀbn åKàŸØ.ææ"c ¾^±.®þåó¿8 ôž!þ¤J¿˜œ?“\ ÀóÄ‹‹¿|ý$?‹Â_LÊ¿x1Ð/_ÿû# =þý!üË”þ»‘ÀÿýPMˆ(%IEND®B`‚django-celery-results-1.0.4/docs/includes/000077500000000000000000000000001337257563700205165ustar00rootroot00000000000000django-celery-results-1.0.4/docs/includes/installation.txt000066400000000000000000000020121337257563700237530ustar00rootroot00000000000000.. _installation: Installation ============ You can install django-celery-results either via the Python Package Index (PyPI) or from source. To install using `pip`,:: $ pip install -U django-celery-results .. _installing-from-source: Downloading and installing from source -------------------------------------- Download the latest version of django-celery-results from http://pypi.python.org/pypi/django-celery-results You can install it by doing the following,:: $ tar xvfz django-celery-results-0.0.0.tar.gz $ cd django-celery-results-0.0.0 $ python setup.py build # python setup.py install The last command must be executed as a privileged user if you are not currently using a virtualenv. .. _installing-from-git: Using the development version ----------------------------- With pip ~~~~~~~~ You can install the latest snapshot of django-celery-results using the following pip command:: $ pip install https://github.com/celery/django-celery-results/zipball/master#egg=django-celery-results django-celery-results-1.0.4/docs/includes/introduction.txt000066400000000000000000000016461337257563700240070ustar00rootroot00000000000000:Version: 1.0.4 :Web: http://django-celery-results.readthedocs.io/ :Download: http://pypi.python.org/pypi/django-celery-results :Source: http://github.com/celery/django-celery-results :Keywords: django, celery, database, results About ===== This extension enables you to store Celery task results using the Django ORM. It defines a single model (``django_celery_results.models.TaskResult``) used to store task results, and you can query this database table like any other Django model. Installing ========== The installation instructions for this extension is available from the `Celery documentation`_: http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html#django-celery-results-using-the-django-orm-cache-as-a-result-backend .. _`Celery documentation`: http://docs.celeryproject.org/en/latest/django/first-steps-with-django.html#django-celery-results-using-the-django-orm-cache-as-a-result-backend django-celery-results-1.0.4/docs/index.rst000066400000000000000000000010001337257563700205400ustar00rootroot00000000000000======================================================================= django-celery-results - Celery Result Backends for Django ======================================================================= .. include:: includes/introduction.txt Contents ======== .. toctree:: :maxdepth: 1 copyright .. toctree:: :maxdepth: 2 reference/index .. toctree:: :maxdepth: 1 changelog glossary Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` django-celery-results-1.0.4/docs/make.bat000066400000000000000000000160441337257563700203220ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. epub3 to make an epub3 echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled echo. coverage to run coverage check of the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) REM Check if sphinx-build is available and fallback to Python version if any %SPHINXBUILD% 1>NUL 2>NUL if errorlevel 9009 goto sphinx_python goto sphinx_ok :sphinx_python set SPHINXBUILD=python -m sphinx.__init__ %SPHINXBUILD% 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) :sphinx_ok if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\PROJ.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\PROJ.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "epub3" ( %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3 if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub3 file is in %BUILDDIR%/epub3. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %~dp0 echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %~dp0 echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "coverage" ( %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage if errorlevel 1 exit /b 1 echo. echo.Testing of coverage in the sources finished, look at the ^ results in %BUILDDIR%/coverage/python.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end django-celery-results-1.0.4/docs/reference/000077500000000000000000000000001337257563700206465ustar00rootroot00000000000000django-celery-results-1.0.4/docs/reference/django_celery_results.backends.cache.rst000066400000000000000000000005011337257563700305750ustar00rootroot00000000000000===================================================== ``django_celery_results.backends.cache`` ===================================================== .. contents:: :local: .. currentmodule:: django_celery_results.backends.cache .. automodule:: django_celery_results.backends.cache :members: :undoc-members: django-celery-results-1.0.4/docs/reference/django_celery_results.backends.database.rst000066400000000000000000000005121337257563700313000ustar00rootroot00000000000000===================================================== ``django_celery_results.backends.database`` ===================================================== .. contents:: :local: .. currentmodule:: django_celery_results.backends.database .. automodule:: django_celery_results.backends.database :members: :undoc-members: django-celery-results-1.0.4/docs/reference/django_celery_results.backends.rst000066400000000000000000000004571337257563700275450ustar00rootroot00000000000000===================================================== ``django_celery_results.backends`` ===================================================== .. contents:: :local: .. currentmodule:: django_celery_results.backends .. automodule:: django_celery_results.backends :members: :undoc-members: django-celery-results-1.0.4/docs/reference/django_celery_results.managers.rst000066400000000000000000000004571337257563700275700ustar00rootroot00000000000000===================================================== ``django_celery_results.managers`` ===================================================== .. contents:: :local: .. currentmodule:: django_celery_results.managers .. automodule:: django_celery_results.managers :members: :undoc-members: django-celery-results-1.0.4/docs/reference/django_celery_results.models.rst000066400000000000000000000004511337257563700272500ustar00rootroot00000000000000===================================================== ``django_celery_results.models`` ===================================================== .. contents:: :local: .. currentmodule:: django_celery_results.models .. automodule:: django_celery_results.models :members: :undoc-members: django-celery-results-1.0.4/docs/reference/django_celery_results.utils.rst000066400000000000000000000004461337257563700271310ustar00rootroot00000000000000===================================================== ``django_celery_results.utils`` ===================================================== .. contents:: :local: .. currentmodule:: django_celery_results.utils .. automodule:: django_celery_results.utils :members: :undoc-members: django-celery-results-1.0.4/docs/reference/index.rst000066400000000000000000000005341337257563700225110ustar00rootroot00000000000000.. _apiref: =============== API Reference =============== :Release: |version| :Date: |today| .. toctree:: :maxdepth: 1 django_celery_results.backends django_celery_results.backends.database django_celery_results.backends.cache django_celery_results.models django_celery_results.managers django_celery_results.utils django-celery-results-1.0.4/docs/templates/000077500000000000000000000000001337257563700207065ustar00rootroot00000000000000django-celery-results-1.0.4/docs/templates/readme.txt000066400000000000000000000027041337257563700227070ustar00rootroot00000000000000===================================================================== Celery Result Backends using the Django ORM/Cache framework. ===================================================================== |build-status| |coverage| |license| |wheel| |pyversion| |pyimp| .. include:: ../includes/introduction.txt .. include:: ../includes/installation.txt .. |build-status| image:: https://secure.travis-ci.org/celery/django-celery-results.png?branch=master :alt: Build status :target: https://travis-ci.org/celery/django-celery-results .. |coverage| image:: https://codecov.io/github/celery/django-celery-results/coverage.svg?branch=master :target: https://codecov.io/github/celery/django-celery-results?branch=master .. |license| image:: https://img.shields.io/pypi/l/django-celery-results.svg :alt: BSD License :target: https://opensource.org/licenses/BSD-3-Clause .. |wheel| image:: https://img.shields.io/pypi/wheel/django-celery-results.svg :alt: django-celery-results can be installed via wheel :target: http://pypi.python.org/pypi/django-celery-results/ .. |pyversion| image:: https://img.shields.io/pypi/pyversions/django-celery-results.svg :alt: Supported Python versions. :target: http://pypi.python.org/pypi/django-celery-results/ .. |pyimp| image:: https://img.shields.io/pypi/implementation/django-celery-results.svg :alt: Support Python implementations. :target: http://pypi.python.org/pypi/django-celery-results/ django-celery-results-1.0.4/extra/000077500000000000000000000000001337257563700171035ustar00rootroot00000000000000django-celery-results-1.0.4/extra/appveyor/000077500000000000000000000000001337257563700207505ustar00rootroot00000000000000django-celery-results-1.0.4/extra/appveyor/install.ps1000066400000000000000000000053421337257563700230470ustar00rootroot00000000000000# Sample script to install Python and pip under Windows # Authors: Olivier Grisel and Kyle Kastner # License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ $BASE_URL = "https://www.python.org/ftp/python/" $GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" $GET_PIP_PATH = "C:\get-pip.py" function DownloadPython ($python_version, $platform_suffix) { $webclient = New-Object System.Net.WebClient $filename = "python-" + $python_version + $platform_suffix + ".msi" $url = $BASE_URL + $python_version + "/" + $filename $basedir = $pwd.Path + "\" $filepath = $basedir + $filename if (Test-Path $filename) { Write-Host "Reusing" $filepath return $filepath } # Download and retry up to 5 times in case of network transient errors. Write-Host "Downloading" $filename "from" $url $retry_attempts = 3 for($i=0; $i -lt $retry_attempts; $i++){ try { $webclient.DownloadFile($url, $filepath) break } Catch [Exception]{ Start-Sleep 1 } } Write-Host "File saved at" $filepath return $filepath } function InstallPython ($python_version, $architecture, $python_home) { Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home if (Test-Path $python_home) { Write-Host $python_home "already exists, skipping." return $false } if ($architecture -eq "32") { $platform_suffix = "" } else { $platform_suffix = ".amd64" } $filepath = DownloadPython $python_version $platform_suffix Write-Host "Installing" $filepath "to" $python_home $args = "/qn /i $filepath TARGETDIR=$python_home" Write-Host "msiexec.exe" $args Start-Process -FilePath "msiexec.exe" -ArgumentList $args -Wait -Passthru Write-Host "Python $python_version ($architecture) installation complete" return $true } function InstallPip ($python_home) { $pip_path = $python_home + "/Scripts/pip.exe" $python_path = $python_home + "/python.exe" if (-not(Test-Path $pip_path)) { Write-Host "Installing pip..." $webclient = New-Object System.Net.WebClient $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH) Write-Host "Executing:" $python_path $GET_PIP_PATH Start-Process -FilePath "$python_path" -ArgumentList "$GET_PIP_PATH" -Wait -Passthru } else { Write-Host "pip already installed." } } function InstallPackage ($python_home, $pkg) { $pip_path = $python_home + "/Scripts/pip.exe" & $pip_path install $pkg } function main () { InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON InstallPip $env:PYTHON InstallPackage $env:PYTHON wheel } main django-celery-results-1.0.4/extra/appveyor/run_with_compiler.cmd000066400000000000000000000034621337257563700251730ustar00rootroot00000000000000:: To build extensions for 64 bit Python 3, we need to configure environment :: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: :: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1) :: :: To build extensions for 64 bit Python 2, we need to configure environment :: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of: :: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0) :: :: 32 bit builds do not require specific environment configurations. :: :: Note: this script needs to be run with the /E:ON and /V:ON flags for the :: cmd interpreter, at least for (SDK v7.0) :: :: More details at: :: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows :: http://stackoverflow.com/a/13751649/163740 :: :: Author: Olivier Grisel :: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ @ECHO OFF SET COMMAND_TO_RUN=%* SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows SET MAJOR_PYTHON_VERSION="%PYTHON_VERSION:~0,1%" IF %MAJOR_PYTHON_VERSION% == "2" ( SET WINDOWS_SDK_VERSION="v7.0" ) ELSE IF %MAJOR_PYTHON_VERSION% == "3" ( SET WINDOWS_SDK_VERSION="v7.1" ) ELSE ( ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%" EXIT 1 ) IF "%PYTHON_ARCH%"=="64" ( ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture SET DISTUTILS_USE_SDK=1 SET MSSdk=1 "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release ECHO Executing: %COMMAND_TO_RUN% call %COMMAND_TO_RUN% || EXIT 1 ) ELSE ( ECHO Using default MSVC build environment for 32 bit architecture ECHO Executing: %COMMAND_TO_RUN% call %COMMAND_TO_RUN% || EXIT 1 ) django-celery-results-1.0.4/manage.py000077500000000000000000000004621337257563700175670ustar00rootroot00000000000000#!/usr/bin/env python from __future__ import absolute_import, unicode_literals import os import sys if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE', 't.proj.settings') from django.core.management import execute_from_command_line execute_from_command_line(sys.argv) django-celery-results-1.0.4/requirements/000077500000000000000000000000001337257563700205035ustar00rootroot00000000000000django-celery-results-1.0.4/requirements/default.txt000066400000000000000000000000211337257563700226610ustar00rootroot00000000000000celery>=4.0,<5.0 django-celery-results-1.0.4/requirements/docs.txt000066400000000000000000000000401337257563700221660ustar00rootroot00000000000000sphinx_celery>=1.1 Django>=1.10 django-celery-results-1.0.4/requirements/pkgutils.txt000066400000000000000000000001601337257563700231030ustar00rootroot00000000000000setuptools>=20.6.7 wheel>=0.29.0 flake8==3.5.0 flakeplus>=1.1 tox>=2.3.1 sphinx2rst>=1.0 bumpversion pydocstyle django-celery-results-1.0.4/requirements/test-ci.txt000066400000000000000000000000231337257563700226070ustar00rootroot00000000000000pytest-cov codecov django-celery-results-1.0.4/requirements/test-django.txt000066400000000000000000000000071337257563700234600ustar00rootroot00000000000000django django-celery-results-1.0.4/requirements/test-django111.txt000066400000000000000000000000231337257563700237010ustar00rootroot00000000000000django>=1.11,<1.12 django-celery-results-1.0.4/requirements/test-django20.txt000066400000000000000000000000211337257563700236160ustar00rootroot00000000000000django>=2.0,<2.1 django-celery-results-1.0.4/requirements/test.txt000066400000000000000000000000571337257563700222250ustar00rootroot00000000000000case>=1.3.1 pytest>=3.0 pytest-django pytz>dev django-celery-results-1.0.4/setup.cfg000066400000000000000000000005301337257563700175770ustar00rootroot00000000000000[tool:pytest] testpaths = t/unit python_classes = test_* DJANGO_SETTINGS_MODULE=t.proj.settings [flake8] # classes can be lowercase, arguments and variables can be uppercase # whenever it makes the code more readable. ignore = N806, N802, N801, N803 [pep257] ignore = D102,D104,D203,D105,D213 match-dir = [^migrations] [wheel] universal = 1 django-celery-results-1.0.4/setup.py000066400000000000000000000103401337257563700174700ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import os import re import sys import codecs import setuptools import setuptools.command.test try: import platform _pyimp = platform.python_implementation except (AttributeError, ImportError): def _pyimp(): return 'Python' NAME = 'django_celery_results' E_UNSUPPORTED_PYTHON = '%s 1.0 requires %%s %%s or later!' % (NAME,) PYIMP = _pyimp() PY26_OR_LESS = sys.version_info < (2, 7) PY3 = sys.version_info[0] == 3 PY33_OR_LESS = PY3 and sys.version_info < (3, 4) PYPY_VERSION = getattr(sys, 'pypy_version_info', None) PYPY = PYPY_VERSION is not None PYPY24_ATLEAST = PYPY_VERSION and PYPY_VERSION >= (2, 4) if PY26_OR_LESS: raise Exception(E_UNSUPPORTED_PYTHON % (PYIMP, '2.7')) elif PY33_OR_LESS and not PYPY24_ATLEAST: raise Exception(E_UNSUPPORTED_PYTHON % (PYIMP, '3.4')) # -*- Classifiers -*- classes = """ Development Status :: 5 - Production/Stable License :: OSI Approved :: BSD License Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: PyPy Framework :: Django Framework :: Django :: 1.8 Framework :: Django :: 1.9 Framework :: Django :: 1.10 Operating System :: OS Independent Topic :: Communications Topic :: System :: Distributed Computing Topic :: Software Development :: Libraries :: Python Modules """ classifiers = [s.strip() for s in classes.split('\n') if s] # -*- Distribution Meta -*- re_meta = re.compile(r'__(\w+?)__\s*=\s*(.*)') re_doc = re.compile(r'^"""(.+?)"""') def add_default(m): attr_name, attr_value = m.groups() return ((attr_name, attr_value.strip("\"'")),) def add_doc(m): return (('doc', m.groups()[0]),) pats = {re_meta: add_default, re_doc: add_doc} here = os.path.abspath(os.path.dirname(__file__)) with open(os.path.join(here, NAME, '__init__.py')) as meta_fh: meta = {} for line in meta_fh: if line.strip() == '# -eof meta-': break for pattern, handler in pats.items(): m = pattern.match(line.strip()) if m: meta.update(handler(m)) # -*- Installation Requires -*- def strip_comments(l): return l.split('#', 1)[0].strip() def _pip_requirement(req): if req.startswith('-r '): _, path = req.split() return reqs(*path.split('/')) return [req] def _reqs(*f): return [ _pip_requirement(r) for r in ( strip_comments(l) for l in open( os.path.join(os.getcwd(), 'requirements', *f)).readlines() ) if r] def reqs(*f): return [req for subreq in _reqs(*f) for req in subreq] # -*- Long Description -*- if os.path.exists('README.rst'): long_description = codecs.open('README.rst', 'r', 'utf-8').read() else: long_description = 'See http://pypi.python.org/pypi/%s' % (NAME,) # -*- %%% -*- class pytest(setuptools.command.test.test): user_options = [('pytest-args=', 'a', 'Arguments to pass to py.test')] def initialize_options(self): setuptools.command.test.test.initialize_options(self) self.pytest_args = [] def run_tests(self): import pytest sys.exit(pytest.main(self.pytest_args)) setuptools.setup( name=NAME, packages=setuptools.find_packages(exclude=['ez_setup', 't', 't.*']), version=meta['version'], description=meta['doc'], long_description=long_description, keywords='celery django database result backend', author=meta['author'], author_email=meta['contact'], url=meta['homepage'], platforms=['any'], license='BSD', classifiers=classifiers, install_requires=reqs('default.txt'), tests_require=reqs('test.txt') + reqs('test-django.txt'), cmdclass={'test': pytest}, entry_points={ 'celery.result_backends': [ 'django-db = django_celery_results.backends:DatabaseBackend', 'django-cache = django_celery_results.backends:CacheBackend', ], }, zip_safe=False, include_package_data=False, ) django-celery-results-1.0.4/t/000077500000000000000000000000001337257563700162235ustar00rootroot00000000000000django-celery-results-1.0.4/t/__init__.py000066400000000000000000000000001337257563700203220ustar00rootroot00000000000000django-celery-results-1.0.4/t/proj/000077500000000000000000000000001337257563700171755ustar00rootroot00000000000000django-celery-results-1.0.4/t/proj/__init__.py000066400000000000000000000000561337257563700213070ustar00rootroot00000000000000from .celery import app as celery_app # noqa django-celery-results-1.0.4/t/proj/celery.py000066400000000000000000000005641337257563700210370ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals import os from celery import Celery os.environ.setdefault('DJANGO_SETTINGS_MODULE', 't.proj.settings') app = Celery('proj') # Using a string here means the worker doesn't have to serialize # the configuration object. app.config_from_object('django.conf:settings', namespace='CELERY') app.autodiscover_tasks() django-celery-results-1.0.4/t/proj/settings.py000066400000000000000000000061351337257563700214140ustar00rootroot00000000000000""" Django settings for Test project. Generated by 'django-admin startproject' using Django 1.9.1. For more information on this file, see https://docs.djangoproject.com/en/1.9/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.9/ref/settings/ """ from __future__ import absolute_import, unicode_literals import os import sys # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, os.path.abspath(os.path.join(BASE_DIR, os.pardir))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'u($kbs9$irs0)436gbo9%!b&#zyd&70tx!n7!i&fl6qun@z1_l' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_celery_results', ] MIDDLEWARE_CLASSES = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', ] ROOT_URLCONF = 't.proj.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 't.proj.wsgi.application' # Database # https://docs.djangoproject.com/en/1.9/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'OPTIONS': { 'timeout': 1000, }, } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', }, 'dummy': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', }, } # Password validation # https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators django_auth = 'django.contrib.auth.password_validation.' AUTH_PASSWORD_VALIDATORS = [ ] # Internationalization # https://docs.djangoproject.com/en/1.9/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True DJANGO_CELERY_RESULTS_TASK_ID_MAX_LENGTH = 191 # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.9/howto/static-files/ STATIC_URL = '/static/' django-celery-results-1.0.4/t/proj/urls.py000066400000000000000000000002651337257563700205370ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals from django.conf.urls import url from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), ] django-celery-results-1.0.4/t/proj/wsgi.py000066400000000000000000000006741337257563700205270ustar00rootroot00000000000000""" WSGI config for Test project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ """ from __future__ import absolute_import, unicode_literals import os from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "t.proj.settings") application = get_wsgi_application() django-celery-results-1.0.4/t/unit/000077500000000000000000000000001337257563700172025ustar00rootroot00000000000000django-celery-results-1.0.4/t/unit/__init__.py000066400000000000000000000000001337257563700213010ustar00rootroot00000000000000django-celery-results-1.0.4/t/unit/backends/000077500000000000000000000000001337257563700207545ustar00rootroot00000000000000django-celery-results-1.0.4/t/unit/backends/__init__.py000066400000000000000000000000001337257563700230530ustar00rootroot00000000000000django-celery-results-1.0.4/t/unit/backends/test_cache.py000066400000000000000000000056461337257563700234430ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals import pytest import sys from datetime import timedelta from billiard.einfo import ExceptionInfo from celery import result from celery import states from celery import uuid from django_celery_results.backends.cache import CacheBackend class SomeClass(object): def __init__(self, data): self.data = data class test_CacheBackend: def setup(self): self.b = CacheBackend(app=self.app) def test_mark_as_done(self): tid = uuid() assert self.b.get_status(tid) == states.PENDING assert self.b.get_result(tid) is None self.b.mark_as_done(tid, 42) assert self.b.get_status(tid) == states.SUCCESS assert self.b.get_result(tid) == 42 def test_forget(self): tid = uuid() self.b.mark_as_done(tid, {'foo': 'bar'}) assert self.b.get_result(tid).get('foo') == 'bar' self.b.forget(tid) assert tid not in self.b._cache assert self.b.get_result(tid) is None @pytest.mark.usefixtures('depends_on_current_app') def test_save_restore_delete_group(self): group_id = uuid() result_ids = [uuid() for i in range(10)] results = list(map(result.AsyncResult, result_ids)) res = result.GroupResult(group_id, results) res.save(backend=self.b) saved = result.GroupResult.restore(group_id, backend=self.b) assert saved.results == results assert saved.id == group_id saved.delete(backend=self.b) assert result.GroupResult.restore(group_id, backend=self.b) is None def test_is_pickled(self): tid2 = uuid() result = {'foo': 'baz', 'bar': SomeClass(12345)} self.b.mark_as_done(tid2, result) # is serialized properly. rindb = self.b.get_result(tid2) assert rindb.get('foo') == 'baz' assert rindb.get('bar').data == 12345 def test_mark_as_failure(self): einfo = None tid3 = uuid() try: raise KeyError('foo') except KeyError as exception: einfo = ExceptionInfo(sys.exc_info()) self.b.mark_as_failure(tid3, exception, traceback=einfo.traceback) assert self.b.get_status(tid3) == states.FAILURE assert isinstance(self.b.get_result(tid3), KeyError) assert self.b.get_traceback(tid3) == einfo.traceback def test_process_cleanup(self): self.b.process_cleanup() def test_set_expires(self): cb1 = CacheBackend(app=self.app, expires=timedelta(seconds=16)) assert cb1.expires == 16 cb2 = CacheBackend(app=self.app, expires=32) assert cb2.expires == 32 class test_custom_CacheBackend: def test_custom_cache_backend(self): self.app.conf.cache_backend = 'dummy' b = CacheBackend(app=self.app) assert ( b.cache_backend.__class__.__module__ == 'django.core.cache.backends.dummy' # noqa ) django-celery-results-1.0.4/t/unit/backends/test_database.py000066400000000000000000000045101337257563700241310ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals import celery import pytest from celery import uuid from celery import states from django_celery_results.backends.database import DatabaseBackend class SomeClass(object): def __init__(self, data): self.data = data @pytest.mark.django_db() @pytest.mark.usefixtures('depends_on_current_app') class test_DatabaseBackend: @pytest.fixture(autouse=True) def setup_backend(self): self.app.conf.result_serializer = 'json' self.app.conf.result_backend = ( 'django_celery_results.backends:DatabaseBackend') self.b = DatabaseBackend(app=self.app) def test_backend__pickle_serialization(self): self.app.conf.result_serializer = 'pickle' self.app.conf.accept_content = {'pickle', 'json'} self.b = DatabaseBackend(app=self.app) tid2 = uuid() result = {'foo': 'baz', 'bar': SomeClass(12345)} self.b.mark_as_done(tid2, result) # is serialized properly. rindb = self.b.get_result(tid2) assert rindb.get('foo') == 'baz' assert rindb.get('bar').data == 12345 tid3 = uuid() try: raise KeyError('foo') except KeyError as exception: self.b.mark_as_failure(tid3, exception) assert self.b.get_status(tid3) == states.FAILURE assert isinstance(self.b.get_result(tid3), KeyError) def xxx_backend(self): tid = uuid() assert self.b.get_status(tid) == states.PENDING assert self.b.get_result(tid) is None self.b.mark_as_done(tid, 42) assert self.b.get_status(tid) == states.SUCCESS assert self.b.get_result(tid) == 42 tid2 = uuid() try: raise KeyError('foo') except KeyError as exception: self.b.mark_as_failure(tid2, exception) assert self.b.get_status(tid2) == states.FAILURE assert isinstance(self.b.get_result(tid2), KeyError) def test_forget(self): tid = uuid() self.b.mark_as_done(tid, {'foo': 'bar'}) x = self.app.AsyncResult(tid) assert x.result.get('foo') == 'bar' x.forget() if celery.VERSION[0:3] == (3, 1, 10): # bug in 3.1.10 means result did not clear cache after forget. x._cache = None assert x.result is None django-celery-results-1.0.4/t/unit/conftest.py000066400000000000000000000016271337257563700214070ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals import pytest from celery.contrib.pytest import depends_on_current_app from celery.contrib.testing.app import TestApp, Trap __all__ = ['app', 'depends_on_current_app'] @pytest.fixture(scope='session', autouse=True) def setup_default_app_trap(): from celery._state import set_default_app set_default_app(Trap()) @pytest.fixture() def app(celery_app): return celery_app @pytest.fixture(autouse=True) def test_cases_shortcuts(request, app, patching): if request.instance: @app.task def add(x, y): return x + y # IMPORTANT: We set an .app attribute for every test case class. request.instance.app = app request.instance.Celery = TestApp request.instance.add = add request.instance.patching = patching yield if request.instance: request.instance.app = None django-celery-results-1.0.4/t/unit/test_models.py000066400000000000000000000042251337257563700221010ustar00rootroot00000000000000from __future__ import absolute_import, unicode_literals import pytest from datetime import datetime, timedelta from celery import states, uuid from celery.five import text_t from django_celery_results.models import TaskResult from django_celery_results.utils import now @pytest.mark.django_db() @pytest.mark.usefixtures('depends_on_current_app') class test_Models: @pytest.fixture(autouse=True) def setup_app(self, app): self.app = app self.app.conf.result_serializer = 'pickle' self.app.conf.result_backend = ( 'django_celery_results.backends:DatabaseBackend') def create_task_result(self): id = uuid() taskmeta, created = TaskResult.objects.get_or_create(task_id=id) return taskmeta def test_taskmeta(self, ctype='application/json', cenc='utf-8'): m1 = self.create_task_result() m2 = self.create_task_result() m3 = self.create_task_result() assert text_t(m1).startswith('