Skip to content
Snippets Groups Projects
Commit b4d9430e authored by Scott Kitterman's avatar Scott Kitterman
Browse files

New upstream version 1.7.0

parent 7ee960c8
No related branches found
No related tags found
No related merge requests found
Metadata-Version: 2.1
Name: dict2xml
Version: 1.6.1
Summary: small script to output xml as a string from a python dictionary
Version: 1.7.0
Summary: Small utility to convert a python dictionary into an XML string
Home-page: http://github.com/delfick/python-dict2xml
Author: Stephen Moore
Author-email: stephen@delfick.com
......@@ -32,20 +32,21 @@ Description: dict2xml
.. code-block:: python
from dict2xml import dict2xml as xmlify
from dict2xml import dict2xml
data = {
'a' : 1
, 'b' : [2, 3]
, 'c' : {
'd' : [
{'p' : 9}
, {'o' : 10}
]
, 'e': 7
}
'a': 1,
'b': [2, 3],
'c': {
'd': [
{'p': 9},
{'o': 10}
],
'e': 7
}
}
print xmlify(data, wrap="all", indent=" ")
print dict2xml(data, wrap="all", indent=" ")
Output
------
......@@ -97,10 +98,16 @@ Description: dict2xml
Changelog
---------
1.6.1
1.7.0 - 16 April, 2020
* Use collections.abc to avoid deprecation warning. Thanks @mangin.
* This library no longer supports Python2 and is only supported for
Python3.6+. Note that the library should still work in Python3.5 as I
have not used f-strings, but the framework I use for the tests is only 3.6+.
1.6.1 - August 27, 2019
* Include readme and LICENSE in the package
1.6
1.6 - April 27, 2018
* No code changes
* changed the licence to MIT
* Added more metadata to pypi
......
......@@ -24,20 +24,21 @@ example
.. code-block:: python
from dict2xml import dict2xml as xmlify
from dict2xml import dict2xml
data = {
'a' : 1
, 'b' : [2, 3]
, 'c' : {
'd' : [
{'p' : 9}
, {'o' : 10}
]
, 'e': 7
}
'a': 1,
'b': [2, 3],
'c': {
'd': [
{'p': 9},
{'o': 10}
],
'e': 7
}
}
print xmlify(data, wrap="all", indent=" ")
print dict2xml(data, wrap="all", indent=" ")
Output
------
......@@ -89,10 +90,16 @@ Limitations
Changelog
---------
1.6.1
1.7.0 - 16 April, 2020
* Use collections.abc to avoid deprecation warning. Thanks @mangin.
* This library no longer supports Python2 and is only supported for
Python3.6+. Note that the library should still work in Python3.5 as I
have not used f-strings, but the framework I use for the tests is only 3.6+.
1.6.1 - August 27, 2019
* Include readme and LICENSE in the package
1.6
1.6 - April 27, 2018
* No code changes
* changed the licence to MIT
* Added more metadata to pypi
......
Metadata-Version: 2.1
Name: dict2xml
Version: 1.6.1
Summary: small script to output xml as a string from a python dictionary
Version: 1.7.0
Summary: Small utility to convert a python dictionary into an XML string
Home-page: http://github.com/delfick/python-dict2xml
Author: Stephen Moore
Author-email: stephen@delfick.com
......@@ -32,20 +32,21 @@ Description: dict2xml
.. code-block:: python
from dict2xml import dict2xml as xmlify
from dict2xml import dict2xml
data = {
'a' : 1
, 'b' : [2, 3]
, 'c' : {
'd' : [
{'p' : 9}
, {'o' : 10}
]
, 'e': 7
}
'a': 1,
'b': [2, 3],
'c': {
'd': [
{'p': 9},
{'o': 10}
],
'e': 7
}
}
print xmlify(data, wrap="all", indent=" ")
print dict2xml(data, wrap="all", indent=" ")
Output
------
......@@ -97,10 +98,16 @@ Description: dict2xml
Changelog
---------
1.6.1
1.7.0 - 16 April, 2020
* Use collections.abc to avoid deprecation warning. Thanks @mangin.
* This library no longer supports Python2 and is only supported for
Python3.6+. Note that the library should still work in Python3.5 as I
have not used f-strings, but the framework I use for the tests is only 3.6+.
1.6.1 - August 27, 2019
* Include readme and LICENSE in the package
1.6
1.6 - April 27, 2018
* No code changes
* changed the licence to MIT
* Added more metadata to pypi
......
LICENSE
MANIFEST.in
README.rst
pyproject.toml
readme.rst
setup.py
dict2xml/__init__.py
......
six
[tests]
fudge
noseOfYeti>=1.7.0
nose
noseOfYeti==2.0.1
pytest==5.3.1
from dict2xml.logic import Converter, Node
def dict2xml(data, *args, **kwargs):
"""Return an XML string of a Python dict object."""
return Converter(*args, **kwargs).build(data)
__all__ = ["dict2xml", "Converter", "Node"]
import collections.abc
import collections
import re
import six
NameStartChar = re.compile(
u"(:|[A-Z]|_|[a-z]|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\u02FF]|[\u0370-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD])",
re.UNICODE)
NameChar = re.compile(
u"(\-|\.|[0-9]|\xB7|[\u0300-\u036F]|[\u203F-\u2040])",
re.UNICODE)
start_ranges = "|".join(
"[{0}]".format(r)
for r in [
"\xC0-\xD6",
"\xD8-\xF6",
"\xF8-\u02FF",
"\u0370-\u037D",
"\u037F-\u1FFF",
"\u200C-\u200D",
"\u2070-\u218F",
"\u2C00-\u2FEF",
"\u3001-\uD7FF",
"\uF900-\uFDCF",
"\uFDF0-\uFFFD",
]
)
NameStartChar = re.compile(r"(:|[A-Z]|_|[a-z]|{0})".format(start_ranges))
NameChar = re.compile(r"(\-|\.|[0-9]|\xB7|[\u0300-\u036F]|[\u203F-\u2040])")
########################
### NODE
########################
class Node(object):
"""
Represents each tag in the tree
......@@ -32,7 +45,7 @@ class Node(object):
"""
# A mapping of characters to treat as escapable entities and their replacements
entities = [('&', '&amp;'), ('<', '&lt;'), ('>', '&gt;')]
entities = [("&", "&amp;"), ("<", "&lt;"), (">", "&gt;")]
def __init__(self, wrap="", tag="", data=None, iterables_repeat_wrap=True):
self.tag = self.sanitize_element(tag)
......@@ -41,7 +54,7 @@ class Node(object):
self.type = self.determine_type()
self.iterables_repeat_wrap = iterables_repeat_wrap
if self.type == 'flat' and isinstance(self.data, six.string_types):
if self.type == "flat" and isinstance(self.data, str):
# Make sure we deal with entities
for entity, replacement in self.entities:
self.data = self.data.replace(entity, replacement)
......@@ -52,8 +65,8 @@ class Node(object):
wrap = self.wrap
end, start = "", ""
if wrap:
end = "</%s>" % wrap
start = "<%s>" % wrap
end = "</{0}>".format(wrap)
start = "<{0}>".format(wrap)
# Convert the data attached in this node into a value and children
value, children = self.convert()
......@@ -70,13 +83,13 @@ class Node(object):
result = []
for c in children:
content = c.serialize(indenter)
if c.type == 'flat':
if c.type == "flat":
# Child with value, it already is surrounded by the tag
result.append(content)
else:
# Child with children of it's own, they need to be wrapped by start and end
content = indenter([content], True)
result.append(''.join((start, content, end)))
result.append("".join((start, content, end)))
# We already have what we want, return the indented result
return indenter(result, False)
......@@ -84,12 +97,12 @@ class Node(object):
result = []
for c in children:
result.append(c.serialize(indenter))
return ''.join([start, indenter(result, True), end])
return "".join([start, indenter(result, True), end])
# If here, either:
# * Have a value
# * Or this node is not an iterable
return ''.join((start, value, content, end))
return "".join((start, value, content, end))
def determine_type(self):
"""
......@@ -100,14 +113,14 @@ class Node(object):
* flat : A string or something that isn't iterable or a mapping
"""
data = self.data
if isinstance(data, six.string_types) or isinstance(data, six.text_type):
return 'flat'
elif isinstance(data, collections.Mapping):
return 'mapping'
elif isinstance(data, collections.Iterable):
return 'iterable'
if isinstance(data, str):
return "flat"
elif isinstance(data, collections.abc.Mapping):
return "mapping"
elif isinstance(data, collections.abc.Iterable):
return "iterable"
else:
return 'flat'
return "flat"
def convert(self):
"""
......@@ -122,23 +135,27 @@ class Node(object):
data = self.data
children = []
if typ == 'mapping':
if typ == "mapping":
sorted_data = data
if not isinstance(data, collections.OrderedDict):
sorted_data = sorted(data)
for key in sorted_data:
item = data[key]
children.append(Node(key, "", item, iterables_repeat_wrap=self.iterables_repeat_wrap))
children.append(
Node(key, "", item, iterables_repeat_wrap=self.iterables_repeat_wrap)
)
elif typ == 'iterable':
elif typ == "iterable":
for item in data:
children.append(Node("", self.wrap, item, iterables_repeat_wrap=self.iterables_repeat_wrap))
children.append(
Node("", self.wrap, item, iterables_repeat_wrap=self.iterables_repeat_wrap,)
)
else:
val = six.text_type(data)
val = str(data)
if self.tag:
val = "<%s>%s</%s>" % (self.tag, val, self.tag)
val = "<{0}>{1}</{2}>".format(self.tag, val, self.tag)
return val, children
......@@ -155,23 +172,26 @@ class Node(object):
:ref: http://www.w3.org/TR/REC-xml/#NT-NameChar
"""
if wrap and isinstance(wrap, six.string_types):
if wrap.lower().startswith('xml'):
wrap = '_' + wrap
return ''.join(
['_' if not NameStartChar.match(wrap) else ''] + \
['_' if not (NameStartChar.match(c) or NameChar.match(c)) else c
for c in wrap])
if wrap and isinstance(wrap, str):
if wrap.lower().startswith("xml"):
wrap = "_" + wrap
return "".join(
["_" if not NameStartChar.match(wrap) else ""]
+ ["_" if not (NameStartChar.match(c) or NameChar.match(c)) else c for c in wrap]
)
else:
return wrap
########################
### CONVERTER
########################
class Converter(object):
"""Logic for creating a Node tree and serialising that tree into a string"""
def __init__(self, wrap=None, indent=' ', newlines=True):
def __init__(self, wrap=None, indent=" ", newlines=True):
"""
wrap: The tag that the everything else will be contained within
indent: The string that is multiplied at the start of each new line, to represent each level of nesting
......@@ -198,7 +218,7 @@ class Converter(object):
def eachline(nodes):
"""Yield each line in each node"""
for node in nodes:
for line in node.split('\n'):
for line in node.split("\n"):
yield line
def ret(nodes, wrapped):
......@@ -210,17 +230,18 @@ class Converter(object):
and indent each line in the child by one indent unit
"""
if wrapped:
seperator = "\n%s" % indent
surrounding = "\n%s%%s\n" % indent
seperator = "\n{0}".format(indent)
surrounding = "\n{0}{{0}}\n".format(indent)
else:
seperator = "\n"
surrounding = "%s"
return surrounding % seperator.join(eachline(nodes))
surrounding = "{0}"
return surrounding.format(seperator.join(eachline(nodes)))
return ret
def build(self, data, iterables_repeat_wrap=True):
"""Create a Node tree from the data and return it as a serialized xml string"""
indenter = self._make_indenter()
return Node(wrap=self.wrap, data=data, iterables_repeat_wrap=iterables_repeat_wrap).serialize(indenter)
return Node(
wrap=self.wrap, data=data, iterables_repeat_wrap=iterables_repeat_wrap
).serialize(indenter)
[tool.black]
line-length = 100
include = '\.py$'
exclude = '''
/(
\.git
| \.tox
| dist
| tools
)/
'''
from setuptools import setup
# fmt: off
# Setup the project
setup(
name = "dict2xml"
, version = '1.6.1'
, version = '1.7.0'
, packages = ['dict2xml']
, extras_require =
{ 'tests' :
[ 'fudge'
, 'noseOfYeti>=1.7.0'
, 'nose'
[ "noseOfYeti==2.0.1"
, "pytest==5.3.1"
]
}
, install_requires =
[ "six"
]
, classifiers =
[ "Development Status :: 5 - Production/Stable"
, "License :: OSI Approved :: MIT License"
......@@ -33,8 +30,9 @@ setup(
, url = "http://github.com/delfick/python-dict2xml"
, author = "Stephen Moore"
, author_email = "stephen@delfick.com"
, description = "small script to output xml as a string from a python dictionary"
, description = "Small utility to convert a python dictionary into an XML string"
, long_description = open("README.rst").read()
, license = "MIT"
)
# fmt: on
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment