# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['django_partisan',
 'django_partisan.config',
 'django_partisan.management',
 'django_partisan.management.commands',
 'django_partisan.migrations',
 'django_partisan.registry',
 'django_partisan.settings',
 'django_partisan.tests',
 'django_partisan.utils']

package_data = \
{'': ['*']}

install_requires = \
['Django>=1.9,<4',
 'psycopg2-binary==2.8.2',
 'pydantic>=1.6.1,<2.0.0',
 'pytz==2019.1',
 'setproctitle==1.1.10',
 'sqlparse==0.3.0']

setup_kwargs = {
    'name': 'django-partisan',
    'version': '1.6.1',
    'description': 'Framework to allow creating background tasks in django without MQ',
    'long_description': "[![codecov](https://codecov.io/gh/ilyachch/django-partisan/branch/master/graph/badge.svg)](https://codecov.io/gh/ilyachch/django-partisan)\n\n[![PyPI version](https://badge.fury.io/py/django-partisan.svg)](https://pypi.org/project/django-partisan/)\n[![Downloads](https://pepy.tech/badge/django-partisan)](https://pepy.tech/project/django-partisan)\n[![PyPI pyversions](https://img.shields.io/pypi/pyversions/django-partisan.svg)](https://pypi.org/project/django-partisan/)\n\n# django-backgroud-tasks-framework\nFramework to allow creating background tasks in django without MQ\n\n# Usage\n\n## Requirements\nPython versions: 3.6+\n\nDjango versions: 1.9+\n\n## General usage\nInstall app with:\n```\n$ pip install django-partisan\n```\n\nAdd it to your `INSTALLED_APPS`\n\nRun migrate command:\n```\n$ python manage.py migrate\n```\n\nWrite your task and register it:\n```python\n# partisan_tasks.py\nfrom django_partisan.processor import BaseTaskProcessor\nfrom django_partisan import registry\n\n\n@registry.register\nclass MyProcessor(BaseTaskProcessor):\n    PRIORITY = 5  # Optional, by default 10\n    UNIQUE_FOR_PARAMS = True  # Optional, by default True\n\n    def run(self):\n        do_something(*self.args, **self.kwargs)\n\n```\n\n> Please note, that all tasks should be in module `partisan_tasks.py` in root of your application. \n> You can write them there or just import from your preferable place. \n> It's needed to make autodiscover available\n\nAnd then put this task to queue:\n```python\nfrom partisan_tasks import MyProcessor\n\n\ndef do_something_and_postpone_task(*args, **kwargs):\n    MyProcessor(args, kwargs).delay()\n\n```\n\nTo start tasks processing you should start workers:\n\n```\n$ python manage.py start_partisan\n``` \n\n## Advanced\n\n### Postpone tasks\n\nYou can postpone task by raising special exception `PostponeTask`:\n\nAlso you can manage posponing delay by setting `DEFAULT_POSTPONE_DELAY_SECONDS` \nin your `settings.py` (by default - 5 seconds) or pass it to `PostponeTask`:\n```python\nfrom django_partisan.exceptions import PostponeTask\n\ndef do_something():\n    raise PostponeTask(300)  # 5 minutes\n\n```\nIt's possible to configure postponing rules for every single processor. \nJust define `POSTPONE_CONFIG` in your processor class as instance of `PostponeConfig`:\n```python\nfrom django_partisan.config.processor_configs import PostponeConfig\nfrom django_partisan.processor import BaseTaskProcessor\nfrom django_partisan import registry\nfrom django_partisan.exceptions import PostponeTask\n\n@registry.register\nclass MyProcessor(BaseTaskProcessor):\n    POSTPONE_CONFIG = PostponeConfig(\n        max_postpones=5\n    )\n    def run(self):\n        do_something(*self.args, **self.kwargs)\n\ndef do_something(*args, **kwargs):\n    raise PostponeTask(300)  # 5 minutes\n\n```\n\nWith such configuration the task will be postponed for 5 times and, if it will be tried to be postponed one more time,\n`MaxPostponesReached` exception will be rised.\n\nAlso you can globally set maximum postpones in settings with `DEFAULT_POSTPONES_COUNT` in `settings.py` (by default - 15).\nIt was made to make task processing finite. If you want to make your task be processed forever, until they would be finished,\nyou can set it to `None`, but it is dangerous.\n\n### Errors handling\nYou can set for task processor special config, that is managing, how to handle errors:\n```python\nfrom django_partisan.config.processor_configs import ErrorsHandleConfig\nfrom django_partisan.config import const\nfrom django_partisan.processor import BaseTaskProcessor\nfrom django_partisan import registry\n\n@registry.register\nclass MyProcessor(BaseTaskProcessor):\n    RETRY_ON_ERROR_CONFIG = ErrorsHandleConfig(\n        retry_on_errors=[TimeoutError,], \n        retries_count=3, retry_pause=3,\n        retry_pause_strategy=const.DELAY_STRATEGY_INCREMENTAL\n    )\n    def run(self):\n        do_something(*self.args, **self.kwargs)\n\ndef do_something(*args, **kwargs):\n    pass\n``` \n\nWith such configuration, the task will be redelayed if `TimeoutError` will be rised for 3 times with 3 sec pause.\n\n`ErrorsHandleConfig` params:\n * `retry_on_errors` - list of exceptions;\n * `retries_count` - positive int. Task will be redelayed for `retries_count` times if any of errors will be rised;\n * `retry_pause` - positive int. Time in seconds to wait before renew task processing;\n * `retry_pause_strategy` - one of options: `django_partisan.config.const.DELAY_STRATEGY_INCREMENTAL`, \n `django_partisan.config.const.DELAY_STRATEGY_CONSTANT`. By default - `DELAY_STRATEGY_CONSTANT`. If is set to `DELAY_STRATEGY_CONSTANT` - \n on error task will be redelayed with `retry_pause` seconds gap every time. If is set to `DELAY_STRATEGY_INCREMENTAL` - \n every next time task will be redelayed with increasing by `retry_pause` time gap \n (with `retry_pause = 3`, and `retries_count = 3` it will redelay for 3, 6, 9 seconds and then fail). \n\n\n### Separate by queues\n\nIf you want to separate your tasks into separate queues, you need to define queues in setting as a dict, \nwhere key is a queue name, and value - dict of settings for this queue:\n\n```python\nPARTISAN_CONFIG = {\n    'default': {  # 'default' - is registered name for default queue, it will be exist anyway\n        # ...\n    },\n    'another_queue': {\n        # ...\n    }\n}\n```\n\nAlso you need to set queue for your tasks:\n```python\nfrom django_partisan.processor import BaseTaskProcessor\nfrom django_partisan import registry\n\n\n@registry.register\nclass MyProcessor(BaseTaskProcessor):\n    QUEUE_NAME = 'another_queue'\n    def run(self):\n        do_something(*self.args, **self.kwargs)\n\ndef do_something(*args, **kwargs):\n    pass\n\n```\n\nAfter it you can run partisan to run this queue:\n\n```bash\n$ python manage.py start_partisan --queue_name another_queue\n```\n\nNote:\n* If you will not set `QUEUE_NAME` for `Processor`, it will be `default`;\n* If you will run this command without specifiing `queue_name` it will serve `default` queue;\n* If you will not set settings for queues, the settings will be default for `default` queue;\n\n# Settings\nIn your project settings you can define such params as:\n\n* `MIN_QUEUE_SIZE` `(int)` - if number of tasks in queue will reach this amount, \nqueue manager will add new tasks (default = 2);\n* `MAX_QUEUE_SIZE` `(int)` - queue manager will fill queue up to this count of tasks (default = 10);\n* `CHECKS_BEFORE_CLEANUP` `(int)` - number of gatherings new tasks before cleaning database connections (default = 50);\n* `WORKERS_COUNT` `(int)` - number of workers, that would be instanced by workers manager (default = number of cores);\n* `SLEEP_DELAY_SECONDS` `(int)` - time to sleep between queue checks (default = 2);\n* `TASKS_PER_WORKER_INSTANCE` `(Optional[int])` - if is set, the worker will be restarted after this count of \ntasks processed (default = None);\n* `DELETE_TASKS_ON_COMPLETE` `(bool)` - if True, task object will be deleted from db, if it successfully processed;\n\nBut it will be better, if you'll make settings as a dict:\n```python\nPARTISAN_CONFIG = {\n    'default': {  # 'default' - is registered name for default queue, it will be exist anyway\n        'MIN_QUEUE_SIZE':10,\n        'MAX_QUEUE_SIZE':20,\n        'CHECKS_BEFORE_CLEANUP':50,\n        'WORKERS_COUNT':5,\n        'SLEEP_DELAY_SECONDS':5,\n        'TASKS_PER_WORKER_INSTANCE': 50,\n        'DELETE_TASKS_ON_COMPLETE':False,\n        'DEFAULT_POSTPONE_DELAY_SECONDS':5,\n        'DEFAULT_POSTPONES_COUNT':None,\n    }\n}\n```\n\nIt is possible to override some of this settings by cli args for `start_partisan`:\n* `--min_queue_size` - `MIN_QUEUE_SIZE`;\n* `--max_queue_size` - `MAX_QUEUE_SIZE`;\n* `--checks_before_cleanup` - `CHECKS_BEFORE_CLEANUP`;\n* `--workers_count` - `WORKERS_COUNT`;\n* `--sleep_delay_seconds` - `SLEEP_DELAY_SECONDS`;\n\n# API\n* `BaseTaskProcessor`\n\n    * `BaseTaskProcessor.delay(*, priority: int = 0, execute_after: datetime = None)` accept only keyword arguments. \n    It is possible to override priority of task and set execution datetime (task will not be processed before this time);\n    * `BaseTaskProcessor.PRIORITY` - property of TaskProcessor. The lower the number, the higher the priority. \n    Tasks with higher priority would be taken for processing first;\n    * `BaseTaskProcessor.UNIQUE_FOR_PARAMS` - boolean property of TaskProcessor. If `True`, it will ignore for \n    task adding if task with exactly same args and kwargs is already in queue;\n    \n    \n# Some behavior features\n* This tool works only with PostgreSQL, as it supports `JSONField`\n* After Manager process got a kill signal, it will wait for workers to finish their jobs, and gracefully shut down them;\n* If for some reason Manager process was killed without gracefull shut down, \nafter restart it will take for work tasks, that were not finished and only after them it will take all other tasks;\n\n# Known issues\n* This tool can be launched on MacOS, but it's strongly recomened to use it only with Linux as multiprocessing Queue \nnot fully compatible with MacOS. Use it on MacOS only for development and debugging.\n* After calling SIG_TERM, tool can cause some exceptions. It does't break anything and I'm trying to fix it. \nDon't worry about it\n\n# Contributing \nIf you experience any problems with usage of this package, \nfeel free to open an issue or pull-request\n\nPull-request requirements:\n* Code style according to PEP-8 (use `make black` for it);\n* 100% test coverage (use `make coverage`);\n* Typing (use `make check_mypy`;\n* Version bump (you can use `make major_release`, `make minor_release`, `make patch_release` for it)\n\nAll this checks are in CI\n",
    'author': 'Ilya Chichak',
    'author_email': 'ilyachch@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/ilyachch/django-partisan',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.6,<4.0',
}


setup(**setup_kwargs)
