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

View File

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

View File

@ -1,5 +1,4 @@
from __future__ import unicode_literals
import six
import random
import string
@ -7,4 +6,4 @@ import string
def create_id():
size = 10
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):

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals
import uuid
import six
import random
import yaml
import os
@ -37,7 +36,7 @@ def generate_stackset_arn(stackset_id, region_name):
def random_suffix():
size = 12
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):

View File

@ -1,5 +1,4 @@
from __future__ import unicode_literals
import six
import random
import string
import hashlib
@ -10,7 +9,7 @@ import base64
def create_id():
size = 26
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):

View File

@ -7,7 +7,6 @@ import inspect
import os
import pkg_resources
import re
import six
import types
from abc import abstractmethod
from io import BytesIO
@ -16,7 +15,8 @@ from botocore.config import Config
from botocore.handlers import BUILTIN_HANDLERS
from botocore.awsrequest import AWSResponse
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 moto import settings
@ -33,7 +33,7 @@ ACCOUNT_ID = os.environ.get("MOTO_ACCOUNT_ID", "123456789012")
RESPONSES_VERSION = pkg_resources.get_distribution("responses").version
class BaseMockAWS(object):
class BaseMockAWS:
nested_count = 0
mocks_active = False
@ -213,12 +213,12 @@ class CallbackResponse(responses.CallbackResponse):
url = urlparse(request.url)
if request.body is None:
body = None
elif isinstance(request.body, six.text_type):
body = six.BytesIO(six.b(request.body))
elif isinstance(request.body, str):
body = BytesIO(request.body.encode("UTF-8"))
elif hasattr(request.body, "read"):
body = six.BytesIO(request.body.read())
body = BytesIO(request.body.read())
else:
body = six.BytesIO(request.body)
body = BytesIO(request.body)
req = Request.from_values(
path="?".join([url.path, url.query]),
input_stream=body,
@ -228,7 +228,7 @@ class CallbackResponse(responses.CallbackResponse):
base_url="{scheme}://{netloc}".format(
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
headers = self.get_headers()
@ -243,7 +243,7 @@ class CallbackResponse(responses.CallbackResponse):
return responses.HTTPResponse(
status=status,
reason=six.moves.http_client.responses.get(status),
reason=http_responses.get(status),
body=body,
headers=headers,
preload_content=False,
@ -261,7 +261,7 @@ class CallbackResponse(responses.CallbackResponse):
if responses._is_string(url):
if responses._has_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")
return self._url_matches_strict(url, 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):
def __init__(self, input):
if isinstance(input, six.text_type):
if isinstance(input, str):
input = input.encode("utf-8")
super(MockRawResponse, self).__init__(input)
@ -330,7 +330,7 @@ class MockRawResponse(BytesIO):
contents = self.read()
class BotocoreStubber(object):
class BotocoreStubber:
def __init__(self):
self.enabled = False
self.methods = defaultdict(list)
@ -363,7 +363,7 @@ class BotocoreStubber(object):
if response_callback is not None:
for header, value in request.headers.items():
if isinstance(value, six.binary_type):
if isinstance(value, bytes):
request.headers[header] = value.decode("utf-8")
status, headers, body = response_callback(
request, request.url, request.headers
@ -479,43 +479,10 @@ class ServerModeMockAWS(BaseMockAWS):
kwargs["endpoint_url"] = "http://localhost:5000"
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._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._resource_patcher.start()
if six.PY2:
self._httplib_patcher.start()
def _get_region(self, *args, **kwargs):
if "region_name" in kwargs:
@ -529,8 +496,6 @@ class ServerModeMockAWS(BaseMockAWS):
if self._client_patcher:
self._client_patcher.stop()
self._resource_patcher.stop()
if six.PY2:
self._httplib_patcher.stop()
class Model(type):
@ -572,8 +537,7 @@ class InstanceTrackerMeta(type):
return cls
@six.add_metaclass(InstanceTrackerMeta)
class BaseModel(object):
class BaseModel(metaclass=InstanceTrackerMeta):
def __new__(cls, *args, **kwargs):
instance = super(BaseModel, cls).__new__(cls)
cls.instances.append(instance)
@ -630,7 +594,7 @@ class CloudFormationModel(BaseModel):
pass
class BaseBackend(object):
class BaseBackend:
def _reset_model_refs(self):
# Remove all references to the models stored
for service, models in model_data.items():
@ -724,7 +688,7 @@ class BaseBackend(object):
# raise NotImplementedError()
class ConfigQueryModel(object):
class ConfigQueryModel:
def __init__(self, backends):
"""Inits based on the resource type's backends (1 for each region if applicable)"""
self.backends = backends
@ -817,7 +781,7 @@ class ConfigQueryModel(object):
raise NotImplementedError()
class base_decorator(object):
class base_decorator:
mock_backend = MockAWS
def __init__(self, backends):

View File

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

View File

@ -6,10 +6,9 @@ import datetime
import inspect
import random
import re
import six
import string
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
@ -68,20 +67,13 @@ def camelcase_to_pascal(argument):
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)]
def get_random_hex(length=8):
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():
@ -184,7 +176,7 @@ class convert_flask_to_responses_response(object):
def __call__(self, request, *args, **kwargs):
for key, val in request.headers.items():
if isinstance(val, six.binary_type):
if isinstance(val, bytes):
request.headers[key] = val.decode("utf-8")
result = self.callback(request, request.url, request.headers)
@ -233,10 +225,6 @@ def gen_amz_crc32(response, headerdict=None):
response = response.encode("utf-8")
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):
headerdict.update({"x-amz-crc32": str(crc)})
@ -261,7 +249,7 @@ def amz_crc32(f):
headers = {}
status = 200
if isinstance(response, six.string_types):
if isinstance(response, str):
body = response
else:
if len(response) == 2:
@ -293,7 +281,7 @@ def amzn_request_id(f):
headers = {}
status = 200
if isinstance(response, six.string_types):
if isinstance(response, str):
body = response
else:
if len(response) == 2:
@ -405,7 +393,7 @@ def remap_nested_keys(root, key_transform):
if isinstance(root, dict):
return {
key_transform(k): remap_nested_keys(v, key_transform)
for k, v in six.iteritems(root)
for k, v in root.items()
}
return root

View File

@ -1,4 +1,3 @@
import six
from moto.compat import collections_abc
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:]
result[normalized_key] = remove_capitalization_of_dict_keys(value)
return result
elif isinstance(obj, collections_abc.Iterable) and not isinstance(
obj, six.string_types
):
elif isinstance(obj, collections_abc.Iterable) and not isinstance(obj, str):
result = obj.__class__()
for item in obj:
result += (remove_capitalization_of_dict_keys(item),)

