С чего начать
Установка
Чтобы установить актуальную версию клиента, воспользуйтесь командой:
Требуется Python 3.10 или новее. Вместе с библиотекой ставятся aiohttp,
pydantic (v2) и certifi — больше ничего доустанавливать не нужно.
Что понадобится
Для работы с API нужны две вещи: идентификатор организации и токен. Библиотека поддерживает две пары значений — выбирайте ту, что соответствует вашей организации.
| Организация | Идентификатор | Токен | Заголовки |
|---|---|---|---|
| Яндекс 360 | org_id |
token (OAuth) |
X-Org-ID, Authorization: OAuth ... |
| Yandex Cloud Organization | cloud_org_id |
iam_token (IAM) |
X-Cloud-Org-ID, Authorization: Bearer ... |
Только одна пара
org_id и cloud_org_id взаимоисключающие, как и token с iam_token.
Если передать оба идентификатора или оба токена, конструктор бросит
ValueError — API запрещает отправлять X-Org-ID и X-Cloud-Org-ID
одновременно.
Где взять значения — в документации Яндекс Трекера:
- идентификатор организации: https://yandex.cloud/ru/docs/tracker/enable-tracker
- OAuth-токен: https://yandex.cloud/ru/docs/tracker/concepts/access
- IAM-токен: https://yandex.cloud/ru/docs/iam/concepts/authorization/iam-token
Инициализация
Импортируйте библиотеку
Создайте экземпляр, передав в конструктор класса необходимые секреты
import os
from yatracker import YaTracker
tracker = YaTracker(
org_id=os.environ["TRACKER_ORG_ID"], # (1)
token=os.environ["TRACKER_TOKEN"],
)
- Не сохраняйте свои учётные данные прямо в коде. Используйте переменные окружения.
Для организации в Yandex Cloud используйте вторую пару параметров — они именованные, передать их позиционно нельзя:
tracker = YaTracker(
cloud_org_id=os.environ["TRACKER_CLOUD_ORG_ID"],
iam_token=os.environ["TRACKER_IAM_TOKEN"],
)
Для работы с одной организацией достаточно одного клиента. Вы один раз создаёте его и далее повторно используете при необходимости.
Ленивая сессия
HTTP-сессия aiohttp создаётся не в конструкторе, а при первом запросе.
Поэтому YaTracker(...) можно спокойно вызывать на уровне модуля,
вне работающего event loop.
Завершение работы
Сессию нужно закрыть — иначе aiohttp пожалуется на незакрытый коннектор.
Есть два способа.
Явный вызов close() — подходит для долгоживущего приложения,
где клиент создаётся один раз:
Асинхронный контекстный менеджер — подходит для скриптов и разовых задач:
async with YaTracker(org_id=..., token=...) as tracker:
issue = await tracker.get_issue("WRITERS-42")
При выходе из блока close() вызывается автоматически.
Повторное использование
После close() клиент закрыт окончательно: следующий запрос завершится
RuntimeError("Client is closed"). Раньше в этом случае втихую создавалась
новая сессия, которую уже некому было закрыть, — и aiohttp ругался на
незакрытый клиент. Нужен новый клиент — создайте новый YaTracker; а лучше
держите один экземпляр на всё приложение.
Проверить состояние можно через tracker._client.closed. На это же свойство
опирается iter_issues: освобождение scroll-сессии пропускается, если трекер
уже закрыт, поэтому закрывайте генератор до выхода из блока async with
(см. «Работа с задачами»).
Использование
Обратите внимание
Все методы YaTracker, вызывающие API, являются асинхронными.
Соответственно, вызывать их нужно внутри корутин.
Но для упрощения примеров они будут использованы напрямую, как будто мы находимся уже внутри функции.
Т.е. вместо
Мы будем писатьДля начала создадим новую задачу в очереди для писателей
WRITERS– ключ очереди
Первые два аргумента — summary и queue, все остальные передаются только
по имени: description, assignee, followers, priority, parent,
type_, sprint, unique, attachment_ids.
Дополним задачу описанием
- Описание можно было задать ещё при создании, а здесь это лишь повод для редактирования.
edit_issue() принимает произвольные **kwargs — любое поле задачи,
которое разрешает менять API.
Если вам известен ключ задачи, то нетрудно её получить
Полученный объект — модель FullIssue, у которой есть и данные, и несколько
собственных методов:
issue = await tracker.get_issue("WRITERS-42")
print(issue.key) # WRITERS-42
print(issue.summary) # Написать шедевр
print(issue.status) # Открыт
print(issue.created_at) # datetime.datetime(...)
comments = await issue.get_comments()
await issue.post_comment("Взял в работу")
Переходы по статусам возвращаются словарём, где ключ — идентификатор перехода:
transitions = await issue.get_transitions()
close = transitions.get("close")
if close is not None:
await close.execute()
Обработка ошибок
Любой ответ с кодом 300 и выше превращается в исключение — наследника
YaTrackerError. Минимальная обработка выглядит так:
from yatracker.exceptions import ObjectNotFoundError, YaTrackerError
try:
issue = await tracker.get_issue("WRITERS-42")
except ObjectNotFoundError:
print("Такой задачи нет")
except YaTrackerError as e:
print(f"Трекер вернул ошибку: {e}")
Подробный разбор иерархии исключений — в разделе Обработка ошибок.
Полный пример
import asyncio
import os
from yatracker import YaTracker
from yatracker.exceptions import YaTrackerError
async def main() -> None:
async with YaTracker(
org_id=os.environ["TRACKER_ORG_ID"],
token=os.environ["TRACKER_TOKEN"],
) as tracker:
try:
issue = await tracker.create_issue(
"Написать шедевр",
"WRITERS",
description="... или нечто ценное",
)
except YaTrackerError as e:
print(f"Не удалось создать задачу: {e}")
return
print(f"Создана задача {issue.key}: {issue.url}")
if __name__ == "__main__":
asyncio.run(main())