shikithon


Nameshikithon JSON
Version 2.6.2 PyPI version JSON
download
home_pagehttps://github.com/SecondThundeR/shikithon
SummaryYet another Python wrapper for Shikimori API
upload_time2024-01-01 02:14:52
maintainer
docs_urlNone
authorSecondThundeR
requires_python>=3.8.10,<4.0.0
licenseMIT
keywords python shikimori api
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            > [!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"
}
        
Elapsed time: 0.47782s