We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
SQS MD5 Hashing Issues
I've started using Moto as a standalone server to aid testing a PHP stack.  I've discovered that once I create a message which contains encapsulated (escaped) JSON - it starts to fail with the AWS PHP SDK, although it works fine with Boto2.

The issue appears to be in and around the calculation of the MD5 sum.  I suspect Boto must be ignoring the MD5, otherwise I'd think it would be reporting the same problem.

The exception I get from PHP SDK:

```
PHP Warning:  Uncaught Aws\Sqs\Exception\SqsException: AWS Error Code: , Status Code: , AWS Request ID: , AWS Error Type: , AWS Error Message: Body MD5 mismatch for array (
  'MessageId' => '97f171c9-b7a5-b764-f3e0-4234555f509f',
  'ReceiptHandle' => 'nntoxkpevzvvbvbvylufszndstdeplilaxnckhsceeztjvmdqtzpxptfoeyndfgscncydyntjilbppbgsrwlldsjpksxklybpayijnoewirfexullvcdtmbvuablunaykrqomudptfmnznriseoegwopnaxidtwwsmoikjndpaxilaicgcbpisdpt',
  'MD5OfBody' => '08ab38f810e137a6cce4990c3952be77',
  'Body' => '{
```

Trying to reproduce that MD5 of the body using the same body contents from a json file:

PHP:

```
php > $body = file_get_contents(__DIR__ . '/test.json');
php > echo md5($body);
6d8dc937d72f4cdfad4b76be545dda6b
```

Python:

```
>>> import hashlib
>>> with open('git_src/api/data/sqs/ses/temp_bounce.json') as myfile:
...     data=myfile.read()
>>> hashlib.md5(data).hexdigest()
'6d8dc937d72f4cdfad4b76be545dda6b'
>>> from xml.sax.saxutils import escape
>>> hashlib.md5(escape(data).encode('utf-8')).hexdigest()
'08ab38f810e137a6cce4990c3952be77'
```

