Skip to content

Commit 38d535c

Browse files
authored
chore: Add basic mypy check (no behavior change) (#2488)
1 parent ff9b657 commit 38d535c

File tree

16 files changed

+70
-29
lines changed

16 files changed

+70
-29
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ black-check:
2626
lint:
2727
# Linter performs static analysis to catch latent bugs
2828
pylint --rcfile .pylintrc samtranslator
29+
# mypy performs type check
30+
mypy samtranslator
2931

3032
prepare-companion-stack:
3133
pytest -v --no-cov integration/setup -m setup

mypy.ini

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
# https://mypy.readthedocs.io/en/stable/config_file.html#config-file-format
3+
4+
[mypy]
5+
warn_return_any=True
6+
warn_unused_configs=True
7+
no_implicit_optional=True
8+
warn_redundant_casts=True
9+
warn_unused_ignores=True
10+
warn_unreachable=True
11+
12+
[mypy-jsonschema,jsonschema.*]
13+
ignore_missing_imports=True

requirements/dev.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,11 @@ docopt~=0.6.2
2525

2626
# formatter
2727
black==20.8b1
28+
29+
# type check
30+
mypy==0.971
31+
32+
# types
33+
boto3-stubs[appconfig,serverlessrepo]>=1.19.5,==1.*
34+
types-PyYAML~=5.4
35+
types-jsonschema~=3.2

samtranslator/intrinsics/actions.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import re
22

3-
from samtranslator.utils.py27hash_fix import Py27UniStr
43
from samtranslator.model.exceptions import InvalidTemplateException, InvalidDocumentException
54

65

@@ -14,7 +13,11 @@ class Action(object):
1413
"""
1514

1615
_resource_ref_separator = "."
17-
intrinsic_name = None
16+
17+
# Note(xinhol): `Action` should have been an abstract class. Disabling the type check for the next
18+
# line to avoid any potential behavior change.
19+
# TODO: Make `Action` an abstract class and not giving `intrinsic_name` initial value.
20+
intrinsic_name: str = None # type: ignore
1821

1922
def __init__(self):
2023
if not self.intrinsic_name:

samtranslator/model/__init__.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
""" CloudFormation Resource serialization, deserialization, and validation """
22
import re
33
import inspect
4+
from typing import Any, Callable, Dict
5+
46
from samtranslator.model.exceptions import InvalidResourceException
57
from samtranslator.plugins import LifeCycleEvents
68
from samtranslator.model.tags.resource_tagging import get_tag_list
@@ -37,8 +39,11 @@ class Resource(object):
3739
be considered invalid.
3840
"""
3941

40-
resource_type = None
41-
property_types = None
42+
# Note(xinhol): `Resource` should have been an abstract class. Disabling the type check for the next
43+
# two lines to avoid any potential behavior change.
44+
# TODO: Make `Resource` an abstract class and not giving `resource_type`/`property_types` initial value.
45+
resource_type: str = None # type: ignore
46+
property_types: Dict[str, PropertyType] = None # type: ignore
4247
_keywords = ["logical_id", "relative_id", "depends_on", "resource_attributes"]
4348

4449
# For attributes in this list, they will be passed into the translated template for the same resource itself.
@@ -54,7 +59,7 @@ class Resource(object):
5459
# attrs = {
5560
# "arn": fnGetAtt(self.logical_id, "Arn")
5661
# }
57-
runtime_attrs = {}
62+
runtime_attrs: Dict[str, Callable[["Resource"], Any]] = {} # TODO: replace Any with something more explicit
5863

5964
def __init__(self, logical_id, relative_id=None, depends_on=None, attributes=None):
6065
"""Initializes a Resource object with the given logical id.
@@ -387,7 +392,7 @@ class SamResourceMacro(ResourceMacro):
387392
# resources, there is a separate process that associates this property with LogicalId of the generated CFN resource
388393
# of the given type.
389394

390-
referable_properties = {}
395+
referable_properties: Dict[str, str] = {}
391396

392397
# Each resource can optionally override this tag:
393398
_SAM_KEY = "lambda:createdBy"

samtranslator/model/api/api_generator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131

3232
_CORS_WILDCARD = "'*'"
3333
CorsProperties = namedtuple(
34-
"_CorsProperties", ["AllowMethods", "AllowHeaders", "AllowOrigin", "MaxAge", "AllowCredentials"]
34+
"CorsProperties", ["AllowMethods", "AllowHeaders", "AllowOrigin", "MaxAge", "AllowCredentials"]
3535
)
3636
# Default the Cors Properties to '*' wildcard and False AllowCredentials. Other properties are actually Optional
3737
CorsProperties.__new__.__defaults__ = (None, None, _CORS_WILDCARD, None, False)
3838

3939
AuthProperties = namedtuple(
40-
"_AuthProperties",
40+
"AuthProperties",
4141
[
4242
"Authorizers",
4343
"DefaultAuthorizer",
@@ -50,7 +50,7 @@
5050
)
5151
AuthProperties.__new__.__defaults__ = (None, None, None, True, None, None, None)
5252
UsagePlanProperties = namedtuple(
53-
"_UsagePlanProperties", ["CreateUsagePlan", "Description", "Quota", "Tags", "Throttle", "UsagePlanName"]
53+
"UsagePlanProperties", ["CreateUsagePlan", "Description", "Quota", "Tags", "Throttle", "UsagePlanName"]
5454
)
5555
UsagePlanProperties.__new__.__defaults__ = (None, None, None, None, None, None)
5656

samtranslator/model/api/http_api_generator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020

2121
_CORS_WILDCARD = "*"
2222
CorsProperties = namedtuple(
23-
"_CorsProperties", ["AllowMethods", "AllowHeaders", "AllowOrigins", "MaxAge", "ExposeHeaders", "AllowCredentials"]
23+
"CorsProperties", ["AllowMethods", "AllowHeaders", "AllowOrigins", "MaxAge", "ExposeHeaders", "AllowCredentials"]
2424
)
2525
CorsProperties.__new__.__defaults__ = (None, None, None, None, None, False)
2626

27-
AuthProperties = namedtuple("_AuthProperties", ["Authorizers", "DefaultAuthorizer", "EnableIamAuthorizer"])
27+
AuthProperties = namedtuple("AuthProperties", ["Authorizers", "DefaultAuthorizer", "EnableIamAuthorizer"])
2828
AuthProperties.__new__.__defaults__ = (None, None, False)
2929
DefaultStageName = "$default"
3030
HttpApiTagName = "httpapi:createdBy"

samtranslator/model/eventsources/pull.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ class PullEventSource(ResourceMacro):
2323
# Event types that support `FilterCriteria`, stored as a list to keep the alphabetical order
2424
RESOURCE_TYPES_WITH_EVENT_FILTERING = ["DynamoDB", "Kinesis", "SQS"]
2525

26-
resource_type = None
26+
# Note(xinhol): `PullEventSource` should have been an abstract class. Disabling the type check for the next
27+
# line to avoid any potential behavior change.
28+
# TODO: Make `PullEventSource` an abstract class and not giving `resource_type` initial value.
29+
resource_type: str = None # type: ignore
2730
requires_stream_queue_broker = True
2831
property_types = {
2932
"Stream": PropertyType(False, is_str()),

samtranslator/model/eventsources/push.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ class PushEventSource(ResourceMacro):
5050
:cvar str principal: The AWS service principal of the source service.
5151
"""
5252

53-
principal = None
53+
# Note(xinhol): `PushEventSource` should have been an abstract class. Disabling the type check for the next
54+
# line to avoid any potential behavior change.
55+
# TODO: Make `PushEventSource` an abstract class and not giving `principal` initial value.
56+
principal: str = None # type: ignore
5457

5558
def _construct_permission(
5659
self, function, source_arn=None, source_account=None, suffix="", event_source_token=None, prefix=None

samtranslator/model/sam_resources.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
""" SAM macro definitions """
22
import copy
3-
from typing import Union
3+
from typing import Any, Dict, Union
44
from samtranslator.intrinsics.resolver import IntrinsicsResolver
55

66
import samtranslator.model.eventsources
@@ -111,7 +111,7 @@ class SamFunction(SamResourceMacro):
111111
#
112112

113113
# Conditions
114-
conditions = {}
114+
conditions: Dict[str, Any] = {} # TODO: Replace `Any` with something more specific
115115

116116
# Customers can refer to the following properties of SAM function
117117
referable_properties = {
@@ -607,7 +607,7 @@ def _validate_dlq(self):
607607
if not self.DeadLetterQueue.get("Type") or not self.DeadLetterQueue.get("TargetArn"):
608608
raise InvalidResourceException(
609609
self.logical_id,
610-
"'DeadLetterQueue' requires Type and TargetArn properties to be specified.".format(valid_dlq_types),
610+
"'DeadLetterQueue' requires Type and TargetArn properties to be specified.",
611611
)
612612

613613
if not (isinstance(self.DeadLetterQueue.get("Type"), str)):

samtranslator/model/sqs.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
from typing import Dict
2+
13
from samtranslator.model import PropertyType, Resource
24
from samtranslator.model.types import is_type, list_of
35
from samtranslator.model.intrinsics import fnGetAtt, ref
46

57

68
class SQSQueue(Resource):
79
resource_type = "AWS::SQS::Queue"
8-
property_types = {}
10+
property_types: Dict[str, PropertyType] = {}
911
runtime_attrs = {
1012
"queue_url": lambda self: ref(self.logical_id),
1113
"arn": lambda self: fnGetAtt(self.logical_id, "Arn"),

samtranslator/model/stepfunctions/events.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ class EventSource(ResourceMacro):
2222
:cvar str principal: The AWS service principal of the source service.
2323
"""
2424

25-
principal = None
25+
# Note(xinhol): `EventSource` should have been an abstract class. Disabling the type check for the next
26+
# line to avoid any potential behavior change.
27+
# TODO: Make `EventSource` an abstract class and not giving `principal` initial value.
28+
principal: str = None # type: ignore
2629

2730
def _generate_logical_id(self, prefix, suffix, resource_type):
2831
"""Helper utility to generate a logicial ID for a new resource

samtranslator/plugins/globals/globals.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from samtranslator.public.sdk.resource import SamResourceType
1+
from typing import Dict, List
2+
3+
from samtranslator.public.sdk.resource import SamResourceType
24
from samtranslator.public.intrinsics import is_intrinsics
35
from samtranslator.swagger.swagger import SwaggerEditor
46

@@ -82,7 +84,7 @@ class Globals(object):
8284
SamResourceType.SimpleTable.value: ["SSESpecification"],
8385
}
8486
# unreleased_properties *must be* part of supported_properties too
85-
unreleased_properties = {}
87+
unreleased_properties: Dict[str, List[str]] = {}
8688

8789
def __init__(self, template):
8890
"""
@@ -179,9 +181,7 @@ def _parse(self, globals_dict):
179181

180182
globals = {}
181183
if not isinstance(globals_dict, dict):
182-
raise InvalidGlobalsSectionException(
183-
self._KEYWORD, "It must be a non-empty dictionary".format(self._KEYWORD)
184-
)
184+
raise InvalidGlobalsSectionException(self._KEYWORD, "It must be a non-empty dictionary")
185185

186186
for section_name, properties in globals_dict.items():
187187
resource_type = self._make_resource_type(section_name)

samtranslator/public/helpers.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

samtranslator/sdk/resource.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from enum import Enum
2+
from typing import Any, Dict
3+
24
from samtranslator.model.exceptions import InvalidDocumentException, InvalidTemplateException
35
from samtranslator.model.types import is_str
46

@@ -11,7 +13,7 @@ class SamResource(object):
1113
"""
1214

1315
type = None
14-
properties = {}
16+
properties: Dict[str, Any] = {} # TODO: Replace `Any` with something more specific
1517

1618
def __init__(self, resource_dict):
1719
"""

samtranslator/utils/py27hash_fix.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
MINSIZE = 8
1818
PERTURB_SHIFT = 5
1919

20-
unicode_string_type = str if sys.version_info.major >= 3 else unicode
21-
long_int_type = int if sys.version_info.major >= 3 else long
20+
unicode_string_type = str # TODO: remove it, python 2 legacy code
21+
long_int_type = int # TODO: remove it, python 2 legacy code
2222

2323

2424
def to_py27_compatible_template(template, parameter_values=None):

0 commit comments

Comments
 (0)