Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop support for Python < 3.6 #1812

Merged
merged 10 commits into from
Mar 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
language: python
dist: xenial
python:
- "2.7"
- "3.5"
- "3.6"
- "3.7.3"
- "3.8"
- "3.9-dev"
- "3.9"
env:
global:
- TROPO_REAL_BOOL=true
Expand All @@ -18,7 +16,6 @@ install:
- pip install --upgrade flake8

before_script:
- if [[ $TRAVIS_PYTHON_VERSION == 3* ]]; then 2to3 -n -w --no-diffs troposphere scripts/cfn2py scripts/gen.py examples/CustomResource.py tests; fi
- flake8 --version
- flake8 . --show-source

Expand Down
4 changes: 2 additions & 2 deletions examples/CustomResource.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class CustomPlacementGroup(AWSCustomObject):
resource_type = "Custom::PlacementGroup"

props = {
'ServiceToken': (basestring, True),
'PlacementGroupName': (basestring, True)
'ServiceToken': (str, True),
'PlacementGroupName': (str, True)
}


Expand Down
2 changes: 1 addition & 1 deletion examples/EC2Conditions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from __future__ import print_function


from troposphere import (
Template, Parameter, Ref, Condition, Equals, And, Or, Not, If
Expand Down
2 changes: 1 addition & 1 deletion examples/ElastiCacheRedis.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
In addition to troposphere, this script requires awacs (Amazon Web Access
Control Subsystem)
"""
from __future__ import absolute_import, division, print_function


import troposphere.ec2 as ec2
import troposphere.elasticache as elasticache
Expand Down
44 changes: 22 additions & 22 deletions examples/Lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,31 +49,31 @@
))

t.add_mapping("AWSInstanceType2Arch",
{u'm1.small': {u'Arch': u'PV64'},
u't2.micro': {u'Arch': u'HVM64'}}
{'m1.small': {'Arch': 'PV64'},
't2.micro': {'Arch': 'HVM64'}}
)

t.add_mapping("AWSRegionArch2AMI",
{u'ap-northeast-1': {u'HVM64': u'ami-cbf90ecb',
u'PV64': u'ami-27f90e27'},
u'ap-southeast-1': {u'HVM64': u'ami-68d8e93a',
u'PV64': u'ami-acd9e8fe'},
u'ap-southeast-2': {u'HVM64': u'ami-fd9cecc7',
u'PV64': u'ami-ff9cecc5'},
u'cn-north-1': {u'HVM64': u'ami-f239abcb',
u'PV64': u'ami-fa39abc3'},
u'eu-central-1': {u'HVM64': u'ami-a8221fb5',
u'PV64': u'ami-ac221fb1'},
u'eu-west-1': {u'HVM64': u'ami-a10897d6',
u'PV64': u'ami-bf0897c8'},
u'sa-east-1': {u'HVM64': u'ami-b52890a8',
u'PV64': u'ami-bb2890a6'},
u'us-east-1': {u'HVM64': u'ami-1ecae776',
u'PV64': u'ami-1ccae774'},
u'us-west-1': {u'HVM64': u'ami-d114f295',
u'PV64': u'ami-d514f291'},
u'us-west-2': {u'HVM64': u'ami-e7527ed7',
u'PV64': u'ami-ff527ecf'}}
{'ap-northeast-1': {'HVM64': 'ami-cbf90ecb',
'PV64': 'ami-27f90e27'},
'ap-southeast-1': {'HVM64': 'ami-68d8e93a',
'PV64': 'ami-acd9e8fe'},
'ap-southeast-2': {'HVM64': 'ami-fd9cecc7',
'PV64': 'ami-ff9cecc5'},
'cn-north-1': {'HVM64': 'ami-f239abcb',
'PV64': 'ami-fa39abc3'},
'eu-central-1': {'HVM64': 'ami-a8221fb5',
'PV64': 'ami-ac221fb1'},
'eu-west-1': {'HVM64': 'ami-a10897d6',
'PV64': 'ami-bf0897c8'},
'sa-east-1': {'HVM64': 'ami-b52890a8',
'PV64': 'ami-bb2890a6'},
'us-east-1': {'HVM64': 'ami-1ecae776',
'PV64': 'ami-1ccae774'},
'us-west-1': {'HVM64': 'ami-d114f295',
'PV64': 'ami-d514f291'},
'us-west-2': {'HVM64': 'ami-e7527ed7',
'PV64': 'ami-ff527ecf'}}
)

code = [
Expand Down
16 changes: 5 additions & 11 deletions scripts/cfn2py
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
#!/usr/bin/env python
#!/usr/bin/env python3

from __future__ import print_function
import argparse
import json
import pprint

try:
getattr(__builtins__, 'basestring')
except AttributeError:
basestring = str


class object_registry(object):
"""Keep track of objects being created as Parameters or Resources
Expand Down Expand Up @@ -258,7 +252,7 @@ def do_resources(d):
tropo_object = top_level_aliases[tropo_object]
print('{} = t.add_resource({}('.format(object_name, tropo_object))
print(' "{}",'.format(k))
for p in filter(lambda x: x in v, ['Metadata', 'Properties']):
for p in (x for x in ['Metadata', 'Properties'] if x in v):
for pk, pv in v[p].items():
if pk == "Tags":
print(' Tags=Tags(')
Expand All @@ -270,7 +264,7 @@ def do_resources(d):
print(" {}={}({}),".format(pk, pk, output_dict(pv)))
elif pk in known_functions:
do_resources_content(pk, pv, p)
elif isinstance(pv, basestring):
elif isinstance(pv, str):
print(' {}="{}",'.format(pk, pv))
else:
print(' {}={},'.format(pk, output_value(pv)))
Expand Down Expand Up @@ -323,7 +317,7 @@ function_map = {
def output_value(v):
"""Output a value which may be a string or a set of function calls."""

if isinstance(v, basestring):
if isinstance(v, str):
return '"{}"'.format(v.replace('\\', '\\\\')
.replace('\n', '\\n')
.replace("\"", "\\\""))
Expand Down Expand Up @@ -357,7 +351,7 @@ def do_outputs(d):
print('{} = t.add_output(Output('.format(k))
print(' "{}",'.format(k))
for pk, pv in v.items():
if isinstance(pv, basestring):
if isinstance(pv, str):
print(' {}="{}",'.format(pk, pv))
else:
print(' {}={},'.format(pk, output_value(pv)))
Expand Down
6 changes: 3 additions & 3 deletions scripts/gen.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python

from __future__ import print_function

import argparse
import json
import yaml
Expand Down Expand Up @@ -339,8 +339,8 @@ def get_required(value):
'Integer': 'integer',
'Json': 'dict',
'Long': 'integer',
'String': 'basestring',
'Timestamp': 'basestring',
'String': 'str',
'Timestamp': 'str',
}


Expand Down
12 changes: 3 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
# ----------------------------------------------------------------------------


# ---- Future
from __future__ import print_function
from __future__ import with_statement

# ---- System
import os
from setuptools import setup
Expand Down Expand Up @@ -67,12 +63,12 @@ def get_version():
"Operating System :: POSIX :: Linux",

"Programming Language :: Python",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 2.7",
],

