> [!CAUTION]
> **Состояние библиотеки:** прекращена поддержка библиотеки
>
> В связи с моим полным переходом на веб-разработку и TypeScript вместо Python, поддерживать эту библиотеку больше нет возможности. Если что-то необходимо исправить -> Just make a fork
<!-- If PyCharm or IDEA will throw a warning here, just ignore it -->
<div align="center">
<img src="https://raw.githubusercontent.com/SecondThundeR/shikithon/main/assets/logo.png" alt="Shikithon Logo">
<h1>Shikithon</h1>
<p>Очередной враппер для Shikimori API, написанный на Python</p>
</div>
[![Publish Shikithon package to PyPI](https://github.com/SecondThundeR/shikithon/actions/workflows/pypi-publish.yml/badge.svg)](https://github.com/SecondThundeR/shikithon/actions/workflows/pypi-publish.yml)
> [!TIP]
> Начиная с версии 2.0.0, библиотека поддерживает асинхронные запросы, отдельные пути к ресурсам API и многое другое
> _[(Инструкция по миграции с версии 1.x.x)](https://github.com/SecondThundeR/shikithon/wiki/%D0%9C%D0%B8%D0%B3%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81-v1-%D0%BD%D0%B0-v2)_
## Описание
Данный враппер предоставляет абстракцию, которая позволяет удобнее работать с методами API и их ответами
Для каждого эндпоинта API существует свой объект с методами, и все данные, возвращаемые API Shikimori, валидируются и парсятся в модели, со всеми необходимыми полями,
а также дополнительными, которые могут вернуть некоторые методы API _(Например /users/whoami и /users/:id/info возвращают разные поля)_.
Это позволяет не задумываться об обработке очередного ответа от сервера и сосредоточиться над реализацией своей идеи
Также благодаря множеству проверок при взаимодействии с запросами, библиотека старается добиться максимально
безопасной работы с API: все ошибки API, переданных параметров, данных и т.д. обратываются, логируются и
пользователю возвращаются значения по умолчанию
> [!NOTE]
> Данная библиотека начинает свою поддержку с Python 3.8.10.
## Установка
```shell
pip install shikithon
# или используя Poetry
poetry add shikithon
```
## Пример использования
```py
import asyncio
from typing import Dict
from json import loads
from shikithon import ShikimoriAPI, JSONStore
# При необходимости, можно также
# экспортировать енамы для использования в методах
from shikithon.enums import AnimeOrder, MangaKind, ...
# Можно установить данные конфигурации в коде
config = {
"app_name": "...",
"client_id": "...",
"client_secret": "...",
"auth_code": "...",
# Необязательно
"access_token": "...",
"refresh_token": "..."
}
# Или же прочитать его из внешнего файла
with open("config.json", "r", encoding="utf-8") as config_file:
config_2: Dict[str, str] = loads(config_file.read())
# Инициализируем API объект с необходимыми опциями
# В данном примере используется JSONStore и отключено логирование
api = ShikimoriAPI(app_name=config['app_name'], store=JSONStore())
async def main():
# Используем объект без авторизации
async with api:
lycoris = await api.animes.get(50709)
print(lycoris)
# >> id=50709 name='Lycoris Recoil' russian='Ликорис Рикоил' ...
# Важно отметить, что внутри нельзя вкладывать async with api.auth(...)
# Используем объект с авторизацией
# Вариант 1
async with api.auth(
client_id=config["client_id"],
client_secret=config["client_secret"],
auth_code=config["auth_code"],
):
print(await api.users.current())
# >> id=723052, nickname='SecondThundeR', ...
# Вариант 2
# Создаем новый объект API
# (По умолчанию используется NullStore в качестве хранилища)
api_2 = ShikimoriAPI(app_name="...")
# В данном случае app_name в __init__ не будет перезаписан,
# а токен будет обновлен при ошибке 401
api_auth_maker = api_2.auth(
app_name=config['app_name'],
client_id=config['client_id'],
client_secret=config['client_secret'],
access_token=config['access_token'],
refresh_token=config['refresh_token']
)
# Далее созданный объект можно использовать сколько угодно раз
async with api_auth_maker:
...
asyncio.run(main())
```
Выполнение нескольких запросов одновременно с помощью метода `multiple_requests`:
```py
# В этом примере используется распаковка, но можно также получать весь массив с данными ответов
# в одной переменнной (chainsaw, lycoris_anime, ... -> data = await ...)
from shikithon import ShikimoriAPI, JSONStore
config = ...
api = ShikimoriAPI(app_name=config['app_name'], store=JSONStore(), logging=False)
async def main():
async with api:
chainsaw, lycoris_chisato, lycoris_ranobe = await api.multiple_requests([
api.animes.get_all(search="Бензопила"),
api.characters.search("Тисато Нисикиги"),
api.ranobes.get_all(search="Ликорис"),
])
print(chainsaw)
print(lycoris_chisato[:1])
print(lycoris_ranobe)
# [AnimeInfo(id=44511, name='Chainsaw Man', russian='Человек-бензопила', ...]
# [CharacterInfo(id=204621, name='Chisato Nishikigi', russian='Тисато Нисикиги', ...]
# [RanobeInfo(id=151431, name='Lycoris Recoil: Ordinary Days', russian='Ликорис Рикоил: Повседневность', ...]
```
Также, если хочется узнать как использовать встроенные хранилища конфигов или хочется создать свой,
посмотрите [этот гайд](https://github.com/SecondThundeR/shikithon/wiki/%D0%93%D0%B0%D0%B9%D0%B4-%D0%BF%D0%BE-%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D0%BB%D0%B8%D1%89%D0%B0%D0%BC-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D0%B8)
### Пара уточнений по использованию
- Возможно вам придется импортировать модели для ручной аннотации возвращаемых моделей в PyCharm
_(в нем немного некорретно работает наследование типа от функции)_
- При отсутствии каких-либо полей в данных конфигурации, библиотека выдает исключение
- Если вы хотите использовать логгирование библиотеки, передайте флаг `logging=True` в объект API:
`api = ShikimoriAPI(app_name="...", logging=True)`
## Получение данных для конфигурации
Для начала вам необходимо создать новое OAuth-приложение [здесь](https://shikimori.me/oauth/applications).
После этого, сохраните `app_name`, `client_id`, `client_secret`, а так же `redirect_uri`, если вы его меняли
Позже, [на данной странице](https://shikimori.me/oauth) выберите свое приложение, необходимые разрешения
и получите код авторизации и сохраните его.
_(Если необходимо, то можно также получить токены авторизации, пройдя следующий этап после получения кода авторизации)_
## Список изменений
Все изменения перечислены на [странице релизов](https://github.com/SecondThundeR/shikithon/releases)
## Помощь проекту
Хотите внести вклад или оставить репорт о баге? Великолепно!
Для таких случаев, стоит почитать [CONTRIBUTING.md](https://github.com/SecondThundeR/shikithon/blob/main/CONTRIBUTING.md)
## Зависимости проекта
Данный проект использует семь библиотек:
- [aiohttp](https://github.com/aio-libs/aiohttp) для асинхронных запросов к API
[(Лицензия)](https://github.com/aio-libs/aiohttp/blob/master/LICENSE.txt)
- [pydantic](https://github.com/samuelcolvin/pydantic/) для валидации данных JSON и преобразования в модели
[(Лицензия)](https://github.com/samuelcolvin/pydantic/blob/master/LICENSE)
- [pyrate-limiter](https://github.com/vutran1710/PyrateLimiter) для огранчений количества запросов к API
[(Лицензия)](https://github.com/vutran1710/PyrateLimiter/blob/master/LICENSE)
- [backoff](https://github.com/litl/backoff) для повторения запросов при их ограничении
[(Лицензия)](https://github.com/litl/backoff/blob/master/LICENSE)
- [loguru](https://github.com/Delgan/loguru) для удобного логгирования
[(Лицензия)](https://github.com/Delgan/loguru/blob/master/LICENSE)
- [validators](https://github.com/kvesteri/validators) для проверки строк на наличие ссылки в ней
[(Лицензия)](https://github.com/kvesteri/validators/blob/master/LICENSE)
- [typing-extensions](https://github.com/python/typing_extensions) для корректной типизации декораторов
[(Лицензия)](https://github.com/python/typing_extensions/blob/main/LICENSE)
Также, данный проект использует две библиотеки в качестве зависимостей для разработки:
- [pre-commit](https://github.com/pre-commit/pre-commit) для автоматизации форматирования и проверки кода
[(Лицензия)](https://github.com/pre-commit/pre-commit/blob/main/LICENSE)
- [mypy](https://github.com/python/mypy) для проверки типов [(Лицензия)](https://github.com/python/mypy/blob/master/LICENSE)
## Лицензия проекта
Данный проект имеет MIT лицензию.
Ознакомиться с ее содержанием можно [здесь](https://github.com/SecondThundeR/shikithon/blob/main/LICENSE)
Проект использует логотип сайта [Shikimori](https://shikimori.org) для логотипа в этом README.md.
Все права принадлежат правообладателям и используются по принципу _fair use_
## Благодарности
- [shiki4py](https://github.com/ren3104/Shiki4py) - взяты некоторые идеи по рефакторингу и добавлению поддержки асинхронных запросов
[(Лицензия)](https://github.com/ren3104/Shiki4py/blob/main/LICENSE)
Raw data
{
"_id": null,
"home_page": "https://github.com/SecondThundeR/shikithon",
"name": "shikithon",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8.10,<4.0.0",
"maintainer_email": "",
"keywords": "Python,Shikimori,API",
"author": "SecondThundeR",
"author_email": "awayfromgalaxy@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/eb/be/36bf49b34a790e868b5e9635ea2604e20b30a2d8a075ee4035aafc8389be/shikithon-2.6.2.tar.gz",
"platform": null,
"description": "> [!CAUTION]\n> **\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438:** \u043f\u0440\u0435\u043a\u0440\u0430\u0449\u0435\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438\n>\n> \u0412 \u0441\u0432\u044f\u0437\u0438 \u0441 \u043c\u043e\u0438\u043c \u043f\u043e\u043b\u043d\u044b\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u043c \u043d\u0430 \u0432\u0435\u0431-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438 TypeScript \u0432\u043c\u0435\u0441\u0442\u043e Python, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438. \u0415\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c -> Just make a fork\n\n<!-- If PyCharm or IDEA will throw a warning here, just ignore it -->\n<div align=\"center\">\n <img src=\"https://raw.githubusercontent.com/SecondThundeR/shikithon/main/assets/logo.png\" alt=\"Shikithon Logo\">\n <h1>Shikithon</h1>\n <p>\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0432\u0440\u0430\u043f\u043f\u0435\u0440 \u0434\u043b\u044f Shikimori API, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 Python</p>\n</div>\n\n[![Publish Shikithon package to PyPI](https://github.com/SecondThundeR/shikithon/actions/workflows/pypi-publish.yml/badge.svg)](https://github.com/SecondThundeR/shikithon/actions/workflows/pypi-publish.yml)\n\n> [!TIP]\n> \u041d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 2.0.0, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u043a \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c API \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435\n> _[(\u0418\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f \u043f\u043e \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 1.x.x)](https://github.com/SecondThundeR/shikithon/wiki/%D0%9C%D0%B8%D0%B3%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81-v1-%D0%BD%D0%B0-v2)_\n\n## \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\n\n\u0414\u0430\u043d\u043d\u044b\u0439 \u0432\u0440\u0430\u043f\u043f\u0435\u0440 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 API \u0438 \u0438\u0445 \u043e\u0442\u0432\u0435\u0442\u0430\u043c\u0438\n\n\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430 API \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u0432\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438, \u0438 \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0435 API Shikimori, \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438 \u043f\u0430\u0440\u0441\u044f\u0442\u0441\u044f \u0432 \u043c\u043e\u0434\u0435\u043b\u0438, \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438,\n\u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b API _(\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 /users/whoami \u0438 /users/:id/info \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u043e\u043b\u044f)_.\n\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0435 \u0437\u0430\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0431 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u0434 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0441\u0432\u043e\u0435\u0439 \u0438\u0434\u0435\u0438\n\n\u0422\u0430\u043a\u0436\u0435 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u043f\u0440\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u0442\u0430\u0440\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\n\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 API: \u0432\u0441\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 API, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442.\u0434. \u043e\u0431\u0440\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f, \u043b\u043e\u0433\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438\n\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e\n\n> [!NOTE]\n> \u0414\u0430\u043d\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u0432\u043e\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441 Python 3.8.10.\n\n## \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\n\n```shell\npip install shikithon\n\n# \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Poetry\npoetry add shikithon\n```\n\n## \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f\n\n```py\nimport asyncio\n\nfrom typing import Dict\n\nfrom json import loads\n\nfrom shikithon import ShikimoriAPI, JSONStore\n\n# \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435\n# \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u043d\u0430\u043c\u044b \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0430\u0445\nfrom shikithon.enums import AnimeOrder, MangaKind, ...\n\n# \u041c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432 \u043a\u043e\u0434\u0435\nconfig = {\n \"app_name\": \"...\",\n \"client_id\": \"...\",\n \"client_secret\": \"...\",\n \"auth_code\": \"...\",\n # \u041d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\n \"access_token\": \"...\",\n \"refresh_token\": \"...\"\n}\n\n# \u0418\u043b\u0438 \u0436\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0435\u0433\u043e \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u0430\nwith open(\"config.json\", \"r\", encoding=\"utf-8\") as config_file:\n config_2: Dict[str, str] = loads(config_file.read())\n\n# \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c API \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u043e\u043f\u0446\u0438\u044f\u043c\u0438\n# \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f JSONStore \u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\napi = ShikimoriAPI(app_name=config['app_name'], store=JSONStore())\n\nasync def main():\n # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0435\u0437 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438\n async with api:\n lycoris = await api.animes.get(50709)\n print(lycoris)\n # >> id=50709 name='Lycoris Recoil' russian='\u041b\u0438\u043a\u043e\u0440\u0438\u0441 \u0420\u0438\u043a\u043e\u0438\u043b' ...\n\n # \u0412\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0435\u043b\u044c\u0437\u044f \u0432\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c async with api.auth(...)\n\n # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439\n # \u0412\u0430\u0440\u0438\u0430\u043d\u0442 1\n async with api.auth(\n client_id=config[\"client_id\"],\n client_secret=config[\"client_secret\"],\n auth_code=config[\"auth_code\"],\n ):\n print(await api.users.current())\n # >> id=723052, nickname='SecondThundeR', ...\n\n # \u0412\u0430\u0440\u0438\u0430\u043d\u0442 2\n\n # \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 API\n # (\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f NullStore \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430)\n api_2 = ShikimoriAPI(app_name=\"...\")\n\n # \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 app_name \u0432 __init__ \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0430\u043d,\n # \u0430 \u0442\u043e\u043a\u0435\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d \u043f\u0440\u0438 \u043e\u0448\u0438\u0431\u043a\u0435 401\n api_auth_maker = api_2.auth(\n app_name=config['app_name'],\n client_id=config['client_id'],\n client_secret=config['client_secret'],\n access_token=config['access_token'],\n refresh_token=config['refresh_token']\n )\n\n # \u0414\u0430\u043b\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u0440\u0430\u0437\n async with api_auth_maker:\n ...\n\nasyncio.run(main())\n```\n\n\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 `multiple_requests`:\n\n```py\n# \u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0430, \u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e\u0442\u0432\u0435\u0442\u043e\u0432\n# \u0432 \u043e\u0434\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043d\u043e\u0439 (chainsaw, lycoris_anime, ... -> data = await ...)\nfrom shikithon import ShikimoriAPI, JSONStore\n\nconfig = ...\n\napi = ShikimoriAPI(app_name=config['app_name'], store=JSONStore(), logging=False)\n\nasync def main():\n async with api:\n chainsaw, lycoris_chisato, lycoris_ranobe = await api.multiple_requests([\n api.animes.get_all(search=\"\u0411\u0435\u043d\u0437\u043e\u043f\u0438\u043b\u0430\"),\n api.characters.search(\"\u0422\u0438\u0441\u0430\u0442\u043e \u041d\u0438\u0441\u0438\u043a\u0438\u0433\u0438\"),\n api.ranobes.get_all(search=\"\u041b\u0438\u043a\u043e\u0440\u0438\u0441\"),\n ])\n print(chainsaw)\n print(lycoris_chisato[:1])\n print(lycoris_ranobe)\n\n# [AnimeInfo(id=44511, name='Chainsaw Man', russian='\u0427\u0435\u043b\u043e\u0432\u0435\u043a-\u0431\u0435\u043d\u0437\u043e\u043f\u0438\u043b\u0430', ...]\n# [CharacterInfo(id=204621, name='Chisato Nishikigi', russian='\u0422\u0438\u0441\u0430\u0442\u043e \u041d\u0438\u0441\u0438\u043a\u0438\u0433\u0438', ...]\n# [RanobeInfo(id=151431, name='Lycoris Recoil: Ordinary Days', russian='\u041b\u0438\u043a\u043e\u0440\u0438\u0441 \u0420\u0438\u043a\u043e\u0438\u043b: \u041f\u043e\u0432\u0441\u0435\u0434\u043d\u0435\u0432\u043d\u043e\u0441\u0442\u044c', ...]\n```\n\n\u0422\u0430\u043a\u0436\u0435, \u0435\u0441\u043b\u0438 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0443\u0437\u043d\u0430\u0442\u044c \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u043e\u0432 \u0438\u043b\u0438 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0439,\n\u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 [\u044d\u0442\u043e\u0442 \u0433\u0430\u0439\u0434](https://github.com/SecondThundeR/shikithon/wiki/%D0%93%D0%B0%D0%B9%D0%B4-%D0%BF%D0%BE-%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D0%BB%D0%B8%D1%89%D0%B0%D0%BC-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D0%B8)\n\n### \u041f\u0430\u0440\u0430 \u0443\u0442\u043e\u0447\u043d\u0435\u043d\u0438\u0439 \u043f\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e\n\n- \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u043b\u044f \u0440\u0443\u0447\u043d\u043e\u0439 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0432 PyCharm\n_(\u0432 \u043d\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 \u043e\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438)_\n- \u041f\u0440\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043f\u043e\u043b\u0435\u0439 \u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0432\u044b\u0434\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\n- \u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043f\u0435\u0440\u0435\u0434\u0430\u0439\u0442\u0435 \u0444\u043b\u0430\u0433 `logging=True` \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 API:\n`api = ShikimoriAPI(app_name=\"...\", logging=True)`\n\n## \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438\n\n\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 OAuth-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 [\u0437\u0434\u0435\u0441\u044c](https://shikimori.me/oauth/applications).\n\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e, \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435 `app_name`, `client_id`, `client_secret`, \u0430 \u0442\u0430\u043a \u0436\u0435 `redirect_uri`, \u0435\u0441\u043b\u0438 \u0432\u044b \u0435\u0433\u043e \u043c\u0435\u043d\u044f\u043b\u0438\n\n\u041f\u043e\u0437\u0436\u0435, [\u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435](https://shikimori.me/oauth) \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f\n\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043a\u043e\u0434 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435 \u0435\u0433\u043e.\n_(\u0415\u0441\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u0440\u043e\u0439\u0434\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u0430\u043f \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438)_\n\n## \u0421\u043f\u0438\u0441\u043e\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439\n\n\u0412\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u043d\u0430 [\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0440\u0435\u043b\u0438\u0437\u043e\u0432](https://github.com/SecondThundeR/shikithon/releases)\n\n## \u041f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0443\n\n\u0425\u043e\u0442\u0438\u0442\u0435 \u0432\u043d\u0435\u0441\u0442\u0438 \u0432\u043a\u043b\u0430\u0434 \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0440\u0435\u043f\u043e\u0440\u0442 \u043e \u0431\u0430\u0433\u0435? \u0412\u0435\u043b\u0438\u043a\u043e\u043b\u0435\u043f\u043d\u043e!\n\n\u0414\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c [CONTRIBUTING.md](https://github.com/SecondThundeR/shikithon/blob/main/CONTRIBUTING.md)\n\n## \u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\n\n\u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0435\u043c\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a:\n\n- [aiohttp](https://github.com/aio-libs/aiohttp) \u0434\u043b\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a API\n[(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/aio-libs/aiohttp/blob/master/LICENSE.txt)\n- [pydantic](https://github.com/samuelcolvin/pydantic/) \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 JSON \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043c\u043e\u0434\u0435\u043b\u0438\n[(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/samuelcolvin/pydantic/blob/master/LICENSE)\n- [pyrate-limiter](https://github.com/vutran1710/PyrateLimiter) \u0434\u043b\u044f \u043e\u0433\u0440\u0430\u043d\u0447\u0435\u043d\u0438\u0439 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a API\n[(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/vutran1710/PyrateLimiter/blob/master/LICENSE)\n- [backoff](https://github.com/litl/backoff) \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u0440\u0438 \u0438\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0438\n[(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/litl/backoff/blob/master/LICENSE)\n- [loguru](https://github.com/Delgan/loguru) \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\n[(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/Delgan/loguru/blob/master/LICENSE)\n- [validators](https://github.com/kvesteri/validators) \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0442\u0440\u043e\u043a \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0432 \u043d\u0435\u0439\n[(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/kvesteri/validators/blob/master/LICENSE)\n- [typing-extensions](https://github.com/python/typing_extensions) \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u043e\u0432\n[(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/python/typing_extensions/blob/main/LICENSE)\n\n\u0422\u0430\u043a\u0436\u0435, \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0434\u0432\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438:\n\n- [pre-commit](https://github.com/pre-commit/pre-commit) \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u0434\u0430\n[(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/pre-commit/pre-commit/blob/main/LICENSE)\n- [mypy](https://github.com/python/mypy) \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 [(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/python/mypy/blob/master/LICENSE)\n\n## \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430\n\n\u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u043c\u0435\u0435\u0442 MIT \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044e.\n\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0435\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c \u043c\u043e\u0436\u043d\u043e [\u0437\u0434\u0435\u0441\u044c](https://github.com/SecondThundeR/shikithon/blob/main/LICENSE)\n\n\u041f\u0440\u043e\u0435\u043a\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043b\u043e\u0433\u043e\u0442\u0438\u043f \u0441\u0430\u0439\u0442\u0430 [Shikimori](https://shikimori.org) \u0434\u043b\u044f \u043b\u043e\u0433\u043e\u0442\u0438\u043f\u0430 \u0432 \u044d\u0442\u043e\u043c README.md.\n\u0412\u0441\u0435 \u043f\u0440\u0430\u0432\u0430 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442 \u043f\u0440\u0430\u0432\u043e\u043e\u0431\u043b\u0430\u0434\u0430\u0442\u0435\u043b\u044f\u043c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 _fair use_\n\n## \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u043d\u043e\u0441\u0442\u0438\n\n- [shiki4py](https://github.com/ren3104/Shiki4py) - \u0432\u0437\u044f\u0442\u044b \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0434\u0435\u0438 \u043f\u043e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0443 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\n[(\u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f)](https://github.com/ren3104/Shiki4py/blob/main/LICENSE)\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Yet another Python wrapper for Shikimori API",
"version": "2.6.2",
"project_urls": {
"Documentation": "https://github.com/SecondThundeR/shikithon/README.md",
"Homepage": "https://github.com/SecondThundeR/shikithon",
"Repository": "https://github.com/SecondThundeR/shikithon"
},
"split_keywords": [
"python",
"shikimori",
"api"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "5a40f6b0bbd677622dcedc3dbf240b2a8f5ad9c4ca716a091c63700034470d74",
"md5": "b29b24a19856eac942158e391cca798c",
"sha256": "f5bd2baef588745986d136ac51d85db1dfbcf5ba7eb380683f79ebff72f7589a"
},
"downloads": -1,
"filename": "shikithon-2.6.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b29b24a19856eac942158e391cca798c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8.10,<4.0.0",
"size": 96545,
"upload_time": "2024-01-01T02:14:49",
"upload_time_iso_8601": "2024-01-01T02:14:49.842389Z",
"url": "https://files.pythonhosted.org/packages/5a/40/f6b0bbd677622dcedc3dbf240b2a8f5ad9c4ca716a091c63700034470d74/shikithon-2.6.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ebbe36bf49b34a790e868b5e9635ea2604e20b30a2d8a075ee4035aafc8389be",
"md5": "aee2eac858e25af802c70085601c60cc",
"sha256": "bc902b70e352034d25076aa77e1a373a03149049550593d90148f4aeecd02029"
},
"downloads": -1,
"filename": "shikithon-2.6.2.tar.gz",
"has_sig": false,
"md5_digest": "aee2eac858e25af802c70085601c60cc",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8.10,<4.0.0",
"size": 55192,
"upload_time": "2024-01-01T02:14:52",
"upload_time_iso_8601": "2024-01-01T02:14:52.076787Z",
"url": "https://files.pythonhosted.org/packages/eb/be/36bf49b34a790e868b5e9635ea2604e20b30a2d8a075ee4035aafc8389be/shikithon-2.6.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-01 02:14:52",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "SecondThundeR",
"github_project": "shikithon",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "shikithon"
}