Remove Py2 support (#3915)

This commit is contained in:
Bert Blommers 2021-07-26 07:40:39 +01:00 committed by GitHub
parent 658f850fcc
commit 7693d77333
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
94 changed files with 313 additions and 565 deletions

View File

@ -40,7 +40,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: [ 2.7, 3.6, 3.7, 3.8 ] python-version: [ 3.6, 3.7, 3.8 ]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -59,7 +59,7 @@ jobs:
path: ${{ steps.pip-cache-dir.outputs.dir }} path: ${{ steps.pip-cache-dir.outputs.dir }}
key: pip-${{ matrix.python-version }}-${{ hashFiles('**/setup.py') }}-4 key: pip-${{ matrix.python-version }}-${{ hashFiles('**/setup.py') }}-4
- name: Update pip - name: Update pip
if: ${{ steps.pip-cache.outputs.cache-hit != 'true' && matrix.python-version != '2.7' }} if: ${{ steps.pip-cache.outputs.cache-hit != 'true' }}
run: | run: |
python -m pip install pip==21.1.3 python -m pip install pip==21.1.3
- name: Install project dependencies - name: Install project dependencies
@ -92,7 +92,6 @@ jobs:
key: pip-${{ matrix.python-version }}-${{ hashFiles('**/setup.py') }}-4 key: pip-${{ matrix.python-version }}-${{ hashFiles('**/setup.py') }}-4
# Update PIP - recent version does not support PY2 though # Update PIP - recent version does not support PY2 though
- name: Update pip - name: Update pip
if: ${{ matrix.python-version != '2.7' }}
run: | run: |
# https://github.com/pypa/pip/issues/10201 # https://github.com/pypa/pip/issues/10201
python -m pip install pip==21.1.3 python -m pip install pip==21.1.3
@ -111,7 +110,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: [2.7, 3.6, 3.7, 3.8] python-version: [3.6, 3.7, 3.8]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -131,7 +130,6 @@ jobs:
path: ${{ steps.pip-cache.outputs.dir }} path: ${{ steps.pip-cache.outputs.dir }}
key: pip-${{ matrix.python-version }}-${{ hashFiles('**/setup.py') }}-4 key: pip-${{ matrix.python-version }}-${{ hashFiles('**/setup.py') }}-4
- name: Update pip - name: Update pip
if: ${{ matrix.python-version != '2.7' }}
run: | run: |
python -m pip install pip==21.1.3 python -m pip install pip==21.1.3
- name: Install project dependencies - name: Install project dependencies
@ -154,7 +152,7 @@ jobs:
needs: lint needs: lint
strategy: strategy:
matrix: matrix:
python-version: [2.7, 3.6, 3.7, 3.8] python-version: [3.6, 3.7, 3.8]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -179,7 +177,6 @@ jobs:
path: ${{ steps.pip-cache.outputs.dir }} path: ${{ steps.pip-cache.outputs.dir }}
key: pip-${{ matrix.python-version }}-${{ hashFiles('**/setup.py') }}-4 key: pip-${{ matrix.python-version }}-${{ hashFiles('**/setup.py') }}-4
- name: Update pip - name: Update pip
if: ${{ matrix.python-version != '2.7' }}
run: | run: |
python -m pip install pip==21.1.3 python -m pip install pip==21.1.3
- name: Install project dependencies - name: Install project dependencies

View File

@ -1,7 +1,7 @@
codecov: codecov:
notify: notify:
# Leave a GitHub comment after all builds have passed # Leave a GitHub comment after all builds have passed
after_n_builds: 8 after_n_builds: 6
coverage: coverage:
status: status:
project: project:

View File

@ -1,5 +1,4 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import six
import random import random
import string import string
@ -7,4 +6,4 @@ import string
def create_id(): def create_id():
size = 10 size = 10
chars = list(range(10)) + list(string.ascii_lowercase) chars = list(range(10)) + list(string.ascii_lowercase)
return "".join(six.text_type(random.choice(chars)) for x in range(size)) return "".join(str(random.choice(chars)) for x in range(size))

View File

@ -1,4 +1,4 @@
from six.moves.urllib.parse import urlparse from urllib.parse import urlparse
def region_from_applicationautoscaling_url(url): def region_from_applicationautoscaling_url(url):

View File

@ -3,8 +3,6 @@ from __future__ import unicode_literals
import json import json
import uuid import uuid
from six import string_types
from moto.awslambda.exceptions import PreconditionFailedException from moto.awslambda.exceptions import PreconditionFailedException
@ -96,7 +94,7 @@ class Policy:
obj[key] = value obj[key] = value
def principal_formatter(self, obj): def principal_formatter(self, obj):
if isinstance(obj, string_types): if isinstance(obj, str):
if obj.endswith(".amazonaws.com"): if obj.endswith(".amazonaws.com"):
return {"Service": obj} return {"Service": obj}
if obj.endswith(":root"): if obj.endswith(":root"):

View File

@ -1,7 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import re import re
from itertools import cycle from itertools import cycle
import six
import datetime import datetime
import time import time
import uuid import uuid
@ -867,7 +866,7 @@ class BatchBackend(BaseBackend):
security_group_names=[], security_group_names=[],
instance_type=instance_type, instance_type=instance_type,
region_name=self.region_name, region_name=self.region_name,
subnet_id=six.next(subnet_cycle), subnet_id=next(subnet_cycle),
key_name=compute_resources.get("ec2KeyPair", "AWS_OWNED"), key_name=compute_resources.get("ec2KeyPair", "AWS_OWNED"),
security_group_ids=compute_resources["securityGroupIds"], security_group_ids=compute_resources["securityGroupIds"],
) )

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import batch_backends from .models import batch_backends
from six.moves.urllib.parse import urlsplit from urllib.parse import urlsplit
from .exceptions import AWSError from .exceptions import AWSError

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
import json import json
import yaml import yaml
from six.moves.urllib.parse import urlparse from urllib.parse import urlparse
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from moto.core.utils import amzn_request_id from moto.core.utils import amzn_request_id

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import uuid import uuid
import six
import random import random
import yaml import yaml
import os import os
@ -37,7 +36,7 @@ def generate_stackset_arn(stackset_id, region_name):
def random_suffix(): def random_suffix():
size = 12 size = 12
chars = list(range(10)) + list(string.ascii_uppercase) chars = list(range(10)) + list(string.ascii_uppercase)
return "".join(six.text_type(random.choice(chars)) for x in range(size)) return "".join(str(random.choice(chars)) for x in range(size))
def yaml_tag_constructor(loader, tag, node): def yaml_tag_constructor(loader, tag, node):

View File

@ -1,5 +1,4 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import six
import random import random
import string import string
import hashlib import hashlib
@ -10,7 +9,7 @@ import base64
def create_id(): def create_id():
size = 26 size = 26
chars = list(range(10)) + list(string.ascii_lowercase) chars = list(range(10)) + list(string.ascii_lowercase)
return "".join(six.text_type(random.choice(chars)) for x in range(size)) return "".join(str(random.choice(chars)) for x in range(size))
def check_secret_hash(app_client_secret, app_client_id, username, secret_hash): def check_secret_hash(app_client_secret, app_client_id, username, secret_hash):

View File