So it seems the XML escaping is causing the problem.  Before I put together a PR I'll confirm how the real AWS SQS service calculates this MD5.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `moto/sqs/models.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 import hashlib
4 import time
5 import re
6 from xml.sax.saxutils import escape
7 
8 import boto.sqs
9 
10 from moto.core import BaseBackend
11 from moto.core.utils import camelcase_to_underscores, get_random_message_id
12 from .utils import generate_receipt_handle, unix_time_millis
13 from .exceptions import (
14     ReceiptHandleIsInvalid,
15     MessageNotInflight
16 )
17 
18 DEFAULT_ACCOUNT_ID = 123456789012
19 
20 
21 class Message(object):
22     def __init__(self, message_id, body):
23         self.id = message_id
24         self._body = body
25         self.message_attributes = {}
26         self.receipt_handle = None
27         self.sender_id = DEFAULT_ACCOUNT_ID
28         self.sent_timestamp = None
29         self.approximate_first_receive_timestamp = None
30         self.approximate_receive_count = 0
31         self.visible_at = 0
32         self.delayed_until = 0
33 
34     @property
35     def md5(self):
36         body_md5 = hashlib.md5()
37         body_md5.update(self.body.encode('utf-8'))
38         return body_md5.hexdigest()
39 
40     @property
41     def body(self):
42         return escape(self._body)
43 
44     def mark_sent(self, delay_seconds=None):
45         self.sent_timestamp = unix_time_millis()
46         if delay_seconds:
47             self.delay(delay_seconds=delay_seconds)
48 
49     def mark_received(self, visibility_timeout=None):
50         """
51         When a message is received we will set the first receive timestamp,
52         tap the ``approximate_receive_count`` and the ``visible_at`` time.
53         """
54         if visibility_timeout:
55             visibility_timeout = int(visibility_timeout)
56         else:
57             visibility_timeout = 0
58 
59         if not self.approximate_first_receive_timestamp:
60             self.approximate_first_receive_timestamp = unix_time_millis()
61 
62         self.approximate_receive_count += 1
63 
64         # Make message visible again in the future unless its
65         # destroyed.
66         if visibility_timeout:
67             self.change_visibility(visibility_timeout)
68 
69         self.receipt_handle = generate_receipt_handle()
70 
71     def change_visibility(self, visibility_timeout):
72         # We're dealing with milliseconds internally
73         visibility_timeout_msec = int(visibility_timeout) * 1000
74         self.visible_at = unix_time_millis() + visibility_timeout_msec
75 
76     def delay(self, delay_seconds):
77         delay_msec = int(delay_seconds) * 1000
78         self.delayed_until = unix_time_millis() + delay_msec
79 
80     @property
81     def visible(self):
82         current_time = unix_time_millis()
83         if current_time > self.visible_at:
84             return True
85         return False
86 
87     @property
88     def delayed(self):
89         current_time = unix_time_millis()
90         if current_time < self.delayed_until:
91             return True
92         return False
93 
94 
95 class Queue(object):
96     camelcase_attributes = ['ApproximateNumberOfMessages',
97                             'ApproximateNumberOfMessagesDelayed',
98                             'ApproximateNumberOfMessagesNotVisible',
99                             'CreatedTimestamp',
100                             'DelaySeconds',
101                             'LastModifiedTimestamp',
102                             'MaximumMessageSize',
103                             'MessageRetentionPeriod',
104                             'QueueArn',
105                             'ReceiveMessageWaitTimeSeconds',
106                             'VisibilityTimeout',
107                             'WaitTimeSeconds']
108 
109     def __init__(self, name, visibility_timeout, wait_time_seconds, region):
110         self.name = name
111         self.visibility_timeout = visibility_timeout or 30
112         self.region = region
113 
114         # wait_time_seconds will be set to immediate return messages
115         self.wait_time_seconds = wait_time_seconds or 0
116         self._messages = []
117 
118         now = time.time()
119 
120         self.created_timestamp = now
121         self.delay_seconds = 0
122         self.last_modified_timestamp = now
123         self.maximum_message_size = 64 << 10
124         self.message_retention_period = 86400 * 4  # four days
125         self.queue_arn = 'arn:aws:sqs:sqs.us-east-1:123456789012:%s' % self.name
126         self.receive_message_wait_time_seconds = 0
127 
128     @classmethod
129     def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
130         properties = cloudformation_json['Properties']
131 
132         sqs_backend = sqs_backends[region_name]
133         return sqs_backend.create_queue(
134             name=properties['QueueName'],
135             visibility_timeout=properties.get('VisibilityTimeout'),
136             wait_time_seconds=properties.get('WaitTimeSeconds')
137         )
138 
139     @classmethod
140     def update_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
141         properties = cloudformation_json['Properties']
142         queue_name = properties['QueueName']
143 
144         sqs_backend = sqs_backends[region_name]
145         queue = sqs_backend.get_queue(queue_name)
146         if 'VisibilityTimeout' in properties:
147             queue.visibility_timeout = int(properties['VisibilityTimeout'])
148 
149         if 'WaitTimeSeconds' in properties:
150             queue.wait_time_seconds = int(properties['WaitTimeSeconds'])
151         return queue
152 
153     @classmethod
154     def delete_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
155         properties = cloudformation_json['Properties']
156         queue_name = properties['QueueName']
157         sqs_backend = sqs_backends[region_name]
158         sqs_backend.delete_queue(queue_name)
159 
160     @property
161     def approximate_number_of_messages_delayed(self):
162         return len([m for m in self._messages if m.delayed])
163 
164     @property
165     def approximate_number_of_messages_not_visible(self):
166         return len([m for m in self._messages if not m.visible])
167 
168     @property
169     def approximate_number_of_messages(self):
170         return len(self.messages)
171 
172     @property
173     def physical_resource_id(self):
174         return self.name
175 
176     @property
177     def attributes(self):
178         result = {}
179         for attribute in self.camelcase_attributes:
180             result[attribute] = getattr(self, camelcase_to_underscores(attribute))
181         return result
182 
183     @property
184     def url(self):
185         return "http://sqs.{0}.amazonaws.com/123456789012/{1}".format(self.region, self.name)
186 
187     @property
188     def messages(self):
189         return [message for message in self._messages if message.visible and not message.delayed]
190 
191     def add_message(self, message):
192         self._messages.append(message)
193 
194     def get_cfn_attribute(self, attribute_name):
195         from moto.cloudformation.exceptions import UnformattedGetAttTemplateException
196         if attribute_name == 'Arn':
197             return self.queue_arn
198         elif attribute_name == 'QueueName':
199             return self.name
200         raise UnformattedGetAttTemplateException()
201 
202 
203 class SQSBackend(BaseBackend):
204     def __init__(self, region_name):
205         self.region_name = region_name
206         self.queues = {}
207         super(SQSBackend, self).__init__()
208 
209     def reset(self):
210         region_name = self.region_name
211         self.__dict__ = {}
212         self.__init__(region_name)
213 
214     def create_queue(self, name, visibility_timeout, wait_time_seconds):
215         queue = self.queues.get(name)
216         if queue is None:
217             queue = Queue(name, visibility_timeout, wait_time_seconds, self.region_name)
218             self.queues[name] = queue
219         return queue
220 
221     def list_queues(self, queue_name_prefix):
222         re_str = '.*'
223         if queue_name_prefix:
224             re_str = '^{0}.*'.format(queue_name_prefix)
225         prefix_re = re.compile(re_str)
226         qs = []
227         for name, q in self.queues.items():
228             if prefix_re.search(name):
229                 qs.append(q)
230         return qs
231 
232     def get_queue(self, queue_name):
233         return self.queues.get(queue_name, None)
234 
235     def delete_queue(self, queue_name):
236         if queue_name in self.queues:
237             return self.queues.pop(queue_name)
238         return False
239 
240     def set_queue_attribute(self, queue_name, key, value):
241         queue = self.get_queue(queue_name)
242         setattr(queue, key, value)
243         return queue
244 
245     def send_message(self, queue_name, message_body, message_attributes=None, delay_seconds=None):
246 
247         queue = self.get_queue(queue_name)
248 
249         if delay_seconds:
250             delay_seconds = int(delay_seconds)
251         else:
252             delay_seconds = queue.delay_seconds
253 
254         message_id = get_random_message_id()
255         message = Message(message_id, message_body)
256 
257         if message_attributes:
258             message.message_attributes = message_attributes
259 
260         message.mark_sent(
261             delay_seconds=delay_seconds
262         )
263 
264         queue.add_message(message)
265 
266         return message
267 
268     def receive_messages(self, queue_name, count, wait_seconds_timeout):
269         """
270         Attempt to retrieve visible messages from a queue.
271 
272         If a message was read by client and not deleted it is considered to be
273         "inflight" and cannot be read. We make attempts to obtain ``count``
274         messages but we may return less if messages are in-flight or there
275         are simple not enough messages in the queue.
276 
277         :param string queue_name: The name of the queue to read from.
278         :param int count: The maximum amount of messages to retrieve.
279         """
280         queue = self.get_queue(queue_name)
281         result = []
282 
283         polling_end = time.time() + wait_seconds_timeout
284 
285         # queue.messages only contains visible messages
286         while True:
287             for message in queue.messages:
288                 message.mark_received(
289                     visibility_timeout=queue.visibility_timeout
290                 )
291                 result.append(message)
292                 if len(result) >= count:
293                     break
294 
295             if result or time.time() > polling_end:
296                 break
297 
298         return result
299 
300     def delete_message(self, queue_name, receipt_handle):
301         queue = self.get_queue(queue_name)
302         new_messages = []
303         for message in queue._messages:
304             # Only delete message if it is not visible and the reciept_handle
305             # matches.
306             if message.receipt_handle == receipt_handle:
307                 continue
308             new_messages.append(message)
309         queue._messages = new_messages
310 
311     def change_message_visibility(self, queue_name, receipt_handle, visibility_timeout):
312         queue = self.get_queue(queue_name)
313         for message in queue._messages:
314             if message.receipt_handle == receipt_handle:
315                 if message.visible:
316                     raise MessageNotInflight
317                 message.change_visibility(visibility_timeout)
318                 return
319         raise ReceiptHandleIsInvalid
320 
321     def purge_queue(self, queue_name):
322         queue = self.get_queue(queue_name)
323         queue._messages = []
324 
325 
326 sqs_backends = {}
327 for region in boto.sqs.regions():
328     sqs_backends[region.name] = SQSBackend(region.name)
329
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/moto/sqs/models.py b/moto/sqs/models.py
--- a/moto/sqs/models.py
+++ b/moto/sqs/models.py
@@ -34,7 +34,7 @@
     @property
     def md5(self):
         body_md5 = hashlib.md5()
