| Index: bindings/scripts/print_idl_diff.py
|
| diff --git a/bindings/scripts/print_idl_diff.py b/bindings/scripts/print_idl_diff.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9a8deea5afa18c9330003a2ac6e97fce94a8019a
|
| --- /dev/null
|
| +++ b/bindings/scripts/print_idl_diff.py
|
| @@ -0,0 +1,433 @@
|
| +#!/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 diff in the alphabetical order or the order of
|
| +diffing tags.
|
| +Usage: print_idl_diff.py diff_file.json order
|
| + diff.json:
|
| + Output of generate_idl_diff.py. The json file contains a dictionary
|
| + that represents a diff between two different Chromium versions. The
|
| + structure of the dictionary is like below.
|
| + order:
|
| + Specify how to sort. Either by "ALPHABET" or "TAG".
|
| +"""
|
| +
|
| +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 the input structure of generate_idl_diff.py and
|
| +that of print_diff.py is whether diffing tags are included or not.
|
| + {'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 outputs a colored text to sys.stdout.
|
| + TODO(bashi): This class doesn't work on Windows. Provide a way to 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 new color to change. It should be one of |COLORS|.
|
| + """
|
| + if color in self.COLORS:
|
| + self.out.write('\033[' + str(color) + 'm')
|
| + else:
|
| + raise Exception('Unsupported color.')
|
| +
|
| + def writeln(self, string):
|
| + """Print text with a line-break.
|
| + """
|
| + self.out.write(string + '\n')
|
| +
|
| + def write(self, string):
|
| + """Print text without a line-break.
|
| + """
|
| + 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 |interface_or_member_list| by tags.
|
| + Args:
|
| + interface_or_member_list: A list of interface names or a list of "members"
|
| + Returns:
|
| + A tuple of (removed, added, unchanged) where
|
| + removed: A list of removed members
|
| + added: A list of added members
|
| + unspecified: A list of other members
|
| + """
|
| + 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 interface names as follows.
|
| + [names of deleted "interface"s
|
| + -> names of added "interface"s
|
| + -> names of other "interface"s]
|
| + Args:
|
| + interfaces: "interface" objects.
|
| + Returns:
|
| + A list of sorted interface names
|
| + """
|
| + 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_names = removed + added + unspecified
|
| + return sorted_interface_names
|
| +
|
| +
|
| +def sort_members_by_tags(interface):
|
| + """Sort members of a given interface in the order of diffing tags.
|
| + 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 in the order of diffing tags.
|
| + 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 the 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'])
|
| + sorted_interface[member_type] = sorted_members
|
| + return sorted_interface
|
| +
|
| +
|
| +def sort_diff_in_alphabetical_order(interfaces):
|
| + """Sort an "interfaces" object in the alphabetical order.
|
| + Args:
|
| + An "interfaces" object.
|
| + Returns:
|
| + A sorted "interfaces" object
|
| + """
|
| + 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 print_member_with_color(member, out):
|
| + """Print the "member" with a colored text. '+' is added to an added
|
| + "member". '-' is added to a removed "member".
|
| + 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 of "ExtAttributes" in the "interface" object
|
| + """
|
| + for extattribute in extattributes:
|
| + out.write(' ')
|
| + print_member_with_color(extattribute, out)
|
| + out.writeln(extattribute['Name'])
|
| +
|
| +
|
| +def print_consts(consts, out):
|
| + """Print consts in an "interface" object.
|
| + Args:
|
| + A list of "Consts" of the "interface" object
|
| + """
|
| + for const in consts:
|
| + out.write(' ')
|
| + print_member_with_color(const, out)
|
| + out.write(str(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_in_member(extattributes, out):
|
| + """Print extattributes in a "member" object.
|
| + Args:
|
| + A list of "ExtAttributes" in the "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 of "Attributes" in the "interface" object
|
| + """
|
| + for attribute in attributes:
|
| + out.write(' ')
|
| + print_member_with_color(attribute, out)
|
| + if attribute['ExtAttributes']:
|
| + print_extattributes_in_member(attribute['ExtAttributes'], out)
|
| + out.write(str(attribute['Type']))
|
| + out.write(' ')
|
| + out.writeln(attribute['Name'])
|
| +
|
| +
|
| +def print_arguments(arguments, out):
|
| + """Print arguments in a "members" object named "Operations".
|
| + Args: A list of "Arguments"
|
| + """
|
| + 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 of "Operations"
|
| + """
|
| + for operation in operations:
|
| + out.write(' ')
|
| + print_member_with_color(operation, out)
|
| + if operation['ExtAttributes']:
|
| + print_extattributes_in_member(operation['ExtAttributes'], out)
|
| + out.write(str(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():
|
| + print_member_with_color(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 print_usage():
|
| + """Show usage."""
|
| + sys.stdout.write('Usage: print_diff.py <diff_file.json> <"TAG"|"ALPHABET">\n')
|
| +
|
| +
|
| +def main(argv):
|
| + if len(argv) != 2:
|
| + print_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:
|
| + print_usage()
|
| + exit(1)
|
| + sorted_diff = sort_func(diff)
|
| + out = Colorize(sys.stdout)
|
| + print_diff(sorted_diff, out)
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + main(sys.argv[1:])
|
|
|