Skip to content

Commit e8f74f5

Browse files
authored
refactor: add support for Python 3 (#490) (#491)
* feat: add support for Python 3 (#428) * refactor: Updated imports to by Py3 compliant * refactor: Move class variable creation to constructor in globals.py Without moving this to the __init__, the globals.py file will not run in Py3 because it can't reference the constants. * refactor: Update update_policy.py to be Py3 compliant In Py3, the function .iteritems() on a dict was removed and replaced with .items(). * refactor: Update deployment_preference_collection.py to be Py3 compliant In Py3, .itervalues() and .iteritems() was replaced with .values() and .items(), respectfully. * refactor: Update swagger.py to be Py3 compliant In Py3, the .keys() method on a dictionary returns a dict_keys object that is a view into the dictionary. In Py2, it returns a list. To support Py3, we need to convert the .keys() to a list. * refactor: Update intrinsics.py to be Py3 compliant In Py3, the .keys() method on a dictionary returns a dict_keys object that is a view into the dictionary. In Py2, it returns a list. To support Py3, we need to convert the .keys() to a list. * Staging translator.py changes Updated .iteritems() to items() * refactor: More updating to be Py3 compliant * refactor: Make hashing constisent between py2 and py3 * refactor: Make exceptions sortable to allow error case tests to pass in Py3 * fix: add support for Python 3 (#445) * refactor: Updated imports to by Py3 compliant * refactor: Move class variable creation to constructor in globals.py Without moving this to the __init__, the globals.py file will not run in Py3 because it can't reference the constants. * refactor: Update update_policy.py to be Py3 compliant In Py3, the function .iteritems() on a dict was removed and replaced with .items(). * refactor: Update deployment_preference_collection.py to be Py3 compliant In Py3, .itervalues() and .iteritems() was replaced with .values() and .items(), respectfully. * refactor: Update swagger.py to be Py3 compliant In Py3, the .keys() method on a dictionary returns a dict_keys object that is a view into the dictionary. In Py2, it returns a list. To support Py3, we need to convert the .keys() to a list. * refactor: Update intrinsics.py to be Py3 compliant In Py3, the .keys() method on a dictionary returns a dict_keys object that is a view into the dictionary. In Py2, it returns a list. To support Py3, we need to convert the .keys() to a list. * Staging translator.py changes Updated .iteritems() to items() * refactor: More updating to be Py3 compliant * refactor: Make hashing constisent between py2 and py3 * refactor: Make exceptions sortable to allow error case tests to pass in Py3 * feat: Run tox from Travis-CI * feat: Update tox to run in Py2 and Py3 * refactor: Force sorting behavior to be Py2 compatible and update Deployment logicalid hash * fix: Update tox to run tests against Py27 and Py36 * Update Travis config to run Py2 and Py3 tests in parallel * Setting region env var in tox file for Travis to pick up * Set AWS region in travis file * Pass AWS_* env vars to tox * Fixing ordering of resource types in Globals error message * Py2/3 compatible implementation of string encoding for logicalId generator Also added lots of comments explaining why/how the deep sorting of lists work in unit tests * Removing redundant usage of bytes
1 parent a3a6d52 commit e8f74f5

29 files changed

+243
-85
lines changed

.travis.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
sudo: false
33
language: python
44

5+
matrix:
6+
include:
7+
- python: 3.6
8+
env:
9+
- TOXENV=py36
10+
- python: 2.7
11+
env:
12+
- TOXENV=py27
13+
14+
515
install:
616
# Install the code requirements
717
- make init
@@ -10,7 +20,7 @@ install:
1020

1121
script:
1222
# Runs unit tests
13-
- make pr
23+
- tox
1424

1525
# Build docs pages only from master branch
1626
- if [ "$TRAVIS_BRANCH" = "master" ]; then make build-docs; fi

samtranslator/intrinsics/resolver.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def _traverse_dict(self, input_dict, resolution_data, resolver_method):
117117
:param resolver_method: Method that can actually resolve an intrinsic function, if it detects one
118118
:return: Modified dictionary with values resolved
119119
"""
120-
for key, value in input_dict.iteritems():
120+
for key, value in input_dict.items():
121121
input_dict[key] = self._traverse(value, resolution_data, resolver_method)
122122

123123
return input_dict
@@ -150,7 +150,7 @@ def _try_resolve_parameter_refs(self, input, parameters):
150150
if not self._is_intrinsic_dict(input):
151151
return input
152152

153-
function_type = input.keys()[0]
153+
function_type = list(input.keys())[0]
154154
return self.supported_intrinsics[function_type].resolve_parameter_refs(input, parameters)
155155

156156
def _try_resolve_sam_resource_refs(self, input, supported_resource_refs):
@@ -168,7 +168,7 @@ def _try_resolve_sam_resource_refs(self, input, supported_resource_refs):
168168
if not self._is_intrinsic_dict(input):
169169
return input
170170

171-
function_type = input.keys()[0]
171+
function_type = list(input.keys())[0]
172172
return self.supported_intrinsics[function_type].resolve_resource_refs(input, supported_resource_refs)
173173

174174
def _is_intrinsic_dict(self, input):
@@ -181,4 +181,4 @@ def _is_intrinsic_dict(self, input):
181181
# All intrinsic functions are dictionaries with just one key
182182
return isinstance(input, dict) \
183183
and len(input) == 1 \
184-
and input.keys()[0] in self.supported_intrinsics
184+
and list(input.keys())[0] in self.supported_intrinsics

samtranslator/model/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def __init__(self, logical_id, relative_id=None, depends_on=None, attributes=Non
6868

6969
self.resource_attributes = {}
7070
if attributes is not None:
71-
for attr, value in attributes.iteritems():
71+
for attr, value in attributes.items():
7272
self.set_resource_attribute(attr, value)
7373

7474
@classmethod
@@ -367,7 +367,7 @@ def get_resource_references(self, generated_cfn_resources, supported_resource_re
367367
# Create a map of {ResourceType: LogicalId} for quick access
368368
resource_id_by_type = {resource.resource_type:resource.logical_id for resource in generated_cfn_resources}
369369

370-
for property, cfn_type in self.referable_properties.iteritems():
370+
for property, cfn_type in self.referable_properties.items():
371371
if cfn_type in resource_id_by_type:
372372
supported_resource_refs.add(self.logical_id, property, resource_id_by_type[cfn_type])
373373

samtranslator/model/eventsources/cloudwatchlogs.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from samtranslator.model import PropertyType
2-
from samtranslator.model.types import is_str
3-
from samtranslator.translator.arn_generator import ArnGenerator
42
from samtranslator.model.intrinsics import fnSub
53
from samtranslator.model.log import SubscriptionFilter
6-
from push import PushEventSource
4+
from samtranslator.model.types import is_str
5+
from samtranslator.translator.arn_generator import ArnGenerator
6+
from .push import PushEventSource
77

88
class CloudWatchLogs(PushEventSource):
99
"""CloudWatch Logs event source for SAM Functions."""

samtranslator/model/exceptions.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class InvalidDocumentException(Exception):
66
causes -- list of errors which caused this document to be invalid
77
"""
88
def __init__(self, causes):
9-
self._causes = causes
9+
self._causes = sorted(causes)
1010

1111
@property
1212
def message(self):
@@ -61,6 +61,9 @@ def __init__(self, logical_id, message):
6161
self._logical_id = logical_id
6262
self._message = message
6363

64+
def __lt__(self, other):
65+
return self._logical_id < other._logical_id
66+
6467
@property
6568
def message(self):
6669
return 'Resource with id [{}] is invalid. {}'.format(self._logical_id, self._message)

samtranslator/model/function_policies.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def _is_policy_template(self, policy):
140140
return self._policy_template_processor is not None and \
141141
isinstance(policy, dict) and \
142142
len(policy) == 1 and \
143-
self._policy_template_processor.has(policy.keys()[0]) is True
143+
self._policy_template_processor.has(list(policy.keys())[0]) is True
144144

145145

146146

samtranslator/model/intrinsics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def is_instrinsic(input):
5151
and isinstance(input, dict) \
5252
and len(input) == 1:
5353

54-
key = input.keys()[0]
54+
key = list(input.keys())[0]
5555
return key == "Ref" or key == "Condition" or key.startswith("Fn::")
5656

5757
return False

samtranslator/model/preferences/deployment_preference_collection.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
from deployment_preference import DeploymentPreference
1+
from .deployment_preference import DeploymentPreference
22
from samtranslator.model.codedeploy import CodeDeployApplication
33
from samtranslator.model.codedeploy import CodeDeployDeploymentGroup
44
from samtranslator.model.iam import IAMRole
5-
from samtranslator.model.update_policy import UpdatePolicy
65
from samtranslator.model.intrinsics import fnSub
6+
from samtranslator.model.update_policy import UpdatePolicy
77
from samtranslator.translator.arn_generator import ArnGenerator
88

99
CODE_DEPLOY_SERVICE_ROLE_LOGICAL_ID = 'CodeDeployServiceRole'
@@ -53,22 +53,22 @@ def any_enabled(self):
5353
"""
5454
:return: boolean whether any deployment preferences in the collection are enabled
5555
"""
56-
return any(preference.enabled for preference in self._resource_preferences.itervalues())
56+
return any(preference.enabled for preference in self._resource_preferences.values())
5757

5858
def can_skip_service_role(self):
5959
"""
6060
If every one of the deployment preferences have a custom IAM role provided, we can skip creating the
6161
service role altogether.
6262
:return: True, if we can skip creating service role. False otherwise
6363
"""
64-
return all(preference.role for preference in self._resource_preferences.itervalues())
64+
return all(preference.role for preference in self._resource_preferences.values())
6565

6666

6767
def enabled_logical_ids(self):
6868
"""
6969
:return: only the logical id's for the deployment preferences in this collection which are enabled
7070
"""
71-
return [logical_id for logical_id, preference in self._resource_preferences.iteritems() if preference.enabled]
71+
return [logical_id for logical_id, preference in self._resource_preferences.items() if preference.enabled]
7272

7373
def _codedeploy_application(self):
7474
codedeploy_application_resource = CodeDeployApplication(CODEDEPLOY_APPLICATION_LOGICAL_ID)

samtranslator/model/s3_utils/uri_parser.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
from urlparse import urlparse, parse_qs
2-
31
from six import string_types
2+
from six.moves.urllib.parse import urlparse, parse_qs
43

54

65
def parse_s3_uri(uri):

samtranslator/model/sam_resources.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
""" SAM macro definitions """
22
from six import string_types
3-
from tags.resource_tagging import get_tag_list
3+
44
import samtranslator.model.eventsources
55
import samtranslator.model.eventsources.pull
66
import samtranslator.model.eventsources.push
77
import samtranslator.model.eventsources.cloudwatchlogs
8+
from .api.api_generator import ApiGenerator
9+
from .s3_utils.uri_parser import parse_s3_uri
10+
from .tags.resource_tagging import get_tag_list
811
from samtranslator.model import (PropertyType, SamResourceMacro,
912
ResourceTypeResolver)
13+
from samtranslator.model.apigateway import ApiGatewayDeployment, ApiGatewayStage
1014
from samtranslator.model.dynamodb import DynamoDBTable
1115
from samtranslator.model.exceptions import (InvalidEventException,
1216
InvalidResourceException)
17+
from samtranslator.model.function_policies import FunctionPolicies, PolicyTypes
1318
from samtranslator.model.iam import IAMRole, IAMRolePolicies
1419
from samtranslator.model.lambda_ import LambdaFunction, LambdaVersion, LambdaAlias
15-
from samtranslator.model.apigateway import ApiGatewayDeployment, ApiGatewayStage
1620
from samtranslator.model.types import dict_of, is_str, is_type, list_of, one_of, any_type
17-
from samtranslator.model.function_policies import FunctionPolicies, PolicyTypes
1821
from samtranslator.translator import logical_id_generator
1922
from samtranslator.translator.arn_generator import ArnGenerator
20-
from api.api_generator import ApiGenerator
21-
from s3_utils.uri_parser import parse_s3_uri
2223

2324

2425
class SamFunction(SamResourceMacro):

0 commit comments

Comments
 (0)