@ -7,7 +7,6 @@ import inspect
import os import os
import pkg_resources import pkg_resources
import re import re
import six
import types import types
from abc import abstractmethod from abc import abstractmethod
from io import BytesIO from io import BytesIO
@ -16,7 +15,8 @@ from botocore.config import Config
from botocore.handlers import BUILTIN_HANDLERS from botocore.handlers import BUILTIN_HANDLERS
from botocore.awsrequest import AWSResponse from botocore.awsrequest import AWSResponse
from distutils.version import LooseVersion from distutils.version import LooseVersion
from six.moves.urllib.parse import urlparse from http.client import responses as http_responses
from urllib.parse import urlparse
from werkzeug.wrappers import Request from werkzeug.wrappers import Request
from moto import settings from moto import settings
@ -33,7 +33,7 @@ ACCOUNT_ID = os.environ.get("MOTO_ACCOUNT_ID", "123456789012")
RESPONSES_VERSION = pkg_resources.get_distribution("responses").version RESPONSES_VERSION = pkg_resources.get_distribution("responses").version
class BaseMockAWS(object): class BaseMockAWS:
nested_count = 0 nested_count = 0
mocks_active = False mocks_active = False
@ -213,12 +213,12 @@ class CallbackResponse(responses.CallbackResponse):
url = urlparse(request.url) url = urlparse(request.url)
if request.body is None: if request.body is None:
body = None body = None
elif isinstance(request.body, six.text_type): elif isinstance(request.body, str):
body = six.BytesIO(six.b(request.body)) body = BytesIO(request.body.encode("UTF-8"))
elif hasattr(request.body, "read"): elif hasattr(request.body, "read"):
body = six.BytesIO(request.body.read()) body = BytesIO(request.body.read())
else: else:
body = six.BytesIO(request.body) body = BytesIO(request.body)
req = Request.from_values( req = Request.from_values(
path="?".join([url.path, url.query]), path="?".join([url.path, url.query]),
input_stream=body, input_stream=body,
@ -228,7 +228,7 @@ class CallbackResponse(responses.CallbackResponse):
base_url="{scheme}://{netloc}".format( base_url="{scheme}://{netloc}".format(
scheme=url.scheme, netloc=url.netloc scheme=url.scheme, netloc=url.netloc
), ),
headers=[(k, v) for k, v in six.iteritems(request.headers)], headers=[(k, v) for k, v in request.headers.items()],
) )
request = req request = req
headers = self.get_headers() headers = self.get_headers()
@ -243,7 +243,7 @@ class CallbackResponse(responses.CallbackResponse):
return responses.HTTPResponse( return responses.HTTPResponse(
status=status, status=status,
reason=six.moves.http_client.responses.get(status), reason=http_responses.get(status),
body=body, body=body,
headers=headers, headers=headers,
preload_content=False, preload_content=False,
@ -261,7 +261,7 @@ class CallbackResponse(responses.CallbackResponse):
if responses._is_string(url): if responses._is_string(url):
if responses._has_unicode(url): if responses._has_unicode(url):
url = responses._clean_unicode(url) url = responses._clean_unicode(url)
if not isinstance(other, six.text_type): if not isinstance(other, str):
other = other.encode("ascii").decode("utf8") other = other.encode("ascii").decode("utf8")
return self._url_matches_strict(url, other) return self._url_matches_strict(url, other)
elif isinstance(url, responses.Pattern) and url.match(other): elif isinstance(url, responses.Pattern) and url.match(other):
@ -319,7 +319,7 @@ BOTOCORE_HTTP_METHODS = ["GET", "DELETE", "HEAD", "OPTIONS", "PATCH", "POST", "P
class MockRawResponse(BytesIO): class MockRawResponse(BytesIO):
def __init__(self, input): def __init__(self, input):
if isinstance(input, six.text_type): if isinstance(input, str):
input = input.encode("utf-8") input = input.encode("utf-8")
super(MockRawResponse, self).__init__(input) super(MockRawResponse, self).__init__(input)
@ -330,7 +330,7 @@ class MockRawResponse(BytesIO):
contents = self.read() contents = self.read()
class BotocoreStubber(object): class BotocoreStubber:
def __init__(self): def __init__(self):
self.enabled = False self.enabled = False
self.methods = defaultdict(list) self.methods = defaultdict(list)
@ -363,7 +363,7 @@ class BotocoreStubber(object):
if response_callback is not None: if response_callback is not None:
for header, value in request.headers.items(): for header, value in request.headers.items():
if isinstance(value, six.binary_type): if isinstance(value, bytes):
request.headers[header] = value.decode("utf-8") request.headers[header] = value.decode("utf-8")
status, headers, body = response_callback( status, headers, body = response_callback(
request, request.url, request.headers request, request.url, request.headers
@ -479,43 +479,10 @@ class ServerModeMockAWS(BaseMockAWS):
kwargs["endpoint_url"] = "http://localhost:5000" kwargs["endpoint_url"] = "http://localhost:5000"
return real_boto3_resource(*args, **kwargs) return real_boto3_resource(*args, **kwargs)
def fake_httplib_send_output(self, message_body=None, *args, **kwargs):
def _convert_to_bytes(mixed_buffer):
bytes_buffer = []
for chunk in mixed_buffer:
if isinstance(chunk, six.text_type):
bytes_buffer.append(chunk.encode("utf-8"))
else:
bytes_buffer.append(chunk)
msg = b"\r\n".join(bytes_buffer)
return msg
self._buffer.extend((b"", b""))
msg = _convert_to_bytes(self._buffer)
del self._buffer[:]
if isinstance(message_body, bytes):
msg += message_body
message_body = None
self.send(msg)
# if self._expect_header_set:
# read, write, exc = select.select([self.sock], [], [self.sock], 1)
# if read:
# self._handle_expect_response(message_body)
# return
if message_body is not None:
self.send(message_body)
self._client_patcher = patch("boto3.client", fake_boto3_client) self._client_patcher = patch("boto3.client", fake_boto3_client)
self._resource_patcher = patch("boto3.resource", fake_boto3_resource) self._resource_patcher = patch("boto3.resource", fake_boto3_resource)
if six.PY2:
self._httplib_patcher = patch(
"httplib.HTTPConnection._send_output", fake_httplib_send_output
)
self._client_patcher.start() self._client_patcher.start()
self._resource_patcher.start() self._resource_patcher.start()
if six.PY2:
self._httplib_patcher.start()
def _get_region(self, *args, **kwargs): def _get_region(self, *args, **kwargs):
if "region_name" in kwargs: if "region_name" in kwargs:
@ -529,8 +496,6 @@ class ServerModeMockAWS(BaseMockAWS):
if self._client_patcher: if self._client_patcher:
self._client_patcher.stop() self._client_patcher.stop()
self._resource_patcher.stop() self._resource_patcher.stop()
if six.PY2:
self._httplib_patcher.stop()
class Model(type): class Model(type):
@ -572,8 +537,7 @@ class InstanceTrackerMeta(type):
return cls return cls
@six.add_metaclass(InstanceTrackerMeta) class BaseModel(metaclass=InstanceTrackerMeta):
class BaseModel(object):
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
instance = super(BaseModel, cls).__new__(cls) instance = super(BaseModel, cls).__new__(cls)
cls.instances.append(instance) cls.instances.append(instance)
@ -630,7 +594,7 @@ class CloudFormationModel(BaseModel):
pass pass
class BaseBackend(object): class BaseBackend:
def _reset_model_refs(self): def _reset_model_refs(self):
# Remove all references to the models stored # Remove all references to the models stored
for service, models in model_data.items(): for service, models in model_data.items():
@ -724,7 +688,7 @@ class BaseBackend(object):
# raise NotImplementedError() # raise NotImplementedError()
class ConfigQueryModel(object): class ConfigQueryModel:
def __init__(self, backends): def __init__(self, backends):
"""Inits based on the resource type's backends (1 for each region if applicable)""" """Inits based on the resource type's backends (1 for each region if applicable)"""
self.backends = backends self.backends = backends
@ -817,7 +781,7 @@ class ConfigQueryModel(object):
raise NotImplementedError() raise NotImplementedError()
class base_decorator(object): class base_decorator:
mock_backend = MockAWS mock_backend = MockAWS
def __init__(self, backends): def __init__(self, backends):

View File

@ -15,8 +15,7 @@ from moto.core.exceptions import DryRunClientError
from jinja2 import Environment, DictLoader, TemplateNotFound from jinja2 import Environment, DictLoader, TemplateNotFound
import six from urllib.parse import parse_qs, parse_qsl, urlparse
from six.moves.urllib.parse import parse_qs, parse_qsl, urlparse
import xmltodict import xmltodict
from werkzeug.exceptions import HTTPException from werkzeug.exceptions import HTTPException
@ -32,24 +31,24 @@ log = logging.getLogger(__name__)
def _decode_dict(d): def _decode_dict(d):
decoded = OrderedDict() decoded = OrderedDict()
for key, value in d.items(): for key, value in d.items():
if isinstance(key, six.binary_type): if isinstance(key, bytes):
newkey = key.decode("utf-8") newkey = key.decode("utf-8")
elif isinstance(key, (list, tuple)): elif isinstance(key, (list, tuple)):
newkey = [] newkey = []
for k in key: for k in key:
if isinstance(k, six.binary_type): if isinstance(k, bytes):
newkey.append(k.decode("utf-8")) newkey.append(k.decode("utf-8"))
else: else:
newkey.append(k) newkey.append(k)
else: else:
newkey = key newkey = key
if isinstance(value, six.binary_type): if isinstance(value, bytes):
newvalue = value.decode("utf-8") newvalue = value.decode("utf-8")
elif isinstance(value, (list, tuple)): elif isinstance(value, (list, tuple)):
newvalue = [] newvalue = []
for v in value: for v in value:
if isinstance(v, six.binary_type): if isinstance(v, bytes):
newvalue.append(v.decode("utf-8")) newvalue.append(v.decode("utf-8"))
else: else:
newvalue.append(v) newvalue.append(v)
@ -221,7 +220,7 @@ class BaseResponse(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
querystring[key] = [value] querystring[key] = [value]
raw_body = self.body raw_body = self.body
if isinstance(self.body, six.binary_type): if isinstance(self.body, bytes):
self.body = self.body.decode("utf-8") self.body = self.body.decode("utf-8")
if not querystring: if not querystring:
@ -405,7 +404,7 @@ class BaseResponse(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
except HTTPException as http_error: except HTTPException as http_error:
response = http_error.description, dict(status=http_error.code) response = http_error.description, dict(status=http_error.code)
if isinstance(response, six.string_types): if isinstance(response, str):
return 200, headers, response return 200, headers, response
else: else:
return self._send_response(headers, response) return self._send_response(headers, response)

View File

@ -6,10 +6,9 @@ import datetime
import inspect import inspect
import random import random
import re import re
import six
import string import string
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from six.moves.urllib.parse import urlparse from urllib.parse import urlparse
REQUEST_ID_LONG = string.digits + string.ascii_uppercase REQUEST_ID_LONG = string.digits + string.ascii_uppercase
@ -68,20 +67,13 @@ def camelcase_to_pascal(argument):
def method_names_from_class(clazz): def method_names_from_class(clazz):
# On Python 2, methods are different from functions, and the `inspect`
# predicates distinguish between them. On Python 3, methods are just
# regular functions, and `inspect.ismethod` doesn't work, so we have to
# use `inspect.isfunction` instead
if six.PY2:
predicate = inspect.ismethod
else:
predicate = inspect.isfunction predicate = inspect.isfunction
return [x[0] for x in inspect.getmembers(clazz, predicate=predicate)] return [x[0] for x in inspect.getmembers(clazz, predicate=predicate)]
def get_random_hex(length=8): def get_random_hex(length=8):
chars = list(range(10)) + ["a", "b", "c", "d", "e", "f"] chars = list(range(10)) + ["a", "b", "c", "d", "e", "f"]
return "".join(six.text_type(random.choice(chars)) for x in range(length)) return "".join(str(random.choice(chars)) for x in range(length))
def get_random_message_id(): def get_random_message_id():
@ -184,7 +176,7 @@ class convert_flask_to_responses_response(object):
def __call__(self, request, *args, **kwargs): def __call__(self, request, *args, **kwargs):
for key, val in request.headers.items(): for key, val in request.headers.items():
if isinstance(val, six.binary_type): if isinstance(val, bytes):
request.headers[key] = val.decode("utf-8") request.headers[key] = val.decode("utf-8")
result = self.callback(request, request.url, request.headers) result = self.callback(request, request.url, request.headers)
@ -233,10 +225,6 @@ def gen_amz_crc32(response, headerdict=None):
response = response.encode("utf-8") response = response.encode("utf-8")
crc = binascii.crc32(response) crc = binascii.crc32(response)
if six.PY2:
# https://python.readthedocs.io/en/v2.7.2/library/binascii.html
# TLDR: Use bitshift to match Py3 behaviour
crc = crc & 0xFFFFFFFF
if headerdict is not None and isinstance(headerdict, dict): if headerdict is not None and isinstance(headerdict, dict):
headerdict.update({"x-amz-crc32": str(crc)}) headerdict.update({"x-amz-crc32": str(crc)})
@ -261,7 +249,7 @@ def amz_crc32(f):
headers = {} headers = {}
status = 200 status = 200
if isinstance(response, six.string_types): if isinstance(response, str):
body = response body = response
else: else:
if len(response) == 2: if len(response) == 2:
@ -293,7 +281,7 @@ def amzn_request_id(f):
headers = {} headers = {}
status = 200 status = 200
if isinstance(response, six.string_types): if isinstance(response, str):
body = response body = response
else: else:
if len(response) == 2: if len(response) == 2:
@ -405,7 +393,7 @@ def remap_nested_keys(root, key_transform):
if isinstance(root, dict): if isinstance(root, dict):
return { return {
key_transform(k): remap_nested_keys(v, key_transform) key_transform(k): remap_nested_keys(v, key_transform)
for k, v in six.iteritems(root) for k, v in root.items()
} }
return root return root

View File

@ -1,4 +1,3 @@
import six
from moto.compat import collections_abc from moto.compat import collections_abc
from moto.core.utils import get_random_hex from moto.core.utils import get_random_hex
@ -14,9 +13,7 @@ def remove_capitalization_of_dict_keys(obj):
normalized_key = key[:1].lower() + key[1:] normalized_key = key[:1].lower() + key[1:]
result[normalized_key] = remove_capitalization_of_dict_keys(value) result[normalized_key] = remove_capitalization_of_dict_keys(value)
return result return result
elif isinstance(obj, collections_abc.Iterable) and not isinstance( elif isinstance(obj, collections_abc.Iterable) and not isinstance(obj, str):
obj, six.string_types
):
result = obj.__class__() result = obj.__class__()
for item in obj: for item in obj:
result += (remove_capitalization_of_dict_keys(item),) result += (remove_capitalization_of_dict_keys(item),)

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import json import json
import six
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from moto.core.utils import camelcase_to_underscores from moto.core.utils import camelcase_to_underscores
@ -28,7 +27,7 @@ class DynamoHandler(BaseResponse):
if endpoint: if endpoint:
endpoint = camelcase_to_underscores(endpoint) endpoint = camelcase_to_underscores(endpoint)
response = getattr(self, endpoint)() response = getattr(self, endpoint)()
if isinstance(response, six.string_types): if isinstance(response, str):
return 200, self.response_headers, response return 200, self.response_headers, response
else: else:

View File

@ -1,5 +1,3 @@
import six
from moto.dynamodb2.comparisons import get_comparison_func from moto.dynamodb2.comparisons import get_comparison_func
from moto.dynamodb2.exceptions import InvalidUpdateExpression, IncorrectDataType from moto.dynamodb2.exceptions import InvalidUpdateExpression, IncorrectDataType
from moto.dynamodb2.models.utilities import attribute_is_list, bytesize from moto.dynamodb2.models.utilities import attribute_is_list, bytesize
@ -200,7 +198,7 @@ class DynamoType(object):
raise TypeError("Sum only supported for Numbers.") raise TypeError("Sum only supported for Numbers.")
def __getitem__(self, item): def __getitem__(self, item):
if isinstance(item, six.string_types): if isinstance(item, str):
# If our DynamoType is a map it should be subscriptable with a key # If our DynamoType is a map it should be subscriptable with a key
if self.type == DDBType.MAP: if self.type == DDBType.MAP:
return self.value[item] return self.value[item]
@ -222,7 +220,7 @@ class DynamoType(object):
self.value.append(value) self.value.append(value)
else: else:
self.value[key] = value self.value[key] = value
elif isinstance(key, six.string_types): elif isinstance(key, str):
if self.is_map(): if self.is_map():
self.value[key] = value self.value[key] = value
else: else:
@ -251,7 +249,7 @@ class DynamoType(object):
Returns DynamoType or None. Returns DynamoType or None.
""" """
if isinstance(key, six.string_types) and self.is_map(): if isinstance(key, str) and self.is_map():
if "." in key and key.split(".")[0] in self.value: if "." in key and key.split(".")[0] in self.value:
return self.value[key.split(".")[0]].child_attr( return self.value[key.split(".")[0]].child_attr(
".".join(key.split(".")[1:]) ".".join(key.split(".")[1:])

View File

@ -2,13 +2,10 @@ import abc
from abc import abstractmethod from abc import abstractmethod
from collections import deque from collections import deque
import six
from moto.dynamodb2.models import DynamoType from moto.dynamodb2.models import DynamoType
@six.add_metaclass(abc.ABCMeta) class Node(metaclass=abc.ABCMeta):
class Node:
def __init__(self, children=None): def __init__(self, children=None):
self.type = self.__class__.__name__ self.type = self.__class__.__name__
assert children is None or isinstance(children, list) assert children is None or isinstance(children, list)
@ -31,8 +28,7 @@ class LeafNode(Node):
super(LeafNode, self).__init__(children) super(LeafNode, self).__init__(children)
@six.add_metaclass(abc.ABCMeta) class Expression(Node, metaclass=abc.ABCMeta):
class Expression(Node):
""" """
Abstract Syntax Tree representing the expression Abstract Syntax Tree representing the expression
@ -51,8 +47,7 @@ class UpdateExpression(Expression):
""" """
@six.add_metaclass(abc.ABCMeta) class UpdateExpressionClause(UpdateExpression, metaclass=abc.ABCMeta):
class UpdateExpressionClause(UpdateExpression):
""" """
UpdateExpressionClause* => UpdateExpressionSetClause UpdateExpressionClause* => UpdateExpressionSetClause
UpdateExpressionClause* => UpdateExpressionRemoveClause UpdateExpressionClause* => UpdateExpressionRemoveClause

View File

@ -1,7 +1,6 @@
import logging import logging
from abc import abstractmethod from abc import abstractmethod
import abc import abc
import six
from collections import deque from collections import deque
from moto.dynamodb2.parsing.ast_nodes import ( from moto.dynamodb2.parsing.ast_nodes import (
@ -127,8 +126,7 @@ class NestableExpressionParserMixin(object):
return target_node return target_node
@six.add_metaclass(abc.ABCMeta) class ExpressionParser(metaclass=abc.ABCMeta):
class ExpressionParser:
"""Abstract class""" """Abstract class"""
def __init__(self, expression_token_list, token_pos=0): def __init__(self, expression_token_list, token_pos=0):
@ -968,8 +966,7 @@ class UpdateExpressionAddActionsParser(UpdateExpressionActionsParser):
return UpdateExpressionAddActions return UpdateExpressionAddActions
@six.add_metaclass(abc.ABCMeta) class UpdateExpressionPathValueParser(ExpressionParser, metaclass=abc.ABCMeta):
class UpdateExpressionPathValueParser(ExpressionParser):
def _parse_path_and_value(self): def _parse_path_and_value(self):
""" """
UpdateExpressionAddActionParser only gets called when expecting an AddAction. So we should be aggressive on UpdateExpressionAddActionParser only gets called when expecting an AddAction. So we should be aggressive on

View File

@ -5,7 +5,6 @@ import json
import re import re
import itertools import itertools
import six
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from moto.core.utils import camelcase_to_underscores, amz_crc32, amzn_request_id from moto.core.utils import camelcase_to_underscores, amz_crc32, amzn_request_id
@ -87,7 +86,7 @@ class DynamoHandler(BaseResponse):
if endpoint: if endpoint:
endpoint = camelcase_to_underscores(endpoint) endpoint = camelcase_to_underscores(endpoint)
response = getattr(self, endpoint)() response = getattr(self, endpoint)()
if isinstance(response, six.string_types): if isinstance(response, str):
return 200, self.response_headers, response return 200, self.response_headers, response
else: else:
@ -482,8 +481,7 @@ class DynamoHandler(BaseResponse):
index = table.schema index = table.schema
reverse_attribute_lookup = dict( reverse_attribute_lookup = dict(
(v, k) (v, k) for k, v in self.body.get("ExpressionAttributeNames", {}).items()
for k, v in six.iteritems(self.body.get("ExpressionAttributeNames", {}))
) )
if " and " in key_condition_expression.lower(): if " and " in key_condition_expression.lower():

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import dynamodbstreams_backends from .models import dynamodbstreams_backends
from six import string_types
class DynamoDBStreamsHandler(BaseResponse): class DynamoDBStreamsHandler(BaseResponse):
@ -25,7 +24,7 @@ class DynamoDBStreamsHandler(BaseResponse):
shard_iterator_type = self._get_param("ShardIteratorType") shard_iterator_type = self._get_param("ShardIteratorType")
sequence_number = self._get_param("SequenceNumber") sequence_number = self._get_param("SequenceNumber")
# according to documentation sequence_number param should be string # according to documentation sequence_number param should be string
if isinstance(sequence_number, string_types): if isinstance(sequence_number, str):
sequence_number = int(sequence_number) sequence_number = int(sequence_number)
return self.backend.get_shard_iterator( return self.backend.get_shard_iterator(

View File

@ -6,7 +6,6 @@ import ipaddress
import json import json
import os import os
import re import re
import six
import warnings import warnings
from boto3 import Session from boto3 import Session
@ -569,12 +568,9 @@ class Instance(TaggedEC2Resource, BotoInstance, CloudFormationModel):
# handle weird bug around user_data -- something grabs the repr(), so # handle weird bug around user_data -- something grabs the repr(), so
# it must be clean # it must be clean
if isinstance(self.user_data, list) and len(self.user_data) > 0: if isinstance(self.user_data, list) and len(self.user_data) > 0:
if six.PY3 and isinstance(self.user_data[0], six.binary_type): if isinstance(self.user_data[0], bytes):
# string will have a "b" prefix -- need to get rid of it # string will have a "b" prefix -- need to get rid of it
self.user_data[0] = self.user_data[0].decode("utf-8") self.user_data[0] = self.user_data[0].decode("utf-8")
elif six.PY2 and isinstance(self.user_data[0], six.text_type):
# string will have a "u" prefix -- need to get rid of it
self.user_data[0] = self.user_data[0].encode("utf-8")
if self.subnet_id: if self.subnet_id:
subnet = ec2_backend.get_subnet(self.subnet_id) subnet = ec2_backend.get_subnet(self.subnet_id)
@ -2281,9 +2277,7 @@ class SecurityGroupBackend(object):
if group is None: if group is None:
raise InvalidSecurityGroupNotFoundError(group_name_or_id) raise InvalidSecurityGroupNotFoundError(group_name_or_id)
if ip_ranges: if ip_ranges:
if isinstance(ip_ranges, str) or ( if isinstance(ip_ranges, str):
six.PY2 and isinstance(ip_ranges, unicode) # noqa
):
ip_ranges = [{"CidrIp": str(ip_ranges)}] ip_ranges = [{"CidrIp": str(ip_ranges)}]
elif not isinstance(ip_ranges, list): elif not isinstance(ip_ranges, list):
ip_ranges = [json.loads(ip_ranges)] ip_ranges = [json.loads(ip_ranges)]
@ -3096,9 +3090,7 @@ class VPCBackend(object):
): ):
vpc_id = random_vpc_id() vpc_id = random_vpc_id()
try: try:
vpc_cidr_block = ipaddress.IPv4Network( vpc_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)
six.text_type(cidr_block), strict=False
)
except ValueError: except ValueError:
raise InvalidCIDRBlockParameterError(cidr_block) raise InvalidCIDRBlockParameterError(cidr_block)
if vpc_cidr_block.prefixlen < 16 or vpc_cidr_block.prefixlen > 28: if vpc_cidr_block.prefixlen < 16 or vpc_cidr_block.prefixlen > 28:
@ -3465,9 +3457,9 @@ class Subnet(TaggedEC2Resource, CloudFormationModel):
self.id = subnet_id self.id = subnet_id
self.vpc_id = vpc_id self.vpc_id = vpc_id
self.cidr_block = cidr_block self.cidr_block = cidr_block
self.cidr = ipaddress.IPv4Network(six.text_type(self.cidr_block), strict=False) self.cidr = ipaddress.IPv4Network(str(self.cidr_block), strict=False)
self._available_ip_addresses = ( self._available_ip_addresses = (
ipaddress.IPv4Network(six.text_type(self.cidr_block)).num_addresses - 5 ipaddress.IPv4Network(str(self.cidr_block)).num_addresses - 5
) )
self._availability_zone = availability_zone self._availability_zone = availability_zone
self.default_for_az = default_for_az self.default_for_az = default_for_az
@ -3479,7 +3471,7 @@ class Subnet(TaggedEC2Resource, CloudFormationModel):
# Theory is we assign ip's as we go (as 16,777,214 usable IPs in a /8) # Theory is we assign ip's as we go (as 16,777,214 usable IPs in a /8)
self._subnet_ip_generator = self.cidr.hosts() self._subnet_ip_generator = self.cidr.hosts()
self.reserved_ips = [ self.reserved_ips = [
six.next(self._subnet_ip_generator) for _ in range(0, 3) next(self._subnet_ip_generator) for _ in range(0, 3)
] # Reserved by AWS ] # Reserved by AWS
self._unused_ips = set() # if instance is destroyed hold IP here for reuse self._unused_ips = set() # if instance is destroyed hold IP here for reuse
self._subnet_ips = {} # has IP: instance self._subnet_ips = {} # has IP: instance
@ -3580,11 +3572,11 @@ class Subnet(TaggedEC2Resource, CloudFormationModel):
try: try:
new_ip = self._unused_ips.pop() new_ip = self._unused_ips.pop()
except KeyError: except KeyError:
new_ip = six.next(self._subnet_ip_generator) new_ip = next(self._subnet_ip_generator)
# Skips any IP's if they've been manually specified # Skips any IP's if they've been manually specified
while str(new_ip) in self._subnet_ips: while str(new_ip) in self._subnet_ips:
new_ip = six.next(self._subnet_ip_generator) new_ip = next(self._subnet_ip_generator)
if new_ip == self.cidr.broadcast_address: if new_ip == self.cidr.broadcast_address:
raise StopIteration() # Broadcast address cant be used obviously raise StopIteration() # Broadcast address cant be used obviously
@ -3646,14 +3638,12 @@ class SubnetBackend(object):
) # Validate VPC exists and the supplied CIDR block is a subnet of the VPC's ) # Validate VPC exists and the supplied CIDR block is a subnet of the VPC's
vpc_cidr_blocks = [ vpc_cidr_blocks = [
ipaddress.IPv4Network( ipaddress.IPv4Network(
six.text_type(cidr_block_association["cidr_block"]), strict=False str(cidr_block_association["cidr_block"]), strict=False
) )
for cidr_block_association in vpc.get_cidr_block_association_set() for cidr_block_association in vpc.get_cidr_block_association_set()
] ]
try: try:
subnet_cidr_block = ipaddress.IPv4Network( subnet_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)
six.text_type(cidr_block), strict=False
)
except ValueError: except ValueError:
raise InvalidCIDRBlockParameterError(cidr_block) raise InvalidCIDRBlockParameterError(cidr_block)
@ -4382,9 +4372,7 @@ class RouteBackend(object):
try: try:
if destination_cidr_block: if destination_cidr_block:
ipaddress.IPv4Network( ipaddress.IPv4Network(str(destination_cidr_block), strict=False)
six.text_type(destination_cidr_block), strict=False
)
except ValueError: except ValueError:
raise InvalidDestinationCIDRBlockParameterError(destination_cidr_block) raise InvalidDestinationCIDRBlockParameterError(destination_cidr_block)
@ -4677,8 +4665,7 @@ class SpotInstanceRequest(BotoSpotRequest, TaggedEC2Resource):
return instance return instance
@six.add_metaclass(Model) class SpotRequestBackend(object, metaclass=Model):
class SpotRequestBackend(object):
def __init__(self): def __init__(self):
self.spot_instance_requests = {} self.spot_instance_requests = {}
super(SpotRequestBackend, self).__init__() super(SpotRequestBackend, self).__init__()

View File

@ -12,7 +12,6 @@ from moto.elbv2 import elbv2_backends
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from copy import deepcopy from copy import deepcopy
import six
class InstanceResponse(BaseResponse): class InstanceResponse(BaseResponse):
@ -322,7 +321,7 @@ class InstanceResponse(BaseResponse):
if isinstance(bool_str, bool): if isinstance(bool_str, bool):
return bool_str return bool_str
if isinstance(bool_str, six.text_type): if isinstance(bool_str, str):
return str(bool_str).lower() == "true" return str(bool_str).lower() == "true"
return False return False

View File

@ -1,5 +1,4 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import six
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from moto.ec2.utils import filters_from_querystring from moto.ec2.utils import filters_from_querystring
@ -15,7 +14,7 @@ class KeyPairs(BaseResponse):
def delete_key_pair(self): def delete_key_pair(self):
name = self._get_param("KeyName") name = self._get_param("KeyName")
if self.is_not_dryrun("DeleteKeyPair"): if self.is_not_dryrun("DeleteKeyPair"):
success = six.text_type(self.ec2_backend.delete_key_pair(name)).lower() success = str(self.ec2_backend.delete_key_pair(name)).lower()
return self.response_template(DELETE_KEY_PAIR_RESPONSE).render( return self.response_template(DELETE_KEY_PAIR_RESPONSE).render(
success=success success=success
) )

View File

@ -1,4 +1,3 @@
import six
import uuid import uuid
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from moto.ec2.models import OWNER_ID from moto.ec2.models import OWNER_ID
@ -29,10 +28,10 @@ def xml_serialize(tree, key, value):
node = ElementTree.SubElement(tree, name) node = ElementTree.SubElement(tree, name)
if isinstance(value, (str, int, float, six.text_type)): if isinstance(value, (str, int, float, str)):
node.text = str(value) node.text = str(value)
elif isinstance(value, dict): elif isinstance(value, dict):
for dictkey, dictvalue in six.iteritems(value): for dictkey, dictvalue in value.items():
xml_serialize(node, dictkey, dictvalue) xml_serialize(node, dictkey, dictvalue)
elif isinstance(value, list): elif isinstance(value, list):
for item in value: for item in value:
@ -53,7 +52,7 @@ def pretty_xml(tree):
def parse_object(raw_data): def parse_object(raw_data):
out_data = {} out_data = {}
for key, value in six.iteritems(raw_data): for key, value in raw_data.items():
key_fix_splits = key.split("_") key_fix_splits = key.split("_")
key_len = len(key_fix_splits) key_len = len(key_fix_splits)
@ -75,7 +74,7 @@ def parse_object(raw_data):
def parse_lists(data): def parse_lists(data):
for key, value in six.iteritems(data): for key, value in data.items():
if isinstance(value, dict): if isinstance(value, dict):
keys = data[key].keys() keys = data[key].keys()
is_list = all(map(lambda k: k.isnumeric(), keys)) is_list = all(map(lambda k: k.isnumeric(), keys))
@ -106,13 +105,13 @@ class LaunchTemplates(BaseResponse):
if "TagSpecifications" not in parsed_template_data: if "TagSpecifications" not in parsed_template_data:
parsed_template_data["TagSpecifications"] = [] parsed_template_data["TagSpecifications"] = []
converted_tag_spec = [] converted_tag_spec = []
for resource_type, tags in six.iteritems(tag_spec): for resource_type, tags in tag_spec.items():
converted_tag_spec.append( converted_tag_spec.append(
{ {
"ResourceType": resource_type, "ResourceType": resource_type,
"Tags": [ "Tags": [
{"Key": key, "Value": value} {"Key": key, "Value": value}
for key, value in six.iteritems(tags) for key, value in tags.items()
], ],
} }
) )

View File

@ -5,7 +5,6 @@ import hashlib
import fnmatch import fnmatch
import random import random
import re import re
import six
from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
@ -53,7 +52,7 @@ EC2_PREFIX_TO_RESOURCE = dict((v, k) for (k, v) in EC2_RESOURCE_TO_PREFIX.items(
def random_resource_id(size=8): def random_resource_id(size=8):
chars = list(range(10)) + ["a", "b", "c", "d", "e", "f"] chars = list(range(10)) + ["a", "b", "c", "d", "e", "f"]
resource_id = "".join(six.text_type(random.choice(chars)) for _ in range(size)) resource_id = "".join(str(random.choice(chars)) for _ in range(size))
return resource_id return resource_id
@ -462,7 +461,7 @@ def is_filter_matching(obj, filter, filter_value):
if filter_value is None: if filter_value is None:
return False return False
if isinstance(value, six.string_types): if isinstance(value, str):
if not isinstance(filter_value, list): if not isinstance(filter_value, list):
filter_value = [filter_value] filter_value = [filter_value]
if any(fnmatch.fnmatch(value, pattern) for pattern in filter_value): if any(fnmatch.fnmatch(value, pattern) for pattern in filter_value):
@ -582,7 +581,7 @@ def rsa_public_key_parse(key_material):
from sshpubkeys.keys import SSHKey from sshpubkeys.keys import SSHKey
try: try:
if not isinstance(key_material, six.binary_type): if not isinstance(key_material, bytes):
key_material = key_material.encode("ascii") key_material = key_material.encode("ascii")
decoded_key = base64.b64decode(key_material).decode("ascii") decoded_key = base64.b64decode(key_material).decode("ascii")

View File

@ -1,5 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from six.moves.urllib.parse import parse_qs from urllib.parse import parse_qs
from botocore.awsrequest import AWSPreparedRequest from botocore.awsrequest import AWSPreparedRequest
from moto.elb.responses import ELBResponse from moto.elb.responses import ELBResponse

View File

@ -6,7 +6,7 @@ from functools import wraps
import pytz import pytz
from six.moves.urllib.parse import urlparse from urllib.parse import urlparse
from moto.core.responses import AWSServiceSpec from moto.core.responses import AWSServiceSpec
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from moto.core.responses import xml_to_json_response from moto.core.responses import xml_to_json_response

View File

@ -9,12 +9,10 @@ from moto.core.utils import (
iso_8601_datetime_with_milliseconds, iso_8601_datetime_with_milliseconds,
) )
import six
def random_id(size=13): def random_id(size=13):
chars = list(range(10)) + list(string.ascii_uppercase) chars = list(range(10)) + list(string.ascii_uppercase)
return "".join(six.text_type(random.choice(chars)) for x in range(size)) return "".join(str(random.choice(chars)) for x in range(size))
def random_cluster_id(size=13): def random_cluster_id(size=13):

View File

@ -10,7 +10,6 @@ from enum import Enum, unique
from operator import lt, le, eq, ge, gt from operator import lt, le, eq, ge, gt
from boto3 import Session from boto3 import Session
from six import string_types
from moto.core.exceptions import JsonRESTError from moto.core.exceptions import JsonRESTError
from moto.core import ACCOUNT_ID, BaseBackend, CloudFormationModel, BaseModel from moto.core import ACCOUNT_ID, BaseBackend, CloudFormationModel, BaseModel
@ -640,7 +639,7 @@ class EventPattern:
return all(nested_filter_matches + filter_list_matches) return all(nested_filter_matches + filter_list_matches)
def _does_item_match_filters(self, item, filters): def _does_item_match_filters(self, item, filters):
allowed_values = [value for value in filters if isinstance(value, string_types)] allowed_values = [value for value in filters if isinstance(value, str)]
allowed_values_match = item in allowed_values if allowed_values else True allowed_values_match = item in allowed_values if allowed_values else True
named_filter_matches = [ named_filter_matches = [
self._does_item_match_named_filter(item, filter) self._does_item_match_named_filter(item, filter)

View File

@ -2,7 +2,6 @@ import re
from datetime import datetime from datetime import datetime
from boto3 import Session from boto3 import Session
from six import iteritems
from moto.core import ACCOUNT_ID, BaseBackend from moto.core import ACCOUNT_ID, BaseBackend
from moto.core.utils import iso_8601_datetime_without_milliseconds from moto.core.utils import iso_8601_datetime_without_milliseconds
@ -160,7 +159,7 @@ class ForecastBackend(BaseBackend):
dsg.update(dataset_arns) dsg.update(dataset_arns)
def list_dataset_groups(self): def list_dataset_groups(self):
return [v for (_, v) in iteritems(self.dataset_groups)] return [v for (_, v) in self.dataset_groups.items()]
def reset(self): def reset(self):
region_name = self.region_name region_name = self.region_name

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import json import json
from six.moves.urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
from moto.core.responses import _TemplateEnvironmentMixin from moto.core.responses import _TemplateEnvironmentMixin
from .models import glacier_backends from .models import glacier_backends

View File

@ -1,7 +1,7 @@
import random import random
import string import string
from six.moves.urllib.parse import urlparse from urllib.parse import urlparse
def region_from_glacier_url(url): def region_from_glacier_url(url):

View File

@ -18,11 +18,9 @@ import re
from abc import abstractmethod, ABCMeta from abc import abstractmethod, ABCMeta
from enum import Enum from enum import Enum
import six
from botocore.auth import SigV4Auth, S3SigV4Auth from botocore.auth import SigV4Auth, S3SigV4Auth
from botocore.awsrequest import AWSRequest from botocore.awsrequest import AWSRequest
from botocore.credentials import Credentials from botocore.credentials import Credentials
from six import string_types
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from moto.core.exceptions import ( from moto.core.exceptions import (
@ -160,8 +158,7 @@ class CreateAccessKeyFailure(Exception):
self.reason = reason self.reason = reason
@six.add_metaclass(ABCMeta) class IAMRequestBase(object, metaclass=ABCMeta):
class IAMRequestBase(object):
def __init__(self, method, path, data, headers): def __init__(self, method, path, data, headers):
log.debug( log.debug(
"Creating {class_name} with method={method}, path={path}, data={data}, headers={headers}".format( "Creating {class_name} with method={method}, path={path}, data={data}, headers={headers}".format(
@ -332,7 +329,7 @@ class IAMPolicy(object):
if policy_version.is_default if policy_version.is_default
) )
policy_document = default_version.document policy_document = default_version.document
elif isinstance(policy, string_types): elif isinstance(policy, str):
policy_document = policy policy_document = policy
else: else:
policy_document = policy["policy_document"] policy_document = policy["policy_document"]

View File

@ -13,7 +13,7 @@ import time
from cryptography import x509 from cryptography import x509
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
from six.moves.urllib import parse from urllib import parse
from moto.core.exceptions import RESTError from moto.core.exceptions import RESTError
from moto.core import BaseBackend, BaseModel, ACCOUNT_ID, CloudFormationModel from moto.core import BaseBackend, BaseModel, ACCOUNT_ID, CloudFormationModel
from moto.core.utils import ( from moto.core.utils import (

View File

@ -1,8 +1,6 @@
import json import json
import re import re
from six import string_types
from moto.iam.exceptions import MalformedPolicyDocument from moto.iam.exceptions import MalformedPolicyDocument
@ -190,7 +188,7 @@ class IAMPolicyDocumentValidator:
@staticmethod @staticmethod
def _validate_effect_syntax(statement): def _validate_effect_syntax(statement):
assert "Effect" in statement assert "Effect" in statement
assert isinstance(statement["Effect"], string_types) assert isinstance(statement["Effect"], str)
assert statement["Effect"].lower() in [ assert statement["Effect"].lower() in [
allowed_effect.lower() for allowed_effect in VALID_EFFECTS allowed_effect.lower() for allowed_effect in VALID_EFFECTS
] ]
@ -222,10 +220,10 @@ class IAMPolicyDocumentValidator:
@staticmethod @staticmethod
def _validate_string_or_list_of_strings_syntax(statement, key): def _validate_string_or_list_of_strings_syntax(statement, key):
if key in statement: if key in statement:
assert isinstance(statement[key], (string_types, list)) assert isinstance(statement[key], (str, list))
if isinstance(statement[key], list): if isinstance(statement[key], list):
for resource in statement[key]: for resource in statement[key]:
assert isinstance(resource, string_types) assert isinstance(resource, str)
@staticmethod @staticmethod
def _validate_condition_syntax(statement): def _validate_condition_syntax(statement):
@ -237,7 +235,7 @@ class IAMPolicyDocumentValidator:
condition_element_key, condition_element_key,
condition_element_value, condition_element_value,
) in condition_value.items(): ) in condition_value.items():
assert isinstance(condition_element_value, (list, string_types)) assert isinstance(condition_element_value, (list, str))
if ( if (
IAMPolicyDocumentValidator._strip_condition_key(condition_key) IAMPolicyDocumentValidator._strip_condition_key(condition_key)
@ -262,11 +260,11 @@ class IAMPolicyDocumentValidator:
@staticmethod @staticmethod
def _validate_sid_syntax(statement): def _validate_sid_syntax(statement):
if "Sid" in statement: if "Sid" in statement:
assert isinstance(statement["Sid"], string_types) assert isinstance(statement["Sid"], str)
def _validate_id_syntax(self): def _validate_id_syntax(self):
if "Id" in self._policy_json: if "Id" in self._policy_json:
assert isinstance(self._policy_json["Id"], string_types) assert isinstance(self._policy_json["Id"], str)
def _validate_resource_exist(self): def _validate_resource_exist(self):
for statement in self._statements: for statement in self._statements:
@ -295,7 +293,7 @@ class IAMPolicyDocumentValidator:
def _validate_action_like_for_prefixes(self, key): def _validate_action_like_for_prefixes(self, key):
for statement in self._statements: for statement in self._statements:
if key in statement: if key in statement:
if isinstance(statement[key], string_types): if isinstance(statement[key], str):
self._validate_action_prefix(statement[key]) self._validate_action_prefix(statement[key])
else: else:
for action in statement[key]: for action in statement[key]:
@ -328,7 +326,7 @@ class IAMPolicyDocumentValidator:
def _validate_resource_like_for_formats(self, key): def _validate_resource_like_for_formats(self, key):
for statement in self._statements: for statement in self._statements:
if key in statement: if key in statement:
if isinstance(statement[key], string_types): if isinstance(statement[key], str):
self._validate_resource_format(statement[key]) self._validate_resource_format(statement[key])
else: else:
for resource in sorted(statement[key], reverse=True): for resource in sorted(statement[key], reverse=True):
@ -438,7 +436,7 @@ class IAMPolicyDocumentValidator:
@staticmethod @staticmethod
def _legacy_parse_resource_like(statement, key): def _legacy_parse_resource_like(statement, key):
if isinstance(statement[key], string_types): if isinstance(statement[key], str):
if statement[key] != "*": if statement[key] != "*":
assert statement[key].count(":") >= 5 or "::" not in statement[key] assert statement[key].count(":") >= 5 or "::" not in statement[key]
assert statement[key].split(":")[2] != "" assert statement[key].split(":")[2] != ""
@ -459,7 +457,7 @@ class IAMPolicyDocumentValidator:
condition_element_key, condition_element_key,
condition_element_value, condition_element_value,
) in condition_value.items(): ) in condition_value.items():
if isinstance(condition_element_value, string_types): if isinstance(condition_element_value, str):
IAMPolicyDocumentValidator._legacy_parse_date_condition_value( IAMPolicyDocumentValidator._legacy_parse_date_condition_value(
condition_element_value condition_element_value
) )

View File

@ -1,12 +1,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import random import random
import string import string
import six
def random_alphanumeric(length): def random_alphanumeric(length):
return "".join( return "".join(
six.text_type(random.choice(string.ascii_letters + string.digits + "+" + "/")) str(random.choice(string.ascii_letters + string.digits + "+" + "/"))
for _ in range(length) for _ in range(length)
) )
@ -14,13 +13,12 @@ def random_alphanumeric(length):
def random_resource_id(size=20): def random_resource_id(size=20):
chars = list(range(10)) + list(string.ascii_lowercase) chars = list(range(10)) + list(string.ascii_lowercase)
return "".join(six.text_type(random.choice(chars)) for x in range(size)) return "".join(str(random.choice(chars)) for x in range(size))
def random_access_key(): def random_access_key():
return "".join( return "".join(
six.text_type(random.choice(string.ascii_uppercase + string.digits)) str(random.choice(string.ascii_uppercase + string.digits)) for _ in range(16)
for _ in range(16)
) )

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime import datetime
import json import json
from six.moves.urllib.parse import urlparse from urllib.parse import urlparse
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import json import json
from six.moves.urllib.parse import unquote from urllib.parse import unquote
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import iot_backends from .models import iot_backends

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import iotdata_backends from .models import iotdata_backends
import json import json
from six.moves.urllib.parse import unquote from urllib.parse import unquote
class IoTDataPlaneResponse(BaseResponse): class IoTDataPlaneResponse(BaseResponse):

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
import datetime import datetime
import time import time
import re import re
import six
import itertools import itertools
from operator import attrgetter from operator import attrgetter
@ -180,13 +179,13 @@ class Stream(CloudFormationModel):
raise ShardNotFoundError(shard_id) raise ShardNotFoundError(shard_id)
def get_shard_for_key(self, partition_key, explicit_hash_key): def get_shard_for_key(self, partition_key, explicit_hash_key):
if not isinstance(partition_key, six.string_types): if not isinstance(partition_key, str):
raise InvalidArgumentError("partition_key") raise InvalidArgumentError("partition_key")
if len(partition_key) > 256: if len(partition_key) > 256:
raise InvalidArgumentError("partition_key") raise InvalidArgumentError("partition_key")
if explicit_hash_key: if explicit_hash_key:
if not isinstance(explicit_hash_key, six.string_types): if not isinstance(explicit_hash_key, str):
raise InvalidArgumentError("explicit_hash_key") raise InvalidArgumentError("explicit_hash_key")
key = int(explicit_hash_key) key = int(explicit_hash_key)
@ -227,7 +226,7 @@ class Stream(CloudFormationModel):
"StreamARN": self.arn, "StreamARN": self.arn,
"StreamName": self.stream_name, "StreamName": self.stream_name,
"StreamStatus": self.status, "StreamStatus": self.status,
"StreamCreationTimestamp": six.text_type(self.creation_datetime), "StreamCreationTimestamp": str(self.creation_datetime),
"OpenShardCount": self.shard_count, "OpenShardCount": self.shard_count,
} }
} }

View File

@ -5,8 +5,6 @@ import json
import os import os
import re import re
import six
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import kms_backends from .models import kms_backends
from .exceptions import ( from .exceptions import (
@ -343,7 +341,7 @@ class KmsResponse(BaseResponse):
self._validate_key_id(key_id) self._validate_key_id(key_id)
if isinstance(plaintext, six.text_type): if isinstance(plaintext, str):
plaintext = plaintext.encode("utf-8") plaintext = plaintext.encode("utf-8")
ciphertext_blob, arn = self.kms_backend.encrypt( ciphertext_blob, arn = self.kms_backend.encrypt(

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import json import json
from six.moves.urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .exceptions import exception_handler from .exceptions import exception_handler

View File

@ -3,7 +3,7 @@ import random
import re import re
import string import string
from six.moves.urllib.parse import parse_qs, urlparse from urllib.parse import parse_qs, urlparse
def region_from_managedblckchain_url(url): def region_from_managedblckchain_url(url):

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
import json import json
import re import re
from six.moves.urllib.parse import urlsplit from urllib.parse import urlsplit
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import polly_backends from .models import polly_backends

View File

@ -5,7 +5,6 @@ import json
import xmltodict import xmltodict
from jinja2 import Template from jinja2 import Template
from six import iteritems
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import redshift_backends from .models import redshift_backends
@ -250,7 +249,7 @@ class RedshiftResponse(BaseResponse):
cluster_kwargs = {} cluster_kwargs = {}
# We only want parameters that were actually passed in, otherwise # We only want parameters that were actually passed in, otherwise
# we'll stomp all over our cluster metadata with None values. # we'll stomp all over our cluster metadata with None values.
for (key, value) in iteritems(request_kwargs): for (key, value) in request_kwargs.items():
if value is not None and value != []: if value is not None and value != []:
cluster_kwargs[key] = value cluster_kwargs[key] = value

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import uuid import uuid
import six
from boto3 import Session from boto3 import Session
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
@ -575,7 +574,7 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
try: try:
while True: while True:
# Generator format: [{'ResourceARN': str, 'Tags': [{'Key': str, 'Value': str]}, ...] # Generator format: [{'ResourceARN': str, 'Tags': [{'Key': str, 'Value': str]}, ...]
next_item = six.next(generator) next_item = next(generator)
resource_tags = len(next_item["Tags"]) resource_tags = len(next_item["Tags"])
if current_resources >= resources_per_page: if current_resources >= resources_per_page:
@ -625,7 +624,7 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
try: try:
while True: while True:
# Generator format: ['tag', 'tag', 'tag', ...] # Generator format: ['tag', 'tag', 'tag', ...]
next_item = six.next(generator) next_item = next(generator)
if current_tags + 1 >= 128: if current_tags + 1 >= 128:
break break
@ -671,7 +670,7 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
try: try:
while True: while True:
# Generator format: ['value', 'value', 'value', ...] # Generator format: ['value', 'value', 'value', ...]
next_item = six.next(generator) next_item = next(generator)
if current_tags + 1 >= 128: if current_tags + 1 >= 128:
break break

View File

@ -1,6 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from jinja2 import Template from jinja2 import Template
from six.moves.urllib.parse import parse_qs, urlparse from urllib.parse import parse_qs, urlparse
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import route53_backend from .models import route53_backend

View File

@ -18,7 +18,6 @@ import sys
import time import time
import uuid import uuid
import six
from bisect import insort from bisect import insort
from moto.core import ACCOUNT_ID, BaseBackend, BaseModel, CloudFormationModel from moto.core import ACCOUNT_ID, BaseBackend, BaseModel, CloudFormationModel
@ -153,7 +152,7 @@ class FakeKey(BaseModel):
# Hack for working around moto's own unit tests; this probably won't # Hack for working around moto's own unit tests; this probably won't
# actually get hit in normal use. # actually get hit in normal use.
if isinstance(new_value, six.text_type): if isinstance(new_value, str):
new_value = new_value.encode(DEFAULT_TEXT_ENCODING) new_value = new_value.encode(DEFAULT_TEXT_ENCODING)
self._value_buffer.write(new_value) self._value_buffer.write(new_value)
self.contentsize = len(new_value) self.contentsize = len(new_value)
@ -284,7 +283,7 @@ class FakeKey(BaseModel):
return state return state
def __setstate__(self, state): def __setstate__(self, state):
self.__dict__.update({k: v for k, v in six.iteritems(state) if k != "value"}) self.__dict__.update({k: v for k, v in state.items() if k != "value"})
self._value_buffer = tempfile.SpooledTemporaryFile( self._value_buffer = tempfile.SpooledTemporaryFile(
max_size=self._max_buffer_size max_size=self._max_buffer_size
@ -628,24 +627,16 @@ class CorsRule(BaseModel):
max_age_seconds=None, max_age_seconds=None,
): ):
self.allowed_methods = ( self.allowed_methods = (
[allowed_methods] [allowed_methods] if isinstance(allowed_methods, str) else allowed_methods
if isinstance(allowed_methods, six.string_types)
else allowed_methods
) )
self.allowed_origins = ( self.allowed_origins = (
[allowed_origins] [allowed_origins] if isinstance(allowed_origins, str) else allowed_origins
if isinstance(allowed_origins, six.string_types)
else allowed_origins
) )
self.allowed_headers = ( self.allowed_headers = (
[allowed_headers] [allowed_headers] if isinstance(allowed_headers, str) else allowed_headers
if isinstance(allowed_headers, six.string_types)
else allowed_headers
) )
self.exposed_headers = ( self.exposed_headers = (
[expose_headers] [expose_headers] if isinstance(expose_headers, str) else expose_headers
if isinstance(expose_headers, six.string_types)
else expose_headers
) )
self.max_age_seconds = max_age_seconds self.max_age_seconds = max_age_seconds
@ -960,20 +951,20 @@ class FakeBucket(CloudFormationModel):
for rule in rules: for rule in rules:
assert isinstance(rule["AllowedMethod"], list) or isinstance( assert isinstance(rule["AllowedMethod"], list) or isinstance(
rule["AllowedMethod"], six.string_types rule["AllowedMethod"], str
) )
assert isinstance(rule["AllowedOrigin"], list) or isinstance( assert isinstance(rule["AllowedOrigin"], list) or isinstance(
rule["AllowedOrigin"], six.string_types rule["AllowedOrigin"], str
) )
assert isinstance(rule.get("AllowedHeader", []), list) or isinstance( assert isinstance(rule.get("AllowedHeader", []), list) or isinstance(
rule.get("AllowedHeader", ""), six.string_types rule.get("AllowedHeader", ""), str
) )
assert isinstance(rule.get("ExposedHeader", []), list) or isinstance( assert isinstance(rule.get("ExposedHeader", []), list) or isinstance(
rule.get("ExposedHeader", ""), six.string_types rule.get("ExposedHeader", ""), str
) )
assert isinstance(rule.get("MaxAgeSeconds", "0"), six.string_types) assert isinstance(rule.get("MaxAgeSeconds", "0"), str)
if isinstance(rule["AllowedMethod"], six.string_types): if isinstance(rule["AllowedMethod"], str):
methods = [rule["AllowedMethod"]] methods = [rule["AllowedMethod"]]
else: else:
methods = rule["AllowedMethod"] methods = rule["AllowedMethod"]

View File

@ -4,7 +4,6 @@ import os
import re import re
import sys import sys
import six
from botocore.awsrequest import AWSPreparedRequest from botocore.awsrequest import AWSPreparedRequest
from moto.core.utils import ( from moto.core.utils import (
@ -12,7 +11,7 @@ from moto.core.utils import (
py2_strip_unicode_keys, py2_strip_unicode_keys,
unix_time_millis, unix_time_millis,
) )
from six.moves.urllib.parse import ( from urllib.parse import (
parse_qs, parse_qs,
parse_qsl, parse_qsl,
urlparse, urlparse,
@ -270,11 +269,11 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
@staticmethod @staticmethod
def _send_response(response): def _send_response(response):
if isinstance(response, six.string_types): if isinstance(response, str):
return 200, {}, response.encode("utf-8") return 200, {}, response.encode("utf-8")
else: else:
status_code, headers, response_content = response status_code, headers, response_content = response
if not isinstance(response_content, six.binary_type): if not isinstance(response_content, bytes):
response_content = response_content.encode("utf-8") response_content = response_content.encode("utf-8")
return status_code, headers, response_content return status_code, headers, response_content
@ -299,7 +298,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
body = request.data body = request.data
if body is None: if body is None:
body = b"" body = b""
if isinstance(body, six.binary_type): if isinstance(body, bytes):
body = body.decode("utf-8") body = body.decode("utf-8")
body = "{0}".format(body).encode("utf-8") body = "{0}".format(body).encode("utf-8")
@ -501,7 +500,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
bucket = self.backend.get_bucket(bucket_name) bucket = self.backend.get_bucket(bucket_name)
prefix = querystring.get("prefix", [None])[0] prefix = querystring.get("prefix", [None])[0]
if prefix and isinstance(prefix, six.binary_type): if prefix and isinstance(prefix, bytes):
prefix = prefix.decode("utf-8") prefix = prefix.decode("utf-8")
delimiter = querystring.get("delimiter", [None])[0] delimiter = querystring.get("delimiter", [None])[0]
max_keys = int(querystring.get("max-keys", [1000])[0]) max_keys = int(querystring.get("max-keys", [1000])[0])
@ -553,7 +552,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
raise InvalidContinuationToken() raise InvalidContinuationToken()
prefix = querystring.get("prefix", [None])[0] prefix = querystring.get("prefix", [None])[0]
if prefix and isinstance(prefix, six.binary_type): if prefix and isinstance(prefix, bytes):
prefix = prefix.decode("utf-8") prefix = prefix.decode("utf-8")
delimiter = querystring.get("delimiter", [None])[0] delimiter = querystring.get("delimiter", [None])[0]
result_keys, result_folders = self.backend.prefix_query( result_keys, result_folders = self.backend.prefix_query(
@ -1002,7 +1001,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
except S3ClientError as s3error: except S3ClientError as s3error:
response = s3error.code, {}, s3error.description response = s3error.code, {}, s3error.description
if isinstance(response, six.string_types): if isinstance(response, str):
status_code = 200 status_code = 200
response_content = response response_content = response
else: else:
@ -1326,7 +1325,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
# you can have a quoted ?version=abc with a version Id, so work on # you can have a quoted ?version=abc with a version Id, so work on
# we need to parse the unquoted string first # we need to parse the unquoted string first
src_key = request.headers.get("x-amz-copy-source") src_key = request.headers.get("x-amz-copy-source")
if isinstance(src_key, six.binary_type): if isinstance(src_key, bytes):
src_key = src_key.decode("utf-8") src_key = src_key.decode("utf-8")
src_key_parsed = urlparse(src_key) src_key_parsed = urlparse(src_key)
src_bucket, src_key = ( src_bucket, src_key = (

View File

@ -2,8 +2,7 @@ from __future__ import unicode_literals
import logging import logging
import re import re
import six from urllib.parse import urlparse, unquote, quote
from six.moves.urllib.parse import urlparse, unquote, quote
from requests.structures import CaseInsensitiveDict from requests.structures import CaseInsensitiveDict
import sys import sys
from moto.settings import S3_IGNORE_SUBDOMAIN_BUCKETNAME from moto.settings import S3_IGNORE_SUBDOMAIN_BUCKETNAME
@ -75,7 +74,7 @@ def metadata_from_headers(headers):
metadata = CaseInsensitiveDict() metadata = CaseInsensitiveDict()
meta_regex = re.compile(r"^x-amz-meta-([a-zA-Z0-9\-_.]+)$", flags=re.IGNORECASE) meta_regex = re.compile(r"^x-amz-meta-([a-zA-Z0-9\-_.]+)$", flags=re.IGNORECASE)
for header, value in headers.items(): for header, value in headers.items():
if isinstance(header, six.string_types): if isinstance(header, str):
result = meta_regex.match(header) result = meta_regex.match(header)
meta_key = None meta_key = None
if result: if result:
@ -94,14 +93,10 @@ def metadata_from_headers(headers):
def clean_key_name(key_name): def clean_key_name(key_name):
if six.PY2:
return unquote(key_name.encode("utf-8")).decode("utf-8")
return unquote(key_name) return unquote(key_name)
def undo_clean_key_name(key_name): def undo_clean_key_name(key_name):
if six.PY2:
return quote(key_name.encode("utf-8")).decode("utf-8")
return quote(key_name) return quote(key_name)

View File

@ -1,5 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from six.moves.urllib.parse import urlparse from urllib.parse import urlparse
def bucket_name_from_url(url): def bucket_name_from_url(url):

View File

@ -2,7 +2,6 @@ from __future__ import unicode_literals
import random import random
import string import string
import six
import re import re
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
@ -56,9 +55,7 @@ def random_password(
if exclude_characters: if exclude_characters:
password = _exclude_characters(password, exclude_characters) password = _exclude_characters(password, exclude_characters)
password = "".join( password = "".join(str(random.choice(password)) for x in range(password_length))
six.text_type(random.choice(password)) for x in range(password_length)
)
if require_each_included_type: if require_each_included_type:
password = _add_password_require_each_included_type( password = _add_password_require_each_included_type(

View File

@ -9,12 +9,11 @@ import signal
import sys import sys
from threading import Lock from threading import Lock
import six
from flask import Flask from flask import Flask
from flask_cors import CORS from flask_cors import CORS
from flask.testing import FlaskClient from flask.testing import FlaskClient
from six.moves.urllib.parse import urlencode from urllib.parse import urlencode
from werkzeug.routing import BaseConverter from werkzeug.routing import BaseConverter
from werkzeug.serving import run_simple from werkzeug.serving import run_simple
@ -134,9 +133,7 @@ class DomainDispatcherApplication(object):
path_info = environ.get("PATH_INFO", "") path_info = environ.get("PATH_INFO", "")
# The URL path might contain non-ASCII text, for instance unicode S3 bucket names # The URL path might contain non-ASCII text, for instance unicode S3 bucket names
if six.PY2 and isinstance(path_info, str): if isinstance(path_info, bytes):
path_info = six.u(path_info)
if six.PY3 and isinstance(path_info, six.binary_type):
path_info = path_info.decode("utf-8") path_info = path_info.decode("utf-8")
if path_info.startswith("/moto-api") or path_info == "/favicon.ico": if path_info.startswith("/moto-api") or path_info == "/favicon.ico":

View File

@ -1,8 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import base64 import base64
import six
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import ses_backend from .models import ses_backend
from datetime import datetime from datetime import datetime
@ -59,7 +57,7 @@ class EmailResponse(BaseResponse):
destinations = {"ToAddresses": [], "CcAddresses": [], "BccAddresses": []} destinations = {"ToAddresses": [], "CcAddresses": [], "BccAddresses": []}
for dest_type in destinations: for dest_type in destinations:
# consume up to 51 to allow exception # consume up to 51 to allow exception
for i in six.moves.range(1, 52): for i in range(1, 52):
field = "Destination.%s.member.%s" % (dest_type, i) field = "Destination.%s.member.%s" % (dest_type, i)
address = self.querystring.get(field) address = self.querystring.get(field)
if address is None: if address is None:
@ -80,7 +78,7 @@ class EmailResponse(BaseResponse):
destinations = {"ToAddresses": [], "CcAddresses": [], "BccAddresses": []} destinations = {"ToAddresses": [], "CcAddresses": [], "BccAddresses": []}
for dest_type in destinations: for dest_type in destinations:
# consume up to 51 to allow exception # consume up to 51 to allow exception
for i in six.moves.range(1, 52): for i in range(1, 52):
field = "Destination.%s.member.%s" % (dest_type, i) field = "Destination.%s.member.%s" % (dest_type, i)
address = self.querystring.get(field) address = self.querystring.get(field)
if address is None: if address is None:
@ -100,11 +98,10 @@ class EmailResponse(BaseResponse):
raw_data = self.querystring.get("RawMessage.Data")[0] raw_data = self.querystring.get("RawMessage.Data")[0]
raw_data = base64.b64decode(raw_data) raw_data = base64.b64decode(raw_data)
if six.PY3:
raw_data = raw_data.decode("utf-8") raw_data = raw_data.decode("utf-8")
destinations = [] destinations = []
# consume up to 51 to allow exception # consume up to 51 to allow exception
for i in six.moves.range(1, 52): for i in range(1, 52):
field = "Destinations.member.%s" % i field = "Destinations.member.%s" % i
address = self.querystring.get(field) address = self.querystring.get(field)
if address is None: if address is None:

View File

@ -5,7 +5,6 @@ import uuid
import json import json
import requests import requests
import six
import re import re
from boto3 import Session from boto3 import Session
@ -59,7 +58,7 @@ class Topic(CloudFormationModel):
self._tags = {} self._tags = {}
def publish(self, message, subject=None, message_attributes=None): def publish(self, message, subject=None, message_attributes=None):
message_id = six.text_type(uuid.uuid4()) message_id = str(uuid.uuid4())
subscriptions, _ = self.sns_backend.list_subscriptions(self.arn) subscriptions, _ = self.sns_backend.list_subscriptions(self.arn)
for subscription in subscriptions: for subscription in subscriptions:
subscription.publish( subscription.publish(
@ -228,7 +227,7 @@ class Subscription(BaseModel):
def _field_match(field, rules, message_attributes): def _field_match(field, rules, message_attributes):
for rule in rules: for rule in rules:
# TODO: boolean value matching is not supported, SNS behavior unknown # TODO: boolean value matching is not supported, SNS behavior unknown
if isinstance(rule, six.string_types): if isinstance(rule, str):
if field not in message_attributes: if field not in message_attributes:
return False return False
if message_attributes[field]["Value"] == rule: if message_attributes[field]["Value"] == rule:
@ -239,7 +238,7 @@ class Subscription(BaseModel):
return True return True
except (ValueError, TypeError): except (ValueError, TypeError):
pass pass
if isinstance(rule, (six.integer_types, float)): if isinstance(rule, (int, float)):
if field not in message_attributes: if field not in message_attributes:
return False return False
if message_attributes[field]["Type"] == "Number": if message_attributes[field]["Type"] == "Number":
@ -273,7 +272,7 @@ class Subscription(BaseModel):
return all( return all(
_field_match(field, rules, message_attributes) _field_match(field, rules, message_attributes)
for field, rules in six.iteritems(self._filter_policy) for field, rules in self._filter_policy.items()
) )
def get_post_data(self, message, message_id, subject, message_attributes=None): def get_post_data(self, message, message_id, subject, message_attributes=None):
@ -356,7 +355,7 @@ class PlatformEndpoint(BaseModel):
raise SnsEndpointDisabled("Endpoint %s disabled" % self.id) raise SnsEndpointDisabled("Endpoint %s disabled" % self.id)
# This is where we would actually send a message # This is where we would actually send a message
message_id = six.text_type(uuid.uuid4()) message_id = str(uuid.uuid4())
self.messages[message_id] = message self.messages[message_id] = message
return message_id return message_id
@ -540,7 +539,7 @@ class SNSBackend(BaseBackend):
if len(message) > MAXIMUM_SMS_MESSAGE_BYTES: if len(message) > MAXIMUM_SMS_MESSAGE_BYTES:
raise ValueError("SMS message must be less than 1600 bytes") raise ValueError("SMS message must be less than 1600 bytes")
message_id = six.text_type(uuid.uuid4()) message_id = str(uuid.uuid4())
self.sms_messages[message_id] = (phone_number, message) self.sms_messages[message_id] = (phone_number, message)
return message_id return message_id
@ -656,7 +655,7 @@ class SNSBackend(BaseBackend):
def _validate_filter_policy(self, value): def _validate_filter_policy(self, value):
# TODO: extend validation checks # TODO: extend validation checks
combinations = 1 combinations = 1
for rules in six.itervalues(value): for rules in value.values():
combinations *= len(rules) combinations *= len(rules)
# Even the official documentation states the total combination of values must not exceed 100, in reality it is 150 # Even the official documentation states the total combination of values must not exceed 100, in reality it is 150
# https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html#subscription-filter-policy-constraints # https://docs.aws.amazon.com/sns/latest/dg/sns-subscription-filter-policies.html#subscription-filter-policy-constraints
@ -665,15 +664,15 @@ class SNSBackend(BaseBackend):
"Invalid parameter: FilterPolicy: Filter policy is too complex" "Invalid parameter: FilterPolicy: Filter policy is too complex"
) )
for field, rules in six.iteritems(value): for field, rules in value.items():
for rule in rules: for rule in rules:
if rule is None: if rule is None:
continue continue
if isinstance(rule, six.string_types): if isinstance(rule, str):
continue continue
if isinstance(rule, bool): if isinstance(rule, bool):
continue continue
if isinstance(rule, (six.integer_types, float)): if isinstance(rule, (int, float)):
if rule <= -1000000000 or rule >= 1000000000: if rule <= -1000000000 or rule >= 1000000000:
raise InternalError("Unknown") raise InternalError("Unknown")
continue continue

View File

@ -7,7 +7,6 @@ import random
import re import re
import string import string
import six
import struct import struct
from copy import deepcopy from copy import deepcopy
from xml.sax.saxutils import escape from xml.sax.saxutils import escape
@ -147,7 +146,7 @@ class Message(BaseModel):
@staticmethod @staticmethod
def utf8(string): def utf8(string):
if isinstance(string, six.string_types): if isinstance(string, str):
return string.encode("utf-8") return string.encode("utf-8")
return string return string
@ -307,7 +306,7 @@ class Queue(CloudFormationModel):
) )
bool_fields = ("ContentBasedDeduplication", "FifoQueue") bool_fields = ("ContentBasedDeduplication", "FifoQueue")
for key, value in six.iteritems(attributes): for key, value in attributes.items():
if key in integer_fields: if key in integer_fields:
value = int(value) value = int(value)
if key in bool_fields: if key in bool_fields:
@ -328,7 +327,7 @@ class Queue(CloudFormationModel):
def _setup_dlq(self, policy): def _setup_dlq(self, policy):
if isinstance(policy, six.text_type): if isinstance(policy, str):
try: try:
self.redrive_policy = json.loads(policy) self.redrive_policy = json.loads(policy)
except ValueError: except ValueError:

View File

@ -10,7 +10,7 @@ from moto.core.utils import (
underscores_to_camelcase, underscores_to_camelcase,
camelcase_to_pascal, camelcase_to_pascal,
) )
from six.moves.urllib.parse import urlparse from urllib.parse import urlparse
from .exceptions import ( from .exceptions import (
EmptyBatchRequest, EmptyBatchRequest,

View File

@ -1,7 +1,7 @@
from functools import wraps from functools import wraps
from botocore.paginate import TokenDecoder, TokenEncoder from botocore.paginate import TokenDecoder, TokenEncoder
from six.moves import reduce from functools import reduce
from .exceptions import InvalidToken from .exceptions import InvalidToken

View File

@ -3,8 +3,6 @@ import os
import random import random
import string import string
import six
ACCOUNT_SPECIFIC_ACCESS_KEY_PREFIX = "8NWMTLYQ" ACCOUNT_SPECIFIC_ACCESS_KEY_PREFIX = "8NWMTLYQ"
ACCOUNT_SPECIFIC_ASSUMED_ROLE_ID_PREFIX = "3X42LBCD" ACCOUNT_SPECIFIC_ASSUMED_ROLE_ID_PREFIX = "3X42LBCD"
SESSION_TOKEN_PREFIX = "FQoGZXIvYXdzEBYaD" SESSION_TOKEN_PREFIX = "FQoGZXIvYXdzEBYaD"
@ -34,6 +32,6 @@ def random_assumed_role_id():
def _random_uppercase_or_digit_sequence(length): def _random_uppercase_or_digit_sequence(length):
return "".join( return "".join(
six.text_type(random.choice(string.ascii_uppercase + string.digits)) str(random.choice(string.ascii_uppercase + string.digits))
for _ in range(length) for _ in range(length)
) )

View File

@ -1,5 +1,4 @@
import json import json
import six
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
@ -31,7 +30,7 @@ class SWFResponse(BaseResponse):
self._check_string(parameter) self._check_string(parameter)
def _check_string(self, parameter): def _check_string(self, parameter):
if not isinstance(parameter, six.string_types): if not isinstance(parameter, str):
raise SWFSerializationException(parameter) raise SWFSerializationException(parameter)
def _check_none_or_list_of_strings(self, parameter): def _check_none_or_list_of_strings(self, parameter):
@ -42,7 +41,7 @@ class SWFResponse(BaseResponse):
if not isinstance(parameter, list): if not isinstance(parameter, list):
raise SWFSerializationException(parameter) raise SWFSerializationException(parameter)
for i in parameter: for i in parameter:
if not isinstance(i, six.string_types): if not isinstance(i, str):
raise SWFSerializationException(parameter) raise SWFSerializationException(parameter)
def _check_exclusivity(self, **kwargs): def _check_exclusivity(self, **kwargs):

View File

@ -1,10 +1,6 @@
import json import json
import random import random
import string import string
import six
if six.PY2:
from io import open
def random_string(length=None): def random_string(length=None):

View File

@ -4,7 +4,7 @@ import datetime
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from moto.core.exceptions import AWSError from moto.core.exceptions import AWSError
from six.moves.urllib.parse import urlsplit from urllib.parse import urlsplit
from .models import xray_backends from .models import xray_backends
from .exceptions import BadSegmentException from .exceptions import BadSegmentException

View File

@ -1,12 +1,11 @@
-e .[all,server] -e .[all,server]
-r requirements-tests.txt -r requirements-tests.txt
black==19.10b0; python_version >= '3.6' black==19.10b0
regex==2019.11.1; python_version >= '3.6' # Needed for black regex==2019.11.1
coverage==4.5.4 coverage==4.5.4
flake8==3.7.8 flake8==3.7.8
boto>=2.45.0 boto>=2.45.0
prompt-toolkit==2.0.10 # 3.x is not available with python2
click click
inflection==0.3.1 inflection==0.3.1
lxml lxml

View File

@ -1,7 +1,4 @@
pytest pytest
pytest-cov; python_version >= '3.6' pytest-cov
# https://github.com/aws/aws-xray-sdk-python/issues/196
# Downgrade pytest-cov to the last version that uses coverage < 5
pytest-cov<=2.10.1; python_version < '3.6'
sure==1.4.11 sure==1.4.11
freezegun freezegun

View File

@ -1,12 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
from __future__ import unicode_literals from __future__ import unicode_literals
import codecs
from io import open from io import open
import os import os
import re import re
import setuptools
from setuptools import setup, find_packages from setuptools import setup, find_packages
import sys
# Borrowed from pip at https://github.com/pypa/pip/blob/62c27dee45625e1b63d1e023b0656310f276e050/setup.py#L11-L15 # Borrowed from pip at https://github.com/pypa/pip/blob/62c27dee45625e1b63d1e023b0656310f276e050/setup.py#L11-L15
here = os.path.abspath(os.path.dirname(__file__)) here = os.path.abspath(os.path.dirname(__file__))
@ -35,43 +32,18 @@ install_requires = [
"cryptography>=3.3.1", "cryptography>=3.3.1",
"requests>=2.5", "requests>=2.5",
"xmltodict", "xmltodict",
"six>1.9",
"werkzeug", "werkzeug",
"pytz", "pytz",
"python-dateutil<3.0.0,>=2.1", "python-dateutil<3.0.0,>=2.1",
"responses>=0.9.0", "responses>=0.9.0",
"MarkupSafe!=2.0.0a1", # This is a Jinja2 dependency, 2.0.0a1 currently seems broken "MarkupSafe!=2.0.0a1", # This is a Jinja2 dependency, 2.0.0a1 currently seems broken
]
#
# Avoid pins where they are not necessary. These pins were introduced by the
# following commit for Py2 compatibility. They are not required for non-Py2
# users.
#
# https://github.com/mpenkov/moto/commit/00134d2df37bb4dcd5f447ef951d383bfec0903c
#
install_requires += [
#
# This is an indirect dependency. Version 5.0.0 claims to be for
# Py2.6+, but it really isn't.
#
# https://github.com/jaraco/configparser/issues/51
#
"configparser<5.0; python_version < '3'",
"Jinja2>=2.10.1", "Jinja2>=2.10.1",
"Jinja2<3.0.0; python_version < '3'",
"mock<=3.0.5; python_version < '3'",
"more-itertools", "more-itertools",
"more-itertools==5.0.0; python_version < '3'",
# Indirect - Py2 works with 4.5, breaks with 4.7, but officially only supported by 4.0
"rsa<=4.0; python_version < '3'",
"setuptools", "setuptools",
"setuptools==44.0.0; python_version < '3'",
] ]
_dep_PyYAML = "PyYAML>=5.1" _dep_PyYAML = "PyYAML>=5.1"
_dep_python_jose_py2 = "python-jose[cryptography]>=3.1.0,<3.3.0; python_version<'3'" _dep_python_jose = "python-jose[cryptography]>=3.1.0,<4.0.0"
_dep_python_jose_py3 = "python-jose[cryptography]>=3.1.0,<4.0.0; python_version>'3'"
_dep_python_jose_ecdsa_pin = ( _dep_python_jose_ecdsa_pin = (
"ecdsa<0.15" # https://github.com/spulec/moto/pull/3263#discussion_r477404984 "ecdsa<0.15" # https://github.com/spulec/moto/pull/3263#discussion_r477404984
) )
@ -80,23 +52,18 @@ _dep_jsondiff = "jsondiff>=1.1.2"
_dep_aws_xray_sdk = "aws-xray-sdk!=0.96,>=0.93" _dep_aws_xray_sdk = "aws-xray-sdk!=0.96,>=0.93"
_dep_idna = "idna<3,>=2.5" _dep_idna = "idna<3,>=2.5"
_dep_cfn_lint = "cfn-lint>=0.4.0" _dep_cfn_lint = "cfn-lint>=0.4.0"
_dep_decorator = "decorator<=4.4.2; python_version<'3'" # Transitive dependency - last version that supports py2.7 _dep_sshpubkeys = "sshpubkeys>=3.1.0"
_dep_sshpubkeys_py2 = "sshpubkeys==3.1.0; python_version<'3'"
_dep_sshpubkeys_py3 = "sshpubkeys>=3.1.0; python_version>'3'"
all_extra_deps = [ all_extra_deps = [
_dep_PyYAML, _dep_PyYAML,
_dep_python_jose_py2, _dep_python_jose,
_dep_python_jose_py3,
_dep_python_jose_ecdsa_pin, _dep_python_jose_ecdsa_pin,
_dep_docker, _dep_docker,
_dep_jsondiff, _dep_jsondiff,
_dep_aws_xray_sdk, _dep_aws_xray_sdk,
_dep_idna, _dep_idna,
_dep_cfn_lint, _dep_cfn_lint,
_dep_decorator, _dep_sshpubkeys,
_dep_sshpubkeys_py2,
_dep_sshpubkeys_py3,
] ]
all_server_deps = all_extra_deps + ["flask", "flask-cors"] all_server_deps = all_extra_deps + ["flask", "flask-cors"]
@ -104,20 +71,20 @@ all_server_deps = all_extra_deps + ["flask", "flask-cors"]
# i.e. even those without extra dependencies. # i.e. even those without extra dependencies.
# Would be good for future-compatibility, I guess. # Would be good for future-compatibility, I guess.
extras_per_service = { extras_per_service = {
"apigateway": [_dep_python_jose_py2, _dep_python_jose_py3, _dep_python_jose_ecdsa_pin], "apigateway": [_dep_python_jose, _dep_python_jose_ecdsa_pin],
"awslambda": [_dep_docker], "awslambda": [_dep_docker],
"batch": [_dep_docker], "batch": [_dep_docker],
"cloudformation": [_dep_docker, _dep_PyYAML, _dep_cfn_lint, _dep_decorator], "cloudformation": [_dep_docker, _dep_PyYAML, _dep_cfn_lint],
"cognitoidp": [_dep_python_jose_py2, _dep_python_jose_py3, _dep_python_jose_ecdsa_pin], "cognitoidp": [_dep_python_jose, _dep_python_jose_ecdsa_pin],
"dynamodb2": [_dep_docker], "dynamodb2": [_dep_docker],
"dynamodbstreams": [_dep_docker], "dynamodbstreams": [_dep_docker],
"ec2": [_dep_docker, _dep_sshpubkeys_py2, _dep_sshpubkeys_py3], "ec2": [_dep_docker, _dep_sshpubkeys],
"iotdata": [_dep_jsondiff], "iotdata": [_dep_jsondiff],
"s3": [_dep_PyYAML], "s3": [_dep_PyYAML],
"ses": [_dep_docker], "ses": [_dep_docker],
"sns": [_dep_docker], "sns": [_dep_docker],
"sqs": [_dep_docker], "sqs": [_dep_docker],
"ssm": [_dep_docker, _dep_PyYAML, _dep_decorator], "ssm": [_dep_docker, _dep_PyYAML],
"xray": [_dep_aws_xray_sdk], "xray": [_dep_aws_xray_sdk],
} }
extras_require = { extras_require = {
@ -127,13 +94,6 @@ extras_require = {
extras_require.update(extras_per_service) extras_require.update(extras_per_service)
# https://hynek.me/articles/conditional-python-dependencies/
if int(setuptools.__version__.split(".", 1)[0]) < 18:
if sys.version_info[0:2] < (3, 3):
install_requires.append("backports.tempfile")
else:
extras_require[":python_version<'3.3'"] = ["backports.tempfile"]
setup( setup(
name="moto", name="moto",
@ -157,8 +117,6 @@ setup(
license="Apache", license="Apache",
test_suite="tests", test_suite="tests",
classifiers=[ classifiers=[
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.6",

7
tests/Dockerfile Normal file
View File

@ -0,0 +1,7 @@
FROM python:3.7-buster
ADD . /moto/
ENV PYTHONUNBUFFERED 1
WORKDIR /moto/
RUN make init
RUN make test

View File

@ -1,7 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import boto import boto
from unittest import SkipTest from unittest import SkipTest
import six
def version_tuple(v): def version_tuple(v):
@ -26,10 +25,3 @@ class requires_boto_gte(object):
if boto_version >= required: if boto_version >= required:
return test return test
return skip_test return skip_test
class disable_on_py3(object):
def __call__(self, test):
if not six.PY3:
return test
return skip_test

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import json import json
from six.moves.urllib.parse import urlencode from urllib.parse import urlencode
import re import re
import sure # noqa import sure # noqa

View File

@ -2,15 +2,12 @@ import unittest
from moto import mock_dynamodb2_deprecated, mock_dynamodb2 from moto import mock_dynamodb2_deprecated, mock_dynamodb2
import socket import socket
from six import PY3
class TestSocketPair(unittest.TestCase): class TestSocketPair(unittest.TestCase):
@mock_dynamodb2_deprecated @mock_dynamodb2_deprecated
def test_asyncio_deprecated(self): def test_asyncio_deprecated(self):
if PY3:
self.assertIn( self.assertIn(
"moto.packages.httpretty.core.fakesock.socket", "httpretty.core.fakesock.socket",
str(socket.socket), str(socket.socket),
"Our mock should be present", "Our mock should be present",
) )
@ -21,10 +18,8 @@ class TestSocketPair(unittest.TestCase):
@mock_dynamodb2_deprecated @mock_dynamodb2_deprecated
def test_socket_pair_deprecated(self): def test_socket_pair_deprecated(self):
# In Python2, the fakesocket is not set, for some reason.
if PY3:
self.assertIn( self.assertIn(
"moto.packages.httpretty.core.fakesock.socket", "httpretty.core.fakesock.socket",
str(socket.socket), str(socket.socket),
"Our mock should be present", "Our mock should be present",
) )

View File

@ -1,5 +1,4 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import six
import boto import boto
import boto.dynamodb import boto.dynamodb
import sure # noqa import sure # noqa

View File

@ -1,12 +1,10 @@
import six
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.asymmetric import rsa
def rsa_check_private_key(private_key_material): def rsa_check_private_key(private_key_material):
assert isinstance(private_key_material, six.string_types) assert isinstance(private_key_material, str)
private_key = serialization.load_pem_private_key( private_key = serialization.load_pem_private_key(
data=private_key_material.encode("ascii"), data=private_key_material.encode("ascii"),

View File

@ -5,7 +5,6 @@ import pytest
import boto import boto
import boto3 import boto3
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
import six
import sure # noqa import sure # noqa
@ -30,7 +29,7 @@ def test_eip_allocate_classic():
standard = conn.allocate_address() standard = conn.allocate_address()
standard.should.be.a(boto.ec2.address.Address) standard.should.be.a(boto.ec2.address.Address)
standard.public_ip.should.be.a(six.text_type) standard.public_ip.should.be.a(str)
standard.instance_id.should.be.none standard.instance_id.should.be.none
standard.domain.should.be.equal("standard") standard.domain.should.be.equal("standard")

View File

@ -8,7 +8,6 @@ from unittest import SkipTest
import base64 import base64
import ipaddress import ipaddress
import six
import boto import boto
import boto3 import boto3
from boto.ec2.instance import Reservation, InstanceAttribute from boto.ec2.instance import Reservation, InstanceAttribute
@ -21,10 +20,7 @@ from tests import EXAMPLE_AMI_ID
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
if six.PY2: decode_method = base64.decodebytes
decode_method = base64.decodestring
else:
decode_method = base64.decodebytes
################ Test Readme ############### ################ Test Readme ###############
def add_servers(ami_id, count): def add_servers(ami_id, count):
@ -1050,7 +1046,7 @@ def test_run_instance_with_subnet_boto3():
instance = resp["Instances"][0] instance = resp["Instances"][0]
instance["SubnetId"].should.equal(subnet_id) instance["SubnetId"].should.equal(subnet_id)
priv_ipv4 = ipaddress.ip_address(six.text_type(instance["PrivateIpAddress"])) priv_ipv4 = ipaddress.ip_address(str(instance["PrivateIpAddress"]))
subnet_cidr.should.contain(priv_ipv4) subnet_cidr.should.contain(priv_ipv4)

View File

@ -8,7 +8,6 @@ from boto.emr.bootstrap_action import BootstrapAction
from boto.emr.instance_group import InstanceGroup from boto.emr.instance_group import InstanceGroup
from boto.emr.step import StreamingStep from boto.emr.step import StreamingStep
import six
import sure # noqa import sure # noqa
from moto import mock_emr_deprecated from moto import mock_emr_deprecated
@ -86,7 +85,7 @@ def test_describe_cluster():
cluster.id.should.equal(cluster_id) cluster.id.should.equal(cluster_id)
cluster.loguri.should.equal(args["log_uri"]) cluster.loguri.should.equal(args["log_uri"])
cluster.masterpublicdnsname.should.be.a(six.string_types) cluster.masterpublicdnsname.should.be.a(str)
cluster.name.should.equal(args["name"]) cluster.name.should.equal(args["name"])
int(cluster.normalizedinstancehours).should.equal(0) int(cluster.normalizedinstancehours).should.equal(0)
# cluster.release_label # cluster.release_label
@ -96,11 +95,11 @@ def test_describe_cluster():
cluster.servicerole.should.equal(args["service_role"]) cluster.servicerole.should.equal(args["service_role"])
cluster.status.state.should.equal("TERMINATED") cluster.status.state.should.equal("TERMINATED")
cluster.status.statechangereason.message.should.be.a(six.string_types) cluster.status.statechangereason.message.should.be.a(str)
cluster.status.statechangereason.code.should.be.a(six.string_types) cluster.status.statechangereason.code.should.be.a(str)
cluster.status.timeline.creationdatetime.should.be.a(six.string_types) cluster.status.timeline.creationdatetime.should.be.a(str)
# cluster.status.timeline.enddatetime.should.be.a(six.string_types) # cluster.status.timeline.enddatetime.should.be.a(str)
# cluster.status.timeline.readydatetime.should.be.a(six.string_types) # cluster.status.timeline.readydatetime.should.be.a(str)
dict((item.key, item.value) for item in cluster.tags).should.equal(input_tags) dict((item.key, item.value) for item in cluster.tags).should.equal(input_tags)
@ -195,10 +194,10 @@ def test_describe_jobflow():
jf = conn.describe_jobflow(cluster_id) jf = conn.describe_jobflow(cluster_id)
jf.amiversion.should.equal(args["ami_version"]) jf.amiversion.should.equal(args["ami_version"])
jf.bootstrapactions.should.equal(None) jf.bootstrapactions.should.equal(None)
jf.creationdatetime.should.be.a(six.string_types) jf.creationdatetime.should.be.a(str)
jf.should.have.property("laststatechangereason") jf.should.have.property("laststatechangereason")
jf.readydatetime.should.be.a(six.string_types) jf.readydatetime.should.be.a(str)
jf.startdatetime.should.be.a(six.string_types) jf.startdatetime.should.be.a(str)
jf.state.should.equal("WAITING") jf.state.should.equal("WAITING")
jf.ec2keyname.should.equal(args["ec2_keyname"]) jf.ec2keyname.should.equal(args["ec2_keyname"])
@ -207,24 +206,24 @@ def test_describe_jobflow():
int(jf.instancecount).should.equal(2) int(jf.instancecount).should.equal(2)
for ig in jf.instancegroups: for ig in jf.instancegroups:
ig.creationdatetime.should.be.a(six.string_types) ig.creationdatetime.should.be.a(str)
# ig.enddatetime.should.be.a(six.string_types) # ig.enddatetime.should.be.a(str)
ig.should.have.property("instancegroupid").being.a(six.string_types) ig.should.have.property("instancegroupid").being.a(str)
int(ig.instancerequestcount).should.equal(1) int(ig.instancerequestcount).should.equal(1)
ig.instancerole.should.be.within(["MASTER", "CORE"]) ig.instancerole.should.be.within(["MASTER", "CORE"])
int(ig.instancerunningcount).should.equal(1) int(ig.instancerunningcount).should.equal(1)
ig.instancetype.should.equal("c1.medium") ig.instancetype.should.equal("c1.medium")
ig.laststatechangereason.should.be.a(six.string_types) ig.laststatechangereason.should.be.a(str)
ig.market.should.equal("ON_DEMAND") ig.market.should.equal("ON_DEMAND")
ig.name.should.be.a(six.string_types) ig.name.should.be.a(str)
ig.readydatetime.should.be.a(six.string_types) ig.readydatetime.should.be.a(str)
ig.startdatetime.should.be.a(six.string_types) ig.startdatetime.should.be.a(str)
ig.state.should.equal("RUNNING") ig.state.should.equal("RUNNING")
jf.keepjobflowalivewhennosteps.should.equal("true") jf.keepjobflowalivewhennosteps.should.equal("true")
jf.masterinstanceid.should.be.a(six.string_types) jf.masterinstanceid.should.be.a(str)
jf.masterinstancetype.should.equal(args["master_instance_type"]) jf.masterinstancetype.should.equal(args["master_instance_type"])
jf.masterpublicdnsname.should.be.a(six.string_types) jf.masterpublicdnsname.should.be.a(str)
int(jf.normalizedinstancehours).should.equal(0) int(jf.normalizedinstancehours).should.equal(0)
jf.availabilityzone.should.equal(args["availability_zone"]) jf.availabilityzone.should.equal(args["availability_zone"])
jf.slaveinstancetype.should.equal(args["slave_instance_type"]) jf.slaveinstancetype.should.equal(args["slave_instance_type"])
@ -288,12 +287,12 @@ def test_list_clusters():
x.name.should.equal(y["name"]) x.name.should.equal(y["name"])
x.normalizedinstancehours.should.equal(y["normalizedinstancehours"]) x.normalizedinstancehours.should.equal(y["normalizedinstancehours"])
x.status.state.should.equal(y["state"]) x.status.state.should.equal(y["state"])
x.status.timeline.creationdatetime.should.be.a(six.string_types) x.status.timeline.creationdatetime.should.be.a(str)
if y["state"] == "TERMINATED": if y["state"] == "TERMINATED":
x.status.timeline.enddatetime.should.be.a(six.string_types) x.status.timeline.enddatetime.should.be.a(str)
else: else:
x.status.timeline.shouldnt.have.property("enddatetime") x.status.timeline.shouldnt.have.property("enddatetime")
x.status.timeline.readydatetime.should.be.a(six.string_types) x.status.timeline.readydatetime.should.be.a(str)
if not hasattr(resp, "marker"): if not hasattr(resp, "marker"):
break break
args = {"marker": resp.marker} args = {"marker": resp.marker}
@ -489,18 +488,18 @@ def test_instance_groups():
y = input_groups[x.name] y = input_groups[x.name]
if hasattr(y, "bidprice"): if hasattr(y, "bidprice"):
x.bidprice.should.equal(y.bidprice) x.bidprice.should.equal(y.bidprice)
x.creationdatetime.should.be.a(six.string_types) x.creationdatetime.should.be.a(str)
# x.enddatetime.should.be.a(six.string_types) # x.enddatetime.should.be.a(str)
x.should.have.property("instancegroupid") x.should.have.property("instancegroupid")
int(x.instancerequestcount).should.equal(y.num_instances) int(x.instancerequestcount).should.equal(y.num_instances)
x.instancerole.should.equal(y.role) x.instancerole.should.equal(y.role)
int(x.instancerunningcount).should.equal(y.num_instances) int(x.instancerunningcount).should.equal(y.num_instances)
x.instancetype.should.equal(y.type) x.instancetype.should.equal(y.type)
x.laststatechangereason.should.be.a(six.string_types) x.laststatechangereason.should.be.a(str)
x.market.should.equal(y.market) x.market.should.equal(y.market)
x.name.should.be.a(six.string_types) x.name.should.be.a(str)
x.readydatetime.should.be.a(six.string_types) x.readydatetime.should.be.a(str)
x.startdatetime.should.be.a(six.string_types) x.startdatetime.should.be.a(str)
x.state.should.equal("RUNNING") x.state.should.equal("RUNNING")
for x in conn.list_instance_groups(job_id).instancegroups: for x in conn.list_instance_groups(job_id).instancegroups:
@ -519,11 +518,11 @@ def test_instance_groups():
int(x.runninginstancecount).should.equal(y.num_instances) int(x.runninginstancecount).should.equal(y.num_instances)
# ShrinkPolicy # ShrinkPolicy
x.status.state.should.equal("RUNNING") x.status.state.should.equal("RUNNING")
x.status.statechangereason.code.should.be.a(six.string_types) x.status.statechangereason.code.should.be.a(str)
x.status.statechangereason.message.should.be.a(six.string_types) x.status.statechangereason.message.should.be.a(str)
x.status.timeline.creationdatetime.should.be.a(six.string_types) x.status.timeline.creationdatetime.should.be.a(str)
# x.status.timeline.enddatetime.should.be.a(six.string_types) # x.status.timeline.enddatetime.should.be.a(str)
x.status.timeline.readydatetime.should.be.a(six.string_types) x.status.timeline.readydatetime.should.be.a(str)
igs = dict((g.name, g) for g in jf.instancegroups) igs = dict((g.name, g) for g in jf.instancegroups)
@ -571,14 +570,14 @@ def test_steps():
for step in jf.steps: for step in jf.steps:
step.actiononfailure.should.equal("TERMINATE_JOB_FLOW") step.actiononfailure.should.equal("TERMINATE_JOB_FLOW")
list(arg.value for arg in step.args).should.have.length_of(8) list(arg.value for arg in step.args).should.have.length_of(8)
step.creationdatetime.should.be.a(six.string_types) step.creationdatetime.should.be.a(str)
# step.enddatetime.should.be.a(six.string_types) # step.enddatetime.should.be.a(str)
step.jar.should.equal("/home/hadoop/contrib/streaming/hadoop-streaming.jar") step.jar.should.equal("/home/hadoop/contrib/streaming/hadoop-streaming.jar")
step.laststatechangereason.should.be.a(six.string_types) step.laststatechangereason.should.be.a(str)
step.mainclass.should.equal("") step.mainclass.should.equal("")
step.name.should.be.a(six.string_types) step.name.should.be.a(str)
# step.readydatetime.should.be.a(six.string_types) # step.readydatetime.should.be.a(str)
# step.startdatetime.should.be.a(six.string_types) # step.startdatetime.should.be.a(str)
step.state.should.be.within(["STARTING", "PENDING"]) step.state.should.be.within(["STARTING", "PENDING"])
expected = dict((s.name, s) for s in input_steps) expected = dict((s.name, s) for s in input_steps)
@ -602,13 +601,13 @@ def test_steps():
x.config.jar.should.equal("/home/hadoop/contrib/streaming/hadoop-streaming.jar") x.config.jar.should.equal("/home/hadoop/contrib/streaming/hadoop-streaming.jar")
x.config.mainclass.should.equal("") x.config.mainclass.should.equal("")
# properties # properties
x.should.have.property("id").should.be.a(six.string_types) x.should.have.property("id").should.be.a(str)
x.name.should.equal(y.name) x.name.should.equal(y.name)
x.status.state.should.be.within(["STARTING", "PENDING"]) x.status.state.should.be.within(["STARTING", "PENDING"])
# x.status.statechangereason # x.status.statechangereason
x.status.timeline.creationdatetime.should.be.a(six.string_types) x.status.timeline.creationdatetime.should.be.a(str)
# x.status.timeline.enddatetime.should.be.a(six.string_types) # x.status.timeline.enddatetime.should.be.a(str)
# x.status.timeline.startdatetime.should.be.a(six.string_types) # x.status.timeline.startdatetime.should.be.a(str)
x = conn.describe_step(cluster_id, x.id) x = conn.describe_step(cluster_id, x.id)
list(arg.value for arg in x.config.args).should.equal( list(arg.value for arg in x.config.args).should.equal(
@ -626,13 +625,13 @@ def test_steps():
x.config.jar.should.equal("/home/hadoop/contrib/streaming/hadoop-streaming.jar") x.config.jar.should.equal("/home/hadoop/contrib/streaming/hadoop-streaming.jar")
x.config.mainclass.should.equal("") x.config.mainclass.should.equal("")
# properties # properties
x.should.have.property("id").should.be.a(six.string_types) x.should.have.property("id").should.be.a(str)
x.name.should.equal(y.name) x.name.should.equal(y.name)
x.status.state.should.be.within(["STARTING", "PENDING"]) x.status.state.should.be.within(["STARTING", "PENDING"])
# x.status.statechangereason # x.status.statechangereason
x.status.timeline.creationdatetime.should.be.a(six.string_types) x.status.timeline.creationdatetime.should.be.a(str)
# x.status.timeline.enddatetime.should.be.a(six.string_types) # x.status.timeline.enddatetime.should.be.a(str)
# x.status.timeline.startdatetime.should.be.a(six.string_types) # x.status.timeline.startdatetime.should.be.a(str)
@requires_boto_gte("2.39") @requires_boto_gte("2.39")
def test_list_steps_with_states(): def test_list_steps_with_states():

View File

@ -7,7 +7,6 @@ from datetime import datetime
import boto3 import boto3
import json import json
import pytz import pytz
import six
import sure # noqa import sure # noqa
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
import pytest import pytest
@ -157,13 +156,13 @@ def test_describe_cluster():
cl["Id"].should.equal(cluster_id) cl["Id"].should.equal(cluster_id)
cl["KerberosAttributes"].should.equal(args["KerberosAttributes"]) cl["KerberosAttributes"].should.equal(args["KerberosAttributes"])
cl["LogUri"].should.equal(args["LogUri"]) cl["LogUri"].should.equal(args["LogUri"])
cl["MasterPublicDnsName"].should.be.a(six.string_types) cl["MasterPublicDnsName"].should.be.a(str)
cl["Name"].should.equal(args["Name"]) cl["Name"].should.equal(args["Name"])
cl["NormalizedInstanceHours"].should.equal(0) cl["NormalizedInstanceHours"].should.equal(0)
# cl['ReleaseLabel'].should.equal('emr-5.0.0') # cl['ReleaseLabel'].should.equal('emr-5.0.0')
cl.shouldnt.have.key("RequestedAmiVersion") cl.shouldnt.have.key("RequestedAmiVersion")
cl["RunningAmiVersion"].should.equal("1.0.0") cl["RunningAmiVersion"].should.equal("1.0.0")
cl["SecurityConfiguration"].should.be.a(six.string_types) cl["SecurityConfiguration"].should.be.a(str)
cl["SecurityConfiguration"].should.equal(args["SecurityConfiguration"]) cl["SecurityConfiguration"].should.equal(args["SecurityConfiguration"])
cl["ServiceRole"].should.equal(args["ServiceRole"]) cl["ServiceRole"].should.equal(args["ServiceRole"])
@ -276,7 +275,7 @@ def test_describe_job_flow():
esd = jf["ExecutionStatusDetail"] esd = jf["ExecutionStatusDetail"]
esd["CreationDateTime"].should.be.a("datetime.datetime") esd["CreationDateTime"].should.be.a("datetime.datetime")
# esd['EndDateTime'].should.be.a('datetime.datetime') # esd['EndDateTime'].should.be.a('datetime.datetime')
# esd['LastStateChangeReason'].should.be.a(six.string_types) # esd['LastStateChangeReason'].should.be.a(str)
esd["ReadyDateTime"].should.be.a("datetime.datetime") esd["ReadyDateTime"].should.be.a("datetime.datetime")
esd["StartDateTime"].should.be.a("datetime.datetime") esd["StartDateTime"].should.be.a("datetime.datetime")
esd["State"].should.equal("WAITING") esd["State"].should.equal("WAITING")
@ -289,21 +288,21 @@ def test_describe_job_flow():
# ig['BidPrice'] # ig['BidPrice']
ig["CreationDateTime"].should.be.a("datetime.datetime") ig["CreationDateTime"].should.be.a("datetime.datetime")
# ig['EndDateTime'].should.be.a('datetime.datetime') # ig['EndDateTime'].should.be.a('datetime.datetime')
ig["InstanceGroupId"].should.be.a(six.string_types) ig["InstanceGroupId"].should.be.a(str)
ig["InstanceRequestCount"].should.be.a(int) ig["InstanceRequestCount"].should.be.a(int)
ig["InstanceRole"].should.be.within(["MASTER", "CORE"]) ig["InstanceRole"].should.be.within(["MASTER", "CORE"])
ig["InstanceRunningCount"].should.be.a(int) ig["InstanceRunningCount"].should.be.a(int)
ig["InstanceType"].should.be.within(["c3.medium", "c3.xlarge"]) ig["InstanceType"].should.be.within(["c3.medium", "c3.xlarge"])
# ig['LastStateChangeReason'].should.be.a(six.string_types) # ig['LastStateChangeReason'].should.be.a(str)
ig["Market"].should.equal("ON_DEMAND") ig["Market"].should.equal("ON_DEMAND")
ig["Name"].should.be.a(six.string_types) ig["Name"].should.be.a(str)
ig["ReadyDateTime"].should.be.a("datetime.datetime") ig["ReadyDateTime"].should.be.a("datetime.datetime")
ig["StartDateTime"].should.be.a("datetime.datetime") ig["StartDateTime"].should.be.a("datetime.datetime")
ig["State"].should.equal("RUNNING") ig["State"].should.equal("RUNNING")
attrs["KeepJobFlowAliveWhenNoSteps"].should.equal(True) attrs["KeepJobFlowAliveWhenNoSteps"].should.equal(True)
# attrs['MasterInstanceId'].should.be.a(six.string_types) # attrs['MasterInstanceId'].should.be.a(str)
attrs["MasterInstanceType"].should.equal(args["Instances"]["MasterInstanceType"]) attrs["MasterInstanceType"].should.equal(args["Instances"]["MasterInstanceType"])
attrs["MasterPublicDnsName"].should.be.a(six.string_types) attrs["MasterPublicDnsName"].should.be.a(str)
attrs["NormalizedInstanceHours"].should.equal(0) attrs["NormalizedInstanceHours"].should.equal(0)
attrs["Placement"]["AvailabilityZone"].should.equal( attrs["Placement"]["AvailabilityZone"].should.equal(
args["Instances"]["Placement"]["AvailabilityZone"] args["Instances"]["Placement"]["AvailabilityZone"]
@ -911,8 +910,8 @@ def test_instance_groups():
x["RunningInstanceCount"].should.equal(y["InstanceCount"]) x["RunningInstanceCount"].should.equal(y["InstanceCount"])
# ShrinkPolicy # ShrinkPolicy
x["Status"]["State"].should.equal("RUNNING") x["Status"]["State"].should.equal("RUNNING")
x["Status"]["StateChangeReason"]["Code"].should.be.a(six.string_types) x["Status"]["StateChangeReason"]["Code"].should.be.a(str)
# x['Status']['StateChangeReason']['Message'].should.be.a(six.string_types) # x['Status']['StateChangeReason']['Message'].should.be.a(str)
x["Status"]["Timeline"]["CreationDateTime"].should.be.a("datetime.datetime") x["Status"]["Timeline"]["CreationDateTime"].should.be.a("datetime.datetime")
# x['Status']['Timeline']['EndDateTime'].should.be.a('datetime.datetime') # x['Status']['Timeline']['EndDateTime'].should.be.a('datetime.datetime')
x["Status"]["Timeline"]["ReadyDateTime"].should.be.a("datetime.datetime") x["Status"]["Timeline"]["ReadyDateTime"].should.be.a("datetime.datetime")
@ -1022,7 +1021,7 @@ def test_steps():
x["Config"]["Jar"].should.equal(y["HadoopJarStep"]["Jar"]) x["Config"]["Jar"].should.equal(y["HadoopJarStep"]["Jar"])
# x['Config']['MainClass'].should.equal(y['HadoopJarStep']['MainClass']) # x['Config']['MainClass'].should.equal(y['HadoopJarStep']['MainClass'])
# Properties # Properties
x["Id"].should.be.a(six.string_types) x["Id"].should.be.a(str)
x["Name"].should.equal(y["Name"]) x["Name"].should.equal(y["Name"])
x["Status"]["State"].should.be.within(["STARTING", "PENDING"]) x["Status"]["State"].should.be.within(["STARTING", "PENDING"])
# StateChangeReason # StateChangeReason
@ -1038,7 +1037,7 @@ def test_steps():
x["Config"]["Jar"].should.equal(y["HadoopJarStep"]["Jar"]) x["Config"]["Jar"].should.equal(y["HadoopJarStep"]["Jar"])
# x['Config']['MainClass'].should.equal(y['HadoopJarStep']['MainClass']) # x['Config']['MainClass'].should.equal(y['HadoopJarStep']['MainClass'])
# Properties # Properties
x["Id"].should.be.a(six.string_types) x["Id"].should.be.a(str)
x["Name"].should.equal(y["Name"]) x["Name"].should.equal(y["Name"])
x["Status"]["State"].should.be.within(["STARTING", "PENDING"]) x["Status"]["State"].should.be.within(["STARTING", "PENDING"])
# StateChangeReason # StateChangeReason

View File

@ -18,7 +18,7 @@ import pytest
from datetime import datetime from datetime import datetime
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
from uuid import uuid4 from uuid import uuid4
from six.moves.urllib import parse from urllib import parse
MOCK_CERT = """-----BEGIN CERTIFICATE----- MOCK_CERT = """-----BEGIN CERTIFICATE-----

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import json import json
from six.moves.urllib.parse import quote from urllib.parse import quote
import pytest import pytest
import sure # noqa import sure # noqa

View File

@ -1,6 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from six.moves.urllib.parse import quote from urllib.parse import quote
import pytest import pytest
import sure # noqa import sure # noqa

View File

@ -5,7 +5,6 @@ import re
import boto.kms import boto.kms
import boto3 import boto3
import six
import sure # noqa import sure # noqa
from boto.exception import JSONResponseError from boto.exception import JSONResponseError
from boto.kms.exceptions import AlreadyExistsException, NotFoundException from boto.kms.exceptions import AlreadyExistsException, NotFoundException
@ -23,7 +22,7 @@ PLAINTEXT_VECTORS = [
def _get_encoded_value(plaintext): def _get_encoded_value(plaintext):
if isinstance(plaintext, six.binary_type): if isinstance(plaintext, bytes):
return plaintext return plaintext
return plaintext.encode("utf-8") return plaintext.encode("utf-8")
@ -682,10 +681,7 @@ def test__assert_default_policy():
) )
if six.PY2: sort = lambda l: sorted(l, key=lambda d: d.keys())
sort = sorted
else:
sort = lambda l: sorted(l, key=lambda d: d.keys())
@mock_kms @mock_kms

View File

@ -7,7 +7,6 @@ import os
import boto3 import boto3
import botocore.exceptions import botocore.exceptions
import six
import sure # noqa import sure # noqa
from freezegun import freeze_time from freezegun import freeze_time
import pytest import pytest
@ -22,7 +21,7 @@ PLAINTEXT_VECTORS = [
def _get_encoded_value(plaintext): def _get_encoded_value(plaintext):
if isinstance(plaintext, six.binary_type): if isinstance(plaintext, bytes):
return plaintext return plaintext
return plaintext.encode("utf-8") return plaintext.encode("utf-8")

View File

@ -2,7 +2,6 @@ import os
import time import time
from unittest import SkipTest from unittest import SkipTest
import boto3 import boto3
import six
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
import pytest import pytest
import sure # noqa import sure # noqa
@ -76,7 +75,7 @@ def test_put_logs():
) )
events = res["events"] events = res["events"]
nextSequenceToken = putRes["nextSequenceToken"] nextSequenceToken = putRes["nextSequenceToken"]
assert isinstance(nextSequenceToken, six.string_types) == True assert isinstance(nextSequenceToken, str) == True
assert len(nextSequenceToken) == 56 assert len(nextSequenceToken) == 56
events.should.have.length_of(2) events.should.have.length_of(2)

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import six
import datetime import datetime
from moto.organizations import utils from moto.organizations import utils
@ -72,7 +71,7 @@ def validate_roots(org, response):
root.should.have.key("Arn").should.equal( root.should.have.key("Arn").should.equal(
utils.ROOT_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], root["Id"]) utils.ROOT_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], root["Id"])
) )
root.should.have.key("Name").should.be.a(six.string_types) root.should.have.key("Name").should.be.a(str)
root.should.have.key("PolicyTypes").should.be.a(list) root.should.have.key("PolicyTypes").should.be.a(list)
root["PolicyTypes"][0].should.have.key("Type").should.equal( root["PolicyTypes"][0].should.have.key("Type").should.equal(
"SERVICE_CONTROL_POLICY" "SERVICE_CONTROL_POLICY"
@ -87,7 +86,7 @@ def validate_organizational_unit(org, response):
ou.should.have.key("Arn").should.equal( ou.should.have.key("Arn").should.equal(
utils.OU_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], ou["Id"]) utils.OU_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], ou["Id"])
) )
ou.should.have.key("Name").should.be.a(six.string_types) ou.should.have.key("Name").should.be.a(str)
def validate_account(org, account): def validate_account(org, account):
@ -103,7 +102,7 @@ def validate_account(org, account):
account["Email"].should.match(utils.EMAIL_REGEX) account["Email"].should.match(utils.EMAIL_REGEX)
account["JoinedMethod"].should.be.within(["INVITED", "CREATED"]) account["JoinedMethod"].should.be.within(["INVITED", "CREATED"])
account["Status"].should.be.within(["ACTIVE", "SUSPENDED"]) account["Status"].should.be.within(["ACTIVE", "SUSPENDED"])
account["Name"].should.be.a(six.string_types) account["Name"].should.be.a(str)
account["JoinedTimestamp"].should.be.a(datetime.datetime) account["JoinedTimestamp"].should.be.a(datetime.datetime)
@ -120,7 +119,7 @@ def validate_create_account_status(create_status):
) )
create_status["Id"].should.match(utils.CREATE_ACCOUNT_STATUS_ID_REGEX) create_status["Id"].should.match(utils.CREATE_ACCOUNT_STATUS_ID_REGEX)
create_status["AccountId"].should.match(utils.ACCOUNT_ID_REGEX) create_status["AccountId"].should.match(utils.ACCOUNT_ID_REGEX)
create_status["AccountName"].should.be.a(six.string_types) create_status["AccountName"].should.be.a(str)
create_status["State"].should.equal("SUCCEEDED") create_status["State"].should.equal("SUCCEEDED")
create_status["RequestedTimestamp"].should.be.a(datetime.datetime) create_status["RequestedTimestamp"].should.be.a(datetime.datetime)
create_status["CompletedTimestamp"].should.be.a(datetime.datetime) create_status["CompletedTimestamp"].should.be.a(datetime.datetime)
@ -132,13 +131,13 @@ def validate_policy_summary(org, summary):
summary.should.have.key("Arn").should.equal( summary.should.have.key("Arn").should.equal(
utils.SCP_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], summary["Id"]) utils.SCP_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], summary["Id"])
) )
summary.should.have.key("Name").should.be.a(six.string_types) summary.should.have.key("Name").should.be.a(str)
summary.should.have.key("Description").should.be.a(six.string_types) summary.should.have.key("Description").should.be.a(str)
summary.should.have.key("Type").should.equal("SERVICE_CONTROL_POLICY") summary.should.have.key("Type").should.equal("SERVICE_CONTROL_POLICY")
summary.should.have.key("AwsManaged").should.be.a(bool) summary.should.have.key("AwsManaged").should.be.a(bool)
def validate_service_control_policy(org, response): def validate_service_control_policy(org, response):
response.should.have.key("PolicySummary").should.be.a(dict) response.should.have.key("PolicySummary").should.be.a(dict)
response.should.have.key("Content").should.be.a(six.string_types) response.should.have.key("Content").should.be.a(str)
validate_policy_summary(org, response["PolicySummary"]) validate_policy_summary(org, response["PolicySummary"])

View File

@ -14,7 +14,6 @@ from moto.organizations.models import (
import boto3 import boto3
import json import json
import six
import sure # noqa import sure # noqa
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
import pytest import pytest
@ -947,9 +946,9 @@ def test_list_targets_for_policy():
response = client.list_targets_for_policy(PolicyId=policy_id) response = client.list_targets_for_policy(PolicyId=policy_id)
for target in response["Targets"]: for target in response["Targets"]:
target.should.be.a(dict) target.should.be.a(dict)
target.should.have.key("Name").should.be.a(six.string_types) target.should.have.key("Name").should.be.a(str)
target.should.have.key("Arn").should.be.a(six.string_types) target.should.have.key("Arn").should.be.a(str)
target.should.have.key("TargetId").should.be.a(six.string_types) target.should.have.key("TargetId").should.be.a(str)
target.should.have.key("Type").should.be.within( target.should.have.key("Type").should.be.within(
["ROOT", "ORGANIZATIONAL_UNIT", "ACCOUNT"] ["ROOT", "ORGANIZATIONAL_UNIT", "ACCOUNT"]
) )

View File

@ -7,7 +7,6 @@ from boto.exception import BotoServerError
import sure # noqa import sure # noqa
from moto import mock_ec2_deprecated, mock_rds_deprecated, mock_rds from moto import mock_ec2_deprecated, mock_rds_deprecated, mock_rds
from tests.helpers import disable_on_py3
@mock_rds_deprecated @mock_rds_deprecated
@ -145,19 +144,6 @@ def test_delete_non_existent_security_group():
) )
@disable_on_py3()
@mock_rds_deprecated
def test_security_group_authorize():
conn = boto.rds.connect_to_region("us-west-2")
security_group = conn.create_dbsecurity_group("db_sg", "DB Security Group")
list(security_group.ip_ranges).should.equal([])
security_group.authorize(cidr_ip="10.3.2.45/32")
security_group = conn.get_all_dbsecurity_groups()[0]
list(security_group.ip_ranges).should.have.length_of(1)
security_group.ip_ranges[0].cidr_ip.should.equal("10.3.2.45/32")
@mock_rds_deprecated @mock_rds_deprecated
def test_add_security_group_to_database(): def test_add_security_group_to_database():
conn = boto.rds.connect_to_region("us-west-2") conn = boto.rds.connect_to_region("us-west-2")

View File

@ -5,9 +5,9 @@ import datetime
import sys import sys
import os import os
from boto3 import Session from boto3 import Session
from six.moves.urllib.request import urlopen from urllib.request import urlopen
from six.moves.urllib.error import HTTPError from urllib.error import HTTPError
from six.moves.urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
from functools import wraps from functools import wraps
from gzip import GzipFile from gzip import GzipFile
from io import BytesIO from io import BytesIO
@ -25,7 +25,6 @@ from botocore.handlers import disable_signing
from boto.s3.connection import S3Connection from boto.s3.connection import S3Connection
from boto.s3.key import Key from boto.s3.key import Key
from freezegun import freeze_time from freezegun import freeze_time
import six
import requests import requests
from moto.s3 import models from moto.s3 import models
@ -3823,7 +3822,7 @@ def test_boto3_list_object_versions():
s3.put_bucket_versioning( s3.put_bucket_versioning(
Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"} Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"}
) )
items = (six.b("v1"), six.b("v2")) items = (b"v1", b"v2")
for body in items: for body in items:
s3.put_object(Bucket=bucket_name, Key=key, Body=body) s3.put_object(Bucket=bucket_name, Key=key, Body=body)
response = s3.list_object_versions(Bucket=bucket_name) response = s3.list_object_versions(Bucket=bucket_name)
@ -3846,7 +3845,7 @@ def test_boto3_list_object_versions_with_versioning_disabled():
bucket_name = "mybucket" bucket_name = "mybucket"
key = "key-with-versions" key = "key-with-versions"
s3.create_bucket(Bucket=bucket_name) s3.create_bucket(Bucket=bucket_name)
items = (six.b("v1"), six.b("v2")) items = (b"v1", b"v2")
for body in items: for body in items:
s3.put_object(Bucket=bucket_name, Key=key, Body=body) s3.put_object(Bucket=bucket_name, Key=key, Body=body)
response = s3.list_object_versions(Bucket=bucket_name) response = s3.list_object_versions(Bucket=bucket_name)
@ -3869,12 +3868,12 @@ def test_boto3_list_object_versions_with_versioning_enabled_late():
bucket_name = "mybucket" bucket_name = "mybucket"
key = "key-with-versions" key = "key-with-versions"
s3.create_bucket(Bucket=bucket_name) s3.create_bucket(Bucket=bucket_name)
items = (six.b("v1"), six.b("v2")) items = (b"v1", b"v2")
s3.put_object(Bucket=bucket_name, Key=key, Body=six.b("v1")) s3.put_object(Bucket=bucket_name, Key=key, Body=b"v1")
s3.put_bucket_versioning( s3.put_bucket_versioning(
Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"} Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"}
) )
s3.put_object(Bucket=bucket_name, Key=key, Body=six.b("v2")) s3.put_object(Bucket=bucket_name, Key=key, Body=b"v2")
response = s3.list_object_versions(Bucket=bucket_name) response = s3.list_object_versions(Bucket=bucket_name)
# Two object versions should be returned # Two object versions should be returned
@ -3901,7 +3900,7 @@ def test_boto3_bad_prefix_list_object_versions():
s3.put_bucket_versioning( s3.put_bucket_versioning(
Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"} Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"}
) )
items = (six.b("v1"), six.b("v2")) items = (b"v1", b"v2")
for body in items: for body in items:
s3.put_object(Bucket=bucket_name, Key=key, Body=body) s3.put_object(Bucket=bucket_name, Key=key, Body=body)
response = s3.list_object_versions(Bucket=bucket_name, Prefix=bad_prefix) response = s3.list_object_versions(Bucket=bucket_name, Prefix=bad_prefix)
@ -3919,7 +3918,7 @@ def test_boto3_delete_markers():
s3.put_bucket_versioning( s3.put_bucket_versioning(
Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"} Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"}
) )
items = (six.b("v1"), six.b("v2")) items = (b"v1", b"v2")
for body in items: for body in items:
s3.put_object(Bucket=bucket_name, Key=key, Body=body) s3.put_object(Bucket=bucket_name, Key=key, Body=body)
@ -3962,7 +3961,7 @@ def test_boto3_multiple_delete_markers():
s3.put_bucket_versioning( s3.put_bucket_versioning(
Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"} Bucket=bucket_name, VersioningConfiguration={"Status": "Enabled"}
) )
items = (six.b("v1"), six.b("v2")) items = (b"v1", b"v2")
for body in items: for body in items:
s3.put_object(Bucket=bucket_name, Key=key, Body=body) s3.put_object(Bucket=bucket_name, Key=key, Body=body)

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import io import io
from six.moves.urllib.parse import urlparse, parse_qs from urllib.parse import urlparse, parse_qs
import sure # noqa import sure # noqa
from flask.testing import FlaskClient from flask.testing import FlaskClient

View File

@ -1,6 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from six.moves.urllib.request import urlopen from urllib.request import urlopen
from six.moves.urllib.error import HTTPError from urllib.error import HTTPError
import boto import boto
from boto.exception import S3ResponseError from boto.exception import S3ResponseError

View File

@ -1,13 +1,10 @@
import json import json
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
import six
from moto.sts.models import ACCOUNT_ID from moto.sts.models import ACCOUNT_ID
@six.add_metaclass(ABCMeta) class TestConfig(metaclass=ABCMeta):
class TestConfig:
"""Provides the interface to use for creating test configurations. """Provides the interface to use for creating test configurations.
This class will provide the interface for what information will be This class will provide the interface for what information will be

View File

@ -11,7 +11,6 @@ import pytz
from datetime import datetime from datetime import datetime
import sure # noqa import sure # noqa
import pytest import pytest
from six import b
DEFAULT_SECRET_NAME = "test-secret" DEFAULT_SECRET_NAME = "test-secret"
@ -48,10 +47,10 @@ def test_get_secret_value_binary():
conn = boto3.client("secretsmanager", region_name="us-west-2") conn = boto3.client("secretsmanager", region_name="us-west-2")
create_secret = conn.create_secret( create_secret = conn.create_secret(
Name="java-util-test-password", SecretBinary=b("foosecret") Name="java-util-test-password", SecretBinary=b"foosecret"
) )
result = conn.get_secret_value(SecretId="java-util-test-password") result = conn.get_secret_value(SecretId="java-util-test-password")
assert result["SecretBinary"] == b("foosecret") assert result["SecretBinary"] == b"foosecret"
@mock_secretsmanager @mock_secretsmanager
@ -776,7 +775,7 @@ def test_put_secret_value_on_non_existing_secret():
@mock_secretsmanager @mock_secretsmanager
def test_put_secret_value_puts_new_secret(): def test_put_secret_value_puts_new_secret():
conn = boto3.client("secretsmanager", region_name="us-west-2") conn = boto3.client("secretsmanager", region_name="us-west-2")
conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretBinary=b("foosecret")) conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretBinary=b"foosecret")
put_secret_value_dict = conn.put_secret_value( put_secret_value_dict = conn.put_secret_value(
SecretId=DEFAULT_SECRET_NAME, SecretId=DEFAULT_SECRET_NAME,
SecretString="foosecret", SecretString="foosecret",
@ -795,10 +794,10 @@ def test_put_secret_value_puts_new_secret():
@mock_secretsmanager @mock_secretsmanager
def test_put_secret_binary_value_puts_new_secret(): def test_put_secret_binary_value_puts_new_secret():
conn = boto3.client("secretsmanager", region_name="us-west-2") conn = boto3.client("secretsmanager", region_name="us-west-2")
conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretBinary=b("foosecret")) conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretBinary=b"foosecret")
put_secret_value_dict = conn.put_secret_value( put_secret_value_dict = conn.put_secret_value(
SecretId=DEFAULT_SECRET_NAME, SecretId=DEFAULT_SECRET_NAME,
SecretBinary=b("foosecret"), SecretBinary=b"foosecret",
VersionStages=["AWSCURRENT"], VersionStages=["AWSCURRENT"],
) )
version_id = put_secret_value_dict["VersionId"] version_id = put_secret_value_dict["VersionId"]
@ -808,21 +807,21 @@ def test_put_secret_binary_value_puts_new_secret():
) )
assert get_secret_value_dict assert get_secret_value_dict
assert get_secret_value_dict["SecretBinary"] == b("foosecret") assert get_secret_value_dict["SecretBinary"] == b"foosecret"
@mock_secretsmanager @mock_secretsmanager
def test_create_and_put_secret_binary_value_puts_new_secret(): def test_create_and_put_secret_binary_value_puts_new_secret():
conn = boto3.client("secretsmanager", region_name="us-west-2") conn = boto3.client("secretsmanager", region_name="us-west-2")
conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretBinary=b("foosecret")) conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretBinary=b"foosecret")
conn.put_secret_value( conn.put_secret_value(
SecretId=DEFAULT_SECRET_NAME, SecretBinary=b("foosecret_update") SecretId=DEFAULT_SECRET_NAME, SecretBinary=b"foosecret_update"
) )
latest_secret = conn.get_secret_value(SecretId=DEFAULT_SECRET_NAME) latest_secret = conn.get_secret_value(SecretId=DEFAULT_SECRET_NAME)
assert latest_secret assert latest_secret
assert latest_secret["SecretBinary"] == b("foosecret_update") assert latest_secret["SecretBinary"] == b"foosecret_update"
@mock_secretsmanager @mock_secretsmanager
@ -840,7 +839,7 @@ def test_put_secret_binary_requires_either_string_or_binary():
@mock_secretsmanager @mock_secretsmanager
def test_put_secret_value_can_get_first_version_if_put_twice(): def test_put_secret_value_can_get_first_version_if_put_twice():
conn = boto3.client("secretsmanager", region_name="us-west-2") conn = boto3.client("secretsmanager", region_name="us-west-2")
conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretBinary=b("foosecret")) conn.create_secret(Name=DEFAULT_SECRET_NAME, SecretBinary=b"foosecret")
put_secret_value_dict = conn.put_secret_value( put_secret_value_dict = conn.put_secret_value(
SecretId=DEFAULT_SECRET_NAME, SecretId=DEFAULT_SECRET_NAME,
SecretString="first_secret", SecretString="first_secret",

View File

@ -3,8 +3,8 @@ import json
import boto3 import boto3
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from six.moves.email_mime_multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from six.moves.email_mime_text import MIMEText from email.mime.text import MIMEText
import pytest import pytest

View File

@ -3,8 +3,6 @@ from __future__ import unicode_literals
import boto3 import boto3
import json import json
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from six.moves.email_mime_multipart import MIMEMultipart
from six.moves.email_mime_text import MIMEText
import sure # noqa import sure # noqa
from moto import mock_ses, mock_sns, mock_sqs from moto import mock_ses, mock_sns, mock_sqs

View File

@ -1,7 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import boto import boto
import json import json
import six
import sure # noqa import sure # noqa
@ -124,14 +123,6 @@ def test_topic_attributes():
DEFAULT_EFFECTIVE_DELIVERY_POLICY DEFAULT_EFFECTIVE_DELIVERY_POLICY
) )
# boto can't handle prefix-mandatory strings:
# i.e. unicode on Python 2 -- u"foobar"
# and bytes on Python 3 -- b"foobar"
if six.PY2:
policy = json.dumps({b"foo": b"bar"})
displayname = b"My display name"
delivery = {b"http": {b"defaultHealthyRetryPolicy": {b"numRetries": 5}}}
else:
policy = json.dumps({"foo": "bar"}) policy = json.dumps({"foo": "bar"})
displayname = "My display name" displayname = "My display name"
delivery = {"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}} delivery = {"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}}

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import boto3 import boto3
import six
import json import json
# import sure # noqa # import sure # noqa
@ -202,18 +201,9 @@ def test_topic_attributes():
# boto can't handle prefix-mandatory strings: # boto can't handle prefix-mandatory strings:
# i.e. unicode on Python 2 -- u"foobar" # i.e. unicode on Python 2 -- u"foobar"
# and bytes on Python 3 -- b"foobar" # and bytes on Python 3 -- b"foobar"
if six.PY2:
policy = json.dumps({b"foo": b"bar"})
displayname = b"My display name"
delivery = json.dumps(
{b"http": {b"defaultHealthyRetryPolicy": {b"numRetries": 5}}}
)
else:
policy = json.dumps({"foo": "bar"}) policy = json.dumps({"foo": "bar"})
displayname = "My display name" displayname = "My display name"
delivery = json.dumps( delivery = json.dumps({"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}})
{"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}}
)
conn.set_topic_attributes( conn.set_topic_attributes(
TopicArn=topic_arn, AttributeName="Policy", AttributeValue=policy TopicArn=topic_arn, AttributeName="Policy", AttributeValue=policy
) )

View File

@ -10,7 +10,6 @@ import hashlib
import boto import boto
import boto3 import boto3
import botocore.exceptions import botocore.exceptions
import six
import sys import sys
import sure # noqa import sure # noqa
from boto.exception import SQSError from boto.exception import SQSError
@ -587,9 +586,9 @@ def test_get_queue_attributes():
response["Attributes"]["ApproximateNumberOfMessages"].should.equal("0") response["Attributes"]["ApproximateNumberOfMessages"].should.equal("0")
response["Attributes"]["ApproximateNumberOfMessagesDelayed"].should.equal("0") response["Attributes"]["ApproximateNumberOfMessagesDelayed"].should.equal("0")
response["Attributes"]["ApproximateNumberOfMessagesNotVisible"].should.equal("0") response["Attributes"]["ApproximateNumberOfMessagesNotVisible"].should.equal("0")
response["Attributes"]["CreatedTimestamp"].should.be.a(six.string_types) response["Attributes"]["CreatedTimestamp"].should.be.a(str)
response["Attributes"]["DelaySeconds"].should.equal("0") response["Attributes"]["DelaySeconds"].should.equal("0")
response["Attributes"]["LastModifiedTimestamp"].should.be.a(six.string_types) response["Attributes"]["LastModifiedTimestamp"].should.be.a(str)
response["Attributes"]["MaximumMessageSize"].should.equal("262144") response["Attributes"]["MaximumMessageSize"].should.equal("262144")
response["Attributes"]["MessageRetentionPeriod"].should.equal("345600") response["Attributes"]["MessageRetentionPeriod"].should.equal("345600")
response["Attributes"]["QueueArn"].should.equal( response["Attributes"]["QueueArn"].should.equal(