| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 # Copyright 2014 Google Inc. | 3 # Copyright 2014 Google Inc. |
| 4 # | 4 # |
| 5 # Use of this source code is governed by a BSD-style license that can be | 5 # Use of this source code is governed by a BSD-style license that can be |
| 6 # found in the LICENSE file. | 6 # found in the LICENSE file. |
| 7 | 7 |
| 8 import collections | 8 import collections |
| 9 import types | 9 import types |
| 10 | 10 |
| 11 # The goal of this class is to store a set of unique items in the order in | 11 # The goal of this class is to store a set of unique items in the order in |
| 12 # which they are inserted. This is important for the final makefile, where | 12 # which they are inserted. This is important for the final makefile, where |
| 13 # we want to make sure the image decoders are in a particular order. See | 13 # we want to make sure the image decoders are in a particular order. See |
| 14 # images.gyp for more information. | 14 # images.gyp for more information. |
| 15 class OrderedSet(object): | 15 class OrderedSet(object): |
| 16 """ | 16 """Ordered set of unique items that supports addition and removal. |
| 17 Ordered set of unique items that supports addition and removal. | 17 |
| 18 Retains the order in which items are inserted. |
| 18 """ | 19 """ |
| 19 | 20 |
| 20 def __init__(self): | 21 def __init__(self): |
| 21 self.__li = [] | 22 self.__ordered_set = [] |
| 22 | 23 |
| 23 def add(self, item): | 24 def add(self, item): |
| 25 """Add item, if it is not already in the set. |
| 26 |
| 27 item is appended to the end if it is not already in the set. |
| 28 |
| 29 Args: |
| 30 item: The item to add. |
| 24 """ | 31 """ |
| 25 Add item, if it is not already in the set. | 32 if item not in self.__ordered_set: |
| 26 @param item The item to add. | 33 self.__ordered_set.append(item) |
| 27 """ | |
| 28 if item not in self.__li: | |
| 29 self.__li.append(item) | |
| 30 | 34 |
| 31 def __contains__(self, item): | 35 def __contains__(self, item): |
| 36 """Whether the set contains item. |
| 37 |
| 38 Args: |
| 39 item: The item to search for in the set. |
| 40 |
| 41 Returns: |
| 42 bool: Whether the item is in the set. |
| 32 """ | 43 """ |
| 33 Whether the set contains item. | 44 return item in self.__ordered_set |
| 34 @param item The item to search for in the set. | |
| 35 @return bool Whether the item is in the set. | |
| 36 """ | |
| 37 return item in self.__li | |
| 38 | 45 |
| 39 def __iter__(self): | 46 def __iter__(self): |
| 47 """Iterator for the set. |
| 40 """ | 48 """ |
| 41 Iterator for the set. | 49 return self.__ordered_set.__iter__() |
| 42 """ | |
| 43 return self.__li.__iter__() | |
| 44 | 50 |
| 45 def remove(self, item): | 51 def remove(self, item): |
| 46 """ | 52 """ |
| 47 Remove item from the set. | 53 Remove item from the set. |
| 48 @param item Item to be removed. | 54 |
| 55 Args: |
| 56 item: Item to be removed. |
| 57 |
| 58 Raises: |
| 59 ValueError if item is not in the set. |
| 49 """ | 60 """ |
| 50 return self.__li.remove(item) | 61 self.__ordered_set.remove(item) |
| 51 | 62 |
| 52 def __len__(self): | 63 def __len__(self): |
| 64 """Number of items in the set. |
| 53 """ | 65 """ |
| 54 Number of items in the set. | 66 return len(self.__ordered_set) |
| 55 """ | |
| 56 return len(self.__li) | |
| 57 | 67 |
| 58 def __getitem__(self, index): | 68 def __getitem__(self, index): |
| 69 """Return item at index. |
| 59 """ | 70 """ |
| 60 Return item at index. | 71 return self.__ordered_set[index] |
| 61 """ | |
| 62 return self.__li[index] | |
| 63 | 72 |
| 64 def reset(self): | 73 def reset(self): |
| 74 """Reset to empty. |
| 65 """ | 75 """ |
| 66 Reset to empty. | 76 self.__ordered_set = [] |
| 77 |
| 78 def set(self, other): |
| 79 """Replace this ordered set with another. |
| 80 |
| 81 Args: |
| 82 other: OrderedSet to replace this one. After this call, this OrderedSet |
| 83 will contain exactly the same elements as other. |
| 67 """ | 84 """ |
| 68 self.__li = [] | 85 self.__ordered_set = list(other.__ordered_set) |
| 69 | 86 |
| 70 VAR_NAMES = ['LOCAL_CFLAGS', | 87 VAR_NAMES = ['LOCAL_CFLAGS', |
| 71 'LOCAL_CPPFLAGS', | 88 'LOCAL_CPPFLAGS', |
| 72 'LOCAL_SRC_FILES', | 89 'LOCAL_SRC_FILES', |
| 73 'LOCAL_SHARED_LIBRARIES', | 90 'LOCAL_SHARED_LIBRARIES', |
| 74 'LOCAL_STATIC_LIBRARIES', | 91 'LOCAL_STATIC_LIBRARIES', |
| 75 'LOCAL_C_INCLUDES', | 92 'LOCAL_C_INCLUDES', |
| 76 'LOCAL_EXPORT_C_INCLUDE_DIRS', | 93 'LOCAL_EXPORT_C_INCLUDE_DIRS', |
| 77 'DEFINES', | 94 'DEFINES', |
| 78 'KNOWN_TARGETS'] | 95 'KNOWN_TARGETS', |
| 96 # These are not parsed by gyp, but set manually. |
| 97 'LOCAL_MODULE_TAGS', |
| 98 'LOCAL_MODULE'] |
| 79 | 99 |
| 80 class VarsDict(collections.namedtuple('VarsDict', VAR_NAMES)): | 100 class VarsDict(collections.namedtuple('VarsDict', VAR_NAMES)): |
| 81 """ | 101 """Custom class for storing the arguments to Android.mk variables. |
| 82 Custom class for storing the arguments to Android.mk variables. Can be | 102 |
| 83 treated as a dictionary with fixed keys. | 103 Can also be treated as a dictionary with fixed keys. |
| 84 """ | 104 """ |
| 85 | 105 |
| 86 __slots__ = () | 106 __slots__ = () |
| 87 | 107 |
| 88 def __new__(cls): | 108 def __new__(cls): |
| 89 lists = [] | 109 lists = [] |
| 90 # TODO (scroggo): Is there a better way add N items? | 110 # TODO (scroggo): Is there a better way add N items? |
| 91 for __unused__ in range(len(VAR_NAMES)): | 111 for __unused__ in range(len(VAR_NAMES)): |
| 92 lists.append(OrderedSet()) | 112 lists.append(OrderedSet()) |
| 93 return tuple.__new__(cls, lists) | 113 return tuple.__new__(cls, lists) |
| 94 | 114 |
| 95 def keys(self): | 115 def keys(self): |
| 96 """ | 116 """Return the field names as strings. |
| 97 Return the field names as strings. | |
| 98 """ | 117 """ |
| 99 return self._fields | 118 return self._fields |
| 100 | 119 |
| 101 def __getitem__(self, index): | 120 def __getitem__(self, index): |
| 102 """ | 121 """Return an item, indexed by a number or a string. |
| 103 Return an item, indexed by a number or a string. | |
| 104 """ | 122 """ |
| 105 if type(index) == types.IntType: | 123 if type(index) == types.IntType: |
| 106 # Treat the index as an array index into a tuple. | 124 # Treat the index as an array index into a tuple. |
| 107 return tuple.__getitem__(self, index) | 125 return tuple.__getitem__(self, index) |
| 108 if type(index) == types.StringType: | 126 if type(index) == types.StringType: |
| 109 # Treat the index as a key into a dictionary. | 127 # Treat the index as a key into a dictionary. |
| 110 return eval('self.%s' % index) | 128 return eval('self.%s' % index) |
| 111 return None | 129 return None |
| 112 | 130 |
| 113 | 131 |
| 114 def intersect(var_dict_list): | 132 def intersect(var_dict_list): |
| 115 """ | 133 """Compute intersection of VarsDicts. |
| 134 |
| 116 Find the intersection of a list of VarsDicts and trim each input to its | 135 Find the intersection of a list of VarsDicts and trim each input to its |
| 117 unique entries. | 136 unique entries. |
| 118 @param var_dict_list list of VarsDicts. WARNING: each VarsDict will be | 137 |
| 119 modified in place, to remove the common elements! | 138 Args: |
| 120 @return VarsDict containing list entries common to all VarsDicts in | 139 var_dict_list: list of VarsDicts. WARNING: each VarsDict will be |
| 121 var_dict_list | 140 modified in place, to remove the common elements! |
| 141 Returns: |
| 142 VarsDict containing list entries common to all VarsDicts in |
| 143 var_dict_list |
| 122 """ | 144 """ |
| 123 intersection = VarsDict() | 145 intersection = VarsDict() |
| 124 # First VarsDict | 146 # First VarsDict |
| 125 var_dict_a = var_dict_list[0] | 147 var_dict_a = var_dict_list[0] |
| 126 # The rest. | 148 # The rest. |
| 127 other_var_dicts = var_dict_list[1:] | 149 other_var_dicts = var_dict_list[1:] |
| 128 | 150 |
| 129 for key in var_dict_a.keys(): | 151 for key in var_dict_a.keys(): |
| 130 # Copy A's list, so we can continue iterating after modifying the original. | 152 # Copy A's list, so we can continue iterating after modifying the original. |
| 131 a_list = list(var_dict_a[key]) | 153 a_list = list(var_dict_a[key]) |
| 132 for item in a_list: | 154 for item in a_list: |
| 133 # If item is in all lists, add to intersection, and remove from all. | 155 # If item is in all lists, add to intersection, and remove from all. |
| 134 in_all_lists = True | 156 in_all_lists = True |
| 135 for var_dict in other_var_dicts: | 157 for var_dict in other_var_dicts: |
| 136 if not item in var_dict[key]: | 158 if not item in var_dict[key]: |
| 137 in_all_lists = False | 159 in_all_lists = False |
| 138 break | 160 break |
| 139 if in_all_lists: | 161 if in_all_lists: |
| 140 intersection[key].add(item) | 162 intersection[key].add(item) |
| 141 for var_dict in var_dict_list: | 163 for var_dict in var_dict_list: |
| 142 var_dict[key].remove(item) | 164 var_dict[key].remove(item) |
| 143 return intersection | 165 return intersection |
| 144 | 166 |
| OLD | NEW |