From 8db23dba5f3565073a050c0d229e2499f65739d2 Mon Sep 17 00:00:00 2001 From: tapple Date: Fri, 16 Jan 2026 05:16:07 -0800 Subject: [PATCH 1/4] Make the output better match the xml files in sim/viewer --- llsd/serde_xml.py | 56 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/llsd/serde_xml.py b/llsd/serde_xml.py index 3833f57..1c00e47 100644 --- a/llsd/serde_xml.py +++ b/llsd/serde_xml.py @@ -69,13 +69,15 @@ class LLSDXMLFormatter(LLSDBaseFormatter): interface to this functionality. """ - def __init__(self, indent_atom = b'', eol = b''): + def __init__(self, indent_atom: bytes = b'', eol: bytes = b'', c_compat: bool = False, sort_maps: bool = False): "Construct a serializer." # Call the super class constructor so that we have the type map super(LLSDXMLFormatter, self).__init__() self._indent_atom = indent_atom self._eol = eol self._depth = 1 + self.c_compat = c_compat + self.sort_maps = sort_maps def _indent(self): pass @@ -85,13 +87,22 @@ def _LLSD(self, v): def _UNDEF(self, _v): self.stream.writelines([b'', self._eol]) def _BOOLEAN(self, v): - if v: - return self.stream.writelines([b'true', self._eol]) - self.stream.writelines([b'false', self._eol]) + if self.c_compat: + s = b'1' if v else b'0' + else: + s = b'true' if v else b'false' + self.stream.writelines([b'', s, b'', self._eol]) def _INTEGER(self, v): self.stream.writelines([b'', str(v).encode('utf-8'), b'', self._eol]) def _REAL(self, v): - self.stream.writelines([b'', str(v).encode('utf-8'), b'', self._eol]) + if self.c_compat: + if int(v) == v: + s = str(int(v)) + else: + s = f"{v:.25g}" + else: + s = str(v) + self.stream.writelines([b'', s.encode('utf-8'), b'', self._eol]) def _UUID(self, v): if v.int == 0: return self.stream.writelines([b'', self._eol]) @@ -124,7 +135,11 @@ def _ARRAY(self, v): def _MAP(self, v): self.stream.writelines([b'', self._eol]) self._depth += 1 - for key, value in v.items(): + keys = v.keys() + if self.sort_maps: + keys = sorted(keys) + for key in keys: + value = v[key] self._indent() if PY2: # pragma: no cover self.stream.writelines([b'', @@ -162,6 +177,7 @@ def _write(self, something): """ self.stream.writelines([b'', self._eol, b'', self._eol]) + self._indent() self._generate(something) self.stream.write(b'' + self._eol) @@ -179,17 +195,29 @@ class LLSDXMLPrettyFormatter(LLSDXMLFormatter): This class is not necessarily suited for serializing very large objects. It sorts on dict (llsd map) keys alphabetically to ease human reading. """ - def __init__(self, indent_atom = b' ', eol = b'\n'): + def __init__(self, indent_atom: bytes = b' ', eol: bytes = b'\n', c_compat: bool = False, sort_maps: bool = True): "Construct a pretty serializer." # Call the super class constructor so that we have the type map - super(LLSDXMLPrettyFormatter, self).__init__(indent_atom = indent_atom, eol = eol) + super(LLSDXMLPrettyFormatter, self).__init__(indent_atom = indent_atom, eol = eol, c_compat=c_compat, sort_maps = sort_maps) def _indent(self): "Write an indentation based on the atom and indentation level." self.stream.writelines([self._indent_atom] * self._depth) + def _ARRAY(self, v): + if not v: + self.stream.writelines([b'', self._eol]) + else: + super()._ARRAY(v) + + def _STRING(self, v): + if not v: + self.stream.writelines([b'', self._eol]) + else: + super()._STRING(v) + -def format_pretty_xml(something): +def format_pretty_xml(something, indent: int = 4, c_compat: bool = False, sort_maps: bool = True): """ Serialize a python object as 'pretty' application/llsd+xml. @@ -205,10 +233,10 @@ def format_pretty_xml(something): objects. It sorts on dict (llsd map) keys alphabetically to ease human reading. """ - return LLSDXMLPrettyFormatter().format(something) + return LLSDXMLPrettyFormatter(indent_atom=b' '*indent, c_compat=c_compat, sort_maps=sort_maps).format(something) -def write_pretty_xml(stream, something): +def write_pretty_xml(stream, something, indent: int = 4, c_compat: bool = False, sort_maps: bool = True): """ Serialize to passed 'stream' the python object 'something' as 'pretty' application/llsd+xml. @@ -225,7 +253,7 @@ def write_pretty_xml(stream, something): objects. It sorts on dict (llsd map) keys alphabetically to ease human reading. """ - return LLSDXMLPrettyFormatter().write(stream, something) + return LLSDXMLPrettyFormatter(indent_atom=b' '*indent, c_compat=c_compat, sort_maps=sort_maps).write(stream, something) def parse_xml(something): @@ -274,7 +302,7 @@ def parse_xml_nohdr(baseparser): return _to_python(element[0]) -def format_xml(something): +def format_xml(something, c_compat = False, sort_maps = False): """ Format a python object as application/llsd+xml @@ -283,7 +311,7 @@ def format_xml(something): See http://wiki.secondlife.com/wiki/LLSD#XML_Serialization """ - return LLSDXMLFormatter().format(something) + return LLSDXMLFormatter(c_compat = c_compat, sort_maps = sort_maps).format(something) def write_xml(stream, something): From 95fd7e32216c646143b91df0c166fc2a8bd492ef Mon Sep 17 00:00:00 2001 From: tapple Date: Thu, 22 Jan 2026 08:45:31 -0800 Subject: [PATCH 2/4] fix python2.7 --- llsd/serde_xml.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/llsd/serde_xml.py b/llsd/serde_xml.py index 1c00e47..d5f5141 100644 --- a/llsd/serde_xml.py +++ b/llsd/serde_xml.py @@ -69,7 +69,7 @@ class LLSDXMLFormatter(LLSDBaseFormatter): interface to this functionality. """ - def __init__(self, indent_atom: bytes = b'', eol: bytes = b'', c_compat: bool = False, sort_maps: bool = False): + def __init__(self, indent_atom = b'', eol = b'', c_compat = False, sort_maps = False): "Construct a serializer." # Call the super class constructor so that we have the type map super(LLSDXMLFormatter, self).__init__() @@ -99,7 +99,7 @@ def _REAL(self, v): if int(v) == v: s = str(int(v)) else: - s = f"{v:.25g}" + s = "%.25g" % v else: s = str(v) self.stream.writelines([b'', s.encode('utf-8'), b'', self._eol]) @@ -195,7 +195,7 @@ class LLSDXMLPrettyFormatter(LLSDXMLFormatter): This class is not necessarily suited for serializing very large objects. It sorts on dict (llsd map) keys alphabetically to ease human reading. """ - def __init__(self, indent_atom: bytes = b' ', eol: bytes = b'\n', c_compat: bool = False, sort_maps: bool = True): + def __init__(self, indent_atom = b' ', eol = b'\n', c_compat = False, sort_maps = True): "Construct a pretty serializer." # Call the super class constructor so that we have the type map super(LLSDXMLPrettyFormatter, self).__init__(indent_atom = indent_atom, eol = eol, c_compat=c_compat, sort_maps = sort_maps) @@ -208,16 +208,16 @@ def _ARRAY(self, v): if not v: self.stream.writelines([b'', self._eol]) else: - super()._ARRAY(v) + super(LLSDXMLPrettyFormatter, self)._ARRAY(v) def _STRING(self, v): if not v: self.stream.writelines([b'', self._eol]) else: - super()._STRING(v) + super(LLSDXMLPrettyFormatter, self)._STRING(v) -def format_pretty_xml(something, indent: int = 4, c_compat: bool = False, sort_maps: bool = True): +def format_pretty_xml(something, indent = 4, c_compat = False, sort_maps = True): """ Serialize a python object as 'pretty' application/llsd+xml. @@ -236,7 +236,7 @@ def format_pretty_xml(something, indent: int = 4, c_compat: bool = False, sort_m return LLSDXMLPrettyFormatter(indent_atom=b' '*indent, c_compat=c_compat, sort_maps=sort_maps).format(something) -def write_pretty_xml(stream, something, indent: int = 4, c_compat: bool = False, sort_maps: bool = True): +def write_pretty_xml(stream, something, indent = 4, c_compat = False, sort_maps = True): """ Serialize to passed 'stream' the python object 'something' as 'pretty' application/llsd+xml. From 22b9a644d97a313b404b1d5ad30f71ef3f20ca6c Mon Sep 17 00:00:00 2001 From: tapple Date: Thu, 22 Jan 2026 08:47:26 -0800 Subject: [PATCH 3/4] fix unit tests --- llsd/serde_xml.py | 4 ++-- tests/llsd_test.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llsd/serde_xml.py b/llsd/serde_xml.py index d5f5141..cbb6182 100644 --- a/llsd/serde_xml.py +++ b/llsd/serde_xml.py @@ -217,7 +217,7 @@ def _STRING(self, v): super(LLSDXMLPrettyFormatter, self)._STRING(v) -def format_pretty_xml(something, indent = 4, c_compat = False, sort_maps = True): +def format_pretty_xml(something, indent = 2, c_compat = False, sort_maps = True): """ Serialize a python object as 'pretty' application/llsd+xml. @@ -236,7 +236,7 @@ def format_pretty_xml(something, indent = 4, c_compat = False, sort_maps = True) return LLSDXMLPrettyFormatter(indent_atom=b' '*indent, c_compat=c_compat, sort_maps=sort_maps).format(something) -def write_pretty_xml(stream, something, indent = 4, c_compat = False, sort_maps = True): +def write_pretty_xml(stream, something, indent = 2, c_compat = False, sort_maps = True): """ Serialize to passed 'stream' the python object 'something' as 'pretty' application/llsd+xml. diff --git a/tests/llsd_test.py b/tests/llsd_test.py index 073a974..f2424a0 100644 --- a/tests/llsd_test.py +++ b/tests/llsd_test.py @@ -1520,7 +1520,7 @@ def testFormatPrettyXML(self): self.assertEqual(output_xml.decode("utf8"), """ - + id string1 From 1adb0bb67e3cc176761ce380b2f95b2f4b7c7ab6 Mon Sep 17 00:00:00 2001 From: tapple Date: Thu, 22 Jan 2026 10:26:08 -0800 Subject: [PATCH 4/4] fix unit tests --- tests/fixtures/viewer-autobuild.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fixtures/viewer-autobuild.xml b/tests/fixtures/viewer-autobuild.xml index 2e4397a..63d4596 100644 --- a/tests/fixtures/viewer-autobuild.xml +++ b/tests/fixtures/viewer-autobuild.xml @@ -1,6 +1,6 @@ - + installables SDL