Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

ExpressApp/smartapp-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

30 Commits

Repository files navigation

SmartApp Template Tutorial

Введение

i️ Инфо
Для взаимодействия с платформой botx используется библиотека pybotx . В документации можно посмотреть примеры её использования. Для реализации SmartApp используется библиотека pybotx-smartapp-rpc . Перед прочтением данного туториала следует с ней ознакомиться.


Шаблон решает проблему написания повторяющего кода в самом начале работы над проектом. Уже существует шаблон для разработки ботов bot-template

Но структура бота и SmartApp отличается друг от друга, поэтому был создан этот шаблон.


1. Развертывание из шаблона и структура проекта

Для развертывания проекта необходимо установить copier и выполнить команду:

$ copier smartapp-template smartapp-example

Структура шаблонного SmartApp состоит из нескольких следующих пакетов и модулей:

.
├── app
│ ├── api - реализация http роутов для приложения, включая необходимые для smartapp
│ ├── bot - команды бота и вспомогательные функции для них
│ ├── caching - классы и функции для работы с in-memory БД
│ ├── db - модели, функции для работы с БД и миграции
│ ├── schemas - сериализаторы, енамы, доменные модели
│ ├── services - сервисы с логикой (бизнес-логика)
│ ├── smartapp - rpc - методы и аргументы для smartapp
│ ├── smartapp-files - статические файлы
│ ├── constants.py - константы
│ ├── logger.py - логгер
│ ├── main.py - запуск сервера с инициализацией необходимых сервисов
│ └── settings.py - настройки приложения
├── extensions - вспомогательные расширения для шаблона
├── scripts - скрипты для запуска тестов, форматеров, линтеров
├── tests - тесты, структура которых соответствует структуре проекта, и хелперы для них
├── poetry.lock - конфигурация текущих зависимостей. используется для их установки
├── pyproject.toml - конфигурация зависимостей, мета информация проекта (название, версия, авторы и т.п.)
└── setup.cfg - конфигурация линтеров и тестов

2. Запуск проекта

Настройка окружения

  1. Устанавливаем зависимости проекта через poetry:
$ poetry install
  1. Определяем переменные окружения в файле .env. Примеры переменных окружения находятся в файле example.env.
  2. Запускаем postges и redis используя docker-compose:
$ docker-compose -f docker-compose.dev.yml up -d
  1. Применяем все миграции для инициализации таблиц с помощью alembic:
$ alembic upgrade head
  1. Запускаем SmartApp как приложение FastAPI через gunicorn. Флаг --reload используется только при разработке для автоматического перезапуска сервера при изменениях в коде:
$ gunicorn "app.main:get_application()" --worker-class uvicorn.workers.UvicornWorker

По необходимости добавить флаг --workers и их колличество, в данном случае 4 рабочих процесса:

$ gunicorn "app.main:get_application()" --worker-class uvicorn.workers.UvicornWorker --workers 4

3. Добавление нового функционала

3.1. Команды SmartApp

Структура пакета команд

Обработчики находятся в пакете app.smartapp.rpc_methods и группируются в отдельные модули в зависимости от логики. Обработчики добавляются с помощью RPCRouter.

Если в модуле становится слишком много команд, следует разбить его на новые модули и сложить в один пакет с названием старого модуля. Например, так:

smartapp
├── rpc_methods
│ ├── common.py
│ ├── jira
│ ├── projects.py
│ ├── issues.py

Регистрация команд

Для добавления модуля с обработчиками нужно импортировать его из модуля нужного вам модуля в app/smartapp/smartapp.py и добавить его в routers smartapp:

from pybotx_smartapp_rpc import SmartAppRPC
from app.smartapp.middlewares.smartlogger import smart_logger_middleware
from app.smartapp.rpc_methods import common, jira
smartapp = SmartAppRPC(
 routers=[common.rpc, jira.rpc],
 middlewares=[smart_logger_middleware],
)

3.2. Взаимодействие с БД

Создание новых моделей

Взаимодействовать с новыми таблицами можно через модели sqlalchemy. С примерами использования можно ознакомиться тут. Модели располагаются в пакете app.db.package_name. Там же хранятся crud функции и репозитории. Структура пакета выглядит следующим образом:

├── app
│ ├── db 
│ ├── migrations
│ ├── exampleapp
│ ├── repo.py - репозиторий/crud функции
│ ├── models.py - модели таблиц

Пример модели:

from sqlalchemy import Column, Integer, String
from app.db.sqlalchemy import Base
class ExampleModel(Base):
 __tablename__ = "examples"
 id: int = Column(Integer, primary_key=True, autoincrement=True)
 text: str = Column(String)

Пример репозитория:

from sqlalchemy import insert
from app.db.sqlalchemy import session
from app.db.example.models import ExampleModel
class ExampleRepo:
 async def create(self, text: str) -> None:
 query = insert(ExampleModel).values(text=text)
 async with session.begin():
 await session.execute(query)

