diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-01-01 12:09:30 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-01-01 12:09:30 +0400 |
commit | e32e6004e43d22f215cb279de482b655a5007b4f (patch) | |
tree | 74785d7f0fbf6b0bfa5690a62fd2dff4e36e0788 /release/scripts/modules/rna_xml.py | |
parent | 6a1643ec1251adb1be06a250798987cbbe18d7fd (diff) |
add the ability to read from XML into RNA for rna_xml module
Diffstat (limited to 'release/scripts/modules/rna_xml.py')
-rw-r--r-- | release/scripts/modules/rna_xml.py | 212 |
1 files changed, 153 insertions, 59 deletions
diff --git a/release/scripts/modules/rna_xml.py b/release/scripts/modules/rna_xml.py index b36d433f87b..80c663de33e 100644 --- a/release/scripts/modules/rna_xml.py +++ b/release/scripts/modules/rna_xml.py @@ -20,27 +20,16 @@ # <pep8 compliant> - import bpy -# easier to read -PRETTY_INTEND = True - -invalid_classes = ( - bpy.types.Operator, - bpy.types.Panel, - bpy.types.KeyingSet, - bpy.types.Header, - ) - -def build_property_typemap(): +def build_property_typemap(skip_classes): property_typemap = {} for attr in dir(bpy.types): cls = getattr(bpy.types, attr) - if issubclass(cls, invalid_classes): + if issubclass(cls, skip_classes): continue properties = cls.bl_rna.properties.keys() @@ -54,9 +43,31 @@ def print_ln(data): print(data, end="") -def rna2xml(fw=print_ln, ident_val=" "): +def rna2xml(fw=print_ln, + root_node="", + root_rna=None, # must be set + root_rna_skip=set(), + ident_val=" ", + skip_classes=(bpy.types.Operator, + bpy.types.Panel, + bpy.types.KeyingSet, + bpy.types.Header, + ), + pretty_format=True, + method='DATA'): + from xml.sax.saxutils import quoteattr - property_typemap = build_property_typemap() + property_typemap = build_property_typemap(skip_classes) + + def number_to_str(val, val_type): + if val_type == int: + return "%d" % val + elif val_type == float: + return "%.6g" % val + elif val_type == bool: + return "TRUE" if val else "FALSE" + else: + raise NotImplemented("this type is not a number %s" % val_type) def rna2xml_node(ident, value, parent): ident_next = ident + ident_val @@ -68,7 +79,7 @@ def rna2xml(fw=print_ln, ident_val=" "): value_type = type(value) - if issubclass(value_type, invalid_classes): + if issubclass(value_type, skip_classes): return # XXX, fixme, pointcache has eternal nested pointer to its self. @@ -81,12 +92,8 @@ def rna2xml(fw=print_ln, ident_val=" "): subvalue = getattr(value, prop) subvalue_type = type(subvalue) - if subvalue_type == int: - node_attrs.append("%s=\"%d\"" % (prop, subvalue)) - elif subvalue_type == float: - node_attrs.append("%s=\"%.4g\"" % (prop, subvalue)) - elif subvalue_type == bool: - node_attrs.append("%s=\"%s\"" % (prop, "TRUE" if subvalue else "FALSE")) + if subvalue_type in (int, bool, float): + node_attrs.append("%s=\"%s\"" % (prop, number_to_str(subvalue, subvalue_type))) elif subvalue_type is str: node_attrs.append("%s=%s" % (prop, quoteattr(subvalue))) elif subvalue_type == set: @@ -95,7 +102,7 @@ def rna2xml(fw=print_ln, ident_val=" "): node_attrs.append("%s=\"NONE\"" % prop) elif issubclass(subvalue_type, bpy.types.ID): # special case, ID's are always referenced. - node_attrs.append("%s=%s" % (prop, quoteattr(subvalue_type.__name__ + ":" + subvalue.name))) + node_attrs.append("%s=%s" % (prop, quoteattr(subvalue_type.__name__ + "::" + subvalue.name))) else: try: subvalue_ls = list(subvalue) @@ -110,8 +117,9 @@ def rna2xml(fw=print_ln, ident_val=" "): if type(subvalue_rna).__name__ == "bpy_prop_array": # TODO, multi-dim! def str_recursive(s): - if type(s) in (int, float, bool): - return str(s) + subsubvalue_type = type(s) + if subsubvalue_type in (int, float, bool): + return number_to_str(s, subsubvalue_type) else: return " ".join([str_recursive(si) for si in s]) @@ -120,21 +128,22 @@ def rna2xml(fw=print_ln, ident_val=" "): nodes_lists.append((prop, subvalue_ls, subvalue_type)) # declare + attributes - if PRETTY_INTEND: + if pretty_format: tmp_str = "<%s " % value_type_name tmp_ident = "\n" + ident + (" " * len(tmp_str)) - + fw("%s%s%s>\n" % (ident, tmp_str, tmp_ident.join(node_attrs))) - + del tmp_str del tmp_ident else: fw("%s<%s %s>\n" % (ident, value_type_name, " ".join(node_attrs))) - # unique members for prop, subvalue, subvalue_type in nodes_items: - rna2xml_node(ident_next, subvalue, value) + fw("%s<%s>\n" % (ident_next, prop)) # XXX, this is awkward, how best to solve? + rna2xml_node(ident_next + ident_val, subvalue, value) + fw("%s</%s>\n" % (ident_next, prop)) # XXX, need to check on this. # list members for prop, subvalue, subvalue_type in nodes_lists: @@ -146,40 +155,125 @@ def rna2xml(fw=print_ln, ident_val=" "): fw("%s</%s>\n" % (ident, value_type_name)) - fw("<root>\n") - for attr in dir(bpy.data): + # ------------------------------------------------------------------------- + # needs re-workign to be generic - # exceptions - if attr.startswith("_"): - continue - elif attr == "window_managers": - continue + if root_node: + fw("<%s>\n" % root_node) + + # bpy.data + if method == 'DATA': + for attr in dir(root_rna): - value = getattr(bpy.data, attr) - try: - ls = value[:] - except: - ls = None + # exceptions + if attr.startswith("_"): + continue + elif attr in root_rna_skip: + continue - if type(ls) == list: - fw("%s<%s>\n" % (ident_val, attr)) - for blend_id in ls: - rna2xml_node(ident_val + ident_val, blend_id, None) - fw("%s</%s>\n" % (ident_val, attr)) + value = getattr(root_rna, attr) + try: + ls = value[:] + except: + ls = None - fw("</root>\n") + if type(ls) == list: + fw("%s<%s>\n" % (ident_val, attr)) + for blend_id in ls: + rna2xml_node(ident_val + ident_val, blend_id, None) + fw("%s</%s>\n" % (ident_val, attr)) + # any attribute + elif method == 'ATTR': + rna2xml_node("", root_rna, None) + if root_node: + fw("</%s>\n" % root_node) + + +def xml2rna(root_xml, + root_rna=None, # must be set + ): + + def rna2xml_node(xml_node, value): +# print("evaluating:", xml_node.nodeName) + + # --------------------------------------------------------------------- + # Simple attributes + + for attr in xml_node.attributes.keys(): +# print(" ", attr) + subvalue = getattr(value, attr, Ellipsis) + + if subvalue is Ellipsis: + print("%s.%s not found" % (type(value).__name__, attr)) + else: + value_xml = xml_node.attributes[attr].value + + subvalue_type = type(subvalue) + tp_name = 'UNKNOWN' + if subvalue_type == float: + value_xml_coerce = float(value_xml) + tp_name = 'FLOAT' + elif subvalue_type == int: + value_xml_coerce = int(value_xml) + tp_name = 'INT' + elif subvalue_type == bool: + value_xml_coerce = {'TRUE': True, 'FALSE': False}[value_xml] + tp_name = 'BOOL' + elif subvalue_type == str: + value_xml_coerce = value_xml + tp_name = 'STR' + elif hasattr(subvalue, "__len__"): + value_xml_split = value_xml.split() + try: + value_xml_coerce = [int(v) for v in value_xml_split] + except ValueError: + value_xml_coerce = [float(v) for v in value_xml_split] + tp_name = 'ARRAY' + +# print(" %s.%s (%s) --- %s" % (type(value).__name__, attr, tp_name, subvalue_type)) + setattr(value, attr, value_xml_coerce) + + # --------------------------------------------------------------------- + # Complex attributes + for child_xml in xml_node.childNodes: + if child_xml.nodeType == child_xml.ELEMENT_NODE: + # print() + # print(child_xml.nodeName) + subvalue = getattr(value, child_xml.nodeName, None) + if subvalue is not None: + + elems = [] + for child_xml_real in child_xml.childNodes: + if child_xml_real.nodeType == child_xml_real.ELEMENT_NODE: + elems.append(child_xml_real) + del child_xml_real + + if hasattr(subvalue, "__len__"): + # Collection + if len(elems) != len(subvalue): + print("Size Mismatch! collection:", child_xml.nodeName) + else: + for i in range(len(elems)): + child_xml_real = elems[i] + subsubvalue = subvalue[i] + + if child_xml_real is None or subsubvalue is None: + print("None found %s - %d collection:", (child_xml.nodeName, i)) + else: + rna2xml_node(child_xml_real, subsubvalue) + + else: +# print(elems) -def main(): - filename = bpy.data.filepath.rstrip(".blend") + ".xml" - file = open(filename, 'w') - rna2xml(file.write) - file.close() + if len(elems) == 1: + # sub node named by its type + child_xml_real, = elems - # read back. - from xml.dom.minidom import parse - xml_nodes = parse(filename) - print("Written:", filename) + # print(child_xml_real, subvalue) + rna2xml_node(child_xml_real, subvalue) + else: + # empty is valid too + pass -if __name__ == "__main__": - main() + rna2xml_node(root_xml, root_rna) |