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

Unified Diff: tools/metrics/histograms/update_histogram_enum.py

Issue 2835733002: Readdress use_counter_feature_enum issue (Closed)
Patch Set: Codereview: nit + defined custom error Created 3 years, 8 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 | « third_party/WebKit/Source/core/frame/PRESUBMIT.py ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/metrics/histograms/update_histogram_enum.py
diff --git a/tools/metrics/histograms/update_histogram_enum.py b/tools/metrics/histograms/update_histogram_enum.py
index f0a29e0fe91c7aaf1c0500e82c572c0d836c4059..a36854309414d58ceaf829a82db697fac30cdcb4 100644
--- a/tools/metrics/histograms/update_histogram_enum.py
+++ b/tools/metrics/histograms/update_histogram_enum.py
@@ -25,224 +25,255 @@ HISTOGRAMS_PATH = path_util.GetHistogramsFile()
class UserError(Exception):
- def __init__(self, message):
- Exception.__init__(self, message)
+ def __init__(self, message):
Ilya Sherman 2017/04/26 00:18:50 Hmm, why did you add extra indentation to all of t
lunalu1 2017/04/27 18:31:42 My bad, I didn't realize chromium and Blink had di
+ Exception.__init__(self, message)
- @property
- def message(self):
- return self.args[0]
+ @property
+ def message(self):
+ return self.args[0]
+
Ilya Sherman 2017/04/26 00:18:50 nit: Please leave two blank lines between top-leve
+class DuplicatedValue(Exception):
+ """Exception raised for duplicated enum values.
+
+ Attributes:
+ first_label: First enum label that shares the duplicated enum value.
+ second_label: Second enum label that shares the duplicated enum value.
+ """
+ def __init__(self, first_label, second_label):
+ self.first_label = first_label
+ self.second_label = second_label
def Log(message):
- logging.info(message)
+ logging.info(message)
def ReadHistogramValues(filename, start_marker, end_marker, strip_k_prefix):
- """Returns a dictionary of enum values and a pair of labels that have the same
- enum values, read from a C++ file.
-
- Args:
- filename: The unix-style path (relative to src/) of the file to open.
- start_marker: A regex that signifies the start of the enum values.
- end_marker: A regex that signifies the end of the enum values.
- strip_k_prefix: Set to True if enum values are declared as kFoo and the
- 'k' should be stripped.
+ """Creates a dictionary of enum values, read from a C++ file.
+
+ Args:
+ filename: The unix-style path (relative to src/) of the file to open.
+ start_marker: A regex that signifies the start of the enum values.
+ end_marker: A regex that signifies the end of the enum values.
+ strip_k_prefix: Set to True if enum values are declared as kFoo and the
+ 'k' should be stripped.
+
+ Returns:
+ A dict mapping enum labels to the corresponding enum values.
+
+ Raises:
+ DuplicatedValue: An error when two enum labels share the same value.
"""
- # Read the file as a list of lines
- with open(path_util.GetInputFile(filename)) as f:
- content = f.readlines()
-
- START_REGEX = re.compile(start_marker)
- ITEM_REGEX = re.compile(r'^(\w+)')
- ITEM_REGEX_WITH_INIT = re.compile(r'(\w+)\s*=\s*(\d*)')
- WRAPPED_INIT = re.compile(r'(\d+)')
- END_REGEX = re.compile(end_marker)
-
- iterator = iter(content)
- # Find the start of the enum
- for line in iterator:
- if START_REGEX.match(line.strip()):
- break
-
- enum_value = 0
- result = {}
- for line in iterator:
- line = line.strip()
- # Exit condition: we reached last enum value
- if END_REGEX.match(line):
- break
- # Inside enum: generate new xml entry
- m = ITEM_REGEX_WITH_INIT.match(line)
- if m:
- label = m.group(1)
- if m.group(2):
- enum_value = int(m.group(2))
- else:
- # Enum name is so long that the value wrapped to the next line
- next_line = next(iterator).strip()
- enum_value = int(WRAPPED_INIT.match(next_line).group(1))
- else:
- m = ITEM_REGEX.match(line)
- if m:
- label = m.group(1)
- else:
- continue
- # If two enum labels have the same value
- if enum_value in result:
- return result, (result[enum_value], label)
- if strip_k_prefix:
- assert label.startswith('k'), "Enum " + label + " should start with 'k'."
- label = label[1:]
- result[enum_value] = label
- enum_value += 1
- return result, None
+ # Read the file as a list of lines
+ with open(path_util.GetInputFile(filename)) as f:
+ content = f.readlines()
+
+ START_REGEX = re.compile(start_marker)
+ ITEM_REGEX = re.compile(r'^(\w+)')
+ ITEM_REGEX_WITH_INIT = re.compile(r'(\w+)\s*=\s*(\d*)')
+ WRAPPED_INIT = re.compile(r'(\d+)')
+ END_REGEX = re.compile(end_marker)
+
+ iterator = iter(content)
+ # Find the start of the enum
+ for line in iterator:
+ if START_REGEX.match(line.strip()):
+ break
+
+ enum_value = 0
+ result = {}
+ for line in iterator:
+ line = line.strip()
+ # Exit condition: we reached last enum value
+ if END_REGEX.match(line):
+ break
+ # Inside enum: generate new xml entry
+ m = ITEM_REGEX_WITH_INIT.match(line)
+ if m:
+ label = m.group(1)
+ if m.group(2):
+ enum_value = int(m.group(2))
+ else:
+ # Enum name is so long that the value wrapped to the next line
+ next_line = next(iterator).strip()
+ enum_value = int(WRAPPED_INIT.match(next_line).group(1))
+ else:
+ m = ITEM_REGEX.match(line)
+ if m:
+ label = m.group(1)
+ else:
+ continue
+ # If two enum labels have the same value
+ if enum_value in result:
+ raise DuplicatedValue(result[enum_value], label)
+ if strip_k_prefix:
+ assert label.startswith('k'), ("Enum " + label +
+ " should start with 'k'.")
+ label = label[1:]
+ result[enum_value] = label
+ enum_value += 1
+ return result
def CreateEnumItemNode(document, value, label):
- """Creates an int element to append to an enum."""
- item_node = document.createElement('int')
- item_node.attributes['value'] = str(value)
- item_node.attributes['label'] = label
- return item_node
+ """Creates an int element to append to an enum."""
+ item_node = document.createElement('int')
+ item_node.attributes['value'] = str(value)
+ item_node.attributes['label'] = label
+ return item_node
def UpdateHistogramDefinitions(histogram_enum_name, source_enum_values,
source_enum_path, document):
- """Updates the enum node named |histogram_enum_name| based on the definition
- stored in |source_enum_values|. Existing items for which |source_enum_values|
- doesn't contain any corresponding data will be preserved. |source_enum_path|
- will be used to insert a comment.
- """
- # Get a dom of <enum name=|histogram_enum_name| ...> node in |document|.
- for enum_node in document.getElementsByTagName('enum'):
- if enum_node.attributes['name'].value == histogram_enum_name:
- break
- else:
- raise UserError('No {0} enum node found'.format(histogram_enum_name))
-
- new_item_nodes = {}
- new_comments = []
-
- # Add a "Generated from (...)" comment.
- new_comments.append(
- document.createComment(' Generated from {0} '.format(source_enum_path)))
-
- # Create item nodes for each of the enum values.
- for value, label in source_enum_values.iteritems():
- new_item_nodes[value] = CreateEnumItemNode(document, value, label)
-
- # Scan existing nodes in |enum_node| for old values and preserve them.
- # - Preserve comments other than the 'Generated from' comment. NOTE:
- # this does not preserve the order of the comments in relation to the
- # old values.
- # - Drop anything else.
- SOURCE_COMMENT_REGEX = re.compile('^ Generated from ')
- for child in enum_node.childNodes:
- if child.nodeName == 'int':
- value = int(child.attributes['value'].value)
- if not source_enum_values.has_key(value):
- new_item_nodes[value] = child
- # Preserve existing non-generated comments.
- elif (child.nodeType == minidom.Node.COMMENT_NODE and
- SOURCE_COMMENT_REGEX.match(child.data) is None):
- new_comments.append(child)
-
- # Update |enum_node|. First, remove everything existing.
- while enum_node.hasChildNodes():
- enum_node.removeChild(enum_node.lastChild)
-
- # Add comments at the top.
- for comment in new_comments:
- enum_node.appendChild(comment)
-
- # Add in the new enums.
- for value in sorted(new_item_nodes.iterkeys()):
- enum_node.appendChild(new_item_nodes[value])
+ """Updates the enum node named |histogram_enum_name| based on the definition
+ stored in |source_enum_values|. Existing items for which
+ |source_enum_values| doesn't contain any corresponding data will be
+ preserved. |source_enum_path| will be used to insert a comment.
+ """
+ # Get a dom of <enum name=|histogram_enum_name| ...> node in |document|.
+ for enum_node in document.getElementsByTagName('enum'):
+ if enum_node.attributes['name'].value == histogram_enum_name:
+ break
+ else:
+ raise UserError('No {0} enum node found'.format(histogram_enum_name))
+
+ new_item_nodes = {}
+ new_comments = []
+
+ # Add a "Generated from (...)" comment.
+ new_comments.append(
+ document.createComment(' Generated from {0} '.format(source_enum_path)))
+
+ # Create item nodes for each of the enum values.
+ for value, label in source_enum_values.iteritems():
+ new_item_nodes[value] = CreateEnumItemNode(document, value, label)
+
+ # Scan existing nodes in |enum_node| for old values and preserve them.
+ # - Preserve comments other than the 'Generated from' comment. NOTE:
+ # this does not preserve the order of the comments in relation to the
+ # old values.
+ # - Drop anything else.
+ SOURCE_COMMENT_REGEX = re.compile('^ Generated from ')
+ for child in enum_node.childNodes:
+ if child.nodeName == 'int':
+ value = int(child.attributes['value'].value)
+ if not source_enum_values.has_key(value):
+ new_item_nodes[value] = child
+ # Preserve existing non-generated comments.
+ elif (child.nodeType == minidom.Node.COMMENT_NODE and
+ SOURCE_COMMENT_REGEX.match(child.data) is None):
+ new_comments.append(child)
+
+ # Update |enum_node|. First, remove everything existing.
+ while enum_node.hasChildNodes():
+ enum_node.removeChild(enum_node.lastChild)
+
+ # Add comments at the top.
+ for comment in new_comments:
+ enum_node.appendChild(comment)
+
+ # Add in the new enums.
+ for value in sorted(new_item_nodes.iterkeys()):
+ enum_node.appendChild(new_item_nodes[value])
def _GetOldAndUpdatedXml(histogram_enum_name, source_enum_values,
source_enum_path):
- """Reads old histogram from |histogram_enum_name| from |HISTOGRAMS_PATH|, and
- calculates new histogram from |source_enum_values| from |source_enum_path|,
- and returns both in XML format.
- """
- Log('Reading existing histograms from "{0}".'.format(HISTOGRAMS_PATH))
- with open(HISTOGRAMS_PATH, 'rb') as f:
- histograms_doc = minidom.parse(f)
- f.seek(0)
- xml = f.read()
+ """Reads old histogram from |histogram_enum_name| from |HISTOGRAMS_PATH|,
+ and calculates new histogram from |source_enum_values| from
+ |source_enum_path|, and returns both in XML format.
+ """
+ Log('Reading existing histograms from "{0}".'.format(HISTOGRAMS_PATH))
+ with open(HISTOGRAMS_PATH, 'rb') as f:
+ histograms_doc = minidom.parse(f)
+ f.seek(0)
+ xml = f.read()
- Log('Comparing histograms enum with new enum definition.')
- UpdateHistogramDefinitions(histogram_enum_name, source_enum_values,
- source_enum_path, histograms_doc)
+ Log('Comparing histograms enum with new enum definition.')
+ UpdateHistogramDefinitions(histogram_enum_name, source_enum_values,
+ source_enum_path, histograms_doc)
- new_xml = print_style.GetPrintStyle().PrettyPrintNode(histograms_doc)
- return (xml, new_xml)
+ new_xml = print_style.GetPrintStyle().PrettyPrintNode(histograms_doc)
+ return (xml, new_xml)
def HistogramNeedsUpdate(histogram_enum_name, source_enum_path, start_marker,
end_marker, strip_k_prefix = False):
- """Reads a C++ enum from a .h file and does a dry run of updating
- histograms.xml to match. Returns true if the histograms.xml file would be
- changed.
-
- Args:
- histogram_enum_name: The name of the XML <enum> attribute to update.
- source_enum_path: A unix-style path, relative to src/, giving
- the C++ header file from which to read the enum.
- start_marker: A regular expression that matches the start of the C++ enum.
- end_marker: A regular expression that matches the end of the C++ enum.
- strip_k_prefix: Set to True if enum values are declared as kFoo and the
- 'k' should be stripped.
- """
- Log('Reading histogram enum definition from "{0}".'.format(source_enum_path))
- source_enum_values, duplicated_values = ReadHistogramValues(
- source_enum_path, start_marker, end_marker, strip_k_prefix)
- if duplicated_values:
- return False, duplicated_values
-
- (xml, new_xml) = _GetOldAndUpdatedXml(histogram_enum_name, source_enum_values,
- source_enum_path)
- return xml != new_xml, None
+ """Reads a C++ enum from a .h file and does a dry run of updating
+ histograms.xml to match.
+
+ Args:
+ histogram_enum_name: The name of the XML <enum> attribute to update.
+ source_enum_path: A unix-style path, relative to src/, giving
+ the C++ header file from which to read the enum.
+ start_marker: A regular expression that matches the start of the C++
+ enum.
+ end_marker: A regular expression that matches the end of the C++ enum.
+ strip_k_prefix: Set to True if enum values are declared as kFoo and the
+ 'k' should be stripped.
+
+ Returns:
+ A boolean indicating whether the histograms.xml file would be changed.
+
+ Raises:
+ DuplicatedValue: An error when two enum labels share the same value.
+ """
+ Log('Reading histogram enum definition from "{0}".'.format(
+ source_enum_path))
+ try:
+ source_enum_values, duplicated_values = ReadHistogramValues(
+ source_enum_path, start_marker, end_marker, strip_k_prefix)
+ except DuplicatedValue:
+ raise
Ilya Sherman 2017/04/26 00:18:50 There's no need to use a try/except here. The nat
+
+ (xml, new_xml) = _GetOldAndUpdatedXml(histogram_enum_name,
+ source_enum_values,
+ source_enum_path)
+ return xml != new_xml
def UpdateHistogramFromDict(histogram_enum_name, source_enum_values,
source_enum_path):
- """Updates |histogram_enum_name| enum in histograms.xml file with values
- from the {value: 'key'} dictionary |source_enum_values|. A comment is added
- to histograms.xml citing that the values in |histogram_enum_name| were
- sourced from |source_enum_path|.
- """
- (xml, new_xml) = _GetOldAndUpdatedXml(histogram_enum_name, source_enum_values,
- source_enum_path)
- if not diff_util.PromptUserToAcceptDiff(
- xml, new_xml, 'Is the updated version acceptable?'):
- Log('Cancelled.')
- return
+ """Updates |histogram_enum_name| enum in histograms.xml file with values
+ from the {value: 'key'} dictionary |source_enum_values|. A comment is added
+ to histograms.xml citing that the values in |histogram_enum_name| were
+ sourced from |source_enum_path|.
+ """
+ (xml, new_xml) = _GetOldAndUpdatedXml(histogram_enum_name,
+ source_enum_values,
+ source_enum_path)
+ if not diff_util.PromptUserToAcceptDiff(
+ xml, new_xml, 'Is the updated version acceptable?'):
+ Log('Cancelled.')
+ return
- with open(HISTOGRAMS_PATH, 'wb') as f:
- f.write(new_xml)
+ with open(HISTOGRAMS_PATH, 'wb') as f:
+ f.write(new_xml)
- Log('Done.')
+ Log('Done.')
def UpdateHistogramEnum(histogram_enum_name, source_enum_path,
start_marker, end_marker, strip_k_prefix = False):
- """Reads a C++ enum from a .h file and updates histograms.xml to match.
-
- Args:
- histogram_enum_name: The name of the XML <enum> attribute to update.
- source_enum_path: A unix-style path, relative to src/, giving
- the C++ header file from which to read the enum.
- start_marker: A regular expression that matches the start of the C++ enum.
- end_marker: A regular expression that matches the end of the C++ enum.
- strip_k_prefix: Set to True if enum values are declared as kFoo and the
- 'k' should be stripped.
- """
-
- Log('Reading histogram enum definition from "{0}".'.format(source_enum_path))
- source_enum_values, ignored = ReadHistogramValues(source_enum_path,
- start_marker, end_marker, strip_k_prefix)
-
- UpdateHistogramFromDict(histogram_enum_name, source_enum_values,
- source_enum_path)
+ """Reads a C++ enum from a .h file and updates histograms.xml to match.
+
+ Args:
+ histogram_enum_name: The name of the XML <enum> attribute to update.
+ source_enum_path: A unix-style path, relative to src/, giving
+ the C++ header file from which to read the enum.
+ start_marker: A regular expression that matches the start of the C++
+ enum.
+ end_marker: A regular expression that matches the end of the C++ enum.
+ strip_k_prefix: Set to True if enum values are declared as kFoo and the
+ 'k' should be stripped.
+ """
+
+ Log('Reading histogram enum definition from "{0}".'.format(
+ source_enum_path))
+ source_enum_values, ignored = ReadHistogramValues(source_enum_path,
+ start_marker,
+ end_marker,
+ strip_k_prefix)
+
+ UpdateHistogramFromDict(Histogram_enum_name, source_enum_values,
Ilya Sherman 2017/04/26 00:18:50 nit: s/Histogram/histogram (text editor keyboard s
+ source_enum_path)
« no previous file with comments | « third_party/WebKit/Source/core/frame/PRESUBMIT.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698