Testing new version of decorator.

This commit is contained in:
Steve Pulec 2017-02-15 22:35:45 -05:00
commit fde721bed7
123 changed files with 2740 additions and 1114 deletions

View file

@ -1,22 +1,23 @@
from __future__ import unicode_literals
from __future__ import absolute_import
import functools
import inspect
import re
from httpretty import HTTPretty
from moto.packages.responses import responses
from moto.packages.httpretty import HTTPretty
from .responses import metadata_response
from .utils import convert_regex_to_flask_path
from .utils import convert_regex_to_flask_path, convert_flask_to_responses_response
class MockAWS(object):
class BaseMockAWS(object):
nested_count = 0
def __init__(self, backends):
self.backends = backends
if self.__class__.nested_count == 0:
HTTPretty.reset()
self.reset()
def __call__(self, func, reset=True):
if inspect.isclass(func):
@ -35,24 +36,7 @@ class MockAWS(object):
for backend in self.backends.values():
backend.reset()
if not HTTPretty.is_enabled():
HTTPretty.enable()
for method in HTTPretty.METHODS:
backend = list(self.backends.values())[0]
for key, value in backend.urls.items():
HTTPretty.register_uri(
method=method,
uri=re.compile(key),
body=value,
)
# Mock out localhost instance metadata
HTTPretty.register_uri(
method=method,
uri=re.compile('http://169.254.169.254/latest/meta-data/.*'),
body=metadata_response
)
self.enable_patching()
def stop(self):
self.__class__.nested_count -= 1
@ -60,9 +44,7 @@ class MockAWS(object):
if self.__class__.nested_count < 0:
raise RuntimeError('Called stop() before start().')
if self.__class__.nested_count == 0:
HTTPretty.disable()
HTTPretty.reset()
self.disable_patching()
def decorate_callable(self, func, reset):
def wrapper(*args, **kwargs):
@ -97,6 +79,73 @@ class MockAWS(object):
return klass
class HttprettyMockAWS(BaseMockAWS):
def reset(self):
HTTPretty.reset()
def enable_patching(self):
if not HTTPretty.is_enabled():
HTTPretty.enable()
for method in HTTPretty.METHODS:
backend = list(self.backends.values())[0]
for key, value in backend.urls.items():
HTTPretty.register_uri(
method=method,
uri=re.compile(key),
body=value,
)
# Mock out localhost instance metadata
HTTPretty.register_uri(
method=method,
uri=re.compile('http://169.254.169.254/latest/meta-data/.*'),
body=metadata_response
)
def disable_patching(self):
if self.__class__.nested_count == 0:
HTTPretty.disable()
HTTPretty.reset()
RESPONSES_METHODS = [responses.GET, responses.DELETE, responses.HEAD,
responses.OPTIONS, responses.PATCH, responses.POST, responses.PUT]
class ResponsesMockAWS(BaseMockAWS):
def reset(self):
responses.reset()
def enable_patching(self):
responses.start()
for method in RESPONSES_METHODS:
backend = list(self.backends.values())[0]
for key, value in backend.urls.items():
responses.add_callback(
method=method,
url=re.compile(key),
callback=convert_flask_to_responses_response(value),
)
# Mock out localhost instance metadata
responses.add_callback(
method=method,
url=re.compile('http://169.254.169.254/latest/meta-data/.*'),
callback=convert_flask_to_responses_response(metadata_response),
)
for pattern in responses.mock._urls:
pattern['stream'] = True
def disable_patching(self):
if self.__class__.nested_count == 0:
try:
responses.stop()
except AttributeError:
pass
responses.reset()
MockAWS = ResponsesMockAWS
class Model(type):
def __new__(self, clsname, bases, namespace):
cls = super(Model, self).__new__(self, clsname, bases, namespace)
@ -187,6 +236,12 @@ class BaseBackend(object):
else:
return MockAWS({'global': self})
def deprecated_decorator(self, func=None):
if func:
return HttprettyMockAWS({'global': self})(func)
else:
return HttprettyMockAWS({'global': self})
class base_decorator(object):
mock_backend = MockAWS
@ -199,3 +254,7 @@ class base_decorator(object):
return self.mock_backend(self.backends)(func)
else:
return self.mock_backend(self.backends)
class deprecated_base_decorator(base_decorator):
mock_backend = HttprettyMockAWS

View file

@ -138,7 +138,7 @@ class BaseResponse(_TemplateEnvironmentMixin):
flat = flatten_json_request_body('', decoded, input_spec)
for key, value in flat.items():
querystring[key] = [value]
else:
elif self.body:
querystring.update(parse_qs(self.body, keep_blank_values=True))
if not querystring:
querystring.update(headers)
@ -152,6 +152,8 @@ class BaseResponse(_TemplateEnvironmentMixin):
self.region = self.get_region_from_url(full_url)
self.headers = request.headers
if 'host' not in self.headers:
self.headers['host'] = urlparse(full_url).netloc
self.response_headers = headers
def get_region_from_url(self, full_url):
@ -189,6 +191,9 @@ class BaseResponse(_TemplateEnvironmentMixin):
body, new_headers = response
status = new_headers.get('status', 200)
headers.update(new_headers)
# Cast status to string
if "status" in headers:
headers['status'] = str(headers['status'])
return status, headers, body
raise NotImplementedError("The {0} action has not been implemented".format(action))
@ -327,6 +332,7 @@ def metadata_response(request, full_url, headers):
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html
"""
parsed_url = urlparse(full_url)
tomorrow = datetime.datetime.utcnow() + datetime.timedelta(days=1)
credentials = dict(

View file

@ -103,6 +103,28 @@ class convert_flask_to_httpretty_response(object):
return response, status, headers
class convert_flask_to_responses_response(object):
def __init__(self, callback):
self.callback = callback
@property
def __name__(self):
# For instance methods, use class and method names. Otherwise
# use module and method name
if inspect.ismethod(self.callback):
outer = self.callback.__self__.__class__.__name__
else:
outer = self.callback.__module__
return "{0}.{1}".format(outer, self.callback.__name__)
def __call__(self, request, *args, **kwargs):
result = self.callback(request, request.url, request.headers)
# result is a status, headers, response tuple
status, headers, response = result
return status, headers, response
def iso_8601_datetime_with_milliseconds(datetime):
return datetime.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + 'Z'