diff options
| author | Stefan Behnel <stefan_ml@behnel.de> | 2019-03-01 15:11:50 +0100 |
|---|---|---|
| committer | Stefan Behnel <stefan_ml@behnel.de> | 2019-03-01 15:11:50 +0100 |
| commit | 8027c39cd60a40323eb2ffcfac6bbc102e317a53 (patch) | |
| tree | e4f8c698e7020f36f7cd37afb4743a66339be764 /src/lxml | |
| parent | b5c8cab47422346d8dd295afc0f70b956c9424b5 (diff) | |
| download | python-lxml-8027c39cd60a40323eb2ffcfac6bbc102e317a53.tar.gz | |
Keep the original dict insertion order in Py3.6+ when setting attributes or namespaces from a user provided dict.
This follows the ElementTree change in Py3.8, see https://bugs.python.org/issue34160.
Diffstat (limited to 'src/lxml')
| -rw-r--r-- | src/lxml/apihelpers.pxi | 17 | ||||
| -rw-r--r-- | src/lxml/objectify.pyx | 2 |
2 files changed, 15 insertions, 4 deletions
diff --git a/src/lxml/apihelpers.pxi b/src/lxml/apihelpers.pxi index cf932d43..5d410e60 100644 --- a/src/lxml/apihelpers.pxi +++ b/src/lxml/apihelpers.pxi @@ -244,6 +244,10 @@ cdef _iter_nsmap(nsmap): The difference to _iter_attrib() is that None doesn't sort with strings in Py3.x. """ + if python.PY_VERSION_HEX >= 0x03060000: + # dicts are insertion-ordered in Py3.6+ => keep the user provided order. + if isinstance(nsmap, dict): + return nsmap.items() if len(nsmap) <= 1: return nsmap.items() # nsmap will usually be a plain unordered dict => avoid type checking overhead @@ -271,7 +275,10 @@ cdef _iter_attrib(attrib): Tries to preserve an existing order and sorts if it assumes no order. """ # attrib will usually be a plain unordered dict - if type(attrib) is dict: + if isinstance(attrib, dict): + if python.PY_VERSION_HEX >= 0x03060000: + # dicts are insertion-ordered in Py3.6+ => keep the user provided order. + return attrib.items() return sorted(attrib.items()) elif isinstance(attrib, (_Attrib, OrderedDict)): return attrib.items() @@ -292,8 +299,12 @@ cdef _initNodeAttributes(xmlNode* c_node, _Document doc, attrib, dict extra): is_html = doc._parser._for_html seen = set() if extra: - for name, value in sorted(extra.items()): - _addAttributeToNode(c_node, doc, is_html, name, value, seen) + if python.PY_VERSION_HEX >= 0x03060000: + for name, value in extra.items(): + _addAttributeToNode(c_node, doc, is_html, name, value, seen) + else: + for name, value in sorted(extra.items()): + _addAttributeToNode(c_node, doc, is_html, name, value, seen) if attrib: for name, value in _iter_attrib(attrib): _addAttributeToNode(c_node, doc, is_html, name, value, seen) diff --git a/src/lxml/objectify.pyx b/src/lxml/objectify.pyx index f5fe7b51..9da49a1c 100644 --- a/src/lxml/objectify.pyx +++ b/src/lxml/objectify.pyx @@ -1327,7 +1327,7 @@ cdef object _dump(_Element element, int indent): result = f"{indentstr}{element.tag} = {value} [{_typename(element)}]\n" xsi_ns = u"{%s}" % XML_SCHEMA_INSTANCE_NS pytype_ns = u"{%s}" % PYTYPE_NAMESPACE - for name, value in cetree.iterattributes(element, 3): + for name, value in sorted(cetree.iterattributes(element, 3)): if u'{' in name: if name == PYTYPE_ATTRIBUTE: if value == TREE_PYTYPE_NAME: |
