03.02.2020       Выпуск 320 (03.02.2020 - 09.02.2020)       Статьи

Авто-дополнение кода и проверка типов для boto3

Сейчас мало кто пишет большие проекты на Python без аннотации типов. Это и просто, и позволяет отловить кучу ошибок еще на этапе написания кода, да и работает очень шустро. Но стоит добавить в зависимости boto3, и mypy начинает пестрить сообщениями о том, что аннотаций типов для boto3 не существует в природе.

 

Не страшно, существует же официальный генератор аннотаций для boto3 botostubs. Только он официально не выпускался, не обновляется и с mypy не работает.

Есть и замечательный boto3-type-annotations, но тоже немного заброшен, и поддержки mypy всё еще нет.

Как же проверять типы для boto3, а бонусом получить автодополнение кода?

Читать>>




Экспериментальная функция:

Ниже вы видите текст статьи по ссылке. По нему можно быстро понять ссылка достойна прочтения или нет

Просим обратить внимание, что текст по ссылке и здесь может не совпадать.

image

Картинка предоcтавлена автором boto3-type-annotations, Allie Fitter

Сейчас мало кто пишет большие проекты на Python без аннотации типов. Это и просто, и позволяет отловить кучу ошибок еще на этапе написания кода, да и работает очень шустро. Но стоит добавить в зависимости boto3, и mypy начинает пестрить сообщениями о том, что аннотаций типов для boto3 не существует в природе.

Не страшно, существует же официальный генератор аннотаций для boto3 botostubs. Только он официально не выпускался, не обновляется и с mypy не работает.

Есть и замечательный boto3-type-annotations, но тоже немного заброшен, и поддержки mypy всё еще нет.

Как же проверять типы для boto3, а бонусом получить автодополнение кода?

Проверка типов в mypy

Предположим, мы пользуемся самой свежей на данный момент версией boto3 1.11.9 для сервисов EC2, DynamoDB и S3. Да и Python у нас 3.6.9 или даже новее. Чтобы получить и проверку типов, и автодополнение, нам нужно установить совместимую версию boto3-stubs 1.11.9.x с указанием сервисов.

# поддерживаются все boto3 сервисы, так что замените на свои
pip install boto3-stubs[s3,ec2,dynamodb]==1.11.9.0

# если вы не используете pip, pipfile или poetry,
# или же устанавливаете whl-пакеты, то нужно еще и сгенерировать
# индекс установленных сервисов
python -m mypy_boto3

И… всё! Уже можно запускать mypy и увидеть, что он, наконец, нашел стабы для boto3, а возможно даже нашел ошибки в проекте.

Там же было еще что-то про автодополнение!

И это тоже есть, но уже чуть сложнее.

В VSCode не поддерживаются полностью аннотации для перегруженных функций, так что типы в некоторых случаях придется указывать явно. А именно для boto3.client, boto3_session.client,boto3.resource, boto3_session.resource, client.get_waiter и client.get_paginator.

В PyCharm авто-определение типов для перегруженных функций может медленно работать и поедать оперативку, если вы установили больше 15 сервисов, так что явные типы пригодятся и там.

import boto3

from mypy_boto3 import dynamodb

# Явное указание типа, чтобы автодополнение работало везде
client: dynamodb.DynamoDBClient = boto3.client("dynamodb")

# IDE подскажет имена и типы агрументов и возвращаемого значения
client.query("my_table")

Пример использования

import boto3

from mypy_boto3 import s3

# PyCharm и mypy работают и без явного указания типа, но лучше указывать
client: s3.S3Client = boto3.client("s3")

# IDE подсказывает и имена, и типы, и всё-всё-всё
client.create_bucket(Bucket="bucket")

# посмотрим, сможет ли mypy отловить ошибки в этом коде

# (mypy) error: Missing positional argument "Key" in call to "get_object" of "S3Client"
client.get_object(Bucket="bucket")

# (mypy) error: Argument "Key" to "get_object" of "S3Client" has incompatible type "None"; expected "str"
client.get_object(Bucket="bucket", Key=None)

resource: s3.S3ServiceResource = boto3.Session(region_name="us-west-1").resource("s3")

# Для ресурсов авто-дополенение и проверка типов тоже работает
bucket = resource.Bucket("bucket")

# (mypy) error: Unexpected keyword argument "key" for "upload_file" of "Bucket"; did you mean "Key"?
bucket.upload_file(Filename="my.txt", key="my-txt")

# waiter'ы  и paginator'ы тоже аннотированы
# и не забываем про явные типы на всякий случай
waiter: s3.BucketExistsWaiter = client.get_waiter("bucket_exists")
paginator: s3.ListMultipartUploadsPaginator = client.get_paginator(
    "list_multipart_uploads"
)

Как оно работает

Аннотации создаются автоматически небольшой библиотекой mypy-boto3-builder и выходят спустя час-два после релиза новой версии boto3. Если вы используете старую версию boto3, то можете сгенерировать пакеты руками по инструкции.

Гененриуется это всё из json-файлов с описанием сервисов из botocore с небольшими патчами, так как boto3 изменяет методы некоторых сервисов.

Помогите советами

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

Для генерации индекса аннотаций для сервисов используется post-install скрипт, который сам по себе грязный хак и не поддерживается в whl-пакетах. Есть ли способ избежать этого?

Так как в boto3 многие методы и классы в одном файле называются одинаково, для корректной работы аннотаций модуль импортирует сам себя. Это не работает в Python 3.6.5 и выглядит не очень. Какие есть альтернативы?

Ну и, наконец, если у вас все в порядке с C#, можно добавить поддержку литералов в перегруженные функции для Python Language Server, чтобы в VSCode всё тоже работало из коробки. Я не смог и сдался.

Всем спасибо!






Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus