De-dup PrefixSet code in SafeBrowsingDatabaseManager.
[chromium-blink-merge.git] / tools / metrics / histograms / update_policies.py
blob79f524f690b97a526fb139a90d0fd5233679b797
1 # Copyright 2013 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 EnterprisePolicies enum in histograms.xml file with policy
6 definitions read from policy_templates.json.
8 If the file was pretty-printed, the updated version is pretty-printed too.
9 """
11 import os
12 import re
13 import sys
15 from ast import literal_eval
16 from optparse import OptionParser
17 from xml.dom import minidom
19 import print_style
21 # Import the metrics/common module.
22 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common'))
23 from diff_util import PromptUserToAcceptDiff
25 HISTOGRAMS_PATH = 'histograms.xml'
26 POLICY_TEMPLATES_PATH = (
27 '../../../components/policy/resources/policy_templates.json')
28 ENUM_NAME = 'EnterprisePolicies'
30 class UserError(Exception):
31 def __init__(self, message):
32 Exception.__init__(self, message)
34 @property
35 def message(self):
36 return self.args[0]
39 def FlattenPolicies(policy_definitions, policy_list):
40 """Appends a list of policies defined in |policy_definitions| to
41 |policy_list|, flattening subgroups.
43 Args:
44 policy_definitions: A list of policy definitions and groups, as in
45 policy_templates.json file.
46 policy_list: A list that has policy definitions appended to it.
47 """
48 for policy in policy_definitions:
49 if policy['type'] == 'group':
50 FlattenPolicies(policy['policies'], policy_list)
51 else:
52 policy_list.append(policy)
55 def ParsePlaceholders(text):
56 """Parse placeholders in |text|, making it more human-readable. The format of
57 |text| is exactly the same as in captions in policy_templates.json: it can
58 contain XML tags (ph, ex) and $1-like substitutions. Note that this function
59 does only a very simple parsing that is not fully correct, but should be
60 enough for all practical situations.
62 Args:
63 text: A string containing placeholders.
65 Returns:
66 |text| with placeholders removed or replaced by readable text.
67 """
68 text = re.sub(r'\$\d+', '', text) # Remove $1-like substitutions.
69 text = re.sub(r'<[^>]+>', '', text) # Remove XML tags.
70 return text
73 def UpdateHistogramDefinitions(policy_templates, doc):
74 """Sets the children of <enum name="EnterprisePolicies" ...> node in |doc| to
75 values generated from policy ids contained in |policy_templates|.
77 Args:
78 policy_templates: A list of dictionaries, defining policies or policy
79 groups. The format is exactly the same as in
80 policy_templates.json file.
81 doc: A minidom.Document object representing parsed histogram definitions
82 XML file.
83 """
84 # Find EnterprisePolicies enum.
85 for enum_node in doc.getElementsByTagName('enum'):
86 if enum_node.attributes['name'].value == ENUM_NAME:
87 policy_enum_node = enum_node
88 break
89 else:
90 raise UserError('No policy enum node found')
92 # Remove existing values.
93 while policy_enum_node.hasChildNodes():
94 policy_enum_node.removeChild(policy_enum_node.lastChild)
96 # Add a "Generated from (...)" comment
97 comment = ' Generated from {0} '.format(POLICY_TEMPLATES_PATH)
98 policy_enum_node.appendChild(doc.createComment(comment))
100 # Add values generated from policy templates.
101 ordered_policies = []
102 FlattenPolicies(policy_templates['policy_definitions'], ordered_policies)
103 ordered_policies.sort(key=lambda policy: policy['id'])
104 for policy in ordered_policies:
105 node = doc.createElement('int')
106 node.attributes['value'] = str(policy['id'])
107 node.attributes['label'] = ParsePlaceholders(policy['caption'])
108 policy_enum_node.appendChild(node)
111 def main():
112 if len(sys.argv) > 1:
113 print >>sys.stderr, 'No arguments expected!'
114 sys.stderr.write(__doc__)
115 sys.exit(1)
117 with open(POLICY_TEMPLATES_PATH, 'rb') as f:
118 policy_templates = literal_eval(f.read())
119 with open(HISTOGRAMS_PATH, 'rb') as f:
120 histograms_doc = minidom.parse(f)
121 f.seek(0)
122 xml = f.read()
124 UpdateHistogramDefinitions(policy_templates, histograms_doc)
125 new_xml = print_style.GetPrintStyle().PrettyPrintNode(histograms_doc)
126 if PromptUserToAcceptDiff(xml, new_xml, 'Is the updated version acceptable?'):
127 with open(HISTOGRAMS_PATH, 'wb') as f:
128 f.write(new_xml)
131 if __name__ == '__main__':
132 try:
133 main()
134 except UserError as e:
135 print >>sys.stderr, e.message
136 sys.exit(1)