We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Syntax warning due to comparison of literals using is in Python 3.8
## Context

Syntax warning due to comparison of literals using is.

## Possible Fix

Use == and != as suggested in the warning

## Steps to Reproduce

```
find . -iname '*.py'  | xargs -P 4 -I{} python -Walways -m py_compile {} 

./zappa/core.py:2026: SyntaxWarning: "is" with a literal. Did you mean "=="?
  elif key is 'LambdaConfig':
./zappa/cli.py:1379: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if token.count('-') is 4 and token.replace('-', '').isalnum():
./zappa/cli.py:2513: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if (token.count('.') is 3 and token.replace('.', '').isnumeric()):
./zappa/cli.py:2548: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if token.count('-') is 4 and token.replace('-', '').isalnum():
./zappa/cli.py:2555: SyntaxWarning: "is" with a literal. Did you mean "=="?
  if token.count('.') is 3 and token.replace('.', '').isnumeric():
./example/authmodule.py:78: DeprecationWarning: invalid escape sequence \*
  pathRegex = "^[/.a-zA-Z0-9-\*]+$"
```

## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
* Zappa version used: master
* Operating System and Python version: Python 3.8
* The output of `pip freeze`:
* Link to your project (optional):
* Your `zappa_settings.json`: 


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `example/authmodule.py`
Content:
```
1 """
2 Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at
4      http://aws.amazon.com/apache2.0/
5 or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
6 """
7 import re
8 import time
9 import pprint
10 import json
11 
12 
13 def lambda_handler(event, context):
14     print("Client token: " + event['authorizationToken'])
15     print("Method ARN: " + event['methodArn'])
16     """validate the incoming token"""
17     """and produce the principal user identifier associated with the token"""
18 
19     """this could be accomplished in a number of ways:"""
20     """1. Call out to OAuth provider"""
21     """2. Decode a JWT token inline"""
22     """3. Lookup in a self-managed DB"""
23     principalId = "user|a1b2c3d4"
24 
25     """you can send a 401 Unauthorized response to the client by failing like so:"""
26     """raise Exception('Unauthorized')"""
27 
28     """if the token is valid, a policy must be generated which will allow or deny access to the client"""
29 
30     """if access is denied, the client will receive a 403 Access Denied response"""
31     """if access is allowed, API Gateway will proceed with the backend integration configured on the method that was called"""
32 
33     """this function must generate a policy that is associated with the recognized principal user identifier."""
34     """depending on your use case, you might store policies in a DB, or generate them on the fly"""
35 
36     """keep in mind, the policy is cached for 5 minutes by default (TTL is configurable in the authorizer)"""
37     """and will apply to subsequent calls to any method/resource in the RestApi"""
38     """made with the same token"""
39 
40     """the example policy below denies access to all resources in the RestApi"""
41     tmp = event['methodArn'].split(':')
42     apiGatewayArnTmp = tmp[5].split('/')
43     awsAccountId = tmp[4]
44 
45     policy = AuthPolicy(principalId, awsAccountId)
46     policy.restApiId = apiGatewayArnTmp[0]
47     policy.region = tmp[3]
48     policy.stage = apiGatewayArnTmp[1]
49 
50     # Blueprint denies all methods by default
51     # policy.denyAllMethods()
52 
53     # Example allows all methods
54     policy.allowAllMethods()
55 
56     """policy.allowMethod(HttpVerb.GET, "/pets/*")"""
57 
58     """finally, build the policy and exit the function using return"""
59     return policy.build()
60 
61 class HttpVerb:
62     GET     = "GET"
63     POST    = "POST"
64     PUT     = "PUT"
65     PATCH   = "PATCH"
66     HEAD    = "HEAD"
67     DELETE  = "DELETE"
68     OPTIONS = "OPTIONS"
69     ALL     = "*"
70 
71 class AuthPolicy:
72     awsAccountId = ""
73     """The AWS account id the policy will be generated for. This is used to create the method ARNs."""
74     principalId = ""
75     """The principal used for the policy, this should be a unique identifier for the end user."""
76     version = "2012-10-17"
77     """The policy version used for the evaluation. This should always be '2012-10-17'"""
78     pathRegex = "^[/.a-zA-Z0-9-\*]+$"
79     """The regular expression used to validate resource paths for the policy"""
80 
81     """these are the internal lists of allowed and denied methods. These are lists
82     of objects and each object has 2 properties: A resource ARN and a nullable
83     conditions statement.
84     the build method processes these lists and generates the appropriate
85     statements for the final policy"""
86     allowMethods = []
87     denyMethods = []
88 
89     restApiId = "*"
90     """The API Gateway API id. By default this is set to '*'"""
91     region = "*"
92     """The region where the API is deployed. By default this is set to '*'"""
93     stage = "*"
94     """The name of the stage used in the policy. By default this is set to '*'"""
95 
96     def __init__(self, principal, awsAccountId):
97         self.awsAccountId = awsAccountId
98         self.principalId = principal
99         self.allowMethods = []
100         self.denyMethods = []
101 
102     def _addMethod(self, effect, verb, resource, conditions):
103         """Adds a method to the internal lists of allowed or denied methods. Each object in
104         the internal list contains a resource ARN and a condition statement. The condition
105         statement can be null."""
106         if verb != "*" and not hasattr(HttpVerb, verb):
107             raise NameError("Invalid HTTP verb " + verb + ". Allowed verbs in HttpVerb class")
108         resourcePattern = re.compile(self.pathRegex)
109         if not resourcePattern.match(resource):
110             raise NameError("Invalid resource path: " + resource + ". Path should match " + self.pathRegex)
111 
112         if resource[:1] == "/":
113             resource = resource[1:]
114 
115         resourceArn = ("arn:aws:execute-api:" +
116             self.region + ":" +
117             self.awsAccountId + ":" +
118             self.restApiId + "/" +
119             self.stage + "/" +
120             verb + "/" +
121             resource)
122 
123         if effect.lower() == "allow":
124             self.allowMethods.append({
125                 'resourceArn' : resourceArn,
126                 'conditions' : conditions
127             })
128         elif effect.lower() == "deny":
129             self.denyMethods.append({
130                 'resourceArn' : resourceArn,
131                 'conditions' : conditions
132             })
133 
134     def _getEmptyStatement(self, effect):
135         """Returns an empty statement object prepopulated with the correct action and the
136         desired effect."""
137         statement = {
138             'Action': 'execute-api:Invoke',
139             'Effect': effect[:1].upper() + effect[1:].lower(),
140             'Resource': []
141         }
142 
143         return statement
144 
145     def _getStatementForEffect(self, effect, methods):
146         """This function loops over an array of objects containing a resourceArn and
147         conditions statement and generates the array of statements for the policy."""
148         statements = []
149 
150         if len(methods) > 0:
151             statement = self._getEmptyStatement(effect)
152 
153             for curMethod in methods:
154                 if curMethod['conditions'] is None or len(curMethod['conditions']) == 0:
155                     statement['Resource'].append(curMethod['resourceArn'])
156                 else:
157                     conditionalStatement = self._getEmptyStatement(effect)
158                     conditionalStatement['Resource'].append(curMethod['resourceArn'])
159                     conditionalStatement['Condition'] = curMethod['conditions']
160                     statements.append(conditionalStatement)
161 
162             statements.append(statement)
163 
164         return statements
165 
166     def allowAllMethods(self):
167         """Adds a '*' allow to the policy to authorize access to all methods of an API"""
168         self._addMethod("Allow", HttpVerb.ALL, "*", [])
169 
170     def denyAllMethods(self):
171         """Adds a '*' allow to the policy to deny access to all methods of an API"""
172         self._addMethod("Deny", HttpVerb.ALL, "*", [])
173 
174     def allowMethod(self, verb, resource):
175         """Adds an API Gateway method (Http verb + Resource path) to the list of allowed
176         methods for the policy"""
177         self._addMethod("Allow", verb, resource, [])
178 
179     def denyMethod(self, verb, resource):
180         """Adds an API Gateway method (Http verb + Resource path) to the list of denied
181         methods for the policy"""
182         self._addMethod("Deny", verb, resource, [])
183 
184     def allowMethodWithConditions(self, verb, resource, conditions):
185         """Adds an API Gateway method (Http verb + Resource path) to the list of allowed
186         methods and includes a condition for the policy statement. More on AWS policy
187         conditions here: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html#Condition"""
188         self._addMethod("Allow", verb, resource, conditions)
189 
190     def denyMethodWithConditions(self, verb, resource, conditions):
191         """Adds an API Gateway method (Http verb + Resource path) to the list of denied
192         methods and includes a condition for the policy statement. More on AWS policy
193         conditions here: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html#Condition"""
194         self._addMethod("Deny", verb, resource, conditions)
195 
196     def build(self):
197         """Generates the policy document based on the internal lists of allowed and denied
198         conditions. This will generate a policy with two main statements for the effect:
199         one statement for Allow and one statement for Deny.
200         Methods that includes conditions will have their own statement in the policy."""
201         if ((self.allowMethods is None or len(self.allowMethods) == 0) and
202             (self.denyMethods is None or len(self.denyMethods) == 0)):
203             raise NameError("No statements defined for the policy")
204 
205         policy = {
206             'principalId' : self.principalId,
207             'policyDocument' : {
208                 'Version' : self.version,
209                 'Statement' : []
210             }
211         }
212 
213         policy['policyDocument']['Statement'].extend(self._getStatementForEffect("Allow", self.allowMethods))
214         policy['policyDocument']['Statement'].extend(self._getStatementForEffect("Deny", self.denyMethods))
215 
216         return policy
217
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/example/authmodule.py b/example/authmodule.py
--- a/example/authmodule.py
+++ b/example/authmodule.py
@@ -75,7 +75,7 @@
     """The principal used for the policy, this should be a unique identifier for the end user."""
     version = "2012-10-17"
     """The policy version used for the evaluation. This should always be '2012-10-17'"""
-    pathRegex = "^[/.a-zA-Z0-9-\*]+$"
+    pathRegex = r"^[/.a-zA-Z0-9-\*]+$"
     """The regular expression used to validate resource paths for the policy"""
 
     """these are the internal lists of allowed and denied methods. These are lists

{"golden_diff": "diff --git a/example/authmodule.py b/example/authmodule.py\n--- a/example/authmodule.py\n+++ b/example/authmodule.py\n@@ -75,7 +75,7 @@\n     \"\"\"The principal used for the policy, this should be a unique identifier for the end user.\"\"\"\n     version = \"2012-10-17\"\n     \"\"\"The policy version used for the evaluation. This should always be '2012-10-17'\"\"\"\n-    pathRegex = \"^[/.a-zA-Z0-9-\\*]+$\"\n+    pathRegex = r\"^[/.a-zA-Z0-9-\\*]+$\"\n     \"\"\"The regular expression used to validate resource paths for the policy\"\"\"\n \n     \"\"\"these are the internal lists of allowed and denied methods. These are lists\n", "issue": "Syntax warning due to comparison of literals using is in Python 3.8\n## Context\r\n\r\nSyntax warning due to comparison of literals using is.\r\n\r\n## Possible Fix\r\n\r\nUse == and != as suggested in the warning\r\n\r\n## Steps to Reproduce\r\n\r\n```\r\nfind . -iname '*.py'  | xargs -P 4 -I{} python -Walways -m py_compile {} \r\n\r\n./zappa/core.py:2026: SyntaxWarning: \"is\" with a literal. Did you mean \"==\"?\r\n  elif key is 'LambdaConfig':\r\n./zappa/cli.py:1379: SyntaxWarning: \"is\" with a literal. Did you mean \"==\"?\r\n  if token.count('-') is 4 and token.replace('-', '').isalnum():\r\n./zappa/cli.py:2513: SyntaxWarning: \"is\" with a literal. Did you mean \"==\"?\r\n  if (token.count('.') is 3 and token.replace('.', '').isnumeric()):\r\n./zappa/cli.py:2548: SyntaxWarning: \"is\" with a literal. Did you mean \"==\"?\r\n  if token.count('-') is 4 and token.replace('-', '').isalnum():\r\n./zappa/cli.py:2555: SyntaxWarning: \"is\" with a literal. Did you mean \"==\"?\r\n  if token.count('.') is 3 and token.replace('.', '').isnumeric():\r\n./example/authmodule.py:78: DeprecationWarning: invalid escape sequence \\*\r\n  pathRegex = \"^[/.a-zA-Z0-9-\\*]+$\"\r\n```\r\n\r\n## Your Environment\r\n<!--- Include as many relevant details about the environment you experienced the bug in -->\r\n* Zappa version used: master\r\n* Operating System and Python version: Python 3.8\r\n* The output of `pip freeze`:\r\n* Link to your project (optional):\r\n* Your `zappa_settings.json`: \r\n\n", "before_files": [{"content": "\"\"\"\nCopyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.\nLicensed under the Apache License, Version 2.0 (the \"License\"). You may not use this file except in compliance with the License. A copy of the License is located at\n     http://aws.amazon.com/apache2.0/\nor in the \"license\" file accompanying this file. This file is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\"\"\"\nimport re\nimport time\nimport pprint\nimport json\n\n\ndef lambda_handler(event, context):\n    print(\"Client token: \" + event['authorizationToken'])\n    print(\"Method ARN: \" + event['methodArn'])\n    \"\"\"validate the incoming token\"\"\"\n    \"\"\"and produce the principal user identifier associated with the token\"\"\"\n\n    \"\"\"this could be accomplished in a number of ways:\"\"\"\n    \"\"\"1. Call out to OAuth provider\"\"\"\n    \"\"\"2. Decode a JWT token inline\"\"\"\n    \"\"\"3. Lookup in a self-managed DB\"\"\"\n    principalId = \"user|a1b2c3d4\"\n\n    \"\"\"you can send a 401 Unauthorized response to the client by failing like so:\"\"\"\n    \"\"\"raise Exception('Unauthorized')\"\"\"\n\n    \"\"\"if the token is valid, a policy must be generated which will allow or deny access to the client\"\"\"\n\n    \"\"\"if access is denied, the client will receive a 403 Access Denied response\"\"\"\n    \"\"\"if access is allowed, API Gateway will proceed with the backend integration configured on the method that was called\"\"\"\n\n    \"\"\"this function must generate a policy that is associated with the recognized principal user identifier.\"\"\"\n    \"\"\"depending on your use case, you might store policies in a DB, or generate them on the fly\"\"\"\n\n    \"\"\"keep in mind, the policy is cached for 5 minutes by default (TTL is configurable in the authorizer)\"\"\"\n    \"\"\"and will apply to subsequent calls to any method/resource in the RestApi\"\"\"\n    \"\"\"made with the same token\"\"\"\n\n    \"\"\"the example policy below denies access to all resources in the RestApi\"\"\"\n    tmp = event['methodArn'].split(':')\n    apiGatewayArnTmp = tmp[5].split('/')\n    awsAccountId = tmp[4]\n\n    policy = AuthPolicy(principalId, awsAccountId)\n    policy.restApiId = apiGatewayArnTmp[0]\n    policy.region = tmp[3]\n    policy.stage = apiGatewayArnTmp[1]\n\n    # Blueprint denies all methods by default\n    # policy.denyAllMethods()\n\n    # Example allows all methods\n    policy.allowAllMethods()\n\n    \"\"\"policy.allowMethod(HttpVerb.GET, \"/pets/*\")\"\"\"\n\n    \"\"\"finally, build the policy and exit the function using return\"\"\"\n    return policy.build()\n\nclass HttpVerb:\n    GET     = \"GET\"\n    POST    = \"POST\"\n    PUT     = \"PUT\"\n    PATCH   = \"PATCH\"\n    HEAD    = \"HEAD\"\n    DELETE  = \"DELETE\"\n    OPTIONS = \"OPTIONS\"\n    ALL     = \"*\"\n\nclass AuthPolicy:\n    awsAccountId = \"\"\n    \"\"\"The AWS account id the policy will be generated for. This is used to create the method ARNs.\"\"\"\n    principalId = \"\"\n    \"\"\"The principal used for the policy, this should be a unique identifier for the end user.\"\"\"\n    version = \"2012-10-17\"\n    \"\"\"The policy version used for the evaluation. This should always be '2012-10-17'\"\"\"\n    pathRegex = \"^[/.a-zA-Z0-9-\\*]+$\"\n    \"\"\"The regular expression used to validate resource paths for the policy\"\"\"\n\n    \"\"\"these are the internal lists of allowed and denied methods. These are lists\n    of objects and each object has 2 properties: A resource ARN and a nullable\n    conditions statement.\n    the build method processes these lists and generates the appropriate\n    statements for the final policy\"\"\"\n    allowMethods = []\n    denyMethods = []\n\n    restApiId = \"*\"\n    \"\"\"The API Gateway API id. By default this is set to '*'\"\"\"\n    region = \"*\"\n    \"\"\"The region where the API is deployed. By default this is set to '*'\"\"\"\n    stage = \"*\"\n    \"\"\"The name of the stage used in the policy. By default this is set to '*'\"\"\"\n\n    def __init__(self, principal, awsAccountId):\n        self.awsAccountId = awsAccountId\n        self.principalId = principal\n        self.allowMethods = []\n        self.denyMethods = []\n\n    def _addMethod(self, effect, verb, resource, conditions):\n        \"\"\"Adds a method to the internal lists of allowed or denied methods. Each object in\n        the internal list contains a resource ARN and a condition statement. The condition\n        statement can be null.\"\"\"\n        if verb != \"*\" and not hasattr(HttpVerb, verb):\n            raise NameError(\"Invalid HTTP verb \" + verb + \". Allowed verbs in HttpVerb class\")\n        resourcePattern = re.compile(self.pathRegex)\n        if not resourcePattern.match(resource):\n            raise NameError(\"Invalid resource path: \" + resource + \". Path should match \" + self.pathRegex)\n\n        if resource[:1] == \"/\":\n            resource = resource[1:]\n\n        resourceArn = (\"arn:aws:execute-api:\" +\n            self.region + \":\" +\n            self.awsAccountId + \":\" +\n            self.restApiId + \"/\" +\n            self.stage + \"/\" +\n            verb + \"/\" +\n            resource)\n\n        if effect.lower() == \"allow\":\n            self.allowMethods.append({\n                'resourceArn' : resourceArn,\n                'conditions' : conditions\n            })\n        elif effect.lower() == \"deny\":\n            self.denyMethods.append({\n                'resourceArn' : resourceArn,\n                'conditions' : conditions\n            })\n\n    def _getEmptyStatement(self, effect):\n        \"\"\"Returns an empty statement object prepopulated with the correct action and the\n        desired effect.\"\"\"\n        statement = {\n            'Action': 'execute-api:Invoke',\n            'Effect': effect[:1].upper() + effect[1:].lower(),\n            'Resource': []\n        }\n\n        return statement\n\n    def _getStatementForEffect(self, effect, methods):\n        \"\"\"This function loops over an array of objects containing a resourceArn and\n        conditions statement and generates the array of statements for the policy.\"\"\"\n        statements = []\n\n        if len(methods) > 0:\n            statement = self._getEmptyStatement(effect)\n\n            for curMethod in methods:\n                if curMethod['conditions'] is None or len(curMethod['conditions']) == 0:\n                    statement['Resource'].append(curMethod['resourceArn'])\n                else:\n                    conditionalStatement = self._getEmptyStatement(effect)\n                    conditionalStatement['Resource'].append(curMethod['resourceArn'])\n                    conditionalStatement['Condition'] = curMethod['conditions']\n                    statements.append(conditionalStatement)\n\n            statements.append(statement)\n\n        return statements\n\n    def allowAllMethods(self):\n        \"\"\"Adds a '*' allow to the policy to authorize access to all methods of an API\"\"\"\n        self._addMethod(\"Allow\", HttpVerb.ALL, \"*\", [])\n\n    def denyAllMethods(self):\n        \"\"\"Adds a '*' allow to the policy to deny access to all methods of an API\"\"\"\n        self._addMethod(\"Deny\", HttpVerb.ALL, \"*\", [])\n\n    def allowMethod(self, verb, resource):\n        \"\"\"Adds an API Gateway method (Http verb + Resource path) to the list of allowed\n        methods for the policy\"\"\"\n        self._addMethod(\"Allow\", verb, resource, [])\n\n    def denyMethod(self, verb, resource):\n        \"\"\"Adds an API Gateway method (Http verb + Resource path) to the list of denied\n        methods for the policy\"\"\"\n        self._addMethod(\"Deny\", verb, resource, [])\n\n    def allowMethodWithConditions(self, verb, resource, conditions):\n        \"\"\"Adds an API Gateway method (Http verb + Resource path) to the list of allowed\n        methods and includes a condition for the policy statement. More on AWS policy\n        conditions here: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html#Condition\"\"\"\n        self._addMethod(\"Allow\", verb, resource, conditions)\n\n    def denyMethodWithConditions(self, verb, resource, conditions):\n        \"\"\"Adds an API Gateway method (Http verb + Resource path) to the list of denied\n        methods and includes a condition for the policy statement. More on AWS policy\n        conditions here: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html#Condition\"\"\"\n        self._addMethod(\"Deny\", verb, resource, conditions)\n\n    def build(self):\n        \"\"\"Generates the policy document based on the internal lists of allowed and denied\n        conditions. This will generate a policy with two main statements for the effect:\n        one statement for Allow and one statement for Deny.\n        Methods that includes conditions will have their own statement in the policy.\"\"\"\n        if ((self.allowMethods is None or len(self.allowMethods) == 0) and\n            (self.denyMethods is None or len(self.denyMethods) == 0)):\n            raise NameError(\"No statements defined for the policy\")\n\n        policy = {\n            'principalId' : self.principalId,\n            'policyDocument' : {\n                'Version' : self.version,\n                'Statement' : []\n            }\n        }\n\n        policy['policyDocument']['Statement'].extend(self._getStatementForEffect(\"Allow\", self.allowMethods))\n        policy['policyDocument']['Statement'].extend(self._getStatementForEffect(\"Deny\", self.denyMethods))\n\n        return policy\n", "path": "example/authmodule.py"}], "after_files": [{"content": "\"\"\"\nCopyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.\nLicensed under the Apache License, Version 2.0 (the \"License\"). You may not use this file except in compliance with the License. A copy of the License is located at\n     http://aws.amazon.com/apache2.0/\nor in the \"license\" file accompanying this file. This file is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n\"\"\"\nimport re\nimport time\nimport pprint\nimport json\n\n\ndef lambda_handler(event, context):\n    print(\"Client token: \" + event['authorizationToken'])\n    print(\"Method ARN: \" + event['methodArn'])\n    \"\"\"validate the incoming token\"\"\"\n    \"\"\"and produce the principal user identifier associated with the token\"\"\"\n\n    \"\"\"this could be accomplished in a number of ways:\"\"\"\n    \"\"\"1. Call out to OAuth provider\"\"\"\n    \"\"\"2. Decode a JWT token inline\"\"\"\n    \"\"\"3. Lookup in a self-managed DB\"\"\"\n    principalId = \"user|a1b2c3d4\"\n\n    \"\"\"you can send a 401 Unauthorized response to the client by failing like so:\"\"\"\n    \"\"\"raise Exception('Unauthorized')\"\"\"\n\n    \"\"\"if the token is valid, a policy must be generated which will allow or deny access to the client\"\"\"\n\n    \"\"\"if access is denied, the client will receive a 403 Access Denied response\"\"\"\n    \"\"\"if access is allowed, API Gateway will proceed with the backend integration configured on the method that was called\"\"\"\n\n    \"\"\"this function must generate a policy that is associated with the recognized principal user identifier.\"\"\"\n    \"\"\"depending on your use case, you might store policies in a DB, or generate them on the fly\"\"\"\n\n    \"\"\"keep in mind, the policy is cached for 5 minutes by default (TTL is configurable in the authorizer)\"\"\"\n    \"\"\"and will apply to subsequent calls to any method/resource in the RestApi\"\"\"\n    \"\"\"made with the same token\"\"\"\n\n    \"\"\"the example policy below denies access to all resources in the RestApi\"\"\"\n    tmp = event['methodArn'].split(':')\n    apiGatewayArnTmp = tmp[5].split('/')\n    awsAccountId = tmp[4]\n\n    policy = AuthPolicy(principalId, awsAccountId)\n    policy.restApiId = apiGatewayArnTmp[0]\n    policy.region = tmp[3]\n    policy.stage = apiGatewayArnTmp[1]\n\n    # Blueprint denies all methods by default\n    # policy.denyAllMethods()\n\n    # Example allows all methods\n    policy.allowAllMethods()\n\n    \"\"\"policy.allowMethod(HttpVerb.GET, \"/pets/*\")\"\"\"\n\n    \"\"\"finally, build the policy and exit the function using return\"\"\"\n    return policy.build()\n\nclass HttpVerb:\n    GET     = \"GET\"\n    POST    = \"POST\"\n    PUT     = \"PUT\"\n    PATCH   = \"PATCH\"\n    HEAD    = \"HEAD\"\n    DELETE  = \"DELETE\"\n    OPTIONS = \"OPTIONS\"\n    ALL     = \"*\"\n\nclass AuthPolicy:\n    awsAccountId = \"\"\n    \"\"\"The AWS account id the policy will be generated for. This is used to create the method ARNs.\"\"\"\n    principalId = \"\"\n    \"\"\"The principal used for the policy, this should be a unique identifier for the end user.\"\"\"\n    version = \"2012-10-17\"\n    \"\"\"The policy version used for the evaluation. This should always be '2012-10-17'\"\"\"\n    pathRegex = r\"^[/.a-zA-Z0-9-\\*]+$\"\n    \"\"\"The regular expression used to validate resource paths for the policy\"\"\"\n\n    \"\"\"these are the internal lists of allowed and denied methods. These are lists\n    of objects and each object has 2 properties: A resource ARN and a nullable\n    conditions statement.\n    the build method processes these lists and generates the appropriate\n    statements for the final policy\"\"\"\n    allowMethods = []\n    denyMethods = []\n\n    restApiId = \"*\"\n    \"\"\"The API Gateway API id. By default this is set to '*'\"\"\"\n    region = \"*\"\n    \"\"\"The region where the API is deployed. By default this is set to '*'\"\"\"\n    stage = \"*\"\n    \"\"\"The name of the stage used in the policy. By default this is set to '*'\"\"\"\n\n    def __init__(self, principal, awsAccountId):\n        self.awsAccountId = awsAccountId\n        self.principalId = principal\n        self.allowMethods = []\n        self.denyMethods = []\n\n    def _addMethod(self, effect, verb, resource, conditions):\n        \"\"\"Adds a method to the internal lists of allowed or denied methods. Each object in\n        the internal list contains a resource ARN and a condition statement. The condition\n        statement can be null.\"\"\"\n        if verb != \"*\" and not hasattr(HttpVerb, verb):\n            raise NameError(\"Invalid HTTP verb \" + verb + \". Allowed verbs in HttpVerb class\")\n        resourcePattern = re.compile(self.pathRegex)\n        if not resourcePattern.match(resource):\n            raise NameError(\"Invalid resource path: \" + resource + \". Path should match \" + self.pathRegex)\n\n        if resource[:1] == \"/\":\n            resource = resource[1:]\n\n        resourceArn = (\"arn:aws:execute-api:\" +\n            self.region + \":\" +\n            self.awsAccountId + \":\" +\n            self.restApiId + \"/\" +\n            self.stage + \"/\" +\n            verb + \"/\" +\n            resource)\n\n        if effect.lower() == \"allow\":\n            self.allowMethods.append({\n                'resourceArn' : resourceArn,\n                'conditions' : conditions\n            })\n        elif effect.lower() == \"deny\":\n            self.denyMethods.append({\n                'resourceArn' : resourceArn,\n                'conditions' : conditions\n            })\n\n    def _getEmptyStatement(self, effect):\n        \"\"\"Returns an empty statement object prepopulated with the correct action and the\n        desired effect.\"\"\"\n        statement = {\n            'Action': 'execute-api:Invoke',\n            'Effect': effect[:1].upper() + effect[1:].lower(),\n            'Resource': []\n        }\n\n        return statement\n\n    def _getStatementForEffect(self, effect, methods):\n        \"\"\"This function loops over an array of objects containing a resourceArn and\n        conditions statement and generates the array of statements for the policy.\"\"\"\n        statements = []\n\n        if len(methods) > 0:\n            statement = self._getEmptyStatement(effect)\n\n            for curMethod in methods:\n                if curMethod['conditions'] is None or len(curMethod['conditions']) == 0:\n                    statement['Resource'].append(curMethod['resourceArn'])\n                else:\n                    conditionalStatement = self._getEmptyStatement(effect)\n                    conditionalStatement['Resource'].append(curMethod['resourceArn'])\n                    conditionalStatement['Condition'] = curMethod['conditions']\n                    statements.append(conditionalStatement)\n\n            statements.append(statement)\n\n        return statements\n\n    def allowAllMethods(self):\n        \"\"\"Adds a '*' allow to the policy to authorize access to all methods of an API\"\"\"\n        self._addMethod(\"Allow\", HttpVerb.ALL, \"*\", [])\n\n    def denyAllMethods(self):\n        \"\"\"Adds a '*' allow to the policy to deny access to all methods of an API\"\"\"\n        self._addMethod(\"Deny\", HttpVerb.ALL, \"*\", [])\n\n    def allowMethod(self, verb, resource):\n        \"\"\"Adds an API Gateway method (Http verb + Resource path) to the list of allowed\n        methods for the policy\"\"\"\n        self._addMethod(\"Allow\", verb, resource, [])\n\n    def denyMethod(self, verb, resource):\n        \"\"\"Adds an API Gateway method (Http verb + Resource path) to the list of denied\n        methods for the policy\"\"\"\n        self._addMethod(\"Deny\", verb, resource, [])\n\n    def allowMethodWithConditions(self, verb, resource, conditions):\n        \"\"\"Adds an API Gateway method (Http verb + Resource path) to the list of allowed\n        methods and includes a condition for the policy statement. More on AWS policy\n        conditions here: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html#Condition\"\"\"\n        self._addMethod(\"Allow\", verb, resource, conditions)\n\n    def denyMethodWithConditions(self, verb, resource, conditions):\n        \"\"\"Adds an API Gateway method (Http verb + Resource path) to the list of denied\n        methods and includes a condition for the policy statement. More on AWS policy\n        conditions here: http://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html#Condition\"\"\"\n        self._addMethod(\"Deny\", verb, resource, conditions)\n\n    def build(self):\n        \"\"\"Generates the policy document based on the internal lists of allowed and denied\n        conditions. This will generate a policy with two main statements for the effect:\n        one statement for Allow and one statement for Deny.\n        Methods that includes conditions will have their own statement in the policy.\"\"\"\n        if ((self.allowMethods is None or len(self.allowMethods) == 0) and\n            (self.denyMethods is None or len(self.denyMethods) == 0)):\n            raise NameError(\"No statements defined for the policy\")\n\n        policy = {\n            'principalId' : self.principalId,\n            'policyDocument' : {\n                'Version' : self.version,\n                'Statement' : []\n            }\n        }\n\n        policy['policyDocument']['Statement'].extend(self._getStatementForEffect(\"Allow\", self.allowMethods))\n        policy['policyDocument']['Statement'].extend(self._getStatementForEffect(\"Deny\", self.denyMethods))\n\n        return policy\n", "path": "example/authmodule.py"}]}