Использование aws-lambda-powertools-python с классом python lambda

#python #amazon-web-services #aws-lambda

#python #amazon-веб-сервисы #aws-lambda

Вопрос:

Я пытаюсь придумать хороший шаблон для будущих лямбд, которые мы пишем в нашей команде.

Одна из целей — попытаться научить объектно-ориентированной разработке некоторых членов команды, поэтому я хотел бы использовать этот шаблон здесь. У меня это нормально работает с другими реальными лямбдами, но, пытаясь добавить полезную библиотеку ‘aws-lambda-powertools-python’, я сталкиваюсь с некоторыми проблемами.

Лямбда-код:

 from aws_lambda_powertools import Logger

logger = Logger()


class LambdaExample:
    @classmethod
    def get_handler(cls, *args, **kwargs):
        """Get handler"""
        def handler(event, context):
            return cls(*args, **kwargs).handle(event, context)

        return handler

    @logger.inject_lambda_context(log_event=True)
    def handle(self, event, context):
        logger.info("Hello World")


lambda_handler = LambdaExample.get_handler()
 

В документах для powertools есть пример кода для pytest. Однако их пример кода не является полным файлом, и, похоже, предполагается, что лямбда-обработчик является автономной функцией, а не методом класса. Я попытался его адаптировать:

 from collections import namedtuple
import pytest
from lambda_example import LambdaExample

@pytest.fixture
def lambda_context():
    lambda_context = {
        "function_name": "test",
        "memory_limit_in_mb": 128,
        "invoked_function_arn": "arn:aws:lambda:eu-west-1:809313241:function:test",
        "aws_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72",
    }

    return namedtuple("LambdaContext", lambda_context.keys())(*lambda_context.values())

class TestLambdaHandler:

    def test_handle_will_pass_when_env_setup(self, lambda_context):
        # Given
        test_event = {'test': 'event'}
        lambda_handler = LambdaExample()
        # When
        lambda_handler.handle(test_event, lambda_context)
 

Результат, который я получаю, таков:

 >       lambda_handler.handle(test_event, lambda_context)
E       TypeError: decorate() takes 2 positional arguments but 3 were given
 

Если я удалю эту строку из метода обработчика, все будет работать нормально:
«@logger.inject_lambda_context(log_event=True)»

Проблема, похоже, в том, что декоратор не работает с аргументом ‘self’ в методе.

Есть идеи о том, как это сделать?

Комментарии:

1. Почему вы хотите запутать вызов лямбда-функции, отличной от OO, с помощью объектно-ориентированной оболочки?

2. не показано в этом простом примере, но в полном примере объект lambda создает экземпляры зависимостей и объединяет их вместе. по сути, это простая реализация внедрения зависимостей. Поскольку зависимым классам не требуется разрешать свои собственные зависимости, это упрощает их тестирование. кроме того, я предпочитаю этот шаблон использованию глобальных переменных для повторного использования ресурсов в нескольких вызовах lambda

Ответ №1:

Понял это. Это был простой случай перемещения аннотации следующим образом:

 from aws_lambda_powertools import Logger

logger = Logger()


class LambdaExample:
    @classmethod
    def get_handler(cls, *args, **kwargs):
        """Get handler"""
        @logger.inject_lambda_context(log_event=True)
        def handler(event, context):
            return cls(*args, **kwargs).handle(event, context)

        return handler

    def handle(self, event, context):
        logger.info("Hello World")


lambda_handler = LambdaExample.get_handler()
 

Затем в тестовом классе вызовите его так же, как и lambda:

     lambda_handler = LambdaExample.get_handler()
    response = lambda_handler(test_event, lambda_context)