packages=[
Expand All @@ -85,11 +81,9 @@ def get_version():
'scripts/cfn2py'
],

python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
python_requires=">=3.6",
install_requires=file_contents("requirements.txt"),
test_suite="tests",
tests_require=["awacs>=0.8"],
extras_require={'policy': ['awacs>=0.8']},

use_2to3=True,
)
2 changes: 1 addition & 1 deletion tests/test_appsync.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class TestAppsyncResolver(unittest.TestCase):
def test_resolver_kind_bad_value(self):
with self.assertRaisesRegexp(ValueError, 'Kind must be one of'):
with self.assertRaisesRegex(ValueError, 'Kind must be one of'):
Resolver(
'MutationField',
DataSourceName='SomeDatasource',
Expand Down
2 changes: 1 addition & 1 deletion tests/test_awslambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_environment_variable_invalid_name(self):
Environment(Variables={var: 'value'})

self.assertTrue('Invalid environment variable name: %s' % var
in context.exception)
in context.exception.args)

def test_environment_variable_reserved(self):
for var in ['AWS_ACCESS_KEY', 'AWS_ACCESS_KEY_ID',
Expand Down
14 changes: 7 additions & 7 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def test_noproperty(self):
def test_empty_awsproperty_outputs_empty_object(self):
t = FakeAWSProperty()
d = t.to_dict()
self.assertEquals(len(d), 0)
self.assertEqual(len(d), 0)


class TestParameter(unittest.TestCase):
Expand Down Expand Up @@ -254,17 +254,17 @@ def test_get_or_add_adds(self):
t = Template()
p = Parameter("param", Type="String", Default="foo")
result = t.get_or_add_parameter(p)
self.assertEquals(t.parameters["param"], p)
self.assertEquals(result, p)
self.assertEqual(t.parameters["param"], p)
self.assertEqual(result, p)

def test_add_or_get_returns_with_out_adding_duplicate(self):
t = Template()
p = Parameter("param", Type="String", Default="foo")
t.add_parameter(p)
result = t.get_or_add_parameter(p)
self.assertEquals(t.parameters["param"], p)
self.assertEquals(result, p)
self.assertEquals(len(t.parameters), 1)
self.assertEqual(t.parameters["param"], p)
self.assertEqual(result, p)
self.assertEqual(len(t.parameters), 1)

def test_property_default(self):
p = Parameter("param", Type="String", Default="foo")
Expand Down Expand Up @@ -381,7 +381,7 @@ def test_ref_eq(self):

def test_ref_hash(self):
s = hash("AWS::NoValue")
r = hash(Ref(s))
r = hash(Ref("AWS::NoValue"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This worked on Python 2, but failed on Python 3.

Python 2.7.18:

>>> hash("AWS::NoValue")
-6577466268859890267
>>> hash(hash("AWS::NoValue"))
-6577466268859890267

Python 3.8.6

>>> hash("AWS::NoValue")
-3204540641682287495
>>> hash(hash("AWS::NoValue"))
-898697632468593544
>>> hash(hash(hash("AWS::NoValue")))
-898697632468593544

ref #1053


wch = cloudformation.WaitConditionHandle("TestResource")

Expand Down
4 changes: 2 additions & 2 deletions tests/test_cloudwatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ def test_validate_units(self):
for unit in cloudwatch.VALID_UNITS:
cloudwatch.validate_unit(unit)
for bad_unit in ['Minutes', 'Bytes/Minute', 'Bits/Hour', '']:
with self.assertRaisesRegexp(ValueError, "must be one of"):
with self.assertRaisesRegex(ValueError, "must be one of"):
cloudwatch.validate_unit(bad_unit)

def test_validate_treat_missing_data(self):
for value in cloudwatch.VALID_TREAT_MISSING_DATA_TYPES:
cloudwatch.validate_treat_missing_data(value)
for bad_value in ['exists', 'notMissing', '']:
with self.assertRaisesRegexp(ValueError, "must be one of"):
with self.assertRaisesRegex(ValueError, "must be one of"):
cloudwatch.validate_treat_missing_data(bad_value)


Expand Down
12 changes: 6 additions & 6 deletions tests/test_codebuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ def test_filter_no_filtergroup(self):
codebuild.ProjectTriggers().validate()

def test_filter_not_list(self):
match = "<type 'int'>, expected <type 'list'>"
with self.assertRaisesRegexp(TypeError, match):
match = "<class 'int'>, expected <class 'list'>"
with self.assertRaisesRegex(TypeError, match):
codebuild.ProjectTriggers(FilterGroups=42).validate()

def test_filter_element_not_a_list(self):
wh = codebuild.WebhookFilter
match = "is <type 'str'>, expected <type 'list'>"
with self.assertRaisesRegexp(TypeError, match):
match = "is <class 'str'>, expected <class 'list'>"
with self.assertRaisesRegex(TypeError, match):
codebuild.ProjectTriggers(FilterGroups=[
[wh(Type="EVENT", Pattern="PULL_REQUEST_CREATED")],
"not a list",
Expand All @@ -73,8 +73,8 @@ def test_filter_element_not_a_list(self):

def test_filter_fail(self):
wh = codebuild.WebhookFilter
match = "<type 'NoneType'>"
with self.assertRaisesRegexp(TypeError, match):
match = "<class 'NoneType'>"
with self.assertRaisesRegex(TypeError, match):
codebuild.ProjectTriggers(FilterGroups=[
[wh(Type="EVENT", Pattern="PULL_REQUEST_CREATED")],
[wh(Type="EVENT", Pattern="PULL_REQUEST_CREATED")],
Expand Down
4 changes: 2 additions & 2 deletions tests/test_codecommit.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_trigger(self):
'deleteReference',
]
)
with self.assertRaisesRegexp(ValueError, "Trigger events: all"):
with self.assertRaisesRegex(ValueError, "Trigger events: all"):
trigger.to_dict()

trigger = cc.Trigger(
Expand All @@ -36,5 +36,5 @@ def test_trigger(self):
'foobar',
]
)
with self.assertRaisesRegexp(ValueError, "invalid event foobar"):
with self.assertRaisesRegex(ValueError, "invalid event foobar"):
trigger.to_dict()
11 changes: 7 additions & 4 deletions tests/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def setUp(self):
def test_valid_data(self):
t = Template()
cd = ecs.ContainerDefinition.from_dict("mycontainer", self.d)
self.assertEquals(cd.Links[0], "containerA")
self.assertEqual(cd.Links[0], "containerA")
td = ecs.TaskDefinition(
"taskdef",
ContainerDefinitions=[cd],
Expand All @@ -61,12 +61,12 @@ def test_invalid_sub_property(self):
def test_toplevel_helper_fn(self):
self.d["Cpu"] = Ref("MyCPU")
cd = ecs.ContainerDefinition.from_dict("mycontainer", self.d)
self.assertEquals(cd.Cpu.data, {"Ref": "MyCPU"})
self.assertEqual(cd.Cpu.data, {"Ref": "MyCPU"})

def test_sub_property_helper_fn(self):
self.d["Environment"][0]["Value"] = Ref("RegistryStorage")
cd = ecs.ContainerDefinition.from_dict("mycontainer", self.d)
self.assertEquals(
self.assertEqual(
cd.Environment[0].Value.data, {"Ref": "RegistryStorage"})

def test_invalid_subproperty_definition(self):
Expand All @@ -75,11 +75,14 @@ def test_invalid_subproperty_definition(self):
ecs.ContainerDefinition.from_dict("mycontainer", self.d)

def test_tags_from_dict(self):
def key(k):
return (k["Key"], k["Value"])

d = {"key1": "value1", "key2": "value2"}
expected = [{"Key": k, "Value": v} for k, v in d.items()]
tags = Tags.from_dict(**d)

self.assertEquals(sorted(expected), sorted(tags.tags))
self.assertEqual(sorted(expected, key=key), sorted(tags.tags, key=key))


if __name__ == '__main__':
Expand Down
Loading