From 0d907e17dc84d539e5aaf2c1e84da9bc5d47785a Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 5 Dec 2021 19:49:09 +0000 Subject: [PATCH 1/2] Bug fixes for XML dumps function concerning dumping documents with few nodes and preserving attributes across repeated dumps. Tests included --- simplexml/core.py | 35 +++++++++++++++++++++++++++-------- tests/test_core.py | 19 +++++++++++++++++++ tox.ini | 2 +- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/simplexml/core.py b/simplexml/core.py index de8af95..a1752d0 100644 --- a/simplexml/core.py +++ b/simplexml/core.py @@ -14,6 +14,11 @@ import re from xml.dom.minidom import getDOMImplementation, parseString +def exclude_attrs_nodes_from_dict(data): + if type(data) == dict: + return {x: data[x] for x in data if x != '_attrs'} + return data + def element_from_dict(document, elRoot, data): if type(data) == list: @@ -30,22 +35,23 @@ def element_from_dict(document, elRoot, data): if '_attrs' in v: for name,value in v["_attrs"].items(): elem.setAttribute(name, str(value)) - del(v["_attrs"]) - + if '_value' in v: value = v.get('_value') textNode = document.createCDATASection(value) if isinstance(value, str) and re.search("[\<\>\&]", value) else document.createTextNode(str(value)) elem.appendChild(textNode) + else: - element_from_dict(document, elem, v) + element_from_dict(document, elem, exclude_attrs_nodes_from_dict(v)) elRoot.appendChild(elem) + elif isinstance(v, list): if k.endswith("s"): elem = document.createElement(k) for item in v: elItem = document.createElement(k[0:len(k)-1]) - element_from_dict(document, elItem, item) + element_from_dict(document, elItem, exclude_attrs_nodes_from_dict(item)) elem.appendChild(elItem) elRoot.appendChild(elem) else: @@ -54,14 +60,13 @@ def element_from_dict(document, elRoot, data): if '_attrs' in item: for name,value in item["_attrs"].items(): elItem.setAttribute(name, str(value)) - del(item["_attrs"]) if '_value' in item: value = item.get('_value') textNode = document.createCDATASection(value) if isinstance(value, str) and re.search("[\<\>\&]", value) else document.createTextNode(str(value)) elItem.appendChild(textNode) else: - element_from_dict(document, elItem, item) + element_from_dict(document, elItem, exclude_attrs_nodes_from_dict(item)) elRoot.appendChild(elItem) @@ -126,9 +131,23 @@ def dumps(data): if type(rootValue) == dict and '_attrs' in rootValue: for name,value in rootValue["_attrs"].items(): rootNode.setAttribute(name, value) - del(rootValue["_attrs"]) + + if type(rootValue) == dict and '_value' in rootValue: + # Handles case where root node contains single text node - allowing for attribute definition and CDATA handling + value = rootValue.get('_value') + textNode = document.createCDATASection(value) if isinstance(value, str) and re.search("[\<\>\&]", value) else document.createTextNode(str(value)) + rootNode.appendChild(textNode) + # Text or CDATA node cannot have children + return document.toxml() + + + if type(rootValue) == str: + # Handles case where root node contains single text node - simple case not allowing for attribute definition + text = document.createTextNode(rootValue) + rootNode.appendChild(text) + return document.toxml() - element_from_dict(document, rootNode, rootValue) + element_from_dict(document, rootNode, exclude_attrs_nodes_from_dict(rootValue)) return document.toxml() diff --git a/tests/test_core.py b/tests/test_core.py index d0fc2fa..b685f41 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -108,3 +108,22 @@ def test_can_dumps_with_first_node_list(): response = simplexml.dumps(sometag) assert 'Should Be NomeShould Be Nome' in response + +def test_can_dumps_with_single_simple_node(): + sometag = {'someTag': 'Should be Name'} + response = simplexml.dumps(sometag) + + assert 'Should be Name' in response + +def test_can_dumps_with_root_node_containing_text_node(): + sometag = {'someTag': {'_attrs': {'id': '1'}, '_value': 'Should be value'}} + response = simplexml.dumps(sometag) + + assert 'Should be value' in response + +def test_repeated_calls_to_dumps_preserves_dict_attrs(): + sometag = {'someTag': {'_attrs': {'id': '1'}, '_value': 'Should be value'}} + response1 = simplexml.dumps(sometag) + response2 = simplexml.dumps(sometag) + + assert 'Should be value' in response2 diff --git a/tox.ini b/tox.ini index 299fa89..6427405 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py26,py27,py33 +envlist = py26,py27,py33,py38 [testenv] deps= nose==1.1.2 From 5f2fb86c0f5c92c53f961418e063e8470cf1cfca Mon Sep 17 00:00:00 2001 From: BenedictBoyle Date: Sun, 5 Dec 2021 20:01:12 +0000 Subject: [PATCH 2/2] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c380f18..8a04e37 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ python: - 2.7 - 3.2 - 3.3 + - 3.8 install: - pip install -r requirements.txt --use-mirrors script: