TL;DR
Static Type Checkers help you find simple (but subtle) bugs in your Python code. Check out
lambda_types.py
and incrementally improve your code base and development/debugging experience with type hints.
Your Lambda Function code will go from this:
def handler(event, context):
first_name = event.get('first_name') or 'John'
last_name = event.get('last_name') or 'Smith'
return {
'message': get_message(first_name, last_name),
}
def get_message(first_name, last_name):
return 'Hello {} {}!'.format(first_name, last_name)
to this:
def handler(event: LambdaDict, context: LambdaContext) -> LambdaDict:
first_name: str = event.get('first_name') or 'John'
last_name: str = event.get('last_name') or 'Smith'
return {
'message': get_message(first_name, last_name),
}
def get_message(first_name: str, last_name: str):
return 'Hello {} {}!'.format(first_name, last_name)
Check out the two Lambda Functions below for more examples.
- Create a Python3 virtual env with
virtualenv venv --python=python3 && source venv/bin/activate
- Install mypy with
pip install mypy
- Run
mypy YOURFILE.py
or addmypy
to your IDE linting configuration (for VSCode, you'll need to enable thepython.linting.mypyEnabled
setting) - Create a local
lambda_types.py
file (you can find it below) and customize it as needed - Learn more about the built-in
typing
module here - (Just FYI: you can run all the tests below with Nose:
pip install nose
and then simply runnosetests
)
- Static code annotations will not affect your code execution, as they are only useful for static checks and code completion
- Of course, static typing works fine with Python classes as well
- Make sure your functions/methods are annotated if you want them to be checked
- You can use either annotations (natively supported only by Python3, sometimes bring to decreased readability) or special comments (e.g.
# type: str
) - You don't have to annotate every single function/file of your codebase to benefit from static type checking (i.e. you could focus on critical or semantically ambiguous/complex sections)
- Writing tests becomes easier/faster as well since many type-related errors will be detected at "compile time" and you won't have to unit-test them (for example, see the
lambda_repeat.get_output
function below) - You can customize
LambdaDict
based on your own event structures and conventions. For example, you may want to useDict[str, str]
orDict[str, Dict[str, Any]]
instead ofDict[str, Any]
- Thanks to code completion, you won't have to memorize all the LambdaContext attributes and methods (e.g.
context.get_remaining_time_in_millis()
,context.client_context.client.installation_id
, etc.)
@alexcasalboni thanks for the example.
Coming from using the Serverless framework with TypeScript, I was surprised how the template generated off of the Python implementation of Serverless does not include any type information (unlike the TypeScript one).
Moreover, given there's a specification in place (see PEP-561) on how to package and distribute type information, I'm surprised there isn't one with the types above.
Perhaps we can extract the above and distribute it as the PEP describes.