View File

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

View File

@ -1,5 +1,3 @@
import six
from moto.dynamodb2.comparisons import get_comparison_func
from moto.dynamodb2.exceptions import InvalidUpdateExpression, IncorrectDataType
from moto.dynamodb2.models.utilities import attribute_is_list, bytesize
@ -200,7 +198,7 @@ class DynamoType(object):
raise TypeError("Sum only supported for Numbers.")
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 self.type == DDBType.MAP:
return self.value[item]
@ -222,7 +220,7 @@ class DynamoType(object):
self.value.append(value)
else:
self.value[key] = value
elif isinstance(key, six.string_types):
elif isinstance(key, str):
if self.is_map():
self.value[key] = value
else:
@ -251,7 +249,7 @@ class DynamoType(object):
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:
return self.value[key.split(".")[0]].child_attr(
".".join(key.split(".")[1:])

View File

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

View File

@ -1,7 +1,6 @@
import logging
from abc import abstractmethod
import abc
import six
from collections import deque
from moto.dynamodb2.parsing.ast_nodes import (
@ -127,8 +126,7 @@ class NestableExpressionParserMixin(object):
return target_node
@six.add_metaclass(abc.ABCMeta)
class ExpressionParser:
class ExpressionParser(metaclass=abc.ABCMeta):
"""Abstract class"""
def __init__(self, expression_token_list, token_pos=0):
@ -968,8 +966,7 @@ class UpdateExpressionAddActionsParser(UpdateExpressionActionsParser):
return UpdateExpressionAddActions
@six.add_metaclass(abc.ABCMeta)
class UpdateExpressionPathValueParser(ExpressionParser):
class UpdateExpressionPathValueParser(ExpressionParser, metaclass=abc.ABCMeta):
def _parse_path_and_value(self):
"""
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 itertools
import six
from moto.core.responses import BaseResponse
from moto.core.utils import camelcase_to_underscores, amz_crc32, amzn_request_id
@ -87,7 +86,7 @@ class DynamoHandler(BaseResponse):
if endpoint:
endpoint = camelcase_to_underscores(endpoint)
response = getattr(self, endpoint)()
if isinstance(response, six.string_types):
if isinstance(response, str):
return 200, self.response_headers, response
else:
@ -482,8 +481,7 @@ class DynamoHandler(BaseResponse):
index = table.schema
reverse_attribute_lookup = dict(
(v, k)
for k, v in six.iteritems(self.body.get("ExpressionAttributeNames", {}))
(v, k) for k, v in self.body.get("ExpressionAttributeNames", {}).items()
)
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 .models import dynamodbstreams_backends
from six import string_types
class DynamoDBStreamsHandler(BaseResponse):
@ -25,7 +24,7 @@ class DynamoDBStreamsHandler(BaseResponse):
shard_iterator_type = self._get_param("ShardIteratorType")
sequence_number = self._get_param("SequenceNumber")
# 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)
return self.backend.get_shard_iterator(

View File

@ -6,7 +6,6 @@ import ipaddress
import json
import os
import re
import six
import warnings
from boto3 import Session
@ -569,12 +568,9 @@ class Instance(TaggedEC2Resource, BotoInstance, CloudFormationModel):
# handle weird bug around user_data -- something grabs the repr(), so
# it must be clean
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
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:
subnet = ec2_backend.get_subnet(self.subnet_id)
@ -2281,9 +2277,7 @@ class SecurityGroupBackend(object):
if group is None:
raise InvalidSecurityGroupNotFoundError(group_name_or_id)
if ip_ranges:
if isinstance(ip_ranges, str) or (
six.PY2 and isinstance(ip_ranges, unicode) # noqa
):
if isinstance(ip_ranges, str):
ip_ranges = [{"CidrIp": str(ip_ranges)}]
elif not isinstance(ip_ranges, list):
ip_ranges = [json.loads(ip_ranges)]
@ -3096,9 +3090,7 @@ class VPCBackend(object):
):
vpc_id = random_vpc_id()
try:
vpc_cidr_block = ipaddress.IPv4Network(
six.text_type(cidr_block), strict=False
)
vpc_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)
except ValueError:
raise InvalidCIDRBlockParameterError(cidr_block)
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.vpc_id = vpc_id
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 = (
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.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)
self._subnet_ip_generator = self.cidr.hosts()
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
self._unused_ips = set() # if instance is destroyed hold IP here for reuse
self._subnet_ips = {} # has IP: instance
@ -3580,11 +3572,11 @@ class Subnet(TaggedEC2Resource, CloudFormationModel):
try:
new_ip = self._unused_ips.pop()
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
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:
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
vpc_cidr_blocks = [
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()
]
try:
subnet_cidr_block = ipaddress.IPv4Network(
six.text_type(cidr_block), strict=False
)
subnet_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)
except ValueError:
raise InvalidCIDRBlockParameterError(cidr_block)
@ -4382,9 +4372,7 @@ class RouteBackend(object):
try:
if destination_cidr_block:
ipaddress.IPv4Network(
six.text_type(destination_cidr_block), strict=False
)
ipaddress.IPv4Network(str(destination_cidr_block), strict=False)
except ValueError:
raise InvalidDestinationCIDRBlockParameterError(destination_cidr_block)
@ -4677,8 +4665,7 @@ class SpotInstanceRequest(BotoSpotRequest, TaggedEC2Resource):
return instance
@six.add_metaclass(Model)
class SpotRequestBackend(object):
class SpotRequestBackend(object, metaclass=Model):
def __init__(self):
self.spot_instance_requests = {}
super(SpotRequestBackend, self).__init__()

View File

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

View File

@ -1,5 +1,4 @@
from __future__ import unicode_literals
import six
from moto.core.responses import BaseResponse
from moto.ec2.utils import filters_from_querystring
@ -15,7 +14,7 @@ class KeyPairs(BaseResponse):
def delete_key_pair(self):
name = self._get_param("KeyName")
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(
success=success
)

View File

@ -1,4 +1,3 @@
import six
import uuid
from moto.core.responses import BaseResponse
from moto.ec2.models import OWNER_ID
@ -29,10 +28,10 @@ def xml_serialize(tree, key, value):
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)
elif isinstance(value, dict):
for dictkey, dictvalue in six.iteritems(value):
for dictkey, dictvalue in value.items():
xml_serialize(node, dictkey, dictvalue)
elif isinstance(value, list):
for item in value:
@ -53,7 +52,7 @@ def pretty_xml(tree):
def parse_object(raw_data):
out_data = {}
for key, value in six.iteritems(raw_data):
for key, value in raw_data.items():
key_fix_splits = key.split("_")
key_len = len(key_fix_splits)
@ -75,7 +74,7 @@ def parse_object(raw_data):
def parse_lists(data):
for key, value in six.iteritems(data):
for key, value in data.items():
if isinstance(value, dict):
keys = data[key].keys()
is_list = all(map(lambda k: k.isnumeric(), keys))
@ -106,13 +105,13 @@ class LaunchTemplates(BaseResponse):
if "TagSpecifications" not in parsed_template_data:
parsed_template_data["TagSpecifications"] = []
converted_tag_spec = []
for resource_type, tags in six.iteritems(tag_spec):
for resource_type, tags in tag_spec.items():
converted_tag_spec.append(
{
"ResourceType": resource_type,
"Tags": [
{"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 random
import re
import six
from cryptography.hazmat.primitives import serialization
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):
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
@ -462,7 +461,7 @@ def is_filter_matching(obj, filter, filter_value):
if filter_value is None:
return False
if isinstance(value, six.string_types):
if isinstance(value, str):
if not isinstance(filter_value, list):
filter_value = [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
try:
if not isinstance(key_material, six.binary_type):
if not isinstance(key_material, bytes):
key_material = key_material.encode("ascii")
decoded_key = base64.b64decode(key_material).decode("ascii")

View File

@ -1,5 +1,5 @@
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 moto.elb.responses import ELBResponse

View File

@ -6,7 +6,7 @@ from functools import wraps
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 BaseResponse
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,
)
import six
def random_id(size=13):
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):

View File

@ -10,7 +10,6 @@ from enum import Enum, unique
from operator import lt, le, eq, ge, gt
from boto3 import Session
from six import string_types
from moto.core.exceptions import JsonRESTError
from moto.core import ACCOUNT_ID, BaseBackend, CloudFormationModel, BaseModel
@ -640,7 +639,7 @@ class EventPattern:
return all(nested_filter_matches + filter_list_matches)
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
named_filter_matches = [
self._does_item_match_named_filter(item, filter)

View File

@ -2,7 +2,6 @@ import re
from datetime import datetime
from boto3 import Session
from six import iteritems
from moto.core import ACCOUNT_ID, BaseBackend
from moto.core.utils import iso_8601_datetime_without_milliseconds
@ -160,7 +159,7 @@ class ForecastBackend(BaseBackend):
dsg.update(dataset_arns)
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):
region_name = self.region_name

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals
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 .models import glacier_backends

View File

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

View File

@ -18,11 +18,9 @@ import re
from abc import abstractmethod, ABCMeta
from enum import Enum
import six
from botocore.auth import SigV4Auth, S3SigV4Auth
from botocore.awsrequest import AWSRequest
from botocore.credentials import Credentials
from six import string_types
from moto.core import ACCOUNT_ID
from moto.core.exceptions import (
@ -160,8 +158,7 @@ class CreateAccessKeyFailure(Exception):
self.reason = reason
@six.add_metaclass(ABCMeta)
class IAMRequestBase(object):
class IAMRequestBase(object, metaclass=ABCMeta):
def __init__(self, method, path, data, headers):
log.debug(
"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
)
policy_document = default_version.document
elif isinstance(policy, string_types):
elif isinstance(policy, str):
policy_document = policy
else:
policy_document = policy["policy_document"]

View File

@ -13,7 +13,7 @@ import time
from cryptography import x509
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 import BaseBackend, BaseModel, ACCOUNT_ID, CloudFormationModel
from moto.core.utils import (

View File

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

View File

@ -1,12 +1,11 @@
from __future__ import unicode_literals
import random
import string
import six
def random_alphanumeric(length):
return "".join(
six.text_type(random.choice(string.ascii_letters + string.digits + "+" + "/"))
str(random.choice(string.ascii_letters + string.digits + "+" + "/"))
for _ in range(length)
)
@ -14,13 +13,12 @@ def random_alphanumeric(length):
def random_resource_id(size=20):
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():
return "".join(
six.text_type(random.choice(string.ascii_uppercase + string.digits))
for _ in range(16)
str(random.choice(string.ascii_uppercase + string.digits)) for _ in range(16)
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
from __future__ import unicode_literals
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 .exceptions import exception_handler

View File

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

View File

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

View File

@ -5,7 +5,6 @@ import json
import xmltodict
from jinja2 import Template
from six import iteritems
from moto.core.responses import BaseResponse
from .models import redshift_backends
@ -250,7 +249,7 @@ class RedshiftResponse(BaseResponse):
cluster_kwargs = {}
# We only want parameters that were actually passed in, otherwise
# 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 != []:
cluster_kwargs[key] = value

View File

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

View File

@ -1,6 +1,6 @@
from __future__ import unicode_literals
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 .models import route53_backend

View File

@ -18,7 +18,6 @@ import sys
import time
import uuid
import six
from bisect import insort
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
# 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)
self._value_buffer.write(new_value)
self.contentsize = len(new_value)
@ -284,7 +283,7 @@ class FakeKey(BaseModel):
return 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(
max_size=self._max_buffer_size
@ -628,24 +627,16 @@ class CorsRule(BaseModel):
max_age_seconds=None,
):
self.allowed_methods = (
[allowed_methods]
if isinstance(allowed_methods, six.string_types)
else allowed_methods
[allowed_methods] if isinstance(allowed_methods, str) else allowed_methods
)
self.allowed_origins = (
[allowed_origins]
if isinstance(allowed_origins, six.string_types)
else allowed_origins
[allowed_origins] if isinstance(allowed_origins, str) else allowed_origins
)
self.allowed_headers = (
[allowed_headers]
if isinstance(allowed_headers, six.string_types)
else allowed_headers
[allowed_headers] if isinstance(allowed_headers, str) else allowed_headers
)
self.exposed_headers = (
[expose_headers]
if isinstance(expose_headers, six.string_types)
else expose_headers
[expose_headers] if isinstance(expose_headers, str) else expose_headers
)
self.max_age_seconds = max_age_seconds
@ -960,20 +951,20 @@ class FakeBucket(CloudFormationModel):
for rule in rules:
assert isinstance(rule["AllowedMethod"], list) or isinstance(
rule["AllowedMethod"], six.string_types
rule["AllowedMethod"], str
)
assert isinstance(rule["AllowedOrigin"], list) or isinstance(
rule["AllowedOrigin"], six.string_types
rule["AllowedOrigin"], str
)
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(
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"]]
else:
methods = rule["AllowedMethod"]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,6 @@
from __future__ import unicode_literals
import base64
import six
from moto.core.responses import BaseResponse
from .models import ses_backend
from datetime import datetime
@ -59,7 +57,7 @@ class EmailResponse(BaseResponse):
destinations = {"ToAddresses": [], "CcAddresses": [], "BccAddresses": []}
for dest_type in destinations:
# 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)
address = self.querystring.get(field)
if address is None:
@ -80,7 +78,7 @@ class EmailResponse(BaseResponse):
destinations = {"ToAddresses": [], "CcAddresses": [], "BccAddresses": []}
for dest_type in destinations:
# 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)
address = self.querystring.get(field)
if address is None:
@ -100,11 +98,10 @@ class EmailResponse(BaseResponse):
raw_data = self.querystring.get("RawMessage.Data")[0]
raw_data = base64.b64decode(raw_data)
if six.PY3:
raw_data = raw_data.decode("utf-8")
raw_data = raw_data.decode("utf-8")
destinations = []
# 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
address = self.querystring.get(field)
if address is None:

View File

@ -5,7 +5,6 @@ import uuid
import json
import requests
import six
import re
from boto3 import Session
@ -59,7 +58,7 @@ class Topic(CloudFormationModel):
self._tags = {}
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)
for subscription in subscriptions:
subscription.publish(
@ -228,7 +227,7 @@ class Subscription(BaseModel):
def _field_match(field, rules, message_attributes):
for rule in rules:
# 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:
return False
if message_attributes[field]["Value"] == rule:
@ -239,7 +238,7 @@ class Subscription(BaseModel):
return True
except (ValueError, TypeError):
pass
if isinstance(rule, (six.integer_types, float)):
if isinstance(rule, (int, float)):
if field not in message_attributes:
return False
if message_attributes[field]["Type"] == "Number":
@ -273,7 +272,7 @@ class Subscription(BaseModel):
return all(
_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):
@ -356,7 +355,7 @@ class PlatformEndpoint(BaseModel):
raise SnsEndpointDisabled("Endpoint %s disabled" % self.id)
# 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
return message_id
@ -540,7 +539,7 @@ class SNSBackend(BaseBackend):
if len(message) > MAXIMUM_SMS_MESSAGE_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)
return message_id
@ -656,7 +655,7 @@ class SNSBackend(BaseBackend):
def _validate_filter_policy(self, value):
# TODO: extend validation checks
combinations = 1
for rules in six.itervalues(value):
for rules in value.values():
combinations *= len(rules)
# 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
@ -665,15 +664,15 @@ class SNSBackend(BaseBackend):
"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:
if rule is None:
continue
if isinstance(rule, six.string_types):
if isinstance(rule, str):
continue
if isinstance(rule, bool):
continue
if isinstance(rule, (six.integer_types, float)):
if isinstance(rule, (int, float)):
if rule <= -1000000000 or rule >= 1000000000:
raise InternalError("Unknown")
continue

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,4 @@
pytest
pytest-cov; python_version >= '3.6'
# 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'
pytest-cov
sure==1.4.11
freezegun

View File

@ -1,12 +1,9 @@
#!/usr/bin/env python
from __future__ import unicode_literals
import codecs
from io import open
import os
import re
import setuptools
from setuptools import setup, find_packages
import sys
# Borrowed from pip at https://github.com/pypa/pip/blob/62c27dee45625e1b63d1e023b0656310f276e050/setup.py#L11-L15
here = os.path.abspath(os.path.dirname(__file__))
@ -35,43 +32,18 @@ install_requires = [
"cryptography>=3.3.1",
"requests>=2.5",
"xmltodict",
"six>1.9",
"werkzeug",
"pytz",
"python-dateutil<3.0.0,>=2.1",
"responses>=0.9.0",
"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<3.0.0; python_version < '3'",
"mock<=3.0.5; python_version < '3'",
"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==44.0.0; python_version < '3'",
]
_dep_PyYAML = "PyYAML>=5.1"
_dep_python_jose_py2 = "python-jose[cryptography]>=3.1.0,<3.3.0; python_version<'3'"
_dep_python_jose_py3 = "python-jose[cryptography]>=3.1.0,<4.0.0; python_version>'3'"
_dep_python_jose = "python-jose[cryptography]>=3.1.0,<4.0.0"
_dep_python_jose_ecdsa_pin = (
"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_idna = "idna<3,>=2.5"
_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_py2 = "sshpubkeys==3.1.0; python_version<'3'"
_dep_sshpubkeys_py3 = "sshpubkeys>=3.1.0; python_version>'3'"
_dep_sshpubkeys = "sshpubkeys>=3.1.0"
all_extra_deps = [
_dep_PyYAML,
_dep_python_jose_py2,
_dep_python_jose_py3,
_dep_python_jose,
_dep_python_jose_ecdsa_pin,
_dep_docker,
_dep_jsondiff,
_dep_aws_xray_sdk,
_dep_idna,
_dep_cfn_lint,
_dep_decorator,
_dep_sshpubkeys_py2,
_dep_sshpubkeys_py3,
_dep_sshpubkeys,
]
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.
# Would be good for future-compatibility, I guess.
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],
"batch": [_dep_docker],
"cloudformation": [_dep_docker, _dep_PyYAML, _dep_cfn_lint, _dep_decorator],
"cognitoidp": [_dep_python_jose_py2, _dep_python_jose_py3, _dep_python_jose_ecdsa_pin],
"cloudformation": [_dep_docker, _dep_PyYAML, _dep_cfn_lint],
"cognitoidp": [_dep_python_jose, _dep_python_jose_ecdsa_pin],
"dynamodb2": [_dep_docker],
"dynamodbstreams": [_dep_docker],
"ec2": [_dep_docker, _dep_sshpubkeys_py2, _dep_sshpubkeys_py3],
"ec2": [_dep_docker, _dep_sshpubkeys],
"iotdata": [_dep_jsondiff],
"s3": [_dep_PyYAML],
"ses": [_dep_docker],
"sns": [_dep_docker],
"sqs": [_dep_docker],
"ssm": [_dep_docker, _dep_PyYAML, _dep_decorator],
"ssm": [_dep_docker, _dep_PyYAML],
"xray": [_dep_aws_xray_sdk],
}
extras_require = {
@ -127,13 +94,6 @@ extras_require = {
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(
name="moto",
@ -157,8 +117,6 @@ setup(
license="Apache",
test_suite="tests",
classifiers=[
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"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
import boto
from unittest import SkipTest
import six
def version_tuple(v):
@ -26,10 +25,3 @@ class requires_boto_gte(object):
if boto_version >= required:
return 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
import json
from six.moves.urllib.parse import urlencode
from urllib.parse import urlencode
import re
import sure # noqa

View File

@ -2,32 +2,27 @@ import unittest
from moto import mock_dynamodb2_deprecated, mock_dynamodb2
import socket
from six import PY3
class TestSocketPair(unittest.TestCase):
@mock_dynamodb2_deprecated
def test_asyncio_deprecated(self):
if PY3:
self.assertIn(
"moto.packages.httpretty.core.fakesock.socket",
str(socket.socket),
"Our mock should be present",
)
import asyncio
self.assertIn(
"httpretty.core.fakesock.socket",
str(socket.socket),
"Our mock should be present",
)
import asyncio
self.assertIsNotNone(asyncio.get_event_loop())
self.assertIsNotNone(asyncio.get_event_loop())
@mock_dynamodb2_deprecated
def test_socket_pair_deprecated(self):
# In Python2, the fakesocket is not set, for some reason.
if PY3:
self.assertIn(
"moto.packages.httpretty.core.fakesock.socket",
str(socket.socket),
"Our mock should be present",
)
self.assertIn(
"httpretty.core.fakesock.socket",
str(socket.socket),
"Our mock should be present",
)
a, b = socket.socketpair()
self.assertIsNotNone(a)
self.assertIsNotNone(b)

View File

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

View File

@ -1,12 +1,10 @@
import six
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
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(
data=private_key_material.encode("ascii"),

View File

@ -5,7 +5,6 @@ import pytest
import boto
import boto3
from boto.exception import EC2ResponseError
import six
import sure # noqa
@ -30,7 +29,7 @@ def test_eip_allocate_classic():
standard = conn.allocate_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.domain.should.be.equal("standard")

View File

@ -8,7 +8,6 @@ from unittest import SkipTest
import base64
import ipaddress
import six
import boto
import boto3
from boto.ec2.instance import Reservation, InstanceAttribute
@ -21,10 +20,7 @@ from tests import EXAMPLE_AMI_ID
from tests.helpers import requires_boto_gte
if six.PY2:
decode_method = base64.decodestring
else:
decode_method = base64.decodebytes
decode_method = base64.decodebytes
################ Test Readme ###############
def add_servers(ami_id, count):
@ -1050,7 +1046,7 @@ def test_run_instance_with_subnet_boto3():
instance = resp["Instances"][0]
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)

View File

@ -8,7 +8,6 @@ from boto.emr.bootstrap_action import BootstrapAction
from boto.emr.instance_group import InstanceGroup
from boto.emr.step import StreamingStep
import six
import sure # noqa
from moto import mock_emr_deprecated
@ -86,7 +85,7 @@ def test_describe_cluster():
cluster.id.should.equal(cluster_id)
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"])
int(cluster.normalizedinstancehours).should.equal(0)
# cluster.release_label
@ -96,11 +95,11 @@ def test_describe_cluster():
cluster.servicerole.should.equal(args["service_role"])
cluster.status.state.should.equal("TERMINATED")
cluster.status.statechangereason.message.should.be.a(six.string_types)
cluster.status.statechangereason.code.should.be.a(six.string_types)
cluster.status.timeline.creationdatetime.should.be.a(six.string_types)
# cluster.status.timeline.enddatetime.should.be.a(six.string_types)
# cluster.status.timeline.readydatetime.should.be.a(six.string_types)
cluster.status.statechangereason.message.should.be.a(str)
cluster.status.statechangereason.code.should.be.a(str)
cluster.status.timeline.creationdatetime.should.be.a(str)
# cluster.status.timeline.enddatetime.should.be.a(str)
# cluster.status.timeline.readydatetime.should.be.a(str)
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.amiversion.should.equal(args["ami_version"])
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.readydatetime.should.be.a(six.string_types)
jf.startdatetime.should.be.a(six.string_types)
jf.readydatetime.should.be.a(str)
jf.startdatetime.should.be.a(str)
jf.state.should.equal("WAITING")
jf.ec2keyname.should.equal(args["ec2_keyname"])
@ -207,24 +206,24 @@ def test_describe_jobflow():
int(jf.instancecount).should.equal(2)
for ig in jf.instancegroups:
ig.creationdatetime.should.be.a(six.string_types)
# ig.enddatetime.should.be.a(six.string_types)
ig.should.have.property("instancegroupid").being.a(six.string_types)
ig.creationdatetime.should.be.a(str)
# ig.enddatetime.should.be.a(str)
ig.should.have.property("instancegroupid").being.a(str)
int(ig.instancerequestcount).should.equal(1)
ig.instancerole.should.be.within(["MASTER", "CORE"])
int(ig.instancerunningcount).should.equal(1)
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.name.should.be.a(six.string_types)
ig.readydatetime.should.be.a(six.string_types)
ig.startdatetime.should.be.a(six.string_types)
ig.name.should.be.a(str)
ig.readydatetime.should.be.a(str)
ig.startdatetime.should.be.a(str)
ig.state.should.equal("RUNNING")
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.masterpublicdnsname.should.be.a(six.string_types)
jf.masterpublicdnsname.should.be.a(str)
int(jf.normalizedinstancehours).should.equal(0)
jf.availabilityzone.should.equal(args["availability_zone"])
jf.slaveinstancetype.should.equal(args["slave_instance_type"])
@ -288,12 +287,12 @@ def test_list_clusters():
x.name.should.equal(y["name"])
x.normalizedinstancehours.should.equal(y["normalizedinstancehours"])
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":
x.status.timeline.enddatetime.should.be.a(six.string_types)
x.status.timeline.enddatetime.should.be.a(str)
else:
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"):
break
args = {"marker": resp.marker}
@ -489,18 +488,18 @@ def test_instance_groups():
y = input_groups[x.name]
if hasattr(y, "bidprice"):
x.bidprice.should.equal(y.bidprice)
x.creationdatetime.should.be.a(six.string_types)
# x.enddatetime.should.be.a(six.string_types)
x.creationdatetime.should.be.a(str)
# x.enddatetime.should.be.a(str)
x.should.have.property("instancegroupid")
int(x.instancerequestcount).should.equal(y.num_instances)
x.instancerole.should.equal(y.role)
int(x.instancerunningcount).should.equal(y.num_instances)
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.name.should.be.a(six.string_types)
x.readydatetime.should.be.a(six.string_types)
x.startdatetime.should.be.a(six.string_types)
x.name.should.be.a(str)
x.readydatetime.should.be.a(str)
x.startdatetime.should.be.a(str)
x.state.should.equal("RUNNING")
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)
# ShrinkPolicy
x.status.state.should.equal("RUNNING")
x.status.statechangereason.code.should.be.a(six.string_types)
x.status.statechangereason.message.should.be.a(six.string_types)
x.status.timeline.creationdatetime.should.be.a(six.string_types)
# x.status.timeline.enddatetime.should.be.a(six.string_types)
x.status.timeline.readydatetime.should.be.a(six.string_types)
x.status.statechangereason.code.should.be.a(str)
x.status.statechangereason.message.should.be.a(str)
x.status.timeline.creationdatetime.should.be.a(str)
# x.status.timeline.enddatetime.should.be.a(str)
x.status.timeline.readydatetime.should.be.a(str)
igs = dict((g.name, g) for g in jf.instancegroups)
@ -571,14 +570,14 @@ def test_steps():
for step in jf.steps:
step.actiononfailure.should.equal("TERMINATE_JOB_FLOW")
list(arg.value for arg in step.args).should.have.length_of(8)
step.creationdatetime.should.be.a(six.string_types)
# step.enddatetime.should.be.a(six.string_types)
step.creationdatetime.should.be.a(str)
# step.enddatetime.should.be.a(str)
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.name.should.be.a(six.string_types)
# step.readydatetime.should.be.a(six.string_types)
# step.startdatetime.should.be.a(six.string_types)
step.name.should.be.a(str)
# step.readydatetime.should.be.a(str)
# step.startdatetime.should.be.a(str)
step.state.should.be.within(["STARTING", "PENDING"])
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.mainclass.should.equal("")
# 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.status.state.should.be.within(["STARTING", "PENDING"])
# x.status.statechangereason
x.status.timeline.creationdatetime.should.be.a(six.string_types)
# x.status.timeline.enddatetime.should.be.a(six.string_types)
# x.status.timeline.startdatetime.should.be.a(six.string_types)
x.status.timeline.creationdatetime.should.be.a(str)
# x.status.timeline.enddatetime.should.be.a(str)
# x.status.timeline.startdatetime.should.be.a(str)
x = conn.describe_step(cluster_id, x.id)
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.mainclass.should.equal("")
# 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.status.state.should.be.within(["STARTING", "PENDING"])
# x.status.statechangereason
x.status.timeline.creationdatetime.should.be.a(six.string_types)
# x.status.timeline.enddatetime.should.be.a(six.string_types)
# x.status.timeline.startdatetime.should.be.a(six.string_types)
x.status.timeline.creationdatetime.should.be.a(str)
# x.status.timeline.enddatetime.should.be.a(str)
# x.status.timeline.startdatetime.should.be.a(str)
@requires_boto_gte("2.39")
def test_list_steps_with_states():

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals
import six
import datetime
from moto.organizations import utils
@ -72,7 +71,7 @@ def validate_roots(org, response):
root.should.have.key("Arn").should.equal(
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["PolicyTypes"][0].should.have.key("Type").should.equal(
"SERVICE_CONTROL_POLICY"
@ -87,7 +86,7 @@ def validate_organizational_unit(org, response):
ou.should.have.key("Arn").should.equal(
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):
@ -103,7 +102,7 @@ def validate_account(org, account):
account["Email"].should.match(utils.EMAIL_REGEX)
account["JoinedMethod"].should.be.within(["INVITED", "CREATED"])
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)
@ -120,7 +119,7 @@ def validate_create_account_status(create_status):
)
create_status["Id"].should.match(utils.CREATE_ACCOUNT_STATUS_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["RequestedTimestamp"].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(
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("Description").should.be.a(six.string_types)
summary.should.have.key("Name").should.be.a(str)
summary.should.have.key("Description").should.be.a(str)
summary.should.have.key("Type").should.equal("SERVICE_CONTROL_POLICY")
summary.should.have.key("AwsManaged").should.be.a(bool)
def validate_service_control_policy(org, response):
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"])

View File

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

View File

@ -7,7 +7,6 @@ from boto.exception import BotoServerError
import sure # noqa
from moto import mock_ec2_deprecated, mock_rds_deprecated, mock_rds
from tests.helpers import disable_on_py3
@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
def test_add_security_group_to_database():
conn = boto.rds.connect_to_region("us-west-2")

View File

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

View File

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

View File

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

View File

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

View File

@ -11,7 +11,6 @@ import pytz
from datetime import datetime
import sure # noqa
import pytest
from six import b
DEFAULT_SECRET_NAME = "test-secret"
@ -48,10 +47,10 @@ def test_get_secret_value_binary():
conn = boto3.client("secretsmanager", region_name="us-west-2")
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")
assert result["SecretBinary"] == b("foosecret")
assert result["SecretBinary"] == b"foosecret"
@mock_secretsmanager
@ -776,7 +775,7 @@ def test_put_secret_value_on_non_existing_secret():
@mock_secretsmanager
def test_put_secret_value_puts_new_secret():
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(
SecretId=DEFAULT_SECRET_NAME,
SecretString="foosecret",
@ -795,10 +794,10 @@ def test_put_secret_value_puts_new_secret():
@mock_secretsmanager
def test_put_secret_binary_value_puts_new_secret():
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(
SecretId=DEFAULT_SECRET_NAME,
SecretBinary=b("foosecret"),
SecretBinary=b"foosecret",
VersionStages=["AWSCURRENT"],
)
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["SecretBinary"] == b("foosecret")
assert get_secret_value_dict["SecretBinary"] == b"foosecret"
@mock_secretsmanager
def test_create_and_put_secret_binary_value_puts_new_secret():
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(
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)
assert latest_secret
assert latest_secret["SecretBinary"] == b("foosecret_update")
assert latest_secret["SecretBinary"] == b"foosecret_update"
@mock_secretsmanager
@ -840,7 +839,7 @@ def test_put_secret_binary_requires_either_string_or_binary():
@mock_secretsmanager
def test_put_secret_value_can_get_first_version_if_put_twice():
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(
SecretId=DEFAULT_SECRET_NAME,
SecretString="first_secret",

View File

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

View File

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

View File

@ -1,7 +1,6 @@
from __future__ import unicode_literals
import boto
import json
import six
import sure # noqa
@ -124,17 +123,9 @@ def test_topic_attributes():
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"})
displayname = "My display name"
delivery = {"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}}
policy = json.dumps({"foo": "bar"})
displayname = "My display name"
delivery = {"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}}
conn.set_topic_attributes(topic_arn, "Policy", policy)
conn.set_topic_attributes(topic_arn, "DisplayName", displayname)
conn.set_topic_attributes(topic_arn, "DeliveryPolicy", delivery)

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals
import boto3
import six
import json
# import sure # noqa
@ -202,18 +201,9 @@ def test_topic_attributes():
# 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 = json.dumps(
{b"http": {b"defaultHealthyRetryPolicy": {b"numRetries": 5}}}
)
else:
policy = json.dumps({"foo": "bar"})
displayname = "My display name"
delivery = json.dumps(
{"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}}
)
policy = json.dumps({"foo": "bar"})
displayname = "My display name"
delivery = json.dumps({"http": {"defaultHealthyRetryPolicy": {"numRetries": 5}}})
conn.set_topic_attributes(
TopicArn=topic_arn, AttributeName="Policy", AttributeValue=policy
)

View File

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