Skip to content

Commit

Permalink
Fix parsing different source formats (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
d3QUone committed Nov 25, 2022
1 parent 80c648b commit c341a60
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
VERBOSE=1

test:
poetry run nose2 --verbosity $(VERBOSE)
poetry run nose2 --verbosity $(VERBOSE) $(target)
2 changes: 1 addition & 1 deletion aiosqs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
SendMessageResponse,
)

VERSION = "1.0.1"
VERSION = "1.0.2"
2 changes: 1 addition & 1 deletion aiosqs/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ async def request(self, params: Dict) -> Union[Dict, List, None]:
self.logger.error(f"SQS API error: status_code={response.status}, body={response_body}")
raise SQSClientBaseError

return parse_xml_result_response(action=params["Action"], body=response_body)
return parse_xml_result_response(action=params["Action"], body=response_body, logger=self.logger)

async def get_queue_url(self, queue_name: str) -> GetQueueUrlResponse:
params = {
Expand Down
33 changes: 26 additions & 7 deletions aiosqs/parser.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,50 @@
from logging import getLogger
from typing import Optional

from lxml import etree

from aiosqs.exceptions import ErrorData, SQSErrorResponse
from aiosqs.types import LoggerType

default_logger = getLogger(__name__)


def el_text(el) -> Optional[str]:
if text := el.text:
return text.strip()
return None


def collect_elements(root, xpath: str):
multi_response = []
for child in root.xpath(xpath):
item = {}
for elem in child:
value = elem.text.strip()
item[elem.tag] = value
item[elem.tag] = el_text(elem)
if item:
multi_response.append(item)
return multi_response


def find_request_id(root) -> Optional[str]:
for child in root.xpath("./RequestId"):
if value := child.text.strip():
return value
if text := el_text(child):
return text
return None


def parse_xml_result_response(action: str, body: str):
root = etree.fromstring(body)
def parse_xml_result_response(action: str, body: str, logger: Optional[LoggerType] = None):
logger = logger or default_logger
logger.debug("Message for %s: %s", action, body)

parser = etree.XMLParser(
remove_blank_text=True,
remove_comments=True,
remove_pis=True,
recover=False,
)
root = etree.fromstring(text=body, parser=parser)

request_id = find_request_id(root=root)

# Check for errors first
Expand All @@ -48,7 +67,7 @@ def parse_xml_result_response(action: str, body: str):
# Response is a list of objects of the same type
if len(elements) == 1 and len(elements[0]) == 1:
key, value = list(elements[0].items())[0]
if value == "":
if not value:
xpath = f"{xpath}/{key}"
return collect_elements(root=root, xpath=xpath)

Expand Down
1 change: 1 addition & 0 deletions aiosqs/tests/fixtures/receive_message_ugly.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<ReceiveMessageResponse><ReceiveMessageResult><Message><MD5OfBody>cc12d89c4c6a34a4d8b78f970cd75534</MD5OfBody><Body>{&quot;external_id&quot;: 29, &quot;market&quot;: &quot;usdtrub&quot;, &quot;side&quot;: &quot;sell&quot;, &quot;amount&quot;: &quot;16.05&quot;}</Body><ReceiptHandle>1669388400-f96963bf-3f5f-40e8-8df2-9ce9ff90adf8</ReceiptHandle><MessageId>f96963bf-3f5f-40e8-8df2-9ce9ff90adf8</MessageId></Message></ReceiveMessageResult><ResponseMetadata><RequestId/></ResponseMetadata></ReceiveMessageResponse>
17 changes: 17 additions & 0 deletions aiosqs/tests/test_receive_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ def test_one_message(self):
],
)

def test_parse_oneline_xml(self):
res = parse_xml_result_response(
action=self.action,
body=load_fixture("receive_message_ugly.xml"),
)
self.assertEqual(
res,
[
{
"MD5OfBody": "cc12d89c4c6a34a4d8b78f970cd75534",
"Body": '{"external_id": 29, "market": "usdtrub", "side": "sell", "amount": "16.05"}',
"ReceiptHandle": "1669388400-f96963bf-3f5f-40e8-8df2-9ce9ff90adf8",
"MessageId": "f96963bf-3f5f-40e8-8df2-9ce9ff90adf8",
},
],
)

def test_many_messages(self):
res = parse_xml_result_response(
action=self.action,
Expand Down

0 comments on commit c341a60

Please sign in to comment.