Chromium Code Reviews| 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..5c86d7d06f1515d372bd250bc970a08c1becba32 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/bindings/scripts/print_idl_diff.py |
| @@ -0,0 +1,424 @@ |
| +#!/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 |
| +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 |
| + expressing a diff between two defferent Chrome versions.The structure |
| + of the dictionary is like below. |
| + order: |
| + Specify how to sort. Either by using diffing tags or in alphabetical order. |
|
bashi
2015/09/25 06:40:58
nit: wrap line after 'alphabetical'.
shimadaa
2015/09/25 07:02:33
Done.
|
| +""" |
| + |
| +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 |
| +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. |
| + {'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'}, |
| + ..., |
| + ] |
| + }, |
| + { |
| + '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'}, |
| + ..., |
| + ] |
| + }, |
| + ..., |
| + } |
| +""" |
| + |
| + |
| +class Colorize(object): |
| + """This class decorates text with colors and outputs it to sys.stdout. |
| + TODO(shimadaa): This class doesn't work on Windows. Provides a way to suppress escape sequences. |
|
bashi
2015/09/25 06:40:58
nit: wrap line after 'a way to'
shimadaa
2015/09/25 07:02:32
Done.
|
| + """ |
| + |
| + 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 and output it to sys.stdout. |
|
bashi
2015/09/25 06:40:58
nit: remove 'and output it to sys.stdout'.
shimadaa
2015/09/25 07:02:33
Done.
|
| + """ |
| + self.out.write('\033[0m') |
| + |
| + def change_color(self, color): |
| + """Change text's color by specifing arguments and output it to sys.stdout. |
|
bashi
2015/09/25 06:40:58
nit: remove 'and output it to sys.stdout'.
shimadaa
2015/09/25 07:02:33
Done.
|
| + Args: |
| + color: A value that represents text's color. Mapping colors into values is below. |
|
bashi
2015/09/25 06:40:58
how about:
color: A color to change. It should be
shimadaa
2015/09/25 07:02:32
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. |
| + """ |
| + self.out.write(string + '\n') |
| + |
| + def write(self, string): |
| + """Print text not to use for line breaks. |
| + """ |
| + 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 tags. |
|
bashi
2015/09/25 06:40:58
nit: wrap line after 'by'
shimadaa
2015/09/25 07:02:33
Done.
|
| + Args: |
| + interface_or_member_list: Interface name's list or "members" object's list. |
|
bashi
2015/09/25 06:40:58
nit: wrap line after "object's"
shimadaa
2015/09/25 07:02:33
Done.
|
| + Returns: |
| + removed: A list that consists of removed ones. |
| + added: A list that consists of added ones. |
| + unspecified: A list that consists of neither removed ones nor added ones. |
|
bashi
2015/09/25 06:40:58
nit: wrap line after 'added'
shimadaa
2015/09/25 07:02:32
Done.
|
| + """ |
| + 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. |
| + [a interface name of "interface" deleted whole |
| + -> a interface name of "interface" added whole |
| + -> a interface name of "interface" changed part] |
| + Args: |
| + interfaces: An "interface" objects. |
| + Returns: |
| + A list consists of interface names sorted |
| + """ |
| + 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 |
| + return (sorted_interface_name) |
|
bashi
2015/09/25 06:40:58
nit: remove paresis.
shimadaa
2015/09/25 07:02:33
Done.
|
| + |
| + |
| +def sort_members_by_tags(interface): |
| + """Sort a "members" object by using diff_tag. |
| + Args: |
| + An "interface" object |
| + Returns: |
| + A sorted "interface" object |
| + """ |
| + sorted_interface = OrderedDict() |
| + if DIFF_TAG in interface: |
| + return interface |
| + else: |
|
bashi
2015/09/25 06:40:58
nit: You can remmove else clause.
if DIFF_TAG in
shimadaa
2015/09/25 07:02:33
Done.
|
| + 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. |
| + 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. |
| + 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']) |
|
bashi
2015/09/25 06:40:58
nit: wrap line after ','
shimadaa
2015/09/25 07:02:33
Done.
|
| + sorted_interface[member_type] = sorted_members |
| + return sorted_interface |
| + |
| + |
| +def sort_diff_in_alphabetical_order(interfaces): |
| + """Sort diff in alphabetical order. |
| + Args: |
| + An "interfaces" object. |
| + Returns: |
| + A sorted "interfaces" object in alphabetical order |
| + """ |
| + 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): |
| + """Change color based on diff_tag and output prefix ('+' or '-') if |member| is added/deleted. |
|
bashi
2015/09/25 06:40:58
nit: wrap line after |member|
shimadaa
2015/09/25 07:02:33
Done.
|
| + 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" |
| + """ |
| + 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" |
| + """ |
| + 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): |
|
bashi
2015/09/25 06:40:58
nit: Please add a comment to describe what this fu
shimadaa
2015/09/25 07:02:33
Done.
|
| + count = 0 |
| + for item in items: |
| + callback(item) |
| + count += 1 |
| + if count < len(items): |
| + out.write(', ') |
| + |
| + |
| +def print_extattributes_of_member(extattributes, out): |
| + """Print extattributes in a "member" object. |
| + Args: |
| + A list included as a value of "ExtAttributes" of "member" object |
| + """ |
| + 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" |
| + """ |
| + 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 |
| + "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" |
| + """ |
| + 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(): |
|
bashi
2015/09/25 06:40:58
nit: Add a comment.
"""Show usage."""
shimadaa
2015/09/25 07:02:33
Done.
|
| + 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:]) |