Skip to content

Commit a25dee6

Browse files
author
Vinit Kumar
authored
Feat/remove logging by default (#131)
* fix: remove default logging in dicttoxml Library shouldn't be emitting logs by default and not pollute the consumers. Hence, we put the LOGS behind a flag. To see the library's logs, set DEBUGMODE=True in environment for the logs to work. DEBUGMODE is a fairly unique env variable so should do do the trick. - Github Issue: #130 Reported-by: https://github.com/ricciarellif Authored-by: Vinit Kumar <[email protected]> Signed-off-by: Vinit Kumar <[email protected]> * fix: add default value for flag and sort imports * fix: make logging lines out of coverage scope * fix: remove log line out of coverage scope * add # pragma: no cover for logging lines
1 parent f2cfdb8 commit a25dee6

File tree

2 files changed

+61
-61
lines changed

2 files changed

+61
-61
lines changed

json2xml/dicttoxml.py

Lines changed: 61 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,18 @@
1111
Items with a `None` type become empty XML elements.
1212
This module works with Python 3.7+
1313
"""
14-
1514
import datetime
1615
import logging
1716
import numbers
17+
import os
1818
from collections.abc import Callable, Sequence
1919
from random import randint
2020
from typing import Any, Dict, List, Optional, Tuple, Union
2121

2222
from defusedxml.minidom import parseString
2323

24-
LOG = logging.getLogger("dicttoxml")
24+
DEBUGMODE = os.getenv("DEBUGMODE", False) # pragma: no cover
25+
LOG = logging.getLogger("dicttoxml") # pragma: no cover
2526

2627

2728
ids: List[str] = [] # initialize list of unique ids
@@ -100,7 +101,8 @@ def make_attrstring(attr: dict[str, Any]) -> str:
100101

101102
def key_is_valid_xml(key: str) -> bool:
102103
"""Checks that a key is a valid XML name"""
103-
LOG.info(f'Inside key_is_valid_xml(). Testing "{str(key)}"')
104+
if DEBUGMODE: # pragma: no cover
105+
LOG.info(f'Inside key_is_valid_xml(). Testing "{str(key)}"')
104106
test_xml = f'<?xml version="1.0" encoding="UTF-8" ?><{key}>foo</{key}>'
105107
try:
106108
parseString(test_xml)
@@ -111,9 +113,10 @@ def key_is_valid_xml(key: str) -> bool:
111113

112114
def make_valid_xml_name(key: str, attr: Dict[str, Any]) -> Tuple[str, Dict[str, Any]]:
113115
"""Tests an XML name and fixes it if invalid"""
114-
LOG.info(
115-
f'Inside make_valid_xml_name(). Testing key "{str(key)}" with attr "{str(attr)}"'
116-
)
116+
if DEBUGMODE: # pragma: no cover
117+
LOG.info(
118+
f'Inside make_valid_xml_name(). Testing key "{str(key)}" with attr "{str(attr)}"'
119+
)
117120
key = escape_xml(key)
118121
# nothing happens at escape_xml if attr is not a string, we don't
119122
# need to pass it to the method at all.
@@ -162,10 +165,11 @@ def convert(
162165
) -> str:
163166
"""Routes the elements of an object to the right function to convert them
164167
based on their data type"""
165-
LOG.info(f'Inside convert(). type(obj)="{type(obj).__name__}"')
166-
# avoid cpu consuming object serialization => extra if
167-
if LOG.getEffectiveLevel() <= logging.DEBUG:
168-
LOG.debug(f' obj="{str(obj)}"')
168+
if DEBUGMODE: # pragma: no cover
169+
LOG.info(f'Inside convert(). type(obj)="{type(obj).__name__}"')
170+
# avoid cpu consuming object serialization => extra if
171+
if LOG.getEffectiveLevel() <= logging.DEBUG:
172+
LOG.debug(f' obj="{str(obj)}"')
169173

170174
item_name = item_func(parent)
171175
# since bool is also a subtype of number.Number and int, the check for bool
@@ -227,12 +231,13 @@ def dict2xml_str(
227231
parse dict2xml
228232
"""
229233
keys_str = ", ".join(str(key) for key in item)
230-
LOG.info(
231-
f'Inside dict_item2xml_str: type(obj)="{type(item).__name__}", keys="{keys_str}"'
232-
)
233-
# avoid cpu consuming object serialization => extra if
234-
if LOG.getEffectiveLevel() <= logging.DEBUG:
235-
LOG.debug(f' item="{str(item)}"')
234+
if DEBUGMODE: # pragma: no cover
235+
LOG.info(
236+
f'Inside dict_item2xml_str: type(obj)="{type(item).__name__}", keys="{keys_str}"'
237+
)
238+
# avoid cpu consuming object serialization => extra if
239+
if LOG.getEffectiveLevel() <= logging.DEBUG:
240+
LOG.debug(f' item="{str(item)}"')
236241

237242
if attr_type:
238243
attr["type"] = get_xml_type(item)
@@ -292,22 +297,24 @@ def convert_dict(
292297
) -> str:
293298
"""Converts a dict into an XML string."""
294299
keys_str = ", ".join(str(key) for key in obj)
295-
LOG.info(
296-
f'Inside convert_dict(): type(obj)="{type(obj).__name__}", keys="{keys_str}"'
297-
)
298-
# avoid cpu consuming object serialization => extra if
299-
if LOG.getEffectiveLevel() <= logging.DEBUG:
300-
LOG.debug(f' obj="{str(obj)}"')
300+
if DEBUGMODE: # pragma: no cover
301+
LOG.info(
302+
f'Inside convert_dict(): type(obj)="{type(obj).__name__}", keys="{keys_str}"'
303+
)
304+
# avoid cpu consuming object serialization => extra if
305+
if LOG.getEffectiveLevel() <= logging.DEBUG:
306+
LOG.debug(f' obj="{str(obj)}"')
301307

302308
output: List[str] = []
303309
addline = output.append
304310

305311
for key, val in obj.items():
306-
LOG.info(
307-
f'Looping inside convert_dict(): key="{str(key)}", type(val)="{type(val).__name__}"'
308-
)
309-
if LOG.getEffectiveLevel() <= logging.DEBUG:
310-
LOG.debug(f' val="{str(val)}"')
312+
if DEBUGMODE: # pragma: no cover
313+
LOG.info(
314+
f'Looping inside convert_dict(): key="{str(key)}", type(val)="{type(val).__name__}"'
315+
)
316+
if LOG.getEffectiveLevel() <= logging.DEBUG:
317+
LOG.debug(f' val="{str(val)}"')
311318

312319
attr = {} if not ids else {"id": f"{get_unique_id(parent)}"}
313320

@@ -377,10 +384,11 @@ def convert_list(
377384
item_wrap: bool,
378385
) -> str:
379386
"""Converts a list into an XML string."""
380-
LOG.info(f'Inside convert_list(): type(items)="{type(items).__name__}"')
381-
# avoid cpu consuming object serialization => extra if
382-
if LOG.getEffectiveLevel() <= logging.DEBUG:
383-
LOG.debug(f' items="{str(items)}"')
387+
if DEBUGMODE: # pragma: no cover
388+
LOG.info(f'Inside convert_list(): type(items)="{type(items).__name__}"')
389+
# avoid cpu consuming object serialization => extra if
390+
if LOG.getEffectiveLevel() <= logging.DEBUG:
391+
LOG.debug(f' items="{str(items)}"')
384392

385393
output: List[str] = []
386394
addline = output.append
@@ -393,12 +401,13 @@ def convert_list(
393401
this_id = get_unique_id(parent)
394402

395403
for i, item in enumerate(items):
396-
LOG.info(
397-
f'Looping inside convert_list(): index="{str(i)}", type="{type(item).__name__}"'
398-
)
399-
# avoid cpu consuming object serialization => extra if
400-
if LOG.getEffectiveLevel() <= logging.DEBUG:
401-
LOG.debug(f' item="{str(item)}"')
404+
if DEBUGMODE: # pragma: no cover
405+
LOG.info(
406+
f'Looping inside convert_list(): index="{str(i)}", type="{type(item).__name__}"'
407+
)
408+
# avoid cpu consuming object serialization => extra if
409+
if LOG.getEffectiveLevel() <= logging.DEBUG:
410+
LOG.debug(f' item="{str(item)}"')
402411

403412
attr = {} if not ids else {"id": f"{this_id}_{i + 1}"}
404413

@@ -474,9 +483,10 @@ def convert_kv(
474483
cdata: bool = False,
475484
) -> str:
476485
"""Converts a number or string into an XML element"""
477-
LOG.info(
478-
f'Inside convert_kv(): key="{str(key)}", val="{str(val)}", type(val) is: "{type(val).__name__}"'
479-
)
486+
if DEBUGMODE: # pragma: no cover
487+
LOG.info(
488+
f'Inside convert_kv(): key="{str(key)}", val="{str(val)}", type(val) is: "{type(val).__name__}"'
489+
)
480490
key, attr = make_valid_xml_name(key, attr)
481491

482492
if attr_type:
@@ -489,9 +499,10 @@ def convert_bool(
489499
key: str, val: bool, attr_type: bool, attr: Dict[str, Any] = {}, cdata: bool = False
490500
) -> str:
491501
"""Converts a boolean into an XML element"""
492-
LOG.info(
493-
f'Inside convert_bool(): key="{str(key)}", val="{str(val)}", type(val) is: "{type(val).__name__}"'
494-
)
502+
if DEBUGMODE: # pragma: no cover
503+
LOG.info(
504+
f'Inside convert_bool(): key="{str(key)}", val="{str(val)}", type(val) is: "{type(val).__name__}"'
505+
)
495506
key, attr = make_valid_xml_name(key, attr)
496507

497508
if attr_type:
@@ -504,7 +515,6 @@ def convert_none(
504515
key: str, attr_type: bool, attr: Dict[str, Any] = {}, cdata: bool = False
505516
) -> str:
506517
"""Converts a null value into an XML element"""
507-
# LOG.info(f'Inside convert_none(): key="{str(key)}" val={type(val)}')
508518
key, attr = make_valid_xml_name(key, attr)
509519

510520
if attr_type:
@@ -554,12 +564,13 @@ def dicttoxml(
554564
{'list': {'@attrs': {'a':'b','c':'d'}, '@val': [4, 5, 6]}
555565
which results in <list a="b" c="d"><item>4</item><item>5</item><item>6</item></list>
556566
"""
557-
LOG.info(
558-
f'Inside dicttoxml(): type(obj) is: "{type(obj).__name__}", type(ids") is : {type(ids).__name__}'
559-
)
560-
# avoid cpu consuming object serialization (problem for large objects) => extra if
561-
if LOG.getEffectiveLevel() <= logging.DEBUG:
562-
LOG.debug(f' obj="{str(obj)}"')
567+
if DEBUGMODE: # pragma: no cover
568+
LOG.info(
569+
f'Inside dicttoxml(): type(obj) is: "{type(obj).__name__}", type(ids") is : {type(ids).__name__}'
570+
)
571+
# avoid cpu consuming object serialization (problem for large objects) => extra if
572+
if LOG.getEffectiveLevel() <= logging.DEBUG:
573+
LOG.debug(f' obj="{str(obj)}"')
563574

564575
output = []
565576
namespacestr = ""

tests/test_json2xml.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ def test_item_wrap(self):
9898
xmldata = json2xml.Json2xml(data, pretty=False).to_xml()
9999
old_dict = xmltodict.parse(xmldata)
100100
# item must be present within my_items
101-
print(xmldata)
102101
assert "item" in old_dict['all']['my_items']
103102
assert "item" in old_dict['all']['my_str_items']
104103

@@ -109,7 +108,6 @@ def test_no_item_wrap(self):
109108
xmldata = json2xml.Json2xml(data, pretty=False, item_wrap=False).to_xml()
110109
old_dict = xmltodict.parse(xmldata)
111110
# my_item must be present within my_items
112-
print(xmldata)
113111
assert "my_item" in old_dict['all']['my_items']
114112
assert "my_str_items" in old_dict['all']
115113

@@ -119,7 +117,6 @@ def test_empty_array(self):
119117
)
120118
xmldata = json2xml.Json2xml(data, pretty=False).to_xml()
121119
old_dict = xmltodict.parse(xmldata)
122-
print(xmldata)
123120
# item empty_list be present within all
124121
assert "empty_list" in old_dict['all']
125122

@@ -129,7 +126,6 @@ def test_attrs(self):
129126
)
130127
xmldata = json2xml.Json2xml(data, pretty=False).to_xml()
131128
old_dict = xmltodict.parse(xmldata)
132-
print(xmldata)
133129
# test all attrs
134130
assert "str" == old_dict['all']['my_string']['@type']
135131
assert "int" == old_dict['all']['my_int']['@type']
@@ -181,9 +177,7 @@ def test_read_boolean_data_from_json(self):
181177
"""Test correct return for boolean types."""
182178
data = readfromjson("examples/booleanjson.json")
183179
result = json2xml.Json2xml(data).to_xml()
184-
print(result)
185180
dict_from_xml = xmltodict.parse(result)
186-
print(dict_from_xml)
187181
assert dict_from_xml["all"]["boolean"]["#text"] != 'True'
188182
assert dict_from_xml["all"]["boolean"]["#text"] == 'true'
189183
assert dict_from_xml["all"]["boolean_dict_list"]["item"][0]["boolean_dict"]["boolean"]["#text"] == 'true'
@@ -195,9 +189,7 @@ def test_read_boolean_data_from_json2(self):
195189
"""Test correct return for boolean types."""
196190
data = readfromjson("examples/booleanjson2.json")
197191
result = json2xml.Json2xml(data).to_xml()
198-
print(result)
199192
dict_from_xml = xmltodict.parse(result)
200-
print(dict_from_xml)
201193
assert dict_from_xml["all"]["boolean_list"]["item"][0]["#text"] != 'True'
202194
assert dict_from_xml["all"]["boolean_list"]["item"][0]["#text"] == 'true'
203195
assert dict_from_xml["all"]["boolean_list"]["item"][1]["#text"] == 'false'
@@ -212,7 +204,6 @@ def test_dict2xml_with_namespaces(self):
212204
data = {'ns1:node1': 'data in namespace 1', 'ns2:node2': 'data in namespace 2'}
213205
namespaces = {'ns1': 'http://www.google.de/ns1', 'ns2': 'http://www.google.de/ns2'}
214206
result = dicttoxml.dicttoxml(data, attr_type=False, xml_namespaces=namespaces)
215-
print(result)
216207
assert b'<?xml version="1.0" encoding="UTF-8" ?>' \
217208
b'<root xmlns:ns1="http://www.google.de/ns1" xmlns:ns2="http://www.google.de/ns2">' \
218209
b'<ns1:node1>data in namespace 1</ns1:node1>' \
@@ -222,7 +213,6 @@ def test_dict2xml_with_namespaces(self):
222213
def test_dict2xml_with_flat(self):
223214
data = {'flat_list@flat': [1, 2, 3], 'non_flat_list': [4, 5, 6]}
224215
result = dicttoxml.dicttoxml(data, attr_type=False)
225-
print(result)
226216
assert b'<?xml version="1.0" encoding="UTF-8" ?>' \
227217
b'<root><item>1</item><item>2</item><item>3</item>' \
228218
b'<non_flat_list><item>4</item><item>5</item><item>6</item></non_flat_list>' \
@@ -232,7 +222,6 @@ def test_dict2xml_with_val_and_custom_attr(self):
232222
# in order to use @attr in non-dict objects, we need to lift into a dict and combine with @val as key
233223
data = {'list1': [1, 2, 3], 'list2': {'@attrs': {'myattr1': 'myval1', 'myattr2': 'myval2'}, '@val': [4, 5, 6]}}
234224
result = dicttoxml.dicttoxml(data, attr_type=False)
235-
print(result)
236225
assert b'<?xml version="1.0" encoding="UTF-8" ?>' \
237226
b'<root><list1><item>1</item><item>2</item><item>3</item></list1>' \
238227
b'<list2 myattr1="myval1" myattr2="myval2"><item>4</item><item>5</item><item>6</item></list2>' \

0 commit comments

Comments
 (0)