[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / tools / metrics / histograms / update_editor_commands.py
blob26afa2efcf54ed19002a5ae13d7cfee383460694
1 # Copyright 2014 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.
5 """Updates MappedEditingCommands enum in histograms.xml file with values read
6 from EditorCommand.cpp.
8 If the file was pretty-printed, the updated version is pretty-printed too.
9 """
11 import logging
12 import os
13 import re
14 import sys
16 from xml.dom import minidom
18 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common'))
19 from diff_util import PromptUserToAcceptDiff
20 import path_util
22 import print_style
24 HISTOGRAMS_PATH = path_util.GetHistogramsFile()
25 ENUM_NAME = 'MappedEditingCommands'
27 EDITOR_COMMAND_CPP = 'third_party/WebKit/Source/core/editing/EditorCommand.cpp'
28 ENUM_START_MARKER = "^ static const CommandEntry commands\[\] = {"
29 ENUM_END_MARKER = "^ };"
32 class UserError(Exception):
33 def __init__(self, message):
34 Exception.__init__(self, message)
36 @property
37 def message(self):
38 return self.args[0]
41 def ReadHistogramValues(filename):
42 """Returns a list of pairs (label, value) corresponding to HistogramValue.
44 Reads the EditorCommand.cpp file, locates the
45 HistogramValue enum definition and returns a pair for each entry.
46 """
48 # Read the file as a list of lines
49 with open(path_util.GetInputFile(filename)) as f:
50 content = f.readlines()
52 # Locate the enum definition and collect all entries in it
53 inside_enum = False # We haven't found the enum definition yet
54 result = []
55 for line in content:
56 if inside_enum:
57 # Exit condition: we reached last enum value
58 if re.match(ENUM_END_MARKER, line):
59 inside_enum = False
60 else:
61 # Inside enum: generate new xml entry
62 m = re.match("^{ \"([\w]+)\", \{([\w]+)", line.strip())
63 if m:
64 result.append((m.group(1), int(m.group(2))))
65 else:
66 if re.match(ENUM_START_MARKER, line):
67 inside_enum = True
68 enum_value = 0 # Start at 'UNKNOWN'
69 return sorted(result, key=lambda pair: pair[1])
72 def UpdateHistogramDefinitions(histogram_values, document):
73 """Sets the children of <enum name="ExtensionFunctions" ...> node in
74 |document| to values generated from policy ids contained in
75 |policy_templates|.
77 Args:
78 histogram_values: A list of pairs (label, value) defining each extension
79 function
80 document: A minidom.Document object representing parsed histogram
81 definitions XML file.
83 """
84 # Find ExtensionFunctions enum.
85 for enum_node in document.getElementsByTagName('enum'):
86 if enum_node.attributes['name'].value == ENUM_NAME:
87 extension_functions_enum_node = enum_node
88 break
89 else:
90 raise UserError('No policy enum node found')
92 # Remove existing values.
93 while extension_functions_enum_node.hasChildNodes():
94 extension_functions_enum_node.removeChild(
95 extension_functions_enum_node.lastChild)
97 # Add a "Generated from (...)" comment
98 comment = ' Generated from {0} '.format(EDITOR_COMMAND_CPP)
99 extension_functions_enum_node.appendChild(document.createComment(comment))
101 # Add values generated from policy templates.
102 for (label, value) in histogram_values:
103 node = document.createElement('int')
104 node.attributes['value'] = str(value)
105 node.attributes['label'] = label
106 extension_functions_enum_node.appendChild(node)
109 def Log(message):
110 logging.info(message)
113 def main():
114 if len(sys.argv) > 1:
115 print >>sys.stderr, 'No arguments expected!'
116 sys.stderr.write(__doc__)
117 sys.exit(1)
119 Log('Reading histogram enum definition from "%s".' % EDITOR_COMMAND_CPP)
120 histogram_values = ReadHistogramValues(EDITOR_COMMAND_CPP)
122 Log('Reading existing histograms from "%s".' % (HISTOGRAMS_PATH))
123 with open(HISTOGRAMS_PATH, 'rb') as f:
124 histograms_doc = minidom.parse(f)
125 f.seek(0)
126 xml = f.read()
128 Log('Comparing histograms enum with new enum definition.')
129 UpdateHistogramDefinitions(histogram_values, histograms_doc)
131 Log('Writing out new histograms file.')
132 new_xml = print_style.GetPrintStyle().PrettyPrintNode(histograms_doc)
133 if PromptUserToAcceptDiff(xml, new_xml, 'Is the updated version acceptable?'):
134 with open(HISTOGRAMS_PATH, 'wb') as f:
135 f.write(new_xml)
137 Log('Done.')
140 if __name__ == '__main__':
141 main()