summaryrefslogtreecommitdiff
path: root/python-fast-bitrix24.spec
diff options
context:
space:
mode:
Diffstat (limited to 'python-fast-bitrix24.spec')
-rw-r--r--python-fast-bitrix24.spec914
1 files changed, 914 insertions, 0 deletions
diff --git a/python-fast-bitrix24.spec b/python-fast-bitrix24.spec
new file mode 100644
index 0000000..4465847
--- /dev/null
+++ b/python-fast-bitrix24.spec
@@ -0,0 +1,914 @@
+%global _empty_manifest_terminate_build 0
+Name: python-fast-bitrix24
+Version: 1.5.16
+Release: 1
+Summary: API wrapper для быстрого получения данных от Битрикс24 через REST API. Параллельные запросы к серверу, упаковка запросов в батчи, контроль скорости запросов, есть синхронный и асинхронный клиенты.
+License: MIT
+URL: https://github.com/leshchenko1979/fast_bitrix24
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/1c/f1/62322143189c60ca416cf6a8292260b1db12fc29fa43382e21d94a0c6424/fast_bitrix24-1.5.16.tar.gz
+BuildArch: noarch
+
+Requires: python3-aiohttp
+Requires: python3-tqdm
+Requires: python3-more-itertools
+Requires: python3-icontract
+Requires: python3-beartype
+
+%description
+# fast_bitrix24
+API wrapper для Питона для быстрого получения данных от Битрикс24 через REST API.
+
+[![Статистика загрузок](https://img.shields.io/pypi/dm/fast-bitrix24.svg)](https://pypistats.org/packages/fast-bitrix24)
+![Статистика тестов](https://github.com/leshchenko1979/fast_bitrix24/workflows/tests/badge.svg)
+[![codecov](https://codecov.io/gh/leshchenko1979/fast_bitrix24/branch/master/graph/badge.svg?token=UEQ3KITRSX)](https://codecov.io/gh/leshchenko1979/fast_bitrix24)
+[![Sourcery](https://img.shields.io/badge/Sourcery-enabled-brightgreen)](https://sourcery.ai)
+[![CodeFactor](https://www.codefactor.io/repository/github/leshchenko1979/fast_bitrix24/badge)](https://www.codefactor.io/repository/github/leshchenko1979/fast_bitrix24)
+
+- [Основная функциональность](#Основная-функциональность)
+- [Начало работы](#Начало-работы)
+- [Примеры использования](#Примеры-использования)
+- [Как это работает](#Как-это-работает)
+- [Советы и подсказки](#Советы-и-подсказки)
+- [Как связаться с автором](#Как-связаться-с-автором)
+- [Подробный справочник по API](API.md)
+
+## Основная функциональность
+
+### Высокая скорость обмена данными
+
+![Тест скорости](speed_test.gif)
+
+- На больших списках скорость обмена данными с сервером достигает тысяч элементов в секунду.
+- Автоматическая упаковка запросов в батчи сокращает количество требуемых запросов к серверу и ускоряет обмен данными.
+- Батчи отправляются на сервер не последовательно, а параллельно.
+- Продвинутые стратегии работы с постраничным доступом ускоряют выгрузку на порядки (см. [результаты тестов](https://github.com/leshchenko1979/fast_bitrix24/discussions/113)).
+
+### Избежание отказов сервера
+- Автоматический autothrottling - если сервер возвращает ошибки, скорость автоматически понижается.
+- Если сервер для сложных запросов начинает возвращать ошибки, можно в одну строку понизить скорость запроосов.
+
+### Удобство кода
+- Высокоуровневые списочные методы для сокращения количества необходимого кода. Большинство операций занимают только одну строку кода. Обработка параллельных запросов, упаковка запросов в батчи и многое другое убрано "под капот".
+- Позволяет задавать параметры запроса именно в таком виде, как они приведены в [документации к Bitrix24 REST API](https://dev.1c-bitrix.ru/rest_help/index.php). Параметры проверяются на корректность для облегчения отладки.
+- Выполнение запросов автоматически сопровождается прогресс-баром из пакета `tqdm`, иллюстрирующим не только количество обработанных элементов, но и прошедшее и оставшееся время выполнения запроса.
+
+### Синхронный и асинхронный клиенты
+- Наличие асинхронного клиента позволяет использовать библиотеку для написания веб-приложений (например, телеграм-ботов).
+
+### Нас используют
+- [Яндекс](https://github.com/leshchenko1979/fast_bitrix24/issues/159#issuecomment-1104539717)
+
+## Начало работы
+Установите модуль через `pip`:
+```shell
+pip install fast-bitrix24
+```
+
+Далее в python:
+
+```python
+from fast_bitrix24 import Bitrix
+
+# замените на ваш вебхук для доступа к Bitrix24
+webhook = "https://your_domain.bitrix24.ru/rest/1/your_code/"
+b = Bitrix(webhook)
+```
+
+Методы полученного объекта `b` в дальнейшем используются для взаимодействия с сервером Битрикс24.
+
+## Примеры использования
+
+### `get_all()`
+
+Чтобы получить полностью список сущностей, используйте метод [`get_all()`](API.md#метод-getallself-method-str-params-dict--none---list--dict):
+
+```python
+# список лидов
+leads = b.get_all('crm.lead.list')
+```
+
+Метод [`get_all()`](API.md#метод-getallself-method-str-params-dict--none---list--dict) возвращает список, где каждый элемент списка является словарем, описывающим одну сущность из запрошенного списка.
+
+Вы также можете использовать параметр `params`, чтобы кастомизировать запрос:
+
+```python
+# список сделок в работе, включая пользовательские поля
+deals = b.get_all(
+ 'crm.deal.list',
+ params={
+ 'select': ['*', 'UF_*'],
+ 'filter': {'CLOSED': 'N'}
+})
+```
+
+Если у вас есть необходимость быстро выгрузить большие объемы информации (значения всех полей в длинных списках - в 20+ тыс. элементов), то используйте метод [`list_and_get()`](https://github.com/leshchenko1979/fast_bitrix24#метод-list_and_getself-method_branch-str---dict).
+
+### `get_by_ID()`
+Если у вас есть список ID сущностей, то вы можете получить их свойства при помощи метода [`get_by_ID()`](API.md#метод-getbyidself-method-str-idlist-iterable-idfieldname-str--id-params-dict--none---dict)
+и использовании методов вида `*.get`:
+
+```python
+'''
+получим список всех контактов, привязанных к сделкам, в виде
+{
+ ID_сделки_1: [контакт_1, контакт_2, ...],
+ ID_сделки_2: [контакт_1, контакт_2, ...],
+ ...
+}
+'''
+
+contacts = b.get_by_ID(
+ 'crm.deal.contact.items.get',
+ [d['ID'] for d in deals])
+```
+Метод [`get_by_ID()`](API.md#метод-getbyidself-method-str-idlist-iterable-idfieldname-str--id-params-dict--none---dict) возвращает словарь с элементами вида `ID: result`, где `result` - ответ сервера относительно этого `ID`.
+
+### `call()`
+Чтобы создавать, изменять или удалять список сущностей, используйте метод [`call()`](API.md#метод-callself-method-str-items-dict--iterabledict--any--none--raw-bool--false---dict--listdict--any):
+
+```python
+# вставим в начало названия всех сделок их ID
+tasks = [
+ {
+ 'ID': d['ID'],
+ 'fields': {
+ 'TITLE': f'{d["ID"]} - {d["TITLE"]}'
+ }
+ }
+ for d in deals
+]
+
+b.call('crm.deal.update', tasks)
+```
+Метод [`call()`](API.md#метод-callself-method-str-items-dict--iterabledict--any--none--raw-bool--false---dict--listdict--any) возвращает список ответов сервера по каждому элементу переданного списка.
+
+### call(raw=True)
+Вызов `call` с парамтером `raw=True` отправляет на сервер переданные ему параметры в оригинальном, необработанном виде (пропуская упаковку в батчи), и возвращает ответ сервера без какой-либо обработки.
+
+Подобный вызов можно использовать в отладочных целях, но кроме того, придется его использовать для отправки запросов, которые:
+- в параметрах имеют `None` (None применяется для стирания значения полей, а упаковка в батчи мешает передавать `None`),
+- используют устревшие методы Битрикс24, которые принимают на вход список (см. [#157](https://github.com/leshchenko1979/fast_bitrix24/issues/157)).
+
+
+```python
+# стереть DESCRIPTION в лиде 123
+params = {"ID": 123, "fields": {"DESCRIPTION": None}}
+b.call('crm.lead.update', params, raw=True)
+
+# добавить комментарий к задаче
+b.call(
+ 'task.commentitem.add',
+ [123, {"POST_MESSAGE": "Комментарий к задаче"}],
+ raw=True
+)
+```
+
+### `call_batch()`
+Если вы хотите вызвать пакетный метод, используйте [`call_batch()`](API.md#метод-callbatchself-params-dict---dict):
+
+```python
+results = b.call_batch ({
+ 'halt': 0,
+ 'cmd': {
+ 'deals': 'crm.deal.list', # берем список сделок
+ # и берем список дел по первой из них
+ 'activities': 'crm.activity.list?filter[ENTITY_TYPE]=3&filter[ENTITY_ID]=$result[deals][0][ID]'
+ }
+})
+
+```
+### Асинхронные вызовы
+Если требуется использование бибилиотеки в асинхронном коде, то вместо клиента `Bitrix()` создавайте клиент класса `BitrixAsync()`:
+```python
+from fast_bitrix24 import BitrixAsync
+b = BitrixAsync(webhook)
+```
+Все методы у него - синхронные аналоги методов из `Bitrix()`, описанных выше:
+```python
+leads = await b.get_all('crm.lead.list')
+```
+## Как это работает
+1. Перед обращением к серверу во всех методах класса `Bitrix` происходит проверка корректности самых популярных параметров, передаваемых к серверу, и поднимаются исключения `TypeError` и `ValueError` при наличии ошибок.
+2. Cоздаются запросы на получение всех элементов из запрошенного списка.
+3. Созданные запросы упаковываются в батчи по 50 запросов в каждом.
+4. Полученные батчи параллельно отправляются на сервер с регулировкой скорости запросов (см. ниже "Как fast_bitrix24 регулирует скорость запросов").
+5. Ответы (содержимое поля `result`) собираются в единый плоский список и возвращаются пользователю.
+ - Поднимаются исключения класса `aiohttp.ClientError`, если сервер Битрикс вернул HTTP-ошибку, и `RuntimeError`, если код ответа был `200`, но ошибка сдержалась в теле ответа сервера.
+ - Происходит сортировка ответов (кроме метода `get_all()`) - порядок элементов в списке результатов совпадает с порядком соответствующих запросов в списке запросов.
+
+В случае с методом `get_all()` пункт 2 выше выглядит немного сложнее:
+ - `get_all()` делает первый запрос к серверу Битрикс24 с указанным методом и параметрами.
+ - Сервер возвращает первую страницу (50 элементов) и параметр `total` - общее количество элементов, найденных по запросу.
+ - Исходя из полученного общего количества элементов, создаются запросы на каждую из страниц (всего `total // 50 - 1` запросов), необходимых для получения всех запрошенных элементов.
+
+В связи с тем, что выполнение `get_all()` по длинным спискам может занимать долгое время, в течение которого пользователи могут добавлять новые элементы в список, может возникнуть ситуация, когда общее полученное количество элементов может не соответствовать изначальному значению `total`. В таких случаях будет выдано стандартное питоновское предупреждение (`warning`).
+
+### Как `fast_bitrix24` регулирует скорость запросов
+По умолчанию `fast_bitrix24` игнорирует официальные ограничения Битрикс24 по скорости запросов (см. ниже "Официальная политика Битрикс24 по скорости запросов") и вместо этого начинает снижать скорость запросов, если сервер начинает возвращать ошибки (autothrottling). Подобный подход позволяет на порядки увеличить скорость получения данных (см. [тесты скорости](https://github.com/leshchenko1979/fast_bitrix24/blob/master/speed_tests/strategies.ipynb)).
+
+Чтобы соблюдать официальные правила, при создании экземпляра класса `Bitrix` укажите параметр `respect_velocity_policy=True`.
+### Официальная политика Битрикс24 по скорости запросов
+1. Существует пул из 50 запросов, которые можно направить без ожидания.
+2. Пул пополняется со скоростью 2 запроса в секунду.
+3. При исчерпании пула и несоблюдении режима ожидания сервер возвращает ошибку.
+
+## Советы и подсказки
+### А умеет ли ваша библиотека ...?
+Посмотрите в [справочник по API](API.md). Если не нашли ответа, [свяжитесь с автором](#как-связаться-с-автором).
+
+### А как мне сформировать запрос к Битриксу, чтобы ...?
+
+1. Поищите в [официальной документации по REST API](https://dev.1c-bitrix.ru/rest_help/).
+1. Если на ваш вопрос там нет ответа - попробуйте задать его в [группе "Партнерский REST API" в Сообществе разработчиков Битрикс24](https://dev.bitrix24.ru/workgroups/group/34/).
+1. Спросите в Телеграме в [группе разработчиков Битрикс24](https://t.me/bit24dev).
+1. Спросите в Телеграме в [группе пользователей fast_bitrix24](https://t.me/+U7hfrV7h53bRvKAS).
+1. Спросите на [русском StackOverflow](https://ru.stackoverflow.com/questions/tagged/битрикс24).
+
+### А как понять, что отправляется на сервер и что он возвращает?
+Включите логирование запросов и ответов сервера.
+```python
+import logging
+
+logging.getLogger('fast_bitrix24').addHandler(logging.StreamHandler())
+```
+
+### Я хочу добавить несколько лидов списком, но получаю ошибку сервера.
+Оберните вызов `call()` в `slow`:
+
+```python
+with b.slow():
+ results = b.call('crm.lead.add', tasks)
+```
+
+[См. подробнее](API.md#контекстный-менеджер-slowmaxconcurrentrequests-int--1) о `slow`.
+
+### Я хочу вызвать `call()` только один раз, а не по списку.
+Передавайте параметры запроса методу `call()`, он может делать как запросы по списку, так и единичный запрос:
+
+```python
+method = 'crm.lead.add'
+params = {'fields': {'TITLE': 'Чпок'}}
+b.call(method, params)
+```
+Результатом будет ответ сервера по этому одному элементу.
+
+Однако, если такие вызовы делаются несколько раз, то более эффективно формировать из них список и вызывать `call()` единожды по всему списку.
+
+### Как сортируются результаты при вызове `get_all()`?
+Пока что никак.
+
+Все обращения к серверу происходят асинхронно и список результатов отсортирован в том порядке, в котором сервер возвращал ответы. Если вам требуется сортировка, то вам нужно делать ее самостоятельно, например:
+
+```python
+deals = b.get_all('crm.deal.list')
+deals.sort(key = lambda d: int(d['ID']))
+```
+
+### Я использую `get_all()` для получения всех полей всех элементов списка, но это происходит слишком долго. Как ускорить этот процесс?
+Попробуйте применить метод `list_and_get()` - он стабильно показывает на порядок лучшие результаты на больших объемах информации.
+
+См. [результаты тестов](https://github.com/leshchenko1979/fast_bitrix24/discussions/113).
+
+### Я получаю ошибку сертификата SSL. Что делать?
+Если вы получаете `SSLCertVerificationError` / `CERTIFICATE_VERIFY_FAILED`, попробуйте отключить верификацию сертификата SSL. При инициализации передайте в `BitrixAsync` параметр `client`, где будет инициализированный вами экземпляр `aiohttp.ClientSession`, у которого будет отключена верификация SSL:
+```python
+import aiohttp
+import asyncio
+
+from fast_bitrix24 import BitrixAsync
+
+
+async def main():
+ # Инициализировать HTTP-клиента без верификации SSL и передать его в `BitrixAsync`
+ connector = aiohttp.TCPConnector(ssl=False)
+ async with aiohttp.ClientSession(connector=connector) as client:
+ b = BitrixAsync(webhook, client=client)
+
+ # Далее ваши вызовы Битрикса
+ ...
+
+
+asyncio.run(main())
+```
+
+## Как связаться с автором
+- telegram: https://t.me/+U7hfrV7h53bRvKAS
+- создать новый github issue: https://github.com/leshchenko1979/fast_bitrix24/issues/new
+
+
+%package -n python3-fast-bitrix24
+Summary: API wrapper для быстрого получения данных от Битрикс24 через REST API. Параллельные запросы к серверу, упаковка запросов в батчи, контроль скорости запросов, есть синхронный и асинхронный клиенты.
+Provides: python-fast-bitrix24
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-fast-bitrix24
+# fast_bitrix24
+API wrapper для Питона для быстрого получения данных от Битрикс24 через REST API.
+
+[![Статистика загрузок](https://img.shields.io/pypi/dm/fast-bitrix24.svg)](https://pypistats.org/packages/fast-bitrix24)
+![Статистика тестов](https://github.com/leshchenko1979/fast_bitrix24/workflows/tests/badge.svg)
+[![codecov](https://codecov.io/gh/leshchenko1979/fast_bitrix24/branch/master/graph/badge.svg?token=UEQ3KITRSX)](https://codecov.io/gh/leshchenko1979/fast_bitrix24)
+[![Sourcery](https://img.shields.io/badge/Sourcery-enabled-brightgreen)](https://sourcery.ai)
+[![CodeFactor](https://www.codefactor.io/repository/github/leshchenko1979/fast_bitrix24/badge)](https://www.codefactor.io/repository/github/leshchenko1979/fast_bitrix24)
+
+- [Основная функциональность](#Основная-функциональность)
+- [Начало работы](#Начало-работы)
+- [Примеры использования](#Примеры-использования)
+- [Как это работает](#Как-это-работает)
+- [Советы и подсказки](#Советы-и-подсказки)
+- [Как связаться с автором](#Как-связаться-с-автором)
+- [Подробный справочник по API](API.md)
+
+## Основная функциональность
+
+### Высокая скорость обмена данными
+
+![Тест скорости](speed_test.gif)
+
+- На больших списках скорость обмена данными с сервером достигает тысяч элементов в секунду.
+- Автоматическая упаковка запросов в батчи сокращает количество требуемых запросов к серверу и ускоряет обмен данными.
+- Батчи отправляются на сервер не последовательно, а параллельно.
+- Продвинутые стратегии работы с постраничным доступом ускоряют выгрузку на порядки (см. [результаты тестов](https://github.com/leshchenko1979/fast_bitrix24/discussions/113)).
+
+### Избежание отказов сервера
+- Автоматический autothrottling - если сервер возвращает ошибки, скорость автоматически понижается.
+- Если сервер для сложных запросов начинает возвращать ошибки, можно в одну строку понизить скорость запроосов.
+
+### Удобство кода
+- Высокоуровневые списочные методы для сокращения количества необходимого кода. Большинство операций занимают только одну строку кода. Обработка параллельных запросов, упаковка запросов в батчи и многое другое убрано "под капот".
+- Позволяет задавать параметры запроса именно в таком виде, как они приведены в [документации к Bitrix24 REST API](https://dev.1c-bitrix.ru/rest_help/index.php). Параметры проверяются на корректность для облегчения отладки.
+- Выполнение запросов автоматически сопровождается прогресс-баром из пакета `tqdm`, иллюстрирующим не только количество обработанных элементов, но и прошедшее и оставшееся время выполнения запроса.
+
+### Синхронный и асинхронный клиенты
+- Наличие асинхронного клиента позволяет использовать библиотеку для написания веб-приложений (например, телеграм-ботов).
+
+### Нас используют
+- [Яндекс](https://github.com/leshchenko1979/fast_bitrix24/issues/159#issuecomment-1104539717)
+
+## Начало работы
+Установите модуль через `pip`:
+```shell
+pip install fast-bitrix24
+```
+
+Далее в python:
+
+```python
+from fast_bitrix24 import Bitrix
+
+# замените на ваш вебхук для доступа к Bitrix24
+webhook = "https://your_domain.bitrix24.ru/rest/1/your_code/"
+b = Bitrix(webhook)
+```
+
+Методы полученного объекта `b` в дальнейшем используются для взаимодействия с сервером Битрикс24.
+
+## Примеры использования
+
+### `get_all()`
+
+Чтобы получить полностью список сущностей, используйте метод [`get_all()`](API.md#метод-getallself-method-str-params-dict--none---list--dict):
+
+```python
+# список лидов
+leads = b.get_all('crm.lead.list')
+```
+
+Метод [`get_all()`](API.md#метод-getallself-method-str-params-dict--none---list--dict) возвращает список, где каждый элемент списка является словарем, описывающим одну сущность из запрошенного списка.
+
+Вы также можете использовать параметр `params`, чтобы кастомизировать запрос:
+
+```python
+# список сделок в работе, включая пользовательские поля
+deals = b.get_all(
+ 'crm.deal.list',
+ params={
+ 'select': ['*', 'UF_*'],
+ 'filter': {'CLOSED': 'N'}
+})
+```
+
+Если у вас есть необходимость быстро выгрузить большие объемы информации (значения всех полей в длинных списках - в 20+ тыс. элементов), то используйте метод [`list_and_get()`](https://github.com/leshchenko1979/fast_bitrix24#метод-list_and_getself-method_branch-str---dict).
+
+### `get_by_ID()`
+Если у вас есть список ID сущностей, то вы можете получить их свойства при помощи метода [`get_by_ID()`](API.md#метод-getbyidself-method-str-idlist-iterable-idfieldname-str--id-params-dict--none---dict)
+и использовании методов вида `*.get`:
+
+```python
+'''
+получим список всех контактов, привязанных к сделкам, в виде
+{
+ ID_сделки_1: [контакт_1, контакт_2, ...],
+ ID_сделки_2: [контакт_1, контакт_2, ...],
+ ...
+}
+'''
+
+contacts = b.get_by_ID(
+ 'crm.deal.contact.items.get',
+ [d['ID'] for d in deals])
+```
+Метод [`get_by_ID()`](API.md#метод-getbyidself-method-str-idlist-iterable-idfieldname-str--id-params-dict--none---dict) возвращает словарь с элементами вида `ID: result`, где `result` - ответ сервера относительно этого `ID`.
+
+### `call()`
+Чтобы создавать, изменять или удалять список сущностей, используйте метод [`call()`](API.md#метод-callself-method-str-items-dict--iterabledict--any--none--raw-bool--false---dict--listdict--any):
+
+```python
+# вставим в начало названия всех сделок их ID
+tasks = [
+ {
+ 'ID': d['ID'],
+ 'fields': {
+ 'TITLE': f'{d["ID"]} - {d["TITLE"]}'
+ }
+ }
+ for d in deals
+]
+
+b.call('crm.deal.update', tasks)
+```
+Метод [`call()`](API.md#метод-callself-method-str-items-dict--iterabledict--any--none--raw-bool--false---dict--listdict--any) возвращает список ответов сервера по каждому элементу переданного списка.
+
+### call(raw=True)
+Вызов `call` с парамтером `raw=True` отправляет на сервер переданные ему параметры в оригинальном, необработанном виде (пропуская упаковку в батчи), и возвращает ответ сервера без какой-либо обработки.
+
+Подобный вызов можно использовать в отладочных целях, но кроме того, придется его использовать для отправки запросов, которые:
+- в параметрах имеют `None` (None применяется для стирания значения полей, а упаковка в батчи мешает передавать `None`),
+- используют устревшие методы Битрикс24, которые принимают на вход список (см. [#157](https://github.com/leshchenko1979/fast_bitrix24/issues/157)).
+
+
+```python
+# стереть DESCRIPTION в лиде 123
+params = {"ID": 123, "fields": {"DESCRIPTION": None}}
+b.call('crm.lead.update', params, raw=True)
+
+# добавить комментарий к задаче
+b.call(
+ 'task.commentitem.add',
+ [123, {"POST_MESSAGE": "Комментарий к задаче"}],
+ raw=True
+)
+```
+
+### `call_batch()`
+Если вы хотите вызвать пакетный метод, используйте [`call_batch()`](API.md#метод-callbatchself-params-dict---dict):
+
+```python
+results = b.call_batch ({
+ 'halt': 0,
+ 'cmd': {
+ 'deals': 'crm.deal.list', # берем список сделок
+ # и берем список дел по первой из них
+ 'activities': 'crm.activity.list?filter[ENTITY_TYPE]=3&filter[ENTITY_ID]=$result[deals][0][ID]'
+ }
+})
+
+```
+### Асинхронные вызовы
+Если требуется использование бибилиотеки в асинхронном коде, то вместо клиента `Bitrix()` создавайте клиент класса `BitrixAsync()`:
+```python
+from fast_bitrix24 import BitrixAsync
+b = BitrixAsync(webhook)
+```
+Все методы у него - синхронные аналоги методов из `Bitrix()`, описанных выше:
+```python
+leads = await b.get_all('crm.lead.list')
+```
+## Как это работает
+1. Перед обращением к серверу во всех методах класса `Bitrix` происходит проверка корректности самых популярных параметров, передаваемых к серверу, и поднимаются исключения `TypeError` и `ValueError` при наличии ошибок.
+2. Cоздаются запросы на получение всех элементов из запрошенного списка.
+3. Созданные запросы упаковываются в батчи по 50 запросов в каждом.
+4. Полученные батчи параллельно отправляются на сервер с регулировкой скорости запросов (см. ниже "Как fast_bitrix24 регулирует скорость запросов").
+5. Ответы (содержимое поля `result`) собираются в единый плоский список и возвращаются пользователю.
+ - Поднимаются исключения класса `aiohttp.ClientError`, если сервер Битрикс вернул HTTP-ошибку, и `RuntimeError`, если код ответа был `200`, но ошибка сдержалась в теле ответа сервера.
+ - Происходит сортировка ответов (кроме метода `get_all()`) - порядок элементов в списке результатов совпадает с порядком соответствующих запросов в списке запросов.
+
+В случае с методом `get_all()` пункт 2 выше выглядит немного сложнее:
+ - `get_all()` делает первый запрос к серверу Битрикс24 с указанным методом и параметрами.
+ - Сервер возвращает первую страницу (50 элементов) и параметр `total` - общее количество элементов, найденных по запросу.
+ - Исходя из полученного общего количества элементов, создаются запросы на каждую из страниц (всего `total // 50 - 1` запросов), необходимых для получения всех запрошенных элементов.
+
+В связи с тем, что выполнение `get_all()` по длинным спискам может занимать долгое время, в течение которого пользователи могут добавлять новые элементы в список, может возникнуть ситуация, когда общее полученное количество элементов может не соответствовать изначальному значению `total`. В таких случаях будет выдано стандартное питоновское предупреждение (`warning`).
+
+### Как `fast_bitrix24` регулирует скорость запросов
+По умолчанию `fast_bitrix24` игнорирует официальные ограничения Битрикс24 по скорости запросов (см. ниже "Официальная политика Битрикс24 по скорости запросов") и вместо этого начинает снижать скорость запросов, если сервер начинает возвращать ошибки (autothrottling). Подобный подход позволяет на порядки увеличить скорость получения данных (см. [тесты скорости](https://github.com/leshchenko1979/fast_bitrix24/blob/master/speed_tests/strategies.ipynb)).
+
+Чтобы соблюдать официальные правила, при создании экземпляра класса `Bitrix` укажите параметр `respect_velocity_policy=True`.
+### Официальная политика Битрикс24 по скорости запросов
+1. Существует пул из 50 запросов, которые можно направить без ожидания.
+2. Пул пополняется со скоростью 2 запроса в секунду.
+3. При исчерпании пула и несоблюдении режима ожидания сервер возвращает ошибку.
+
+## Советы и подсказки
+### А умеет ли ваша библиотека ...?
+Посмотрите в [справочник по API](API.md). Если не нашли ответа, [свяжитесь с автором](#как-связаться-с-автором).
+
+### А как мне сформировать запрос к Битриксу, чтобы ...?
+
+1. Поищите в [официальной документации по REST API](https://dev.1c-bitrix.ru/rest_help/).
+1. Если на ваш вопрос там нет ответа - попробуйте задать его в [группе "Партнерский REST API" в Сообществе разработчиков Битрикс24](https://dev.bitrix24.ru/workgroups/group/34/).
+1. Спросите в Телеграме в [группе разработчиков Битрикс24](https://t.me/bit24dev).
+1. Спросите в Телеграме в [группе пользователей fast_bitrix24](https://t.me/+U7hfrV7h53bRvKAS).
+1. Спросите на [русском StackOverflow](https://ru.stackoverflow.com/questions/tagged/битрикс24).
+
+### А как понять, что отправляется на сервер и что он возвращает?
+Включите логирование запросов и ответов сервера.
+```python
+import logging
+
+logging.getLogger('fast_bitrix24').addHandler(logging.StreamHandler())
+```
+
+### Я хочу добавить несколько лидов списком, но получаю ошибку сервера.
+Оберните вызов `call()` в `slow`:
+
+```python
+with b.slow():
+ results = b.call('crm.lead.add', tasks)
+```
+
+[См. подробнее](API.md#контекстный-менеджер-slowmaxconcurrentrequests-int--1) о `slow`.
+
+### Я хочу вызвать `call()` только один раз, а не по списку.
+Передавайте параметры запроса методу `call()`, он может делать как запросы по списку, так и единичный запрос:
+
+```python
+method = 'crm.lead.add'
+params = {'fields': {'TITLE': 'Чпок'}}
+b.call(method, params)
+```
+Результатом будет ответ сервера по этому одному элементу.
+
+Однако, если такие вызовы делаются несколько раз, то более эффективно формировать из них список и вызывать `call()` единожды по всему списку.
+
+### Как сортируются результаты при вызове `get_all()`?
+Пока что никак.
+
+Все обращения к серверу происходят асинхронно и список результатов отсортирован в том порядке, в котором сервер возвращал ответы. Если вам требуется сортировка, то вам нужно делать ее самостоятельно, например:
+
+```python
+deals = b.get_all('crm.deal.list')
+deals.sort(key = lambda d: int(d['ID']))
+```
+
+### Я использую `get_all()` для получения всех полей всех элементов списка, но это происходит слишком долго. Как ускорить этот процесс?
+Попробуйте применить метод `list_and_get()` - он стабильно показывает на порядок лучшие результаты на больших объемах информации.
+
+См. [результаты тестов](https://github.com/leshchenko1979/fast_bitrix24/discussions/113).
+
+### Я получаю ошибку сертификата SSL. Что делать?
+Если вы получаете `SSLCertVerificationError` / `CERTIFICATE_VERIFY_FAILED`, попробуйте отключить верификацию сертификата SSL. При инициализации передайте в `BitrixAsync` параметр `client`, где будет инициализированный вами экземпляр `aiohttp.ClientSession`, у которого будет отключена верификация SSL:
+```python
+import aiohttp
+import asyncio
+
+from fast_bitrix24 import BitrixAsync
+
+
+async def main():
+ # Инициализировать HTTP-клиента без верификации SSL и передать его в `BitrixAsync`
+ connector = aiohttp.TCPConnector(ssl=False)
+ async with aiohttp.ClientSession(connector=connector) as client:
+ b = BitrixAsync(webhook, client=client)
+
+ # Далее ваши вызовы Битрикса
+ ...
+
+
+asyncio.run(main())
+```
+
+## Как связаться с автором
+- telegram: https://t.me/+U7hfrV7h53bRvKAS
+- создать новый github issue: https://github.com/leshchenko1979/fast_bitrix24/issues/new
+
+
+%package help
+Summary: Development documents and examples for fast-bitrix24
+Provides: python3-fast-bitrix24-doc
+%description help
+# fast_bitrix24
+API wrapper для Питона для быстрого получения данных от Битрикс24 через REST API.
+
+[![Статистика загрузок](https://img.shields.io/pypi/dm/fast-bitrix24.svg)](https://pypistats.org/packages/fast-bitrix24)
+![Статистика тестов](https://github.com/leshchenko1979/fast_bitrix24/workflows/tests/badge.svg)
+[![codecov](https://codecov.io/gh/leshchenko1979/fast_bitrix24/branch/master/graph/badge.svg?token=UEQ3KITRSX)](https://codecov.io/gh/leshchenko1979/fast_bitrix24)
+[![Sourcery](https://img.shields.io/badge/Sourcery-enabled-brightgreen)](https://sourcery.ai)
+[![CodeFactor](https://www.codefactor.io/repository/github/leshchenko1979/fast_bitrix24/badge)](https://www.codefactor.io/repository/github/leshchenko1979/fast_bitrix24)
+
+- [Основная функциональность](#Основная-функциональность)
+- [Начало работы](#Начало-работы)
+- [Примеры использования](#Примеры-использования)
+- [Как это работает](#Как-это-работает)
+- [Советы и подсказки](#Советы-и-подсказки)
+- [Как связаться с автором](#Как-связаться-с-автором)
+- [Подробный справочник по API](API.md)
+
+## Основная функциональность
+
+### Высокая скорость обмена данными
+
+![Тест скорости](speed_test.gif)
+
+- На больших списках скорость обмена данными с сервером достигает тысяч элементов в секунду.
+- Автоматическая упаковка запросов в батчи сокращает количество требуемых запросов к серверу и ускоряет обмен данными.
+- Батчи отправляются на сервер не последовательно, а параллельно.
+- Продвинутые стратегии работы с постраничным доступом ускоряют выгрузку на порядки (см. [результаты тестов](https://github.com/leshchenko1979/fast_bitrix24/discussions/113)).
+
+### Избежание отказов сервера
+- Автоматический autothrottling - если сервер возвращает ошибки, скорость автоматически понижается.
+- Если сервер для сложных запросов начинает возвращать ошибки, можно в одну строку понизить скорость запроосов.
+
+### Удобство кода
+- Высокоуровневые списочные методы для сокращения количества необходимого кода. Большинство операций занимают только одну строку кода. Обработка параллельных запросов, упаковка запросов в батчи и многое другое убрано "под капот".
+- Позволяет задавать параметры запроса именно в таком виде, как они приведены в [документации к Bitrix24 REST API](https://dev.1c-bitrix.ru/rest_help/index.php). Параметры проверяются на корректность для облегчения отладки.
+- Выполнение запросов автоматически сопровождается прогресс-баром из пакета `tqdm`, иллюстрирующим не только количество обработанных элементов, но и прошедшее и оставшееся время выполнения запроса.
+
+### Синхронный и асинхронный клиенты
+- Наличие асинхронного клиента позволяет использовать библиотеку для написания веб-приложений (например, телеграм-ботов).
+
+### Нас используют
+- [Яндекс](https://github.com/leshchenko1979/fast_bitrix24/issues/159#issuecomment-1104539717)
+
+## Начало работы
+Установите модуль через `pip`:
+```shell
+pip install fast-bitrix24
+```
+
+Далее в python:
+
+```python
+from fast_bitrix24 import Bitrix
+
+# замените на ваш вебхук для доступа к Bitrix24
+webhook = "https://your_domain.bitrix24.ru/rest/1/your_code/"
+b = Bitrix(webhook)
+```
+
+Методы полученного объекта `b` в дальнейшем используются для взаимодействия с сервером Битрикс24.
+
+## Примеры использования
+
+### `get_all()`
+
+Чтобы получить полностью список сущностей, используйте метод [`get_all()`](API.md#метод-getallself-method-str-params-dict--none---list--dict):
+
+```python
+# список лидов
+leads = b.get_all('crm.lead.list')
+```
+
+Метод [`get_all()`](API.md#метод-getallself-method-str-params-dict--none---list--dict) возвращает список, где каждый элемент списка является словарем, описывающим одну сущность из запрошенного списка.
+
+Вы также можете использовать параметр `params`, чтобы кастомизировать запрос:
+
+```python
+# список сделок в работе, включая пользовательские поля
+deals = b.get_all(
+ 'crm.deal.list',
+ params={
+ 'select': ['*', 'UF_*'],
+ 'filter': {'CLOSED': 'N'}
+})
+```
+
+Если у вас есть необходимость быстро выгрузить большие объемы информации (значения всех полей в длинных списках - в 20+ тыс. элементов), то используйте метод [`list_and_get()`](https://github.com/leshchenko1979/fast_bitrix24#метод-list_and_getself-method_branch-str---dict).
+
+### `get_by_ID()`
+Если у вас есть список ID сущностей, то вы можете получить их свойства при помощи метода [`get_by_ID()`](API.md#метод-getbyidself-method-str-idlist-iterable-idfieldname-str--id-params-dict--none---dict)
+и использовании методов вида `*.get`:
+
+```python
+'''
+получим список всех контактов, привязанных к сделкам, в виде
+{
+ ID_сделки_1: [контакт_1, контакт_2, ...],
+ ID_сделки_2: [контакт_1, контакт_2, ...],
+ ...
+}
+'''
+
+contacts = b.get_by_ID(
+ 'crm.deal.contact.items.get',
+ [d['ID'] for d in deals])
+```
+Метод [`get_by_ID()`](API.md#метод-getbyidself-method-str-idlist-iterable-idfieldname-str--id-params-dict--none---dict) возвращает словарь с элементами вида `ID: result`, где `result` - ответ сервера относительно этого `ID`.
+
+### `call()`
+Чтобы создавать, изменять или удалять список сущностей, используйте метод [`call()`](API.md#метод-callself-method-str-items-dict--iterabledict--any--none--raw-bool--false---dict--listdict--any):
+
+```python
+# вставим в начало названия всех сделок их ID
+tasks = [
+ {
+ 'ID': d['ID'],
+ 'fields': {
+ 'TITLE': f'{d["ID"]} - {d["TITLE"]}'
+ }
+ }
+ for d in deals
+]
+
+b.call('crm.deal.update', tasks)
+```
+Метод [`call()`](API.md#метод-callself-method-str-items-dict--iterabledict--any--none--raw-bool--false---dict--listdict--any) возвращает список ответов сервера по каждому элементу переданного списка.
+
+### call(raw=True)
+Вызов `call` с парамтером `raw=True` отправляет на сервер переданные ему параметры в оригинальном, необработанном виде (пропуская упаковку в батчи), и возвращает ответ сервера без какой-либо обработки.
+
+Подобный вызов можно использовать в отладочных целях, но кроме того, придется его использовать для отправки запросов, которые:
+- в параметрах имеют `None` (None применяется для стирания значения полей, а упаковка в батчи мешает передавать `None`),
+- используют устревшие методы Битрикс24, которые принимают на вход список (см. [#157](https://github.com/leshchenko1979/fast_bitrix24/issues/157)).
+
+
+```python
+# стереть DESCRIPTION в лиде 123
+params = {"ID": 123, "fields": {"DESCRIPTION": None}}
+b.call('crm.lead.update', params, raw=True)
+
+# добавить комментарий к задаче
+b.call(
+ 'task.commentitem.add',
+ [123, {"POST_MESSAGE": "Комментарий к задаче"}],
+ raw=True
+)
+```
+
+### `call_batch()`
+Если вы хотите вызвать пакетный метод, используйте [`call_batch()`](API.md#метод-callbatchself-params-dict---dict):
+
+```python
+results = b.call_batch ({
+ 'halt': 0,
+ 'cmd': {
+ 'deals': 'crm.deal.list', # берем список сделок
+ # и берем список дел по первой из них
+ 'activities': 'crm.activity.list?filter[ENTITY_TYPE]=3&filter[ENTITY_ID]=$result[deals][0][ID]'
+ }
+})
+
+```
+### Асинхронные вызовы
+Если требуется использование бибилиотеки в асинхронном коде, то вместо клиента `Bitrix()` создавайте клиент класса `BitrixAsync()`:
+```python
+from fast_bitrix24 import BitrixAsync
+b = BitrixAsync(webhook)
+```
+Все методы у него - синхронные аналоги методов из `Bitrix()`, описанных выше:
+```python
+leads = await b.get_all('crm.lead.list')
+```
+## Как это работает
+1. Перед обращением к серверу во всех методах класса `Bitrix` происходит проверка корректности самых популярных параметров, передаваемых к серверу, и поднимаются исключения `TypeError` и `ValueError` при наличии ошибок.
+2. Cоздаются запросы на получение всех элементов из запрошенного списка.
+3. Созданные запросы упаковываются в батчи по 50 запросов в каждом.
+4. Полученные батчи параллельно отправляются на сервер с регулировкой скорости запросов (см. ниже "Как fast_bitrix24 регулирует скорость запросов").
+5. Ответы (содержимое поля `result`) собираются в единый плоский список и возвращаются пользователю.
+ - Поднимаются исключения класса `aiohttp.ClientError`, если сервер Битрикс вернул HTTP-ошибку, и `RuntimeError`, если код ответа был `200`, но ошибка сдержалась в теле ответа сервера.
+ - Происходит сортировка ответов (кроме метода `get_all()`) - порядок элементов в списке результатов совпадает с порядком соответствующих запросов в списке запросов.
+
+В случае с методом `get_all()` пункт 2 выше выглядит немного сложнее:
+ - `get_all()` делает первый запрос к серверу Битрикс24 с указанным методом и параметрами.
+ - Сервер возвращает первую страницу (50 элементов) и параметр `total` - общее количество элементов, найденных по запросу.
+ - Исходя из полученного общего количества элементов, создаются запросы на каждую из страниц (всего `total // 50 - 1` запросов), необходимых для получения всех запрошенных элементов.
+
+В связи с тем, что выполнение `get_all()` по длинным спискам может занимать долгое время, в течение которого пользователи могут добавлять новые элементы в список, может возникнуть ситуация, когда общее полученное количество элементов может не соответствовать изначальному значению `total`. В таких случаях будет выдано стандартное питоновское предупреждение (`warning`).
+
+### Как `fast_bitrix24` регулирует скорость запросов
+По умолчанию `fast_bitrix24` игнорирует официальные ограничения Битрикс24 по скорости запросов (см. ниже "Официальная политика Битрикс24 по скорости запросов") и вместо этого начинает снижать скорость запросов, если сервер начинает возвращать ошибки (autothrottling). Подобный подход позволяет на порядки увеличить скорость получения данных (см. [тесты скорости](https://github.com/leshchenko1979/fast_bitrix24/blob/master/speed_tests/strategies.ipynb)).
+
+Чтобы соблюдать официальные правила, при создании экземпляра класса `Bitrix` укажите параметр `respect_velocity_policy=True`.
+### Официальная политика Битрикс24 по скорости запросов
+1. Существует пул из 50 запросов, которые можно направить без ожидания.
+2. Пул пополняется со скоростью 2 запроса в секунду.
+3. При исчерпании пула и несоблюдении режима ожидания сервер возвращает ошибку.
+
+## Советы и подсказки
+### А умеет ли ваша библиотека ...?
+Посмотрите в [справочник по API](API.md). Если не нашли ответа, [свяжитесь с автором](#как-связаться-с-автором).
+
+### А как мне сформировать запрос к Битриксу, чтобы ...?
+
+1. Поищите в [официальной документации по REST API](https://dev.1c-bitrix.ru/rest_help/).
+1. Если на ваш вопрос там нет ответа - попробуйте задать его в [группе "Партнерский REST API" в Сообществе разработчиков Битрикс24](https://dev.bitrix24.ru/workgroups/group/34/).
+1. Спросите в Телеграме в [группе разработчиков Битрикс24](https://t.me/bit24dev).
+1. Спросите в Телеграме в [группе пользователей fast_bitrix24](https://t.me/+U7hfrV7h53bRvKAS).
+1. Спросите на [русском StackOverflow](https://ru.stackoverflow.com/questions/tagged/битрикс24).
+
+### А как понять, что отправляется на сервер и что он возвращает?
+Включите логирование запросов и ответов сервера.
+```python
+import logging
+
+logging.getLogger('fast_bitrix24').addHandler(logging.StreamHandler())
+```
+
+### Я хочу добавить несколько лидов списком, но получаю ошибку сервера.
+Оберните вызов `call()` в `slow`:
+
+```python
+with b.slow():
+ results = b.call('crm.lead.add', tasks)
+```
+
+[См. подробнее](API.md#контекстный-менеджер-slowmaxconcurrentrequests-int--1) о `slow`.
+
+### Я хочу вызвать `call()` только один раз, а не по списку.
+Передавайте параметры запроса методу `call()`, он может делать как запросы по списку, так и единичный запрос:
+
+```python
+method = 'crm.lead.add'
+params = {'fields': {'TITLE': 'Чпок'}}
+b.call(method, params)
+```
+Результатом будет ответ сервера по этому одному элементу.
+
+Однако, если такие вызовы делаются несколько раз, то более эффективно формировать из них список и вызывать `call()` единожды по всему списку.
+
+### Как сортируются результаты при вызове `get_all()`?
+Пока что никак.
+
+Все обращения к серверу происходят асинхронно и список результатов отсортирован в том порядке, в котором сервер возвращал ответы. Если вам требуется сортировка, то вам нужно делать ее самостоятельно, например:
+
+```python
+deals = b.get_all('crm.deal.list')
+deals.sort(key = lambda d: int(d['ID']))
+```
+
+### Я использую `get_all()` для получения всех полей всех элементов списка, но это происходит слишком долго. Как ускорить этот процесс?
+Попробуйте применить метод `list_and_get()` - он стабильно показывает на порядок лучшие результаты на больших объемах информации.
+
+См. [результаты тестов](https://github.com/leshchenko1979/fast_bitrix24/discussions/113).
+
+### Я получаю ошибку сертификата SSL. Что делать?
+Если вы получаете `SSLCertVerificationError` / `CERTIFICATE_VERIFY_FAILED`, попробуйте отключить верификацию сертификата SSL. При инициализации передайте в `BitrixAsync` параметр `client`, где будет инициализированный вами экземпляр `aiohttp.ClientSession`, у которого будет отключена верификация SSL:
+```python
+import aiohttp
+import asyncio
+
+from fast_bitrix24 import BitrixAsync
+
+
+async def main():
+ # Инициализировать HTTP-клиента без верификации SSL и передать его в `BitrixAsync`
+ connector = aiohttp.TCPConnector(ssl=False)
+ async with aiohttp.ClientSession(connector=connector) as client:
+ b = BitrixAsync(webhook, client=client)
+
+ # Далее ваши вызовы Битрикса
+ ...
+
+
+asyncio.run(main())
+```
+
+## Как связаться с автором
+- telegram: https://t.me/+U7hfrV7h53bRvKAS
+- создать новый github issue: https://github.com/leshchenko1979/fast_bitrix24/issues/new
+
+
+%prep
+%autosetup -n fast-bitrix24-1.5.16
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-fast-bitrix24 -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Thu May 18 2023 Python_Bot <Python_Bot@openeuler.org> - 1.5.16-1
+- Package Spec generated