# -*- coding: utf-8 -*- # # Copyright 2019-2020 Fabien Bourgeois # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . """ XML helpers and macros """ from os import path import xml.etree.ElementTree as ET from xml.dom import minidom from collections import namedtuple from functools import partial XMLDictElement = namedtuple('XMLDictElement', ['tag', 'attrs', 'children']) def xmlroot(tree): """ Special process for root XML Node """ rootel = ET.Element(tree['tag'], tree['attrs']) if 'children' in tree: xmlchild(rootel, tree['children']) return rootel def xmlchild(parent, children): """ Handling of children (ie non root) XML Nodes with/o text and subchildren (recursive) """ if isinstance(children, str): parent.text = children elif isinstance(children, XMLDictElement): attrs = {unicode(k): unicode(v) for [k, v] in children.attrs.items()} new_parent = ET.SubElement(parent, children.tag, attrs) subchildren = children.children if subchildren: xmlchild(new_parent, subchildren) elif isinstance(children, list): map(partial(xmlchild, parent), children) else: raise TypeError('Invalid arguments for xmlchild') def xmln(tag='', attrs={}, children=[]): """ XMLDictElement building from dict object, with defaults """ if isinstance(attrs, list): children = attrs attrs = {} xmldictel = partial(XMLDictElement, tag, attrs) if isinstance(children, str): return xmldictel([children]) if isinstance(children, list): return xmldictel(children) raise TypeError('Invalid arguments for xmln') def xml_write(filepath, tree): """ Write XML file according to filename and given tree """ if filepath.endswith('.py'): # if .pyc, no need to generate XML output_xml = minidom.parseString(ET.tostring(tree)).toprettyxml(indent=' ') output_path = path.dirname(path.abspath(filepath)) fpath = u'/'.join([output_path, path.basename(filepath)]).replace('.py', '_views.xml') with open(fpath, 'w') as output_file: output_file.write(output_xml)