Создание новых миграций

Для генерации миграций используется alembic. Все файлы миграции хранятся в директории app.db.migrations. Для генерации новой миграции необходимо создать модель sqlalchemy и выполнить команду:

$ alembic revision --autogenerate -m "migration message"

Новый файл миграции будет создан в следующей директории:

├── app
│ ├── db 
│ ├── migrations
│ ├── versions
│ ├── 0123456789ab_migration_message.py

Чтобы применить все миграции, следует выполнить команду:

$ alembic upgrade head

или:

$ alembic upgrade 1

для применения только одной миграции.

Для отмены одной миграции необходимо выолнить:

$ alembic downgrade -1

3.3. Сервисы и бизнес-логика

Вся бизнес-логика проекта выносится в пакет app.services. Бизнес-логика - логика, характерная только для данного проекта. Туда же выносятся запросы, клиенты для использования API сторонних сервисов, обработка данных по заданным (в ТЗ) правилам.

Структура следующая:

├── app
│ ├── services
│ │ ├── errors.py - исключения, вызываемые в клиенте
│ │ ├── client.py - клиент для обращения к стороннему сервису 

3.4. Конфиги и переменные среды

Новые переменные среды можно добавить в класс AppSettings из файла app/settings.py. Если у переменной нет значения по умолчанию, то оно будет браться из файла .env. Чтобы использовать эту переменную в боте, необходимо:

from app.settings import settings
...
settings.MY_VAR

i️ Инфо Через переменные среды можно указывать окружения, в которых будет запускаться smartapp. test, dev или prod. Просто добавьте в файл .env переменную APP_ENV=prod.


4. Линтеры и форматирование кода

Запуск

Для запуска всех форматеров необходимо выполнить скрипт:

$ ./scripts/format

Для запуска всех линтеров необходимо выполнить скрипт:

$ ./scripts/lint

Описание

Используется для форматирования кода к единому стилю: разбивает длинные строки, следит за отступами и импортами.

⚠️ Примечание
В некоторых моментах isort конфликтует с black. Конфликт решается настройкой файла конфигурации setup.cfg.

Используется для сортировки импортов. Сначала импорты из стандартных библиотек python, затем из внешних библиотек и в конце из модулей данного проекта. Между собой импорты сортируются по алфавиту.

Используется для удаления неиспользуемых импортов и переменных.

Используется для проверки типов. Помогает находить некоторые ошибки еще на стадии разработки.

⚠️ Примечание
К сожалению, не все библиотеки поддерживают типизацию. Чтобы подсказать это mypy необходимо добавить следующие строки в файл конфигурации setup.cfg:

[mypy]
# ...
[mypy-your_library_name.*]
ignore_missing_imports = True

Некоторые же наоборот имеют специальные плагины для mypy, например pydantic:

[mypy]
plugins = pydantic.mypy
...
[pydantic-mypy]
init_forbid_extra = True
init_typed = True
warn_required_dynamic_aliases = True
warn_untyped_fields = True

Используется для комплексной проверки. Анализирует допустимые имена перменных и их длину, сложность вложенных конструкций, правильную обработку исключений и многое другое. Для каждого типа ошибок есть свой уникальный номер, объяснение, почему так делать не стоит, и объяснение, как делать правильно. Список ошибок можно посмотреть тут.

i️ Инфо
В некоторых редких случаях можно игнорировать правила линтера. Для этого необходимо либо прописать комментарий с меткой noqa на проблемной строке:

var = problem_function() # noqa: WPS999 

либо указать ignore ошибки в setup.cfg:

[flake8]
# ...
ignore =
 # f-strings are useful
 WPS305,

Также можно исключать модули и пакеты.


5. Тестирование

5.1. Запуск и добавление тестов

Все тесты пишутся с помощью библиотеки pytest. Запустить тесты можно командой:

$ pytest

Во время тестирования поднимается docker-контейнер с БД. Порт выбирается свободный, поэтому запущенная локально БД не будет мешать. Если вы хотите запускать тесты используя вашу локальную БД, необходимо добавить в .env переменную DB=1, либо выполнить команду:

$ DB=1 pytest

i️ Инфо
Поскольку pytest не умеет в асинхронные тесты, для работы с ними ему необходим плагин pytest-asyncio .

5.2. Покрытие

Покрытие показывает процент протестированного исходного кода, как всего, так и отдельных модулей. Покрытие помогает определить какие фрагменты кода не запускались в тестах. Для генерации отчетов покрытия используется плагин pytest-cov.

Чтобы не прописывать все флаги каждый раз, можно использовать эти скрипты:

$ ./scripts/test
$ ./scripts/html-cov-test

Первый выводит отчет в терминале, второй генерирует отчет в виде htmlстраниц с подсветкой непокрытых участков кода.

About

SmartApp backend template

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 7

Languages

AltStyle によって変換されたページ (->オリジナル) /