# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['pyckish',
 'pyckish.basic_elements',
 'pyckish.exceptions',
 'pyckish.http_elements',
 'pyckish.types']

package_data = \
{'': ['*']}

install_requires = \
['pydantic==1.10.4']

setup_kwargs = {
    'name': 'pyckish',
    'version': '0.4.0',
    'description': 'Pyckish is a micro framework to deal with AWS Lambdas in Python in beautiful manner.',
    'long_description': '<p align="center">\n  <img alt="Midjourney attempt on pyckish logo" src="https://i.imgur.com/kqtYQTv.png" height="400">\n</p>\n\n# Pyckish\n\n### Create _AWS Lambdas_ professionally with this micro framework\n\n\n[![PyPI](https://img.shields.io/pypi/v/pyckish)](https://pypi.org/project/pyckish/)\n\n```bash\npip install pyckish\n```\n\nPyckish is a micro framework to deal with _AWS Lambdas_ in Python in beautiful manner, it includes an \n"extract, parse and validate" solution for input, creation of exception handlers to deal with exceptions and better\noutput, allowing you to return Pydantic models instead of dicts. One of Pyckish goals is to make using \n"Lambdas as handlers of HTTP requests" as an alternative that works similarly to other frameworks for \nback-end applications, like FastAPI.\n\nCurrently, it can be used to extract HTTP data that comes in the event/context dictionary. It extracts from \nthe dictionary, parses it and validates it. It relies heavily on Pydantic, and will make your life simpler if you \nonly like to deal with validated and correctly typed data.\n\n#### Instead of doing this:\n```python\n# No validation\n# No parsing\n# No exception handling\n# No default value\ndef lambda_handler(event: dict, context: dict) -> dict:\n    auth = event[\'headers\'][\'authorization_token\']\n    store = event[\'pathParameters\'][\'store\']\n    item = event[\'body\']\n    user = get_user(auth)\n    similar_item: dict = get_similar_item(item, store, user)\n    return similar_item\n```\n\n#### Do this:\n\n```python\nimport pyckish\nfrom pyckish.http_elements import Body, Header, PathParameter\nfrom my_models import Item\n\n\n@pyckish.Lambda()\ndef lambda_handler(\n        auth: str = Header(alias=\'authorization_token\'),\n        store: str = PathParameter(),\n        item: Item = Body()\n) -> float:\n    user = get_user(auth)\n    similar_item: Item = get_similar_item(item, store, user)\n    return similar_item\n```\n\nAnd get validation and parsing free of trouble thanks to integration with Pydantic. Enjoy the advantages of a much\nmore robust codebase, leaving behind having to extract and manage issues related to missing/wrong values.\n\nThough Pyckish is active development it is ready for production, since it\'s APIs aren\'t going to change.\n\n## What are _AWS Lambda Functions_\nLambdas are just simple functions that you can write in languages like Python, Javascript, etc. that are meant to be \ndeployed on AWS. They can be activated/triggered by AWS whenever an event happens, it might a client application \nhitting on AWS API Gateway or a cron-job activation triggered by AWS Event Bridge. AWS manages every computer resource\nfor you, this makes AWS Lambdas exceptionally easy to deploy. It is integrated with most things on AWS, meaning there is almost\nalways a way to do what you want with Lambdas.\n\nThe interesting thing about Lambdas is that beyond being just a simple functions easy to write that you can extract data\nfrom its inputs and put whenever logic you want inside it, Lambdas also are really, really cheap. You could activate it \na million times per month with being charged, and this is only on AWS free tier. All of this makes Lambdas an \nattractive technology for most companies.\n\nLambdas, normally have only two parameters, both are two JSON\'s that are converted to python dictionaries, event and \ncontext. This library extracts, validates and parses values from those parameters.\n\n## Motivation\n\n(Today, together with AWS API Gateway, it is possible to use only AWS Lambdas as back-end for your application.\nThe problem is, unlike modern Frameworks, like FastAPI and Starlite, using only AWS Lambdas requires you to develop\nyour own solutions for extracting, parsing, validating as well as creating error handling for the inputs of your code.\nThere are solutions that allow you to use ASGI Frameworks with AWS Lambdas, like Mangum. But it is yet another \ntechnology that sits above your bulky framework. Personally, I think that the problem could be solved in a more \nsimple and direct manner. Pyckish aims to be that solution.\n\nUsing tools like Serverless Framework with its integration with CloudFormation, many AWS Lambdas can be deployed\nfrom a single repository. Those "monorepos" solutions could also make heavy use of Pyckish in order to handle its\ninputs.\n\nRight now, Pyckish is a tiny baby, and I\'m not sure of its future. Weather it will become a full Framework with more\ncapabilities than Chalice Framework, or it is going to remain as a simple "extractor/parser/validator" I do not know.\n\nBut I encourage you to try, simplicity and types will seduce you into it.\n\n## Usage\n\nCurrently, Pyckish provides you with these features:\n\n- Extract/parse/validate the data contained in the Lambda Inputs all with adequate Exceptions raised in case of\nfailure.\n- Improves readability of your Lambda function by clearly stating the data your Lambda function requires.\n- Allow you to add exception handlers to your Lambda in a easy manner, allowing to gracefully deal with exceptions.\n\n\n### _Lambda_ Decorator\nIn order to pyckish to work it is required to add an instance of the Lambda class as a decorator above your lambda\nfunction. That is the only requirement. But in order to your function accept parameters you have to create some\nparameters in your function with type annotation.\n\n### Extract HTTP Data from Event\n\nPyckish provides classes that allows you to extract HTTP Data from the event, such ass `Path`, `Method`, \n`PathParameter`, `PathParameters`, `Header`, `Headers`, `QueryParameter`, `QueryParameters` and `Body`. These classes\nare all children classes of _LambdaInputElement_ class.\n\nThe version in the singular means they are going to extract only one parameter. They require \na type annotation that it the type of that specific parameter. The ones in the plural means\nthey are going to extract all parameters at once, the type annotation needs to be a Pydantic Model.\n\nCheckout the difference:\n```python\nimport pyckish\nfrom pyckish.http_elements import Header, Headers\nimport pydantic\n\nclass MyAuthHeader(pydantic.BaseModel):\n    auth: str = pydantic.Field(alias=\'authorization\')\n    host: str\n\nevent = {\n    \'headers\': {\'authorization\': \'token\', \'host\': \'177.177\'}\n}\ncontext = {}\n\n@pyckish.Lambda()\ndef lambda_handler(\n        auth: str = Header(),\n        my_header: MyAuthHeader = Headers() \n) -> None:\n    print(auth)\n    print(my_header)\n\nlambda_handler(event, context)\n``` \n\n\n### Simple extraction from Event\nIf you do not provide a child of _LambdaInputElement_ class on the default value, the name of the parameter act as\na key to be extracted on the event.\n\n```python\nimport pyckish\n\nevent, context = {\'my_value_on_event\': \'200\'}, {}\n\n\n@pyckish.Lambda()\ndef lambda_handler(\n        my_param_on_event: int = 500\n) -> None:\n    print(f\'value: {my_param_on_event}, type: {type(my_param_on_event)}\')\n\n\nlambda_handler(event, context)\n``` \n\n### Custom _LambdaInputElement_\nIf you want to extract your own value from the event or context with validation and parsing capabilities, you can\ncreate your own _LambdaInputElement_ child class. It is required that this class implements a method called "extract"\naccepting a _LambdaInput_ instance. _LambdaInput_ is just a dataclass with two attributes, event and context.\n```python\nimport pyckish\nfrom pyckish import LambdaInputElement, LambdaInput\nfrom pyckish import ValidationError\n\nclass MySpecialParameter(LambdaInputElement):\n    def extract(self, lambda_input: LambdaInput) -> str:\n        try:\n            return lambda_input.event[\'my_special_parameter_key\'][\'another\']\n        except KeyError:\n            raise ValidationError(\'My special parameter is missing\')\n\n@pyckish.Lambda()\ndef lambda_handler(\n        param: str = MySpecialParameter()\n) -> None:\n    print(f\'my param: {param}\')\n``` \n\n### Adding Exception Handlers\nException Handlers are functions to be executed when an error occurs in your lambda. To make a function to each error\nuse the `add_exception_handler` method.\n\n```python\nimport pyckish\nfrom pyckish import LambdaInput\n\nclass MyException(Exception):\n    pass\n\n# This signature is required\ndef handler_for_my_exception(lambda_input: LambdaInput, exception: Exception) -> str:\n    # this return is going to be the lambda\'s return value\n    return \'My exception occurred\'\n\npyckish_lambda = pyckish.Lambda()\n\n# Here you define what function is going to be executed when the exception you pass occurs\npyckish_lambda.add_exception_handler(handler_for_my_exception, MyException)\n\n# realize you have to use the instance you instantiated above\n@pyckish_lambda\ndef lambda_handler() -> None:\n    raise MyException()\n\n\nlambda_handler({}, {})\n``` ',
    'author': 'Pedro Dardengo',
    'author_email': 'pedrodardengo@hotmail.com',
    'maintainer': 'None',
    'maintainer_email': 'None',
    'url': 'None',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '==3.9.13',
}


setup(**setup_kwargs)
