Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Unified Diff: tools/metrics/common/models.py

Issue 925753002: Add pretty printing for rappor.xml (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/metrics/actions/extract_actions.py ('k') | tools/metrics/common/presubmit_util.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/metrics/common/models.py
diff --git a/tools/metrics/common/models.py b/tools/metrics/common/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ba301c4eec8bfd368f0d983c9c24c7cb47ef4aa
--- /dev/null
+++ b/tools/metrics/common/models.py
@@ -0,0 +1,214 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Model types for describing description xml models."""
+
+from xml.dom import minidom
+
+import sys
+import os
+
+import pretty_print_xml
+
+
+def GetComments(node):
+ """Extracts comments in the current node.
+
+ Args:
+ node: The DOM node to extract comments from.
+ Returns:
+ A list of comment DOM nodes.
+ """
+ return [n for n in node.childNodes if n.nodeType == minidom.Node.COMMENT_NODE]
+
+
+def PutComments(node, comments):
+ """Append comments to the DOM node.
+
+ Args:
+ node: The DOM node to write comments to.
+ comments: A list of comment DOM nodes.
+ """
+ for n in comments:
+ node.appendChild(n)
+
+
+class NodeType(object):
+ """Base type for a type of XML node.
+
+ Args:
+ dont_indent: True iff this node should not have it's children indented
+ when pretty printing.
+ extra_newlines: None or a triple of integers describing the number of
+ newlines that should be printed (after_open, before_close, after_close)
+ single_line: True iff this node may be squashed into a single line.
+ """
+ def __init__(self, tag,
+ dont_indent=False,
+ extra_newlines=None,
+ single_line=False):
+ self.tag = tag
+ self.dont_indent = dont_indent
+ self.extra_newlines = extra_newlines
+ self.single_line = single_line
+
+ def Unmarshall(self, node):
+ return None
+
+ def Marshall(self, doc, obj):
+ return None
+
+ def GetAttributes(self):
+ return []
+
+ def GetNodeTypes(self):
+ return {self.tag: self}
+
+
+class TextNodeType(NodeType):
+ """A type for simple nodes that just have a tag and some text content.
+
+ Unmarshalls nodes to strings.
+
+ Args:
+ tag: The name of XML tag for this type of node.
+ """
+ def __init__(self, tag, **kwargs):
+ NodeType.__init__(self, tag, **kwargs)
+
+ def __str__(self):
+ return 'TextNodeType("%s")' % self.tag
+
+ def Unmarshall(self, node):
+ return node.firstChild.nodeValue.strip()
+
+ def Marshall(self, doc, obj):
+ node = doc.createElement(self.tag)
+ node.appendChild(doc.createTextNode(obj))
+ return node
+
+
+class ChildType(object):
+ """Metadata about a nodes children.
+
+ Args:
+ attr: The field name of the parents model object storing the child's model.
+ node_type: The NodeType of the child.
+ multiple: True if the child can be repeated.
+ """
+ def __init__(self, attr, node_type, multiple):
+ self.attr = attr
+ self.node_type = node_type
+ self.multiple = multiple
+
+
+class ObjectNodeType(NodeType):
+ """A complex node type that has attributes or other nodes as children.
+
+ Unmarshalls nodes to objects.
+
+ Args:
+ tag: The name of XML tag for this type of node.
+ int_attributes: A list of names of integer attributes.
+ float_attributes: A list of names of float attributes.
+ string_attributes: A list of names of string attributes.
+ children: A list of ChildTypes describing the objects children.
+ """
+ def __init__(self, tag,
+ int_attributes=[],
+ float_attributes=[],
+ string_attributes=[],
+ children=[],
+ **kwargs):
+ NodeType.__init__(self, tag, **kwargs)
+ self.int_attributes = int_attributes
+ self.float_attributes = float_attributes
+ self.string_attributes = string_attributes
+ self.children = children
+
+ def __str__(self):
+ return 'ObjectNodeType("%s")' % self.tag
+
+ def Unmarshall(self, node):
+ obj = {}
+
+ obj['comments'] = GetComments(node)
+
+ for attr in self.int_attributes:
+ obj[attr] = int(node.getAttribute(attr))
+
+ for attr in self.float_attributes:
+ obj[attr] = float(node.getAttribute(attr))
+
+ for attr in self.string_attributes:
+ obj[attr] = node.getAttribute(attr)
+
+ for child in self.children:
+ nodes = node.getElementsByTagName(child.node_type.tag)
+ if child.multiple:
+ obj[child.attr] = [child.node_type.Unmarshall(n) for n in nodes]
+ else:
+ obj[child.attr] = child.node_type.Unmarshall(nodes[0])
+ return obj
+
+ def Marshall(self, doc, obj):
+ node = doc.createElement(self.tag)
+ attributes = (self.int_attributes +
+ self.float_attributes +
+ self.string_attributes)
+ for attr in attributes:
+ node.setAttribute(attr, str(obj[attr]))
+
+ PutComments(node, obj['comments'])
+
+ for child in self.children:
+ if child.multiple:
+ for o in obj[child.attr]:
+ node.appendChild(child.node_type.Marshall(doc, o))
+ else:
+ node.appendChild(child.node_type.Marshall(doc, obj[child.attr]))
+ return node
+
+ def GetAttributes(self):
+ return self.int_attributes + self.float_attributes + self.string_attributes
+
+ def GetNodeTypes(self):
+ types = {self.tag: self}
+ for child in self.children:
+ types.update(child.node_type.GetNodeTypes())
+ return types
+
+
+class DocumentType(object):
+ """Model for the root of an XML description file.
+
+ Args:
+ root_type: A NodeType describing the root tag of the document.
+ """
+ def __init__(self, root_type):
+ self.root_type = root_type
+
+ def Parse(self, input_file):
+ tree = minidom.parseString(input_file)
+ comments = GetComments(tree)
+ return comments, self.root_type.Unmarshall(
+ tree.getElementsByTagName(self.root_type.tag)[0])
+
+ def GetPrintStyle(self):
+ types = self.root_type.GetNodeTypes()
+ return pretty_print_xml.XmlStyle(
+ {t: types[t].GetAttributes() for t in types},
+ {t: types[t].extra_newlines for t in types if types[t].extra_newlines},
+ [t for t in types if types[t].dont_indent],
+ [t for t in types if types[t].single_line])
+
+ def ToXML(self, comments, obj):
+ doc = minidom.Document()
+ for comment in comments:
+ doc.appendChild(comment)
+ doc.appendChild(self.root_type.Marshall(doc, obj))
+ return doc
+
+ def PrettyPrint(self, comments, obj):
+ return self.GetPrintStyle().PrettyPrintNode(self.ToXML(comments, obj))
« no previous file with comments | « tools/metrics/actions/extract_actions.py ('k') | tools/metrics/common/presubmit_util.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698