Index: third_party/WebKit/Source/bindings/scripts/print_idl_diff.py |
diff --git a/third_party/WebKit/Source/bindings/scripts/print_idl_diff.py b/third_party/WebKit/Source/bindings/scripts/print_idl_diff.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..1927b2c4ed63ec62addc4bf417bcf6678b8a5f4a |
--- /dev/null |
+++ b/third_party/WebKit/Source/bindings/scripts/print_idl_diff.py |
@@ -0,0 +1,439 @@ |
+#!/usr/bin/env python |
+# Copyright 2015 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""Print a diff generated by generate_idl_diff.py. |
+Before printing, sort the idl data of the diff in alphabetical order or by |
haraken
2015/09/25 10:30:19
sort the diff in the alphabetical order or the ord
shimadaa
2015/09/25 11:31:27
Done.
|
+diffing tags. |
+Usage: print_idl_diff.py diff_file.json order |
+ diff.json: |
+ Output of generate_idl_diff.py. A json file consists of a dictionary |
haraken
2015/09/25 10:30:19
The json file contains a dictionary that represent
shimadaa
2015/09/25 11:31:27
Done.
|
+ expressing a diff between two defferent Chrome versions. The structure |
haraken
2015/09/25 10:30:18
different Chromium versions
shimadaa
2015/09/25 11:31:28
Done.
|
+ of the dictionary is like below. |
+ order: |
+ Specify how to sort. Either by using diffing tags or in alphabetical |
haraken
2015/09/25 10:30:18
"ALPHABET" or "TAG"
shimadaa
2015/09/25 11:31:27
Done.
|
+ order. |
+""" |
+ |
+from collections import OrderedDict |
+import json |
+import sys |
+ |
+from generate_idl_diff import load_json_file |
+from generate_idl_diff import EXTATTRIBUTES_AND_MEMBER_TYPES |
+from generate_idl_diff import DIFF_TAG |
+from generate_idl_diff import DIFF_TAG_ADDED |
+from generate_idl_diff import DIFF_TAG_DELETED |
+ |
+ |
+"""Refer to the explanation of generate_idl_diff.py's input files. |
+The deffference between input structure of generate_idl_diff.py and |
haraken
2015/09/25 10:30:19
The difference between the input structure...
shimadaa
2015/09/25 11:31:27
Done.
|
+that of print_diff.py is whether diffing tags are included or not. |
+The diffing tags are included in a parts that have a diff. |
haraken
2015/09/25 10:30:18
I'd remove this sentence.
shimadaa
2015/09/25 11:31:27
Done.
|
+ {'Interface': { |
+ 'diff_tag': 'deleted' |
+ 'ExtAttributes': [{'Name': '...' |
+ 'diff_tag': 'deleted'}, |
+ ..., |
+ ], |
+ 'Consts': [{'Type': '...', |
+ 'Name': '...', |
+ 'Value': '...' |
+ 'diff_tag': 'deleted'}, |
+ ..., |
+ ], |
+ 'Attributes': [{'Type': '...', |
+ 'Name': '...', |
+ 'ExtAttributes':[{'Name': '...'}, |
+ ..., |
+ ] |
+ 'diff_tag': 'deleted'}, |
+ ..., |
+ ], |
+ 'Operations': [{'Type': '...', |
+ 'Name': '...', |
+ 'ExtAttributes':[{'Name': '...'}, |
+ ..., |
+ ], |
+ 'Arguments': [{'Type': '...', |
+ 'Name': '...'}, |
+ ..., |
+ ] |
+ 'diff_tag': 'deleted'}, |
+ ..., |
+ ], |
+ 'Name': '...' |
+ }, |
+ { |
+ 'ExtAttributes': [{'Name': '...'}, |
+ ..., |
+ ], |
+ 'Consts': [{'Type': '...', |
+ 'Name': '...', |
+ 'Value': '...' |
+ 'diff_tag': 'added'}, |
+ ..., |
+ ], |
+ 'Attributes': [{'Type': '...', |
+ 'Name': '...', |
+ 'ExtAttributes':[{'Name': '...'}, |
+ ..., |
+ ]}, |
+ ..., |
+ ], |
+ 'Operations': [{'Type': '...', |
+ 'Name': '...', |
+ 'ExtAttributes':[{'Name': '...'}, |
+ ..., |
+ ], |
+ 'Arguments': [{'Type': '...', |
+ 'Name': '...'}, |
+ ..., |
+ ] |
+ 'diff_tag': 'deleted'}, |
+ ..., |
+ ], |
+ 'Name': '...' |
+ }, |
+ ..., |
+ } |
+""" |
+ |
+ |
+class Colorize(object): |
+ """This class decorates text with colors and outputs it to sys.stdout. |
haraken
2015/09/25 10:30:19
This class outputs a colored text to sys.stdout.
shimadaa
2015/09/25 11:31:27
Done.
|
+ TODO(shimadaa): This class doesn't work on Windows. Provides a way to |
haraken
2015/09/25 10:30:19
TODO(bashi)
haraken
2015/09/25 10:30:19
Provide
shimadaa
2015/09/25 11:31:27
Done.
shimadaa
2015/09/25 11:31:28
Done.
|
+ suppress escape sequences. |
+ """ |
+ |
+ BLACK = 30 |
+ RED = 31 |
+ GREEN = 32 |
+ YELLOW = 33 |
+ COLORS = (BLACK, RED, GREEN, YELLOW) |
+ |
+ def __init__(self, out): |
+ self.out = out |
+ |
+ def reset_color(self): |
+ """Reset text's color to default. |
+ """ |
+ self.out.write('\033[0m') |
+ |
+ def change_color(self, color): |
+ """Change text's color by specifing arguments. |
+ Args: |
+ color: A color to change. It should be one of |COLORS|. |
haraken
2015/09/25 10:30:19
A new color.
shimadaa
2015/09/25 11:31:27
Done.
|
+ """ |
+ if color in self.COLORS: |
+ self.out.write('\033[' + str(color) + 'm') |
+ else: |
+ raise Exception('Unsupported color.') |
+ |
+ def writeln(self, string): |
+ """Print text to use for line breaks. |
haraken
2015/09/25 10:30:19
Print text with a line-break.
shimadaa
2015/09/25 11:31:27
Done.
|
+ """ |
+ self.out.write(string + '\n') |
+ |
+ def write(self, string): |
+ """Print text not to use for line breaks. |
haraken
2015/09/25 10:30:18
Print text without a line-break.
shimadaa
2015/09/25 11:31:26
Done.
|
+ """ |
+ self.out.write(string) |
+ |
+ |
+def sort_member_types(interface): |
+ """Sort the members in the order of EXTATTRIBUTES_AND_MEMBER_TYPES. |
+ Args: |
+ interface: An "interface" object |
+ Returns: |
+ A sorted "interface" object |
+ """ |
+ sorted_interface = OrderedDict() |
+ for member_type in EXTATTRIBUTES_AND_MEMBER_TYPES: |
+ sorted_interface[member_type] = interface.get(member_type) |
+ sorted_interface[DIFF_TAG] = interface.get(DIFF_TAG) |
+ return sorted_interface |
+ |
+ |
+def group_by_tag(interface_or_member_list): |
+ """Group members of a given argument (an interface or a list of members) by |
haraken
2015/09/25 10:30:20
Group members of |interface_or_member_list| by tag
shimadaa
2015/09/25 11:31:27
Done.
|
+ tags. |
+ Args: |
+ interface_or_member_list: Interface name's list or "members" object's |
haraken
2015/09/25 10:30:20
A list of interface names or a list of "members"
shimadaa
2015/09/25 11:31:28
Done.
|
+ list. |
+ Returns: |
+ A tuple of (removed, added, unchanged) where |
+ removed: A list that consists of removed ones. |
haraken
2015/09/25 10:30:18
A list of removed members
shimadaa
2015/09/25 11:31:27
Done.
|
+ added: A list that consists of added ones. |
haraken
2015/09/25 10:30:19
A list of added members
shimadaa
2015/09/25 11:31:28
Done.
|
+ unspecified: A list that consists of neither removed ones nor added |
haraken
2015/09/25 10:30:19
A list of other members
shimadaa
2015/09/25 11:31:28
Done.
|
+ ones. |
+ """ |
+ removed = [] |
+ added = [] |
+ unspecified = [] |
+ for interface_or_member in interface_or_member_list: |
+ if DIFF_TAG in interface_or_member: |
+ if interface_or_member[DIFF_TAG] == DIFF_TAG_DELETED: |
+ removed.append(interface_or_member) |
+ elif interface_or_member[DIFF_TAG] == DIFF_TAG_ADDED: |
+ added.append(interface_or_member) |
+ else: |
+ unspecified.append(interface_or_member) |
+ return (removed, added, unspecified) |
+ |
+ |
+def sort_interface_names_by_tags(interfaces): |
+ """Sort the order of interface names like below. |
haraken
2015/09/25 10:30:19
Sort interface names as follows.
shimadaa
2015/09/25 11:31:27
Done.
|
+ [a interface name of "interface" deleted whole |
haraken
2015/09/25 10:30:19
names of deleted "interface"s
shimadaa
2015/09/25 11:31:28
Done.
|
+ -> a interface name of "interface" added whole |
haraken
2015/09/25 10:30:20
names of added "interface"s
shimadaa
2015/09/25 11:31:27
Done.
|
+ -> a interface name of "interface" changed part] |
haraken
2015/09/25 10:30:19
names of other "interface"s
shimadaa
2015/09/25 11:31:27
Done.
|
+ Args: |
+ interfaces: An "interface" objects. |
haraken
2015/09/25 10:30:19
"interface" objects
shimadaa
2015/09/25 11:31:27
Done.
|
+ Returns: |
+ A list consists of interface names sorted |
haraken
2015/09/25 10:30:19
A list of sorted interface names
shimadaa
2015/09/25 11:31:26
Done.
|
+ """ |
+ interface_list = interfaces.values() |
+ removed, added, unspecified = group_by_tag(interface_list) |
+ removed = map(lambda interface: interface['Name'], removed) |
+ added = map(lambda interface: interface['Name'], added) |
+ unspecified = map(lambda interface: interface['Name'], unspecified) |
+ sorted_interface_name = removed + added + unspecified |
haraken
2015/09/25 10:30:20
sorted_interface_names
shimadaa
2015/09/25 11:31:28
Done.
|
+ return sorted_interface_name |
+ |
+ |
+def sort_members_by_tags(interface): |
+ """Sort a "members" object by using diff_tag. |
haraken
2015/09/25 10:30:19
Sort members of a given interface in the order of
shimadaa
2015/09/25 11:31:27
Done.
|
+ Args: |
+ An "interface" object |
+ Returns: |
+ A sorted "interface" object |
+ """ |
+ sorted_interface = OrderedDict() |
+ if DIFF_TAG in interface: |
+ return interface |
+ for member_type in EXTATTRIBUTES_AND_MEMBER_TYPES: |
+ member_list = interface[member_type] |
+ removed, added, unspecified = group_by_tag(member_list) |
+ sorted_interface[member_type] = removed + added + unspecified |
+ return sorted_interface |
+ |
+ |
+def sort_diff_by_tags(interfaces): |
+ """Sort an "interfaces" object expressing a diff by using diff_tag. |
haraken
2015/09/25 10:30:19
Sort an "interfaces" object in the order of diffin
shimadaa
2015/09/25 11:31:27
Done.
|
+ Args: |
+ An "interfaces" object loaded by load_json_data(). |
+ Returns: |
+ A sorted "interfaces" object |
+ """ |
+ sorted_interfaces = OrderedDict() |
+ sorted_interface_names = sort_interface_names_by_tags(interfaces) |
+ for interface_name in sorted_interface_names: |
+ interface = sort_members_by_tags(interfaces[interface_name]) |
+ sorted_interfaces[interface_name] = sort_member_types(interface) |
+ return sorted_interfaces |
+ |
+ |
+def sort_members_in_alphabetical_order(interface): |
+ """Sort a "members" object in alphabetical order. |
haraken
2015/09/25 10:30:19
in the alphabetical order
shimadaa
2015/09/25 11:31:28
Done.
|
+ Args: |
+ An "interface" object |
+ Returns: |
+ A sorted "interface" object |
+ """ |
+ sorted_interface = OrderedDict() |
+ for member_type in EXTATTRIBUTES_AND_MEMBER_TYPES: |
+ sorted_members = sorted(interface[member_type], |
+ key=lambda member: member['Name']) |
+ sorted_interface[member_type] = sorted_members |
+ return sorted_interface |
+ |
+ |
+def sort_diff_in_alphabetical_order(interfaces): |
+ """Sort diff in alphabetical order. |
haraken
2015/09/25 10:30:18
Sort an "interfaces" object in the alphabetical or
shimadaa
2015/09/25 11:31:28
Done.
|
+ Args: |
+ An "interfaces" object. |
+ Returns: |
+ A sorted "interfaces" object in alphabetical order |
haraken
2015/09/25 10:30:20
A sorted "interfaces" object
shimadaa
2015/09/25 11:31:28
Done.
|
+ """ |
+ sorted_interfaces = OrderedDict() |
+ for interface_name in sorted(interfaces.keys()): |
+ interface = interfaces[interface_name] |
+ sorted_interface = sort_members_in_alphabetical_order(interface) |
+ sorted_interface[DIFF_TAG] = interface.get(DIFF_TAG) |
+ sorted_interfaces[interface_name] = sorted_interface |
+ return sorted_interfaces |
+ |
+ |
+def change_color_based_on_tag(member, out): |
haraken
2015/09/25 10:30:18
change_color_based_on_tag => print_member_with_col
shimadaa
2015/09/25 11:31:27
Done.
|
+ """Change color based on diff_tag and output prefix ('+' or '-') if |member| |
haraken
2015/09/25 10:30:19
Print the "member" with a colored text. '+' is add
shimadaa
2015/09/25 11:31:27
Done.
|
+ is added/deleted. |
+ Args: |
+ member: A "member" object |
+ """ |
+ if DIFF_TAG in member: |
+ if member[DIFF_TAG] == DIFF_TAG_DELETED: |
+ out.change_color(Colorize.RED) |
+ out.write('- ') |
+ elif member[DIFF_TAG] == DIFF_TAG_ADDED: |
+ out.change_color(Colorize.GREEN) |
+ out.write('+ ') |
+ else: |
+ out.change_color(Colorize.BLACK) |
+ out.write(' ') |
+ |
+ |
+def print_extattributes(extattributes, out): |
+ """Print extattributes in an "interface" object. |
+ Args: |
+ A list included as a value of "member" object named "ExtAttributes" |
haraken
2015/09/25 10:30:19
A list of "ExtAttributes" in the "interface" objec
shimadaa
2015/09/25 11:31:27
Done.
|
+ """ |
+ for extattribute in extattributes: |
+ out.write(' ') |
+ change_color_based_on_tag(extattribute, out) |
+ out.writeln(extattribute['Name']) |
+ |
+ |
+def print_consts(consts, out): |
+ """Print consts in an "interface" object. |
+ Args: |
+ A list included as a value of "member" object named "Consts" |
haraken
2015/09/25 10:30:19
A list of "Consts" of the "interface" object
shimadaa
2015/09/25 11:31:28
Done.
|
+ """ |
+ for const in consts: |
+ out.write(' ') |
+ change_color_based_on_tag(const, out) |
+ out.write(const['Type']) |
+ out.write(' ') |
+ out.write(const['Name']) |
+ out.write(' ') |
+ out.writeln(const['Value']) |
+ |
+ |
+def print_items(items, callback, out): |
+ """Calls |callback| for each item in |items|, printing commas between |
+ |callback| calls. |
+ Args: |
+ items: extattributes or arguments |
+ """ |
+ count = 0 |
+ for item in items: |
+ callback(item) |
+ count += 1 |
+ if count < len(items): |
+ out.write(', ') |
+ |
+ |
+def print_extattributes_of_member(extattributes, out): |
haraken
2015/09/25 10:30:19
Why do we need to distinguish print_extattributes_
haraken
2015/09/25 10:30:19
print_extattributes_in_member
shimadaa
2015/09/25 11:31:27
Done.
shimadaa
2015/09/25 11:31:27
Sorry I don't have time to modify...
|
+ """Print extattributes in a "member" object. |
+ Args: |
+ A list included as a value of "ExtAttributes" of "member" object |
haraken
2015/09/25 10:30:19
A list of "ExtAttributes" in the "member" object
shimadaa
2015/09/25 11:31:28
Done.
|
+ """ |
+ def callback(extattribute): |
+ out.write(extattribute['Name']) |
+ |
+ out.write('[') |
+ print_items(extattributes, callback, out) |
+ out.write(']') |
+ |
+ |
+def print_attributes(attributes, out): |
+ """Print attributes in an "interface" object. |
+ Args: |
+ A list included as a value of "member" object named "Attributes" |
haraken
2015/09/25 10:30:19
A list of "Attributes" in the "interface" object
shimadaa
2015/09/25 11:31:28
Done.
|
+ """ |
+ for attribute in attributes: |
+ out.write(' ') |
+ change_color_based_on_tag(attribute, out) |
+ if attribute['ExtAttributes']: |
+ print_extattributes_of_member(attribute['ExtAttributes'], out) |
+ out.write(attribute['Type']) |
+ out.write(' ') |
+ out.writeln(attribute['Name']) |
+ |
+ |
+def print_arguments(arguments, out): |
+ """Print arguments in a "members" object named "Operations". |
+ Args: A list included as a value of "Arguments" of "member" object named |
haraken
2015/09/25 10:30:19
A list of "Arguments".
shimadaa
2015/09/25 11:31:27
Done.
|
+ "Operations" |
+ """ |
+ def callback(argument): |
+ out.write(argument['Name']) |
+ |
+ out.write('(') |
+ print_items(arguments, callback, out) |
+ out.writeln(')') |
+ |
+ |
+def print_operations(operations, out): |
+ """Print operations in a "member" object. |
+ Args: |
+ A list included as a value of "member" object named "Operations" |
haraken
2015/09/25 10:30:20
A list of "Operations"
shimadaa
2015/09/25 11:31:28
Done.
|
+ """ |
+ for operation in operations: |
+ out.write(' ') |
+ change_color_based_on_tag(operation, out) |
+ if operation['ExtAttributes']: |
+ print_extattributes_of_member(operation['ExtAttributes'], out) |
+ out.write(operation['Type']) |
+ out.write(' ') |
+ if operation['Arguments']: |
+ out.write(operation['Name']) |
+ print_arguments(operation['Arguments'], out) |
+ else: |
+ out.writeln(operation['Name']) |
+ |
+ |
+def print_diff(diff, out): |
+ """Print the diff on a shell. |
+ Args: |
+ A sorted diff |
+ """ |
+ for interface_name, interface in diff.iteritems(): |
+ change_color_based_on_tag(interface, out) |
+ out.change_color(Colorize.YELLOW) |
+ out.write('[[') |
+ out.write(interface_name) |
+ out.writeln(']]') |
+ out.reset_color() |
+ for member_name, member in interface.iteritems(): |
+ if member_name == 'ExtAttributes': |
+ out.writeln('ExtAttributes') |
+ print_extattributes(member, out) |
+ elif member_name == 'Consts': |
+ out.writeln(' Consts') |
+ print_consts(member, out) |
+ elif member_name == 'Attributes': |
+ out.writeln(' Attributes') |
+ print_attributes(member, out) |
+ elif member_name == 'Operations': |
+ out.writeln(' Operations') |
+ print_operations(member, out) |
+ out.reset_color() |
+ |
+ |
+def usage(): |
haraken
2015/09/25 10:30:18
print_usage
|
+ """Show usage.""" |
+ sys.stdout.write('Usage: print_diff.py <diff_file.json> <"TAG"|"ALPHABET">\n') |
+ |
+ |
+def main(argv): |
+ if len(argv) != 2: |
+ usage() |
+ exit(1) |
+ json_data = argv[0] |
+ order = argv[1] |
+ diff = load_json_file(json_data) |
+ if order == 'TAG': |
+ sort_func = sort_diff_by_tags |
+ elif order == 'ALPHABET': |
+ sort_func = sort_diff_in_alphabetical_order |
+ else: |
+ usage() |
+ exit(1) |
+ sorted_diff = sort_func(diff) |
+ out = Colorize(sys.stdout) |
+ print_diff(sorted_diff, out) |
+ |
+ |
+if __name__ == '__main__': |
+ main(sys.argv[1:]) |