Asyncio Yandex Tracker API client
Documentation: https://olegt0rr.github.io/YaTracker/
API docs: https://yandex.cloud/en/docs/tracker/about-api
- Fully asynchronous, built on
aiohttp— no blocking calls, no threads. - Responses are parsed into
pydanticv2 models, withdatetimefields already converted. - Typed end to end:
@overloads keep your own issue/queue models flowing through the return types. - Supports both Yandex 360 (
X-Org-ID+ OAuth) and Yandex Cloud (X-Cloud-Org-ID+ IAM) organizations. - Covers the whole documented Tracker API: issues (including changelog,
links, suggest and reports), queues (fields, versions, tags, access
rights, triggers, autoactions, workflows), components, projects (both the
legacy
/projectsAPI and the entities API behind projects, portfolios and goals, with their comments, attachments, checklists, links and access rights), macros, boards (including columns and sprints), comments and reactions, checklists, worklogs, attachments, users, administration dictionaries (issue types, statuses, resolutions, priorities), global and local fields, filters, dashboards, absences (gaps), bulk changes, external applications and remote links, and import of issues, comments, links, attachments and worklogs. - Local (custom) queue fields are supported via your own model subclasses.
- Pluggable transport: swap
aiohttpfor any client by subclassingBaseClient.
- All
selfproperties are renamed tourl, becauseselfis a reserved name in Python. Aurl=keyword argument is sent to the API asurl; models embedded in a request body keep the API'sselfkey. - All
camelCaseproperties are renamed topythonic_case. - All datetime values are converted to Python
datetime.datetimeobjects. - Methods are named by the author, because the Yandex API has no clear method names.
pip install yatracker
from yatracker import YaTracker
tracker = YaTracker(org_id=..., token=...)
async def foo():
# create an issue
issue = await tracker.create_issue("New Issue", "KEY")
# get an issue
issue = await tracker.get_issue("KEY-1")
# update an issue (just pass kwargs)
issue = await tracker.edit_issue("KEY-1", description="Hello World")
# get transitions (a dict keyed by transition id)
transitions = await issue.get_transitions()
# execute a transition
close = transitions.get("close")
if close is not None:
await close.execute()# don't forget to close tracker on app shutdown
async def on_shutdown():
await tracker.close()YaTracker is also an async context manager, which closes the session for you:
async with YaTracker(org_id=..., token=...) as tracker:
issue = await tracker.get_issue("KEY-1")Pass exactly one organization id and exactly one token.
# Yandex 360 organization (sends `X-Org-ID`) with an OAuth token
tracker = YaTracker(org_id=..., token=...)
# Yandex Cloud organization (sends `X-Cloud-Org-ID`) with an IAM token
tracker = YaTracker(cloud_org_id=..., iam_token=...)org_id and cloud_org_id are mutually exclusive, so are token and
iam_token. API v3 is used by default, v2 is still available via
YaTracker(..., api_version="v2").
Every response with a status of 300 or above is raised as a YaTrackerError
subclass:
from yatracker.exceptions import ObjectNotFoundError, YaTrackerError
try:
issue = await tracker.get_issue("KEY-1")
except ObjectNotFoundError:
... # 404: wrong id or key
except YaTrackerError as e:
... # anything else the API rejectedNotAuthorizedError (401), SufficientRightsError (403),
ObjectNotFoundError (404) and AlreadyExistsError (409) are the
specialised cases; any other status raises the base YaTrackerError with
the response body as its message.
See the error handling guide for details.