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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Model types for describing description xml models."""
6
7 from xml.dom import minidom
8
9 import sys
10 import os
11
12 import pretty_print_xml
13
14
15 def GetComments(node):
Alexei Svitkine (slow) 2015/02/13 14:36:37 I think we have some server-side code that mirrors
Steven Holte 2015/02/14 01:11:18 I haven't refactored any existing code to use the
16 """Extracts comments in the current node.
17
18 Args:
19 node: The DOM node to extract comments from.
20 Returns:
21 A list of comment DOM nodes.
22 """
23 return [n for n in node.childNodes if n.nodeType == minidom.Node.COMMENT_NODE]
24
25
26 def PutComments(node, comments):
27 """Append comments to the DOM node.
28
29 Args:
30 node: The DOM node to write comments to.
31 comments: A list of comment DOM nodes.
32 """
33 for n in comments:
34 node.appendChild(n)
35
36
37 class NodeType(object):
38 """Base type for a type of XML node.
39
40 Args:
41 dont_indent: True iff this node should not have it's children indented
42 when pretty printing.
43 extra_newlines: None or a triple of integers describing the number of
44 newlines that should be printed (after_open, before_close, after_close)
45 single_line: True iff this node may be squashed into a single line.
46 """
47 def __init__(self, tag,
48 dont_indent=False,
49 extra_newlines=None,
50 single_line=False):
51 self.tag = tag
52 self.dont_indent = dont_indent
53 self.extra_newlines = extra_newlines
54 self.single_line = single_line
55
56 def Unmarshall(self, node):
57 return None
58
59 def Marshall(self, doc, obj):
60 return None
61
62 def GetAttributes(self):
63 return []
64
65 def GetNodeTypes(self):
66 return {self.tag: self}
67
68
69 class TextNodeType(NodeType):
70 """A type for simple nodes that just have a tag and some text content.
71
72 Unmarshalls nodes to strings.
73
74 Args:
75 tag: The name of XML tag for this type of node.
76 """
77 def __init__(self, tag, **kwargs):
78 NodeType.__init__(self, tag, **kwargs)
79
80 def __str__(self):
81 return 'TextNodeType("%s")' % self.tag
82
83 def Unmarshall(self, node):
84 return node.firstChild.nodeValue.strip()
85
86 def Marshall(self, doc, obj):
87 node = doc.createElement(self.tag)
88 node.appendChild(doc.createTextNode(obj))
89 return node
90
91
92 class ChildType(object):
93 """Metadata about a nodes children.
94
95 Args:
96 attr: The field name of the parents model object storing the child's model.
97 node_type: The NodeType of the child.
98 multiple: True if the child can be repeated.
99 """
100 def __init__(self, attr, node_type, multiple):
101 self.attr = attr
102 self.node_type = node_type
103 self.multiple = multiple
104
105
106 class ObjectNodeType(NodeType):
107 """A complex node type that has attributes or other nodes as children.
108
109 Unmarshalls nodes to objects.
110
111 Args:
112 tag: The name of XML tag for this type of node.
113 int_attributes: A list of names of integer attributes.
114 float_attributes: A list of names of float attributes.
115 string_attributes: A list of names of string attributes.
116 children: A list of ChildTypes describing the objects children.
117 """
118 def __init__(self, tag,
119 int_attributes=[],
120 float_attributes=[],
121 string_attributes=[],
122 children=[],
123 **kwargs):
124 NodeType.__init__(self, tag, **kwargs)
125 self.int_attributes = int_attributes
126 self.float_attributes = float_attributes
127 self.string_attributes = string_attributes
128 self.children = children
129
130 def __str__(self):
131 return 'ObjectNodeType("%s")' % self.tag
132
133 def Unmarshall(self, node):
134 obj = {}
135
136 obj['comments'] = GetComments(node)
137
138 for attr in self.int_attributes:
139 obj[attr] = int(node.getAttribute(attr))
140
141 for attr in self.float_attributes:
142 obj[attr] = float(node.getAttribute(attr))
143
144 for attr in self.string_attributes:
145 obj[attr] = node.getAttribute(attr)
146
147 for child in self.children:
148 nodes = node.getElementsByTagName(child.node_type.tag)
149 if child.multiple:
150 obj[child.attr] = [child.node_type.Unmarshall(n) for n in nodes]
151 else:
152 obj[child.attr] = child.node_type.Unmarshall(nodes[0])
153 return obj
154
155 def Marshall(self, doc, obj):
156 node = doc.createElement(self.tag)
157 attributes = (self.int_attributes +
158 self.float_attributes +
159 self.string_attributes)
160 for attr in attributes:
161 node.setAttribute(attr, str(obj[attr]))
162
163 PutComments(node, obj['comments'])
164
165 for child in self.children:
166 if child.multiple:
167 for o in obj[child.attr]:
168 node.appendChild(child.node_type.Marshall(doc, o))
169 else:
170 node.appendChild(child.node_type.Marshall(doc, obj[child.attr]))
171 return node
172
173 def GetAttributes(self):
174 return self.int_attributes + self.float_attributes + self.string_attributes
175
176 def GetNodeTypes(self):
177 types = {self.tag: self}
178 for child in self.children:
179 types.update(child.node_type.GetNodeTypes())
180 return types
181
182
183 class DocumentType(object):
184 """Model for the root of an XML description file.
185
186 Args:
187 root_type: A NodeType describing the root tag of the document.
188 """
189 def __init__(self, root_type):
190 self.root_type = root_type
191
192 def Parse(self, input_file):
193 tree = minidom.parseString(input_file)
194 comments = GetComments(tree)
195 return comments, self.root_type.Unmarshall(
196 tree.getElementsByTagName(self.root_type.tag)[0])
197
198 def GetPrintStyle(self):
199 types = self.root_type.GetNodeTypes()
200 return pretty_print_xml.XmlStyle(
201 {t: types[t].GetAttributes() for t in types},
202 {t: types[t].extra_newlines for t in types if types[t].extra_newlines},
203 [t for t in types if types[t].dont_indent],
204 [t for t in types if types[t].single_line])
205
206 def ToXML(self, comments, obj):
207 doc = minidom.Document()
208 for comment in comments:
209 doc.appendChild(comment)
210 doc.appendChild(self.root_type.Marshall(doc, obj))
211 return doc
212
213 def PrettyPrint(self, comments, obj):
214 return self.GetPrintStyle().PrettyPrintNode(self.ToXML(comments, obj))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698