diff sat/tools/xml_tools.py @ 3472:e12e9e1535d3

tools (xml_tools): new `dataForm2dataDict` and `dataDict2dataForm`: those methods convert a serialisable dict format to `wokkel.data_form.Form` and vice versa
author Goffi <goffi@goffi.org>
date Sat, 27 Feb 2021 18:36:38 +0100
parents 80f8635dc66e
children be6d91572633
line wrap: on
line diff
--- a/sat/tools/xml_tools.py	Sat Feb 27 18:33:53 2021 +0100
+++ b/sat/tools/xml_tools.py	Sat Feb 27 18:36:38 2021 +0100
@@ -194,6 +194,92 @@
     return dataForm2Widgets(form_ui, form, read_only=read_only)
 
 
+def dataForm2dataDict(form: data_form.Form) -> dict:
+    """Convert data form to a simple dict, easily serialisable
+
+    see dataDict2dataForm for a description of the format
+    """
+    fields = []
+    data_dict = {
+        "fields": fields
+    }
+    if form.formNamespace:
+        data_dict["namespace"] = form.formNamespace
+    for form_field in form.fieldList:
+        field = {"type": form_field.fieldType}
+        fields.append(field)
+        for src_name, dest_name in (
+            ('var', 'name'),
+            ('label', 'label'),
+            ('value', 'value'),
+        ):
+            value = getattr(form_field, src_name, None)
+            if value:
+                field[dest_name] = value
+        if form_field.options:
+            options = field["options"] = []
+            for form_opt in form_field.options:
+                opt = {"value": form_opt.value}
+                if form_opt.label:
+                    opt["label"] = form_opt.label
+                options.append(opt)
+
+        if form_field.fieldType is None and form_field.ext_type == "xml":
+            if isinstance(form_field.value, domish.Element):
+                if ((form_field.value.uri == C.NS_XHTML
+                     and form_field.value.name == "div")):
+                    field["type"] = "xhtml"
+                    if form_field.value.children:
+                        log.warning(
+                            "children are not managed for XHTML fields: "
+                            f"{form_field.value.toXml()}"
+                        )
+    return data_dict
+
+
+def dataDict2dataForm(data_dict):
+    """Convert serialisable dict of data to a data form
+
+    The format of the dict is as follow:
+        - an optional "namespace" key with form namespace
+        - a mandatory "fields" key with list of fields as follow:
+            - "type" is mostly the same as data_form.Field.fieldType
+            - "var", "label", and "value" follow same attribude in data_form.Field
+            - "xhtml" is used for "xml" fields with child in the C.NS_XHTML namespace
+            - "options" are list of dict with optional "label" and mandatory "value"
+              following suitable attributes from data_form.Option
+    """
+    # TODO: describe format
+    fields = []
+    for field_data in data_dict["fields"]:
+        field_type = field_data.get('type', 'text-single')
+        kwargs = {
+            "fieldType": field_type,
+            "var": field_data["name"],
+            "label": field_data.get('label'),
+            "value": field_data.get("value"),
+        }
+        if field_type == "xhtml":
+            kwargs.update({
+                "fieldType": None,
+                "ext_type": "xml",
+            })
+            if kwargs["value"] is None:
+                kwargs["value"] = domish.Element((C.NS_XHTML, "div"))
+        elif "options" in field_data:
+            kwargs["options"] = [
+                data_form.Option(o["value"], o.get("label"))
+                for o in field_data["options"]
+            ]
+        field = data_form.Field(**kwargs)
+        fields.append(field)
+    return data_form.Form(
+        "form",
+        formNamespace=data_dict.get("namespace"),
+        fields=fields
+    )
+
+
 def dataFormEltResult2XMLUIData(form_xml):
     """Parse a data form result (not parsed by Wokkel's XEP-0004 implementation).