OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/python | |
2 | |
3 # Copyright 2014 Google Inc. | |
4 # | |
5 # Use of this source code is governed by a BSD-style license that can be | |
6 # found in the LICENSE file. | |
7 | |
8 import collections | |
9 import types | |
10 | |
11 class OrderedSet(object): | |
epoger
2014/02/03 17:26:32
Cool beans. Seems like it may be generally useful
| |
12 """ | |
13 Ordered set of unique items that supports addition and removal. | |
14 """ | |
15 | |
16 def __init__(self): | |
17 self.__li = [] | |
18 | |
19 def add(self, item): | |
20 """ | |
21 Add item, if it is not already in the set. | |
22 @param item The item to add. | |
23 """ | |
24 if item not in self.__li: | |
25 self.__li.append(item) | |
26 | |
27 def __contains__(self, item): | |
28 """ | |
29 Whether the set contains item. | |
30 @param item The item to search for in the set. | |
31 @return bool Whether the item is in the set. | |
32 """ | |
33 return item in self.__li | |
34 | |
35 def __iter__(self): | |
36 """ | |
37 Iterator for the set. | |
38 """ | |
39 return self.__li.__iter__() | |
40 | |
41 def remove(self, item): | |
42 """ | |
43 Remove item from the set. | |
44 @param item Item to be removed. | |
45 """ | |
46 return self.__li.remove(item) | |
47 | |
48 def __len__(self): | |
49 """ | |
50 Number of items in the set. | |
51 """ | |
52 return len(self.__li) | |
53 | |
54 VAR_NAMES = ['LOCAL_CFLAGS', | |
55 'LOCAL_CPPFLAGS', | |
56 'LOCAL_SRC_FILES', | |
57 'LOCAL_SHARED_LIBRARIES', | |
58 'LOCAL_STATIC_LIBRARIES', | |
59 'LOCAL_C_INCLUDES', | |
60 'LOCAL_EXPORT_C_INCLUDE_DIRS', | |
61 'KNOWN_TARGETS'] | |
62 | |
63 class VarsDict(collections.namedtuple('VarsDict', VAR_NAMES)): | |
64 """ | |
65 Custom class for storing the arguments to Android.mk variables. Can be | |
66 treated as a dictionary with fixed keys. | |
67 """ | |
68 | |
69 __slots__ = () | |
70 | |
71 def __new__(cls): | |
72 lists = [] | |
73 # TODO (scroggo): Is there a better way add N items? | |
74 for __unused__ in range(len(VAR_NAMES)): | |
75 lists.append(OrderedSet()) | |
76 return tuple.__new__(cls, lists) | |
77 | |
78 def keys(self): | |
79 """ | |
80 Return the field names as strings. | |
81 """ | |
82 return self._fields | |
83 | |
84 def __getitem__(self, index): | |
85 """ | |
86 Return an item, indexed by a number or a string. | |
87 """ | |
88 if type(index) == types.IntType: | |
89 # Treat the index as an array index into a tuple. | |
90 return tuple.__getitem__(self, index) | |
91 if type(index) == types.StringType: | |
92 # Treat the index as a key into a dictionary. | |
93 return eval('self.%s' % index) | |
94 return None | |
95 | |
96 | |
97 def intersect(var_dict_list): | |
98 """ | |
99 Find the intersection of a list of VarsDicts and trim each input to its | |
100 unique entries. | |
101 @param var_dict_list list of VarsDicts. | |
epoger
2014/02/03 17:26:32
WARNING: each VarsDict will be modified in place,
scroggo
2014/02/03 23:22:31
Done.
| |
102 @return VarsDict containing list entries common to all VarsDicts in | |
103 var_dict_list | |
104 """ | |
105 intersection = VarsDict() | |
106 # First VarsDict | |
107 var_dict_a = var_dict_list[0] | |
108 # The rest. | |
109 other_var_dicts = var_dict_list[1:] | |
110 | |
111 for key in var_dict_a.keys(): | |
112 # Copy A's list, so we can continue iterating after modifying the original. | |
113 a_list = list(var_dict_a[key]) | |
114 for item in a_list: | |
115 # If item is in all lists, add to intersection, and remove from all. | |
116 in_all_lists = True | |
117 for var_dict in other_var_dicts: | |
118 if not item in var_dict[key]: | |
119 in_all_lists = False | |
120 break | |
121 if in_all_lists: | |
122 intersection[key].add(item) | |
123 for var_dict in var_dict_list: | |
124 var_dict[key].remove(item) | |
125 return intersection | |
126 | |
OLD | NEW |