-        body_md5.update(self.body.encode('utf-8'))
+        body_md5.update(self._body.encode('utf-8'))
         return body_md5.hexdigest()
 
     @property

{"golden_diff": "diff --git a/moto/sqs/models.py b/moto/sqs/models.py\n--- a/moto/sqs/models.py\n+++ b/moto/sqs/models.py\n@@ -34,7 +34,7 @@\n     @property\n     def md5(self):\n         body_md5 = hashlib.md5()\n-        body_md5.update(self.body.encode('utf-8'))\n+        body_md5.update(self._body.encode('utf-8'))\n         return body_md5.hexdigest()\n \n     @property\n", "issue": "SQS MD5 Hashing Issues\nI've started using Moto as a standalone server to aid testing a PHP stack.  I've discovered that once I create a message which contains encapsulated (escaped) JSON - it starts to fail with the AWS PHP SDK, although it works fine with Boto2.\n\nThe issue appears to be in and around the calculation of the MD5 sum.  I suspect Boto must be ignoring the MD5, otherwise I'd think it would be reporting the same problem.\n\nThe exception I get from PHP SDK:\n\n```\nPHP Warning:  Uncaught Aws\\Sqs\\Exception\\SqsException: AWS Error Code: , Status Code: , AWS Request ID: , AWS Error Type: , AWS Error Message: Body MD5 mismatch for array (\n  'MessageId' => '97f171c9-b7a5-b764-f3e0-4234555f509f',\n  'ReceiptHandle' => 'nntoxkpevzvvbvbvylufszndstdeplilaxnckhsceeztjvmdqtzpxptfoeyndfgscncydyntjilbppbgsrwlldsjpksxklybpayijnoewirfexullvcdtmbvuablunaykrqomudptfmnznriseoegwopnaxidtwwsmoikjndpaxilaicgcbpisdpt',\n  'MD5OfBody' => '08ab38f810e137a6cce4990c3952be77',\n  'Body' => '{\n```\n\nTrying to reproduce that MD5 of the body using the same body contents from a json file:\n\nPHP:\n\n```\nphp > $body = file_get_contents(__DIR__ . '/test.json');\nphp > echo md5($body);\n6d8dc937d72f4cdfad4b76be545dda6b\n```\n\nPython:\n\n```\n>>> import hashlib\n>>> with open('git_src/api/data/sqs/ses/temp_bounce.json') as myfile:\n...     data=myfile.read()\n>>> hashlib.md5(data).hexdigest()\n'6d8dc937d72f4cdfad4b76be545dda6b'\n>>> from xml.sax.saxutils import escape\n>>> hashlib.md5(escape(data).encode('utf-8')).hexdigest()\n'08ab38f810e137a6cce4990c3952be77'\n```\n\nSo it seems the XML escaping is causing the problem.  Before I put together a PR I'll confirm how the real AWS SQS service calculates this MD5.\n\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nimport hashlib\nimport time\nimport re\nfrom xml.sax.saxutils import escape\n\nimport boto.sqs\n\nfrom moto.core import BaseBackend\nfrom moto.core.utils import camelcase_to_underscores, get_random_message_id\nfrom .utils import generate_receipt_handle, unix_time_millis\nfrom .exceptions import (\n    ReceiptHandleIsInvalid,\n    MessageNotInflight\n)\n\nDEFAULT_ACCOUNT_ID = 123456789012\n\n\nclass Message(object):\n    def __init__(self, message_id, body):\n        self.id = message_id\n        self._body = body\n        self.message_attributes = {}\n        self.receipt_handle = None\n        self.sender_id = DEFAULT_ACCOUNT_ID\n        self.sent_timestamp = None\n        self.approximate_first_receive_timestamp = None\n        self.approximate_receive_count = 0\n        self.visible_at = 0\n        self.delayed_until = 0\n\n    @property\n    def md5(self):\n        body_md5 = hashlib.md5()\n        body_md5.update(self.body.encode('utf-8'))\n        return body_md5.hexdigest()\n\n    @property\n    def body(self):\n        return escape(self._body)\n\n    def mark_sent(self, delay_seconds=None):\n        self.sent_timestamp = unix_time_millis()\n        if delay_seconds:\n            self.delay(delay_seconds=delay_seconds)\n\n    def mark_received(self, visibility_timeout=None):\n        \"\"\"\n        When a message is received we will set the first receive timestamp,\n        tap the ``approximate_receive_count`` and the ``visible_at`` time.\n        \"\"\"\n        if visibility_timeout:\n            visibility_timeout = int(visibility_timeout)\n        else:\n            visibility_timeout = 0\n\n        if not self.approximate_first_receive_timestamp:\n            self.approximate_first_receive_timestamp = unix_time_millis()\n\n        self.approximate_receive_count += 1\n\n        # Make message visible again in the future unless its\n        # destroyed.\n        if visibility_timeout:\n            self.change_visibility(visibility_timeout)\n\n        self.receipt_handle = generate_receipt_handle()\n\n    def change_visibility(self, visibility_timeout):\n        # We're dealing with milliseconds internally\n        visibility_timeout_msec = int(visibility_timeout) * 1000\n        self.visible_at = unix_time_millis() + visibility_timeout_msec\n\n    def delay(self, delay_seconds):\n        delay_msec = int(delay_seconds) * 1000\n        self.delayed_until = unix_time_millis() + delay_msec\n\n    @property\n    def visible(self):\n        current_time = unix_time_millis()\n        if current_time > self.visible_at:\n            return True\n        return False\n\n    @property\n    def delayed(self):\n        current_time = unix_time_millis()\n        if current_time < self.delayed_until:\n            return True\n        return False\n\n\nclass Queue(object):\n    camelcase_attributes = ['ApproximateNumberOfMessages',\n                            'ApproximateNumberOfMessagesDelayed',\n                            'ApproximateNumberOfMessagesNotVisible',\n                            'CreatedTimestamp',\n                            'DelaySeconds',\n                            'LastModifiedTimestamp',\n                            'MaximumMessageSize',\n                            'MessageRetentionPeriod',\n                            'QueueArn',\n                            'ReceiveMessageWaitTimeSeconds',\n                            'VisibilityTimeout',\n                            'WaitTimeSeconds']\n\n    def __init__(self, name, visibility_timeout, wait_time_seconds, region):\n        self.name = name\n        self.visibility_timeout = visibility_timeout or 30\n        self.region = region\n\n        # wait_time_seconds will be set to immediate return messages\n        self.wait_time_seconds = wait_time_seconds or 0\n        self._messages = []\n\n        now = time.time()\n\n        self.created_timestamp = now\n        self.delay_seconds = 0\n        self.last_modified_timestamp = now\n        self.maximum_message_size = 64 << 10\n        self.message_retention_period = 86400 * 4  # four days\n        self.queue_arn = 'arn:aws:sqs:sqs.us-east-1:123456789012:%s' % self.name\n        self.receive_message_wait_time_seconds = 0\n\n    @classmethod\n    def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):\n        properties = cloudformation_json['Properties']\n\n        sqs_backend = sqs_backends[region_name]\n        return sqs_backend.create_queue(\n            name=properties['QueueName'],\n            visibility_timeout=properties.get('VisibilityTimeout'),\n            wait_time_seconds=properties.get('WaitTimeSeconds')\n        )\n\n    @classmethod\n    def update_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):\n        properties = cloudformation_json['Properties']\n        queue_name = properties['QueueName']\n\n        sqs_backend = sqs_backends[region_name]\n        queue = sqs_backend.get_queue(queue_name)\n        if 'VisibilityTimeout' in properties:\n            queue.visibility_timeout = int(properties['VisibilityTimeout'])\n\n        if 'WaitTimeSeconds' in properties:\n            queue.wait_time_seconds = int(properties['WaitTimeSeconds'])\n        return queue\n\n    @classmethod\n    def delete_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):\n        properties = cloudformation_json['Properties']\n        queue_name = properties['QueueName']\n        sqs_backend = sqs_backends[region_name]\n        sqs_backend.delete_queue(queue_name)\n\n    @property\n    def approximate_number_of_messages_delayed(self):\n        return len([m for m in self._messages if m.delayed])\n\n    @property\n    def approximate_number_of_messages_not_visible(self):\n        return len([m for m in self._messages if not m.visible])\n\n    @property\n    def approximate_number_of_messages(self):\n        return len(self.messages)\n\n    @property\n    def physical_resource_id(self):\n        return self.name\n\n    @property\n    def attributes(self):\n        result = {}\n        for attribute in self.camelcase_attributes:\n            result[attribute] = getattr(self, camelcase_to_underscores(attribute))\n        return result\n\n    @property\n    def url(self):\n        return \"http://sqs.{0}.amazonaws.com/123456789012/{1}\".format(self.region, self.name)\n\n    @property\n    def messages(self):\n        return [message for message in self._messages if message.visible and not message.delayed]\n\n    def add_message(self, message):\n        self._messages.append(message)\n\n    def get_cfn_attribute(self, attribute_name):\n        from moto.cloudformation.exceptions import UnformattedGetAttTemplateException\n        if attribute_name == 'Arn':\n            return self.queue_arn\n        elif attribute_name == 'QueueName':\n            return self.name\n        raise UnformattedGetAttTemplateException()\n\n\nclass SQSBackend(BaseBackend):\n    def __init__(self, region_name):\n        self.region_name = region_name\n        self.queues = {}\n        super(SQSBackend, self).__init__()\n\n    def reset(self):\n        region_name = self.region_name\n        self.__dict__ = {}\n        self.__init__(region_name)\n\n    def create_queue(self, name, visibility_timeout, wait_time_seconds):\n        queue = self.queues.get(name)\n        if queue is None:\n            queue = Queue(name, visibility_timeout, wait_time_seconds, self.region_name)\n            self.queues[name] = queue\n        return queue\n\n    def list_queues(self, queue_name_prefix):\n        re_str = '.*'\n        if queue_name_prefix:\n            re_str = '^{0}.*'.format(queue_name_prefix)\n        prefix_re = re.compile(re_str)\n        qs = []\n        for name, q in self.queues.items():\n            if prefix_re.search(name):\n                qs.append(q)\n        return qs\n\n    def get_queue(self, queue_name):\n        return self.queues.get(queue_name, None)\n\n    def delete_queue(self, queue_name):\n        if queue_name in self.queues:\n            return self.queues.pop(queue_name)\n        return False\n\n    def set_queue_attribute(self, queue_name, key, value):\n        queue = self.get_queue(queue_name)\n        setattr(queue, key, value)\n        return queue\n\n    def send_message(self, queue_name, message_body, message_attributes=None, delay_seconds=None):\n\n        queue = self.get_queue(queue_name)\n\n        if delay_seconds:\n            delay_seconds = int(delay_seconds)\n        else:\n            delay_seconds = queue.delay_seconds\n\n        message_id = get_random_message_id()\n        message = Message(message_id, message_body)\n\n        if message_attributes:\n            message.message_attributes = message_attributes\n\n        message.mark_sent(\n            delay_seconds=delay_seconds\n        )\n\n        queue.add_message(message)\n\n        return message\n\n    def receive_messages(self, queue_name, count, wait_seconds_timeout):\n        \"\"\"\n        Attempt to retrieve visible messages from a queue.\n\n        If a message was read by client and not deleted it is considered to be\n        \"inflight\" and cannot be read. We make attempts to obtain ``count``\n        messages but we may return less if messages are in-flight or there\n        are simple not enough messages in the queue.\n\n        :param string queue_name: The name of the queue to read from.\n        :param int count: The maximum amount of messages to retrieve.\n        \"\"\"\n        queue = self.get_queue(queue_name)\n        result = []\n\n        polling_end = time.time() + wait_seconds_timeout\n\n        # queue.messages only contains visible messages\n        while True:\n            for message in queue.messages:\n                message.mark_received(\n                    visibility_timeout=queue.visibility_timeout\n                )\n                result.append(message)\n                if len(result) >= count:\n                    break\n\n            if result or time.time() > polling_end:\n                break\n\n        return result\n\n    def delete_message(self, queue_name, receipt_handle):\n        queue = self.get_queue(queue_name)\n        new_messages = []\n        for message in queue._messages:\n            # Only delete message if it is not visible and the reciept_handle\n            # matches.\n            if message.receipt_handle == receipt_handle:\n                continue\n            new_messages.append(message)\n        queue._messages = new_messages\n\n    def change_message_visibility(self, queue_name, receipt_handle, visibility_timeout):\n        queue = self.get_queue(queue_name)\n        for message in queue._messages:\n            if message.receipt_handle == receipt_handle:\n                if message.visible:\n                    raise MessageNotInflight\n                message.change_visibility(visibility_timeout)\n                return\n        raise ReceiptHandleIsInvalid\n\n    def purge_queue(self, queue_name):\n        queue = self.get_queue(queue_name)\n        queue._messages = []\n\n\nsqs_backends = {}\nfor region in boto.sqs.regions():\n    sqs_backends[region.name] = SQSBackend(region.name)\n", "path": "moto/sqs/models.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport hashlib\nimport time\nimport re\nfrom xml.sax.saxutils import escape\n\nimport boto.sqs\n\nfrom moto.core import BaseBackend\nfrom moto.core.utils import camelcase_to_underscores, get_random_message_id\nfrom .utils import generate_receipt_handle, unix_time_millis\nfrom .exceptions import (\n    ReceiptHandleIsInvalid,\n    MessageNotInflight\n)\n\nDEFAULT_ACCOUNT_ID = 123456789012\n\n\nclass Message(object):\n    def __init__(self, message_id, body):\n        self.id = message_id\n        self._body = body\n        self.message_attributes = {}\n        self.receipt_handle = None\n        self.sender_id = DEFAULT_ACCOUNT_ID\n        self.sent_timestamp = None\n        self.approximate_first_receive_timestamp = None\n        self.approximate_receive_count = 0\n        self.visible_at = 0\n        self.delayed_until = 0\n\n    @property\n    def md5(self):\n        body_md5 = hashlib.md5()\n        body_md5.update(self._body.encode('utf-8'))\n        return body_md5.hexdigest()\n\n    @property\n    def body(self):\n        return escape(self._body)\n\n    def mark_sent(self, delay_seconds=None):\n        self.sent_timestamp = unix_time_millis()\n        if delay_seconds:\n            self.delay(delay_seconds=delay_seconds)\n\n    def mark_received(self, visibility_timeout=None):\n        \"\"\"\n        When a message is received we will set the first receive timestamp,\n        tap the ``approximate_receive_count`` and the ``visible_at`` time.\n        \"\"\"\n        if visibility_timeout:\n            visibility_timeout = int(visibility_timeout)\n        else:\n            visibility_timeout = 0\n\n        if not self.approximate_first_receive_timestamp:\n            self.approximate_first_receive_timestamp = unix_time_millis()\n\n        self.approximate_receive_count += 1\n\n        # Make message visible again in the future unless its\n        # destroyed.\n        if visibility_timeout:\n            self.change_visibility(visibility_timeout)\n\n        self.receipt_handle = generate_receipt_handle()\n\n    def change_visibility(self, visibility_timeout):\n        # We're dealing with milliseconds internally\n        visibility_timeout_msec = int(visibility_timeout) * 1000\n        self.visible_at = unix_time_millis() + visibility_timeout_msec\n\n    def delay(self, delay_seconds):\n        delay_msec = int(delay_seconds) * 1000\n        self.delayed_until = unix_time_millis() + delay_msec\n\n    @property\n    def visible(self):\n        current_time = unix_time_millis()\n        if current_time > self.visible_at:\n            return True\n        return False\n\n    @property\n    def delayed(self):\n        current_time = unix_time_millis()\n        if current_time < self.delayed_until:\n            return True\n        return False\n\n\nclass Queue(object):\n    camelcase_attributes = ['ApproximateNumberOfMessages',\n                            'ApproximateNumberOfMessagesDelayed',\n                            'ApproximateNumberOfMessagesNotVisible',\n                            'CreatedTimestamp',\n                            'DelaySeconds',\n                            'LastModifiedTimestamp',\n                            'MaximumMessageSize',\n                            'MessageRetentionPeriod',\n                            'QueueArn',\n                            'ReceiveMessageWaitTimeSeconds',\n                            'VisibilityTimeout',\n                            'WaitTimeSeconds']\n\n    def __init__(self, name, visibility_timeout, wait_time_seconds, region):\n        self.name = name\n        self.visibility_timeout = visibility_timeout or 30\n        self.region = region\n\n        # wait_time_seconds will be set to immediate return messages\n        self.wait_time_seconds = wait_time_seconds or 0\n        self._messages = []\n\n        now = time.time()\n\n        self.created_timestamp = now\n        self.delay_seconds = 0\n        self.last_modified_timestamp = now\n        self.maximum_message_size = 64 << 10\n        self.message_retention_period = 86400 * 4  # four days\n        self.queue_arn = 'arn:aws:sqs:sqs.us-east-1:123456789012:%s' % self.name\n        self.receive_message_wait_time_seconds = 0\n\n    @classmethod\n    def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):\n        properties = cloudformation_json['Properties']\n\n        sqs_backend = sqs_backends[region_name]\n        return sqs_backend.create_queue(\n            name=properties['QueueName'],\n            visibility_timeout=properties.get('VisibilityTimeout'),\n            wait_time_seconds=properties.get('WaitTimeSeconds')\n        )\n\n    @classmethod\n    def update_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):\n        properties = cloudformation_json['Properties']\n        queue_name = properties['QueueName']\n\n        sqs_backend = sqs_backends[region_name]\n        queue = sqs_backend.get_queue(queue_name)\n        if 'VisibilityTimeout' in properties:\n            queue.visibility_timeout = int(properties['VisibilityTimeout'])\n\n        if 'WaitTimeSeconds' in properties:\n            queue.wait_time_seconds = int(properties['WaitTimeSeconds'])\n        return queue\n\n    @classmethod\n    def delete_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):\n        properties = cloudformation_json['Properties']\n        queue_name = properties['QueueName']\n        sqs_backend = sqs_backends[region_name]\n        sqs_backend.delete_queue(queue_name)\n\n    @property\n    def approximate_number_of_messages_delayed(self):\n        return len([m for m in self._messages if m.delayed])\n\n    @property\n    def approximate_number_of_messages_not_visible(self):\n        return len([m for m in self._messages if not m.visible])\n\n    @property\n    def approximate_number_of_messages(self):\n        return len(self.messages)\n\n    @property\n    def physical_resource_id(self):\n        return self.name\n\n    @property\n    def attributes(self):\n        result = {}\n        for attribute in self.camelcase_attributes:\n            result[attribute] = getattr(self, camelcase_to_underscores(attribute))\n        return result\n\n    @property\n    def url(self):\n        return \"http://sqs.{0}.amazonaws.com/123456789012/{1}\".format(self.region, self.name)\n\n    @property\n    def messages(self):\n        return [message for message in self._messages if message.visible and not message.delayed]\n\n    def add_message(self, message):\n        self._messages.append(message)\n\n    def get_cfn_attribute(self, attribute_name):\n        from moto.cloudformation.exceptions import UnformattedGetAttTemplateException\n        if attribute_name == 'Arn':\n            return self.queue_arn\n        elif attribute_name == 'QueueName':\n            return self.name\n        raise UnformattedGetAttTemplateException()\n\n\nclass SQSBackend(BaseBackend):\n    def __init__(self, region_name):\n        self.region_name = region_name\n        self.queues = {}\n        super(SQSBackend, self).__init__()\n\n    def reset(self):\n        region_name = self.region_name\n        self.__dict__ = {}\n        self.__init__(region_name)\n\n    def create_queue(self, name, visibility_timeout, wait_time_seconds):\n        queue = self.queues.get(name)\n        if queue is None:\n            queue = Queue(name, visibility_timeout, wait_time_seconds, self.region_name)\n            self.queues[name] = queue\n        return queue\n\n    def list_queues(self, queue_name_prefix):\n        re_str = '.*'\n        if queue_name_prefix:\n            re_str = '^{0}.*'.format(queue_name_prefix)\n        prefix_re = re.compile(re_str)\n        qs = []\n        for name, q in self.queues.items():\n            if prefix_re.search(name):\n                qs.append(q)\n        return qs\n\n    def get_queue(self, queue_name):\n        return self.queues.get(queue_name, None)\n\n    def delete_queue(self, queue_name):\n        if queue_name in self.queues:\n            return self.queues.pop(queue_name)\n        return False\n\n    def set_queue_attribute(self, queue_name, key, value):\n        queue = self.get_queue(queue_name)\n        setattr(queue, key, value)\n        return queue\n\n    def send_message(self, queue_name, message_body, message_attributes=None, delay_seconds=None):\n\n        queue = self.get_queue(queue_name)\n\n        if delay_seconds:\n            delay_seconds = int(delay_seconds)\n        else:\n            delay_seconds = queue.delay_seconds\n\n        message_id = get_random_message_id()\n        message = Message(message_id, message_body)\n\n        if message_attributes:\n            message.message_attributes = message_attributes\n\n        message.mark_sent(\n            delay_seconds=delay_seconds\n        )\n\n        queue.add_message(message)\n\n        return message\n\n    def receive_messages(self, queue_name, count, wait_seconds_timeout):\n        \"\"\"\n        Attempt to retrieve visible messages from a queue.\n\n        If a message was read by client and not deleted it is considered to be\n        \"inflight\" and cannot be read. We make attempts to obtain ``count``\n        messages but we may return less if messages are in-flight or there\n        are simple not enough messages in the queue.\n\n        :param string queue_name: The name of the queue to read from.\n        :param int count: The maximum amount of messages to retrieve.\n        \"\"\"\n        queue = self.get_queue(queue_name)\n        result = []\n\n        polling_end = time.time() + wait_seconds_timeout\n\n        # queue.messages only contains visible messages\n        while True:\n            for message in queue.messages:\n                message.mark_received(\n                    visibility_timeout=queue.visibility_timeout\n                )\n                result.append(message)\n                if len(result) >= count:\n                    break\n\n            if result or time.time() > polling_end:\n                break\n\n        return result\n\n    def delete_message(self, queue_name, receipt_handle):\n        queue = self.get_queue(queue_name)\n        new_messages = []\n        for message in queue._messages:\n            # Only delete message if it is not visible and the reciept_handle\n            # matches.\n            if message.receipt_handle == receipt_handle:\n                continue\n            new_messages.append(message)\n        queue._messages = new_messages\n\n    def change_message_visibility(self, queue_name, receipt_handle, visibility_timeout):\n        queue = self.get_queue(queue_name)\n        for message in queue._messages:\n            if message.receipt_handle == receipt_handle:\n                if message.visible:\n                    raise MessageNotInflight\n                message.change_visibility(visibility_timeout)\n                return\n        raise ReceiptHandleIsInvalid\n\n    def purge_queue(self, queue_name):\n        queue = self.get_queue(queue_name)\n        queue._messages = []\n\n\nsqs_backends = {}\nfor region in boto.sqs.regions():\n    sqs_backends[region.name] = SQSBackend(region.name)\n", "path": "moto/sqs/models.py"}]}