Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright 2015 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 | |
| 6 import logging | |
| 7 import sys | |
| 8 import os | |
| 9 | |
| 10 # Import the metrics/common module for pretty print xml. | |
| 11 sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common')) | |
| 12 import models | |
| 13 import presubmit_util | |
| 14 | |
| 15 | |
| 16 # Model definitions for rappor.xml content | |
| 17 summaryType = models.TextNodeType('summary') | |
| 18 | |
| 19 parametersType = models.ObjectNodeType('parameters', | |
|
Alexei Svitkine (slow)
2015/02/13 14:36:37
Nit: camelCase isn't a thing in Python style...
I
Steven Holte
2015/02/14 01:11:18
Done.
| |
| 20 int_attributes=[ | |
| 21 'num-cohorts', | |
| 22 'bytes', | |
| 23 'hash-functions', | |
| 24 ], | |
| 25 float_attributes=[ | |
| 26 'fake-prob', | |
| 27 'fake-one-prob', | |
| 28 'one-coin-prob', | |
| 29 'zero-coin-prob', | |
| 30 ], | |
| 31 string_attributes=[ | |
| 32 'reporting-level' | |
| 33 ]) | |
| 34 | |
| 35 rapporParametersType = models.ObjectNodeType('rappor-parameters', | |
| 36 extra_newlines=(1, 1, 1), | |
| 37 string_attributes=['name'], | |
| 38 children=[ | |
| 39 models.ChildType('summary', summaryType, False), | |
| 40 models.ChildType('parameters', parametersType, False), | |
| 41 ]) | |
| 42 | |
| 43 rapporParameterTypesType = models.ObjectNodeType('rappor-parameter-types', | |
| 44 extra_newlines=(1, 1, 1), | |
| 45 dont_indent=True, | |
| 46 children=[ | |
| 47 models.ChildType('types', rapporParametersType, True), | |
| 48 ]) | |
| 49 | |
| 50 ownerType = models.TextNodeType('owner', single_line=True) | |
| 51 | |
| 52 rapporMetricType = models.ObjectNodeType('rappor-metric', | |
| 53 extra_newlines=(1, 1, 1), | |
| 54 string_attributes=['name', 'type'], | |
| 55 children=[ | |
| 56 models.ChildType('owners', ownerType, True), | |
| 57 models.ChildType('summary', summaryType, False), | |
| 58 ]) | |
| 59 | |
| 60 rapporMetricsType = models.ObjectNodeType('rappor-metrics', | |
| 61 extra_newlines=(1, 1, 1), | |
| 62 dont_indent=True, | |
| 63 children=[ | |
| 64 models.ChildType('metrics', rapporMetricType, True), | |
| 65 ]) | |
| 66 | |
| 67 rapporConfigurationType = models.ObjectNodeType('rappor-configuration', | |
| 68 dont_indent=True, | |
| 69 children=[ | |
| 70 models.ChildType('parameterTypes', rapporParameterTypesType, False), | |
| 71 models.ChildType('metrics', rapporMetricsType, False), | |
| 72 ]) | |
| 73 | |
| 74 rapporXmlType = models.DocumentType(rapporConfigurationType) | |
| 75 | |
| 76 | |
| 77 def HasMissingOwners(metrics): | |
|
Alexei Svitkine (slow)
2015/02/13 14:36:37
Can you add some tests?
Steven Holte
2015/02/14 01:11:18
Done.
| |
| 78 """Check that all of the metrics have owners. | |
| 79 | |
| 80 Args: | |
| 81 metrics: A list of rappor metric description objects. | |
| 82 | |
| 83 Returns: | |
| 84 True iff some metrics are missing owners. | |
| 85 """ | |
| 86 missing_owners = [m for m in metrics if not m['owners']] | |
| 87 for metric in missing_owners: | |
| 88 logging.error('Rappor metric "%s" is missing an owner.', metric['name']) | |
| 89 print metric | |
| 90 return bool(missing_owners) | |
| 91 | |
| 92 | |
| 93 def HasInvalidTypes(type_names, metrics): | |
| 94 """Check that all of the metrics have valid types. | |
| 95 | |
| 96 Args: | |
| 97 type_names: The set of valid type names. | |
| 98 metrics: A list of rappor metric description objects. | |
| 99 | |
| 100 Returns: | |
| 101 True iff some metrics have invalid types. | |
| 102 """ | |
| 103 invalid_types = [m for m in metrics if m['type'] not in type_names] | |
| 104 for metric in invalid_types: | |
| 105 logging.error('Rappor metric "%s" has invalid type "%s"', | |
| 106 metric['name'], metric['type']) | |
| 107 return bool(invalid_types) | |
| 108 | |
| 109 | |
| 110 def HasErrors(obj): | |
| 111 """Check that rappor.xml passes some basic validation checks. | |
| 112 | |
| 113 Args: | |
| 114 obj: The parsed rappor.xml contents. | |
| 115 | |
| 116 Returns: | |
| 117 True iff there are validation errors. | |
| 118 """ | |
| 119 metrics = obj['metrics']['metrics'] | |
| 120 type_names = set(p['name'] for p in obj['parameterTypes']['types']) | |
| 121 return (HasMissingOwners(metrics) or | |
| 122 HasInvalidTypes(type_names, metrics)) | |
| 123 | |
| 124 | |
| 125 def Cleanup(obj): | |
| 126 """Preform cleanup on description contents, such as sorting metrics. | |
| 127 | |
| 128 Args: | |
| 129 obj: The parsed rappor.xml contents. | |
| 130 """ | |
| 131 types = obj['parameterTypes']['types'] | |
| 132 types.sort(key=lambda x: x['name']) | |
| 133 metrics = obj['metrics']['metrics'] | |
| 134 metrics.sort(key=lambda x: x['name']) | |
| 135 | |
| 136 | |
| 137 def UpdateXml(original_xml): | |
| 138 """Parse the original xml and return a pretty printed version. | |
| 139 | |
| 140 Args: | |
| 141 original_xml: A string containing the original xml file contents. | |
| 142 | |
| 143 Returns: | |
| 144 A Pretty printed xml string. | |
| 145 """ | |
| 146 comments, obj = rapporXmlType.Parse(original_xml) | |
| 147 | |
| 148 if HasErrors(obj): | |
| 149 return None | |
| 150 | |
| 151 Cleanup(obj) | |
| 152 | |
| 153 return rapporXmlType.PrettyPrint(comments, obj) | |
| 154 | |
| 155 | |
| 156 def main(argv): | |
| 157 presubmit_util.DoPresubmitMain(argv, 'rappor.xml', 'rappor.old.xml', | |
| 158 'pretty_print.py', UpdateXml) | |
| 159 | |
| 160 | |
| 161 if '__main__' == __name__: | |
| 162 sys.exit(main(sys.argv)) | |
| OLD | NEW |