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 |