I'm still new to python, but my history is in the C/C++ world with plenty of Makefiles, though I've rarely written from scratch such elaborate ones as this.  The Hitchhiker's Guide to Python gave me permission to use a Makefile to organize my Python project, so that's what I did.I'm looking for suggestions on how to make this code more idiomatic, from the perspectives of both Makefile alone and also common usage of Makefile in Python projects. Any and all other feedback also welcome and appreciated.Consider also reviewing the Python that this Makefile deploys.all: deployment_test form.html # TODO: delete line when d'test depends on f'htmldeployment_test: deploy deployment.url web_response.ics.masked.expected    wget $(shell cat deployment.url)?place=flint%20hill%20va\&lookaheaddays=1 \        --output-document=web_response.ics    sed -e 's/DATE-TIME:.*/DATE-TIME:.../' \        -e 's/Sextant/*/' \        -e 's/Trine/*/' \        web_response.ics > web_response.ics.masked    diff -b web_response.ics.masked \         web_response.ics.masked.expected    echo Deployment test\(s\) passed. $(TIMESTAMP_FILE_CONTENTS) \        > deployment_testform.html: form.html_blank_action deployment.url    sed -e 's!form action=\\!form action=\$(shell cat deployment.url)\!' \        form.html_blank_action > form.htmlAWS_NAME=aspectusAWS_DESCRIPTION=aspect+prospectus. Generates iCalendars with astrological aspect events.AWS_APIGATEWAY_DEPLOYMENT_STAGE_NAME=proddeployment.url: configure_aws_environment    echo https://$(shell cat aws_apigateway_api_id).execute-api.$(shell aws configure get region).amazonaws.com/$(AWS_APIGATEWAY_DEPLOYMENT_STAGE_NAME)/$(AWS_NAME)>deployment.urldeploy: deployment.zip configure_aws_environment    aws s3 cp deployment.zip s3://$(AWS_NAME)/    aws lambda update-function-code \        --function-name $(AWS_NAME) \        --s3-bucket $(AWS_NAME) \        --s3-key deployment.zip \        > deploy    echo Deployment successful. $(TIMESTAMP_FILE_CONTENTS)>deployunit_test: *.py tests/*.py    python -m unittest discover -s tests    @echo Unit test\(s\) passed. $(TIMESTAMP_FILE_CONTENTS) > unit_testdeployment.zip: unit_test deployment_dependency_libraries    rm -rf deployment    mkdir deployment    cp *.py deployment    cp -R deployment_dependency_libraries/* deployment    cd deployment ; \        zip -qr ../deployment.zip *    rm -rf deploymentconfigure_aws_environment: aws_lambda_arn \                           aws_apigateway_api_id \                           aws_apigateway_resource_id \                           aws_apigateway_method \                           aws_apigateway_api_arn    aws apigateway put-integration \        --rest-api-id $(shell cat aws_apigateway_api_id) \        --resource-id $(shell cat aws_apigateway_resource_id) \        --http-method $(shell cat aws_apigateway_method) \        --type AWS_PROXY \        --integration-http-method POST \        --uri arn:aws:apigateway:$(shell aws configure get region):lambda:path/2015-03-31/functions/$(shell cat aws_lambda_arn)/invocations #\        #--request-parameters 'method.request.queryString.place=string,method.request.queryString.lookaheaddays=string'    aws apigateway put-method-response \        --rest-api-id $(shell cat aws_apigateway_api_id) \        --resource-id $(shell cat aws_apigateway_resource_id) \        --http-method $(shell cat aws_apigateway_method) \        --status-code 200 \        --response-models {}    aws apigateway put-integration-response \        --rest-api-id $(shell cat aws_apigateway_api_id) \        --resource-id $(shell cat aws_apigateway_resource_id) \        --http-method $(shell cat aws_apigateway_method) \        --status-code 200 \        --selection-pattern .*    aws apigateway create-deployment \        --rest-api-id $(shell cat aws_apigateway_api_id) \        --description $(AWS_DESCRIPTION) \        --stage-name $(AWS_APIGATEWAY_DEPLOYMENT_STAGE_NAME)    aws lambda add-permission \        --function-name $(AWS_NAME) \        --statement-id $(AWS_NAME)-all-stages \        --action lambda:InvokeFunction \        --principal apigateway.amazonaws.com \        --source-arn $(shell cat aws_apigateway_api_arn)/*/$(shell cat aws_apigateway_method)/$(AWS_NAME)    aws lambda add-permission \        --function-name $(AWS_NAME) \        --statement-id \            apigateway-$(AWS_NAME)-stage-$(AWS_APIGATEWAY_DEPLOYMENT_STAGE_NAME) \        --action lambda:InvokeFunction \        --principal apigateway.amazonaws.com \        --source-arn $(shell cat aws_apigateway_api_arn)/$(AWS_APIGATEWAY_DEPLOYMENT_STAGE_NAME)/$(shell cat aws_apigateway_method)/$(AWS_NAME)    aws s3 mb s3://$(AWS_NAME)    echo AWS environment configured. $(TIMESTAMP_FILE_CONTENTS) \        > configure_aws_environmentaws_apigateway_api_id:    aws apigateway create-rest-api \        --name $(AWS_NAME) \        --description $(AWS_DESCRIPTION) \        --output text \        --query id \        > aws_apigateway_api_id \        || (rm -f aws_apigateway_api_id ; false)aws_apigateway_resource_id: aws_apigateway_parent_resource_id    aws apigateway create-resource \        --rest-api-id $(shell cat aws_apigateway_api_id) \        --parent-id $(shell cat aws_apigateway_parent_resource_id) \        --path-part $(AWS_NAME) \        --query 'id' \        --output text \        > aws_apigateway_resource_id \        || (rm -f aws_apigateway_resource_id ; false)aws_apigateway_parent_resource_id:    aws apigateway get-resources \        --rest-api-id $(shell cat aws_apigateway_api_id) \        --query items[?path=='/'].id \        --output text \        > aws_apigateway_parent_resource_id \        || (rm -f aws_apigateway_parent_resource_id ; false)aws_apigateway_method: aws_apigateway_api_id aws_apigateway_resource_id    aws apigateway put-method \        --rest-api-id $(shell cat aws_apigateway_api_id) \        --resource-id $(shell cat aws_apigateway_resource_id) \        --http-method GET \        --authorization-type NONE \        --query 'httpMethod' \        --output text \        > aws_apigateway_method \        || (rm -f aws_apigateway_method ; false)aws_apigateway_api_arn: aws_lambda_arn aws_apigateway_api_id    sed -e 's/lambda/execute-api/' \        -e s/function:$(AWS_NAME)/$(shell cat aws_apigateway_api_id)/ \        aws_lambda_arn > aws_apigateway_api_arnaws_lambda_arn: aws_iam_role_arn     zip empty.zip aws_iam_role_arn    aws lambda create-function \        --function-name $(AWS_NAME) \        --description $(AWS_DESCRIPTION) \        --runtime python2.7 \        --role $(shell cat aws_iam_role_arn) \        --handler $(AWS_NAME).lambda_handler \        --zip-file fileb://empty.zip \        --query 'FunctionArn' \        --output text \        > aws_lambda_arn \        || (rm -f empty.zip aws_lambda_arn ; false)    rm -f empty.zipaws_iam_role_arn: aws_iam_assume_role_policy.jsonifeq $(wildcard aws_iam_role_arn)     $(info file aws_iam_role_arn does not exist. creating.)    aws iam create-role \        --role-name $(AWS_NAME) \        --assume-role-policy-document file://aws_iam_assume_role_policy.json \        --path /service-role/ \        --output text \        --query Role.Arn \        > aws_iam_role_arn \        || (rm -f aws_iam_role_arn ; false)    aws iam attach-role-policy \        --role-name $(AWS_NAME) \        --policy-arn \            arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole \        || (rm aws_iam_role_arn ; false)    sleep 10 # to let it sink in. w/out this, lambda create-function complainselse    $(info file aws_iam_role_arn already exists. updating existing arn.)    aws iam update-assume-role-policy \        --role-name $(AWS_NAME) \        --policy-document file://aws_iam_assume_role_policy.jsonendifdeployment_dependency_libraries: requirements.txt    $(info may fail if pip compiles binaries for non-x86_64 Linux)    rm -rf ./deployment_dependency_libraries    pip install \        --requirement requirements.txt \        --target ./deployment_dependency_libraries \        --compileclean: clean_aws_environment    rm -rf *.pyc \           web_response.ics \           web_response.ics.masked \           unit_test    rm -rf deployment_test \           form.html \           deployment.url \           deploy           deployment.zip \           deployment_dependency_librariesclean_aws_environment:ifneq $(wildcard aws_apigateway_api_id)     aws apigateway delete-rest-api \       --rest-api-id $(shell cat aws_apigateway_api_id)    rm -f aws_apigateway_api_idendif    $(info if there are multiple apigateways to delete, or if the created API ID does not get captured in the file aws_apigateway_api_id, this can take forever...)    $(info without these crazy sleeps, we will get TooManyRequestsException)    for i in `aws apigateway get-rest-apis \                  --output text \                  --query items[?name=='$(AWS_NAME)'].id` ; do \        aws apigateway delete-rest-api --rest-api-id $$i ; \        sleep 30 ; done    rm -f aws_apigateway_api_arn \          aws_apigateway_method \          aws_apigateway_parent_resource_id \          aws_apigateway_resource_id \          configure_aws_environment \          aws_iam_role_arn \          aws_lambda_arn    if aws iam list-roles | grep -q $(AWS_NAME) ; then \        aws iam detach-role-policy \            --role-name $(AWS_NAME) \            --policy-arn \                arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole \            || false ; \        aws iam delete-role --role-name $(AWS_NAME) || false ; fi    if aws lambda list-functions | grep -q $(AWS_NAME) ; then \        aws lambda delete-function --function-name $(AWS_NAME) || false ; fi    if aws s3 ls | grep -q $(AWS_NAME) ; then \        aws s3 rm --recursive s3://$(AWS_NAME)/ --include \* || false ; \        aws s3 rb s3://$(AWS_NAME) || false ; fiTIMESTAMP_FILE_CONTENTS=This file is a placeholder whose only significance is \in its timestamp. Its purpose is to indicate which Makefile targets need to \be executed. Changing the timestamp of this file \(such as by \updating/writing to it\) will likely break Makefile funcionality.# Backlog of improvements to this file:## As a maintainer, I want a Selenium WebDriver deployment test, which uses (and# whose target target depends) on both the Selenium script and form.html, in# order to integrate the form with the delivery & test pipeline.  (Then remove# the all: target, and make the deployment_test: target be first in this file.)## As a maintainer, I want Travis CI to do continuous unit testing triggered by# every commit to GitHub, with a status badge in REAME.md, so that the# fundamental functionality of the code is always known to be in a usable state.## As a maintainer, I want my AWS credentials securely conveyed to Travis CI, so# that every commit can also enable continuous deployment in addition to# continuous unit testing.  (Likely define encrypted variables in .travis.yml.# See:# * https://docs.travis-ci.com/user/environment-variables/#Defining-encrypted-variables-in-.travis.yml# * http://docs.aws.amazon.com/cli/latest/topic/config-vars.html)## As a maintainer, I want the Selenium deployment scripts to be automatically# run with each commit to GitHub, in order to enable continuous deployment# testing.  (Use Sauce Labs as in# https://docs.travis-ci.com/user/gui-and-headless-browsers/.)
Deploy a Python script as an AWS Lambda micro web service
python;makefile;amazon web services;integration testing