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

packages = \
['python_redis_orm', 'python_redis_orm.tests']

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

install_requires = \
['pytz>=2021,<2022', 'redis>=3.5.3,<4.0.0']

setup_kwargs = {
    'name': 'python-redis-orm',
    'version': '0.3.1',
    'description': 'Python Redis ORM library that gives redis easy-to-use objects with fields and speeds a development up, inspired by Django ORM',
    'long_description': '# python-redis-orm\n\n## **Python Redis ORM library that gives redis easy-to-use objects with fields and speeds a development up, inspired by Django ORM**\n\n[![Full test](https://github.com/gh0st-work/python_redis_orm/actions/workflows/python-app.yml/badge.svg?event=push)](https://github.com/gh0st-work/python_redis_orm/actions/workflows/python-app.yml)\n\nFor one project, I needed to work with redis, but redis-py provides a minimum level of work with redis. I didn\'t find any Django-like ORM for redis, so I wrote this library, then there will be a port to Django.\n\n### Working with this library, you are expected:\n\n- Fully works in 2021\n- Django-like architecture\n- Easy adaptation to your needs\n- Adequate informational messages and error messages\n- Built-in RedisRoot class that stores specified models, with:\n    - **redis_instance** setting - your redis connection (from redis-py)\n    - **prefix** setting - prefix of this RedisRoot to be stored in redis\n    - **ignore_deserialization_errors** setting - do not raise errors, while deserializing data\n    - **save_consistency** setting - show structure-first data\n    - **economy** setting - to not return full data and save some requests (usually, speeds up your app on 80%)\n- 13 built-in types of fields:\n    - **RedisField** - base class for nesting\n    - **RedisString** - string\n    - **RedisNumber** - int or float\n    - **RedisId** - instances IDs\n    - **RedisBool** - bool\n    - **RedisDecimal** - working accurately with numbers via decimal\n    - **RedisJson** - for data, that can be JSONed\n    - **RedisList** - list\n    - **RedisDict** - dict\n    - **RedisDateTime** - for work with date and time, via python datetime.datetime\n    - **RedisDate** - for work with date, via python datetime.data\n    - **RedisForeignKey** - for link to other instance\n    - **RedisManyToMany** - for links to other instances\n\n- All fields supports:\n    - Automatically serialization\n    - Automatically deserialization\n    - TTL (Time To Live) setting\n    - Default values\n    - Providing functions without call, to call, while need\n    - Allow null values setting\n    - Choices\n    - Filtering (and deep filtering):\n        - **exact** - equality\n        - **iexact** - case-independent equality\n        - **contains** - is filter string in the value string\n        - **icontains** - is filter string case-independent in the value string\n        - **in** - is value in the provided list\n        - **gt** - is value greater\n        - **gte** - is value greater or equals\n        - **lt** - is value less\n        - **lte** - is value less or equals\n        - **startswith** - is string starts with\n        - **istartswith** - is string case-independent starts with\n        - **endswith** - is string ends with\n        - **iendswith** - is string case-independent ends wth\n        - **range** - is value in provided range\n        - **isnull** - is value in ["null", None]\n- Built-in RedisModel class, with:\n    - All fields that you want\n    - TTL (Time To Live)\n- CRUD (Create Read Update Delete), in our variation: save, get, filter, order, update, delete:\n    - `example_instance = ExampleModel(example_field=\'example_data\').save()` - to create an instance and get its data dict\n    - or:\n    - `example_instance = redis_root.create(ExampleModel, example_field=\'example_data\')`\n    - `filtered_example_instances = redis_root.get(ExampleModel, example_field=\'example_data\')` - to get all ExampleModel instances with example_field filter and get its data dict\n    - `ordered_instances = redis_root.order(filtered_example_instances, \'-id\')` - to get ordered filtered_example_instances by id (\'-\' for reverse)\n    - `updated_example_instances = redis_root.update(ExampleModel, ordered_instances, example_field=\'another_example_data\')` - to update all ordered_instances example_field with value \'another_example_data\' and get its data dict\n    - `redis_root.delete(ExampleModel, updated_example_instances)` - to delete updated_example_instances\n\n\n# Installation\n`pip install python-redis-orm`\n\n[Here is PyPI](https://pypi.org/project/python-redis-orm/)\n\nObviously, you need to install and run redis server on your machine, we support v3+ \n\n\n# Usage\n\n1. Create **RedisRoot** with params:\n    - **prefix** (str) - prefix for your redis root\n    - **connection_pool** (redis.ConnectionPool) - redis-py redis.ConnectionPool instance, with decode_responses=True\n    - **ignore_deserialization_errors** (bool) - to ignore deserialization errors or raise exception\n    - **save_consistency** (bool) - to use structure-first data\n    - **economy** (bool) - if True, all update requests will return only instance id \n    - **use_keys** (bool) - to use Redis keys command (uses memory instead of CPU) instead of scan\n2. Create your models\n3. Call **register_models()** on your RedisRoot instance and provide list with your models\n4. Use our CRUD\n\n\n# Example usage\n\nAll features:\n\n[full_test.py](https://github.com/gh0st-work/python_redis_orm/blob/master/python_redis_orm/tests/full_test.py)\n```python\nimport random\nfrom time import sleep\nimport asyncio\n# from python_redis_orm.core import *\n\n\ndef generate_token(chars_count):\n    allowed_chars = \'QWERTYUIOPASDFGHJKLZXCVBNM1234567890\'\n    token = f\'{"".join([random.choice(allowed_chars) for i in range(chars_count)])}\'\n    return token\n\n\ndef generate_token_12_chars():\n    return generate_token(12)\n\n\nclass BotSession(RedisModel):\n    session_token = RedisString(default=generate_token_12_chars)\n    created = RedisDateTime(default=datetime.datetime.now)\n\n\nclass TaskChallenge(RedisModel):\n    bot_session = RedisForeignKey(model=BotSession)\n    task_id = RedisNumber(default=0, null=False)\n    status = RedisString(default=\'in_work\', choices={\n        \'in_work\': \'В работе\',\n        \'completed\': \'Завершён успешно\',\n        \'completed_frozen_points\': \'Завершён успешно, получил поинты в холде\',\n        \'completed_points\': \'Завершён успешно, получил поинты\',\n        \'completed_decommissioning\': \'Завершён успешно, поинты списаны\',\n        \'failed_bot\': \'Зафейлил бот\',\n        \'failed_task_creator\': \'Зафейлил создатель задания\',\n    }, null=False)\n    account_checks_count = RedisNumber(default=0)\n    created = RedisDateTime(default=datetime.datetime.now)\n\n\nclass TtlCheckModel(RedisModel):\n    redis_number_with_ttl = RedisNumber(default=0, null=False)\n\n\nclass MetaTtlCheckModel(RedisModel):\n    redis_number = RedisNumber(default=0, null=False)\n    \n    class Meta:\n        ttl = 5\n\n\nclass DictCheckModel(RedisModel):\n    redis_dict = RedisDict()\n\n\nclass ListCheckModel(RedisModel):\n    redis_list = RedisList()\n\n\ndef clean_db_after_test(connection_pool, prefix):\n    redis_instance = redis.Redis(connection_pool=connection_pool)\n    for key in redis_instance.keys(f\'{prefix}:*\'):\n        redis_instance.delete(key)\n\n\ndef basic_test(connection_pool, prefix):\n    try:\n        redis_root = RedisRoot(\n            prefix=prefix,\n            connection_pool=connection_pool,\n            ignore_deserialization_errors=True\n        )\n        redis_root.register_models([\n            TaskChallenge,\n        ])\n        for i in range(5):\n            TaskChallenge(\n                redis_root=redis_root,\n                status=\'in_work\',\n            ).save()\n        task_challenges_without_keys = redis_root.get(TaskChallenge)\n        task_challenges_with_keys = redis_root.get(TaskChallenge, return_dict=True)\n        have_exception = False\n        if not len(task_challenges_without_keys):\n            have_exception = True\n        if not task_challenges_with_keys:\n            have_exception = True\n        else:\n            if not task_challenges_with_keys.keys():\n                have_exception = True\n            else:\n                if len(list(task_challenges_with_keys.keys())) != len(task_challenges_without_keys):\n                    have_exception = True\n    except BaseException as ex:\n        have_exception = True\n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef auto_reg_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    task_challenge_1 = TaskChallenge(\n        redis_root=redis_root,\n        status=\'in_work\',\n    ).save()\n    try:\n        task_challenges = redis_root.get(TaskChallenge)\n        have_exception = False\n    except BaseException as ex:\n        have_exception = True\n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef no_connection_pool_test(*args, **kwargs):\n    try:\n        redis_root = RedisRoot(\n            ignore_deserialization_errors=True\n        )\n        task_challenge_1 = TaskChallenge(\n            redis_root=redis_root,\n            status=\'in_work\',\n        )\n        task_challenge_1.save()\n        task_challenges = redis_root.get(TaskChallenge)\n        have_exception = False\n        connection_pool = redis.ConnectionPool(\n            host=\'localhost\',\n            port=6379,\n            db=0,\n            decode_responses=True\n        )\n        clean_db_after_test(connection_pool, redis_root.prefix)\n    except BaseException as ex:\n        have_exception = True\n    return have_exception\n\n\ndef choices_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    task_challenge_1 = TaskChallenge(\n        redis_root=redis_root,\n        status=\'bruh\',\n    )\n    try:\n        task_challenge_1.save()\n        task_challenges = redis_root.get(TaskChallenge)\n        have_exception = True\n    except BaseException as ex:\n        have_exception = False\n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef order_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    for i in range(3):\n        TaskChallenge(\n            redis_root=redis_root\n        ).save()\n    have_exception = True\n    try:\n        task_challenges = redis_root.get(TaskChallenge)\n        first_task_challenge = redis_root.order(task_challenges, \'id\')[0]\n        last_task_challenge = redis_root.order(task_challenges, \'-id\')[0]\n        if first_task_challenge[\'id\'] == 1 and last_task_challenge[\'id\'] == len(task_challenges):\n            have_exception = False\n    except BaseException as ex:\n        pass\n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef filter_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    have_exception = True\n    try:\n        same_tokens_count = 2\n        random_tokens_count = 8\n        same_token = generate_token(50)\n        random_tokens = [generate_token(50) for i in range(random_tokens_count)]\n        for i in range(same_tokens_count):\n            BotSession(redis_root, session_token=same_token).save()\n        for random_token in random_tokens:\n            BotSession(redis_root, session_token=random_token).save()\n        task_challenges_with_same_token = redis_root.get(BotSession, session_token=same_token)\n        if len(task_challenges_with_same_token) == same_tokens_count:\n            have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef update_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    have_exception = True\n    try:\n        bot_session_1 = BotSession(redis_root, session_token=\'123\').save()\n        bot_session_1_id = bot_session_1[\'id\']\n        redis_root.update(BotSession, bot_session_1, session_token=\'234\')\n        bot_sessions_filtered = redis_root.get(BotSession, id=bot_session_1_id)\n        if len(bot_sessions_filtered) == 1:\n            bot_session_1_new = bot_sessions_filtered[0]\n            if \'session_token\' in bot_session_1_new.keys():\n                if bot_session_1_new[\'session_token\'] == \'234\':\n                    have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef functions_like_defaults_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    have_exception = False\n    try:\n        bot_session_1 = BotSession(redis_root).save()\n        bot_session_2 = BotSession(redis_root).save()\n        if bot_session_1.session_token == bot_session_2.session_token:\n            have_exception = True\n    except BaseException as ex:\n        pass\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef redis_foreign_key_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    have_exception = True\n    try:\n        bot_session_1 = BotSession(\n            redis_root=redis_root,\n        ).save()\n        task_challenge_1 = TaskChallenge(\n            redis_root=redis_root,\n            bot_session=bot_session_1\n        ).save()\n        bot_sessions = redis_root.get(BotSession)\n        bot_session = redis_root.order(bot_sessions, \'-id\')[0]\n        task_challenges = redis_root.get(TaskChallenge)\n        task_challenge = redis_root.order(task_challenges, \'-id\')[0]\n        if type(task_challenge[\'bot_session\']) == dict:\n            if task_challenge[\'bot_session\'] == bot_session:\n                have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef delete_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    have_exception = True\n    try:\n        bot_session_1 = BotSession(\n            redis_root=redis_root,\n        ).save()\n        task_challenge_1 = TaskChallenge(\n            redis_root=redis_root,\n            bot_session=bot_session_1\n        ).save()\n        redis_root.delete(BotSession, bot_session_1)\n        redis_root.delete(TaskChallenge, task_challenge_1)\n        bot_sessions = redis_root.get(BotSession)\n        task_challenges = redis_root.get(TaskChallenge)\n        if len(bot_sessions) == 0 and len(task_challenges) == 0:\n            have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef save_consistency_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True,\n        save_consistency=True,\n    )\n    have_exception = True\n    try:\n        ttl_check_model_1 = TtlCheckModel(\n            redis_root=redis_root,\n        ).save()\n        ttl_check_models = redis_root.get(TtlCheckModel)\n        if len(ttl_check_models):\n            ttl_check_model = ttl_check_models[0]\n            if \'redis_number_with_ttl\' in ttl_check_model.keys():\n                sleep(6)\n                ttl_check_models = redis_root.get(TtlCheckModel)\n                if len(ttl_check_models):\n                    ttl_check_model = ttl_check_models[0]\n                    if \'redis_number_with_ttl\' in ttl_check_model.keys():  # because consistency is saved\n                        have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef meta_ttl_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True,\n    )\n    have_exception = True\n    try:\n        meta_ttl_check_model_1 = MetaTtlCheckModel(\n            redis_root=redis_root,\n        ).save()\n        meta_ttl_check_models = redis_root.get(MetaTtlCheckModel)\n        if len(meta_ttl_check_models):\n            meta_ttl_check_model = meta_ttl_check_models[0]\n            if \'redis_number\' in meta_ttl_check_model.keys():\n                sleep(6)\n                meta_ttl_check_models = redis_root.get(MetaTtlCheckModel)\n                if not len(meta_ttl_check_models):\n                    have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef economy_test(connection_pool, prefix):\n    have_exception = True\n    try:\n        \n        redis_root = RedisRoot(\n            prefix=prefix,\n            connection_pool=connection_pool,\n            ignore_deserialization_errors=True,\n            economy=True\n        )\n        started_in_economy = datetime.datetime.now()\n        tests_count = 100\n        for i in range(tests_count):\n            task_challenge_1 = TaskChallenge(\n                redis_root=redis_root,\n                status=\'in_work\',\n            ).save()\n            redis_root.update(TaskChallenge, task_challenge_1, account_checks_count=1)\n        ended_in_economy = datetime.datetime.now()\n        economy_time = (ended_in_economy - started_in_economy).total_seconds()\n        clean_db_after_test(connection_pool, prefix)\n        \n        redis_root = RedisRoot(\n            prefix=prefix,\n            connection_pool=connection_pool,\n            ignore_deserialization_errors=True,\n            economy=False\n        )\n        started_in_no_economy = datetime.datetime.now()\n        for i in range(tests_count):\n            task_challenge_1 = TaskChallenge(\n                redis_root=redis_root,\n                status=\'in_work\',\n            ).save()\n            redis_root.update(TaskChallenge, task_challenge_1, account_checks_count=1)\n        ended_in_no_economy = datetime.datetime.now()\n        no_economy_time = (ended_in_no_economy - started_in_no_economy).total_seconds()\n        clean_db_after_test(connection_pool, prefix)\n        economy_percent = round((no_economy_time / economy_time - 1) * 100, 2)\n        economy_symbol = (\'+\' if economy_percent > 0 else \'\')\n        print(f\'Economy gives {economy_symbol}{economy_percent}% efficiency\')\n        if economy_symbol == \'+\':\n            have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef use_keys_test(connection_pool, prefix):\n    have_exception = True\n    try:\n        \n        redis_root = RedisRoot(\n            prefix=prefix,\n            connection_pool=connection_pool,\n            ignore_deserialization_errors=True,\n            use_keys=True\n        )\n        started_in_keys = datetime.datetime.now()\n        tests_count = 100\n        for i in range(tests_count):\n            task_challenge_1 = TaskChallenge(\n                redis_root=redis_root,\n                status=\'in_work\',\n            ).save()\n            redis_root.update(TaskChallenge, task_challenge_1, account_checks_count=1)\n        ended_in_keys = datetime.datetime.now()\n        keys_time = (ended_in_keys - started_in_keys).total_seconds()\n        clean_db_after_test(connection_pool, prefix)\n        \n        redis_root = RedisRoot(\n            prefix=prefix,\n            connection_pool=connection_pool,\n            ignore_deserialization_errors=True,\n            use_keys=False\n        )\n        started_in_no_keys = datetime.datetime.now()\n        for i in range(tests_count):\n            task_challenge_1 = TaskChallenge(\n                redis_root=redis_root,\n                status=\'in_work\',\n            ).save()\n            redis_root.update(TaskChallenge, task_challenge_1, account_checks_count=1)\n        ended_in_no_keys = datetime.datetime.now()\n        no_keys_time = (ended_in_no_keys - started_in_no_keys).total_seconds()\n        clean_db_after_test(connection_pool, prefix)\n        keys_percent = round((no_keys_time / keys_time - 1) * 100, 2)\n        keys_symbol = (\'+\' if keys_percent > 0 else \'\')\n        print(f\'Keys usage gives {keys_symbol}{keys_percent}% efficiency\')\n        have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef dict_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    have_exception = True\n    try:\n        some_dict = {\n            \'age\': 19,\n            \'weed\': True\n        }\n        DictCheckModel(\n            redis_root=redis_root,\n            redis_dict=some_dict\n        ).save()\n        dict_check_model_instance = redis_root.get(DictCheckModel)[0]\n        if \'redis_dict\' in dict_check_model_instance.keys():\n            if dict_check_model_instance[\'redis_dict\'] == some_dict:\n                have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef list_test(connection_pool, prefix):\n    redis_root = RedisRoot(\n        prefix=prefix,\n        connection_pool=connection_pool,\n        ignore_deserialization_errors=True\n    )\n    have_exception = True\n    try:\n        some_list = [5, 9, \'s\', 4.5, False]\n        ListCheckModel(\n            redis_root=redis_root,\n            redis_list=some_list\n        ).save()\n        list_check_model_instance = redis_root.get(ListCheckModel)[0]\n        if \'redis_list\' in list_check_model_instance.keys():\n            if list_check_model_instance[\'redis_list\'] == some_list:\n                have_exception = False\n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef async_test(connection_pool, prefix):\n    have_exception = True\n    try:\n        \n        async def async_task(data_count, use_async=True):\n            redis_roots = []\n            connection_pool = redis.ConnectionPool(host=\'localhost\', port=6379, db=0, decode_responses=True)\n            for i in range(data_count):\n                redis_root = RedisRoot(\n                    prefix=prefix,\n                    connection_pool=connection_pool,\n                    ignore_deserialization_errors=True\n                )\n                redis_roots.append(redis_root)\n            \n            async def create_list(redis_roots, redis_root_index, list_length):\n                some_list = [random.choice(\'ABCDEF\') for i in range(list_length)]\n                redis_root = redis_roots[redis_root_index]\n                list_check_model_instance = ListCheckModel(\n                    redis_root=redis_root,\n                    redis_list=some_list\n                ).save()\n                return {\n                    \'list\': some_list,\n                    \'id\': list_check_model_instance[\'id\']\n                }\n            \n            async def get_object_existence(redis_roots, redis_root_index, lists_with_ids):\n                exists = False\n                redis_root = redis_roots[redis_root_index]\n                objects = redis_root.get(ListCheckModel, redis_list=lists_with_ids[\'list\'])\n                if objects:\n                    if len(objects) == 1:\n                        exists = objects[0][\'id\'] == lists_with_ids[\'id\']\n                return exists\n            \n            async def update_list(redis_roots, redis_root_index, lists_with_ids):\n                result = False\n                redis_root = redis_roots[redis_root_index]\n                objects = redis_root.get(ListCheckModel, redis_list=lists_with_ids[\'list\'])\n                if objects:\n                    if len(objects) == 1:\n                        obj = objects[0]\n                        new_list = deepcopy(lists_with_ids[\'list\'])\n                        new_list.append(\'check_value\')\n                        updated_obj = redis_root.update(ListCheckModel, obj, redis_list=new_list)\n                        updated_objects = redis_root.get(ListCheckModel, redis_list=new_list)\n                        if updated_objects:\n                            if len(updated_objects) == 1:\n                                result = updated_objects[0][\'id\'] == lists_with_ids[\'id\']\n                return result\n            \n            async def delete_list(redis_roots, redis_root_index, id):\n                result = False\n                redis_root = redis_roots[redis_root_index]\n                objects = redis_root.get(ListCheckModel, id=id)\n                if objects:\n                    if len(objects) == 1:\n                        obj = objects[0]\n                        redis_root.delete(ListCheckModel, obj)\n                        objects = redis_root.get(ListCheckModel, id=id)\n                        if not objects:\n                            result = True\n                return result\n            \n            async def create_lists(lists_count, use_async=True):\n                if use_async:\n                    async_create_lists_tasks = [\n                        create_list(redis_roots, i, i + 100)\n                        for i in range(lists_count)\n                    ]\n                    list_of_lists_with_ids = await asyncio.gather(*async_create_lists_tasks)\n                else:\n                    list_of_lists_with_ids = [\n                        await create_list(redis_roots, i, i + 100)\n                        for i in range(lists_count)\n                    ]\n                return list_of_lists_with_ids\n            \n            async def get_objects_existence(list_of_lists_with_ids, use_async=True):\n                if use_async:\n                    async_get_object_by_list_tasks = [\n                        get_object_existence(redis_roots, i, lists_with_ids)\n                        for i, lists_with_ids in enumerate(list_of_lists_with_ids)\n                    ]\n                    list_of_results = await asyncio.gather(*async_get_object_by_list_tasks)\n                else:\n                    list_of_results = [\n                        await get_object_existence(redis_roots, i, lists_with_ids)\n                        for i, lists_with_ids in enumerate(list_of_lists_with_ids)\n                    ]\n                return list_of_results\n            \n            async def update_lists(list_of_lists_with_ids, use_async=True):\n                if use_async:\n                    async_update_list_tasks = [\n                        update_list(redis_roots, i, lists_with_ids)\n                        for i, lists_with_ids in enumerate(list_of_lists_with_ids)\n                    ]\n                    list_of_results = await asyncio.gather(*async_update_list_tasks)\n                else:\n                    list_of_results = [\n                        await update_list(redis_roots, i, lists_with_ids)\n                        for i, lists_with_ids in enumerate(list_of_lists_with_ids)\n                    ]\n                return list_of_results\n            \n            async def delete_lists(list_of_lists_with_ids, use_async=True):\n                if use_async:\n                    async_delete_list_tasks = [\n                        delete_list(redis_roots, i, lists_with_ids[\'id\'])\n                        for i, lists_with_ids in enumerate(list_of_lists_with_ids)\n                    ]\n                    list_of_results = await asyncio.gather(*async_delete_list_tasks)\n                else:\n                    list_of_results = [\n                        await delete_list(redis_roots, i, lists_with_ids)\n                        for i, lists_with_ids in enumerate(list_of_lists_with_ids)\n                    ]\n                return list_of_results\n            \n            list_of_lists_with_ids = await create_lists(data_count, use_async)\n            list_of_results = await get_objects_existence(list_of_lists_with_ids, use_async)\n            if all(list_of_results):\n                list_of_results = await update_lists(list_of_lists_with_ids, use_async)\n                if all(list_of_results):\n                    list_of_results = await delete_lists(list_of_lists_with_ids, use_async)\n            return all(list_of_results)\n        \n        data_count = 10\n        async_started_in = datetime.datetime.now()\n        async_result = asyncio.run(async_task(data_count))\n        async_ended_in = datetime.datetime.now()\n        async_time = (async_ended_in - async_started_in).total_seconds()\n        have_exception = not async_result\n        sync_started_in = datetime.datetime.now()\n        sync_result = asyncio.run(async_task(data_count, False))\n        sync_ended_in = datetime.datetime.now()\n        sync_time = (sync_ended_in - sync_started_in).total_seconds()\n        \n        async_percent = round((async_time / sync_time - 1) * 100, 2)\n        async_symbol = (\'+\' if async_percent > 0 else \'\')\n        print(f\'Async gives {async_symbol}{async_percent}% efficiency\')\n    \n    except BaseException as ex:\n        print(ex)\n    \n    clean_db_after_test(connection_pool, prefix)\n    return have_exception\n\n\ndef run_tests():\n    connection_pool = redis.ConnectionPool(\n        host=\'localhost\',\n        port=6379,\n        db=0,\n        decode_responses=True\n    )\n    tests = [\n        basic_test,\n        auto_reg_test,\n        no_connection_pool_test,\n        choices_test,\n        order_test,\n        filter_test,\n        functions_like_defaults_test,\n        redis_foreign_key_test,\n        update_test,\n        delete_test,\n        save_consistency_test,\n        meta_ttl_test,\n        economy_test,\n        use_keys_test,\n        list_test,\n        dict_test,\n        async_test,\n    ]\n    results = []\n    started_in = datetime.datetime.now()\n    print(\'STARTING TESTS\\n\')\n    for i, test in enumerate(tests):\n        print(f\'Starting {int(i + 1)} test: {test.__name__.replace("_", " ")}\')\n        test_started_in = datetime.datetime.now()\n        result = not test(connection_pool, test.__name__)\n        test_ended_in = datetime.datetime.now()\n        test_time = (test_ended_in - test_started_in).total_seconds()\n        print(f\'{result = } / {test_time}s\\n\')\n        results.append(result)\n    ended_in = datetime.datetime.now()\n    time = (ended_in - started_in).total_seconds()\n    success_message = \'SUCCESS\' if all(results) else \'FAILED\'\n    print(\'\\n\'\n          f\'{success_message}!\\n\')\n    results_success_count = 0\n    for i, result in enumerate(results):\n        result_message = \'SUCCESS\' if result else \'FAILED\'\n        print(f\'Test {(i + 1)}/{len(results)}: {result_message} ({tests[i].__name__.replace("_", " ")})\')\n        if result:\n            results_success_count += 1\n    print(f\'\\n\'\n          f\'{results_success_count} / {len(results)} tests ran successfully\\n\'\n          f\'All tests completed in {time}s\\n\')\n\n\nif __name__ == \'__main__\':\n    run_tests()\n\n```',
    'author': 'Anton Nechaev',
    'author_email': 'antonnechaev990@gmail.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/gh0st-work/python_redis_orm',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.6,<4.0',
}


setup(**setup_kwargs)
