11
22from copy import deepcopy
3+ from itertools import product
34
45from pythonforandroid.logger import (info, info_notify, warning)
56from pythonforandroid.recipe import Recipe
@@ -115,6 +116,84 @@ def find_order(self, index=0):
115116 bset.discard(result)
116117
117118
119+ class RecipeOrder(dict):
120+
121+ def __init__(self, ctx):
122+ self.ctx = ctx
123+
124+ def conflicts(self, name):
125+ for name in self.keys():
126+ try:
127+ recipe = Recipe.get_recipe(name, self.ctx)
128+ conflicts = recipe.conflicts
129+ except OSError:
130+ conflicts = []
131+
132+ if any([c in self for c in recipe.conflicts]):
133+ return True
134+ return False
135+
136+ def recursively_collect_orders(name, ctx, orders=[]):
137+ '''For each possible recipe ordering we were passed, try to add the
138+ new recipe name to that order. Recursively do the same thing with
139+ all the dependencies of each recipe.
140+ '''
141+ try:
142+ recipe = Recipe.get_recipe(name, ctx)
143+ if recipe.depends is None:
144+ dependencies = []
145+ else:
146+ # make all dependencies into lists so that product will work
147+ dependencies = [([dependency] if not isinstance(dependency, (list, tuple))
148+ else dependency) for dependency in recipe.depends]
149+ except OSError:
150+ # The recipe does not exist, so we assume it can be installed
151+ # via pip with no extra dependencies
152+ dependencies = []
153+
154+ new_orders = []
155+ # for each existing recipe order, see if we can add the new recipe name
156+ for order in orders:
157+ if name in order:
158+ new_orders.append(deepcopy(order))
159+ continue
160+ if order.conflicts(name):
161+ continue
162+
163+ for dependency_set in product(*dependencies):
164+ new_order = deepcopy(order)
165+ new_order[name] = set(dependency_set)
166+
167+ dependency_new_orders = [new_order]
168+ for dependency in dependency_set:
169+ dependency_new_orders = recursively_collect_orders(
170+ dependency, ctx, dependency_new_orders)
171+
172+ new_orders.extend(dependency_new_orders)
173+
174+ return new_orders
175+
176+
177+ def new_get_recipe_order_and_bootstrap(ctx, names, bs=None):
178+ recipes_to_load = set(names)
179+ # if bs is not None and bs.recipe_depends:
180+ # recipes_to_load = recipes_to_load.union(set(bs.recipe_depends))
181+
182+ possible_orders = [RecipeOrder(ctx)]
183+
184+ # get all possible recipe orders
185+ for name in names:
186+ possible_orders = recursively_collect_orders(name, ctx, orders=possible_orders)
187+
188+ # prefer python2 and SDL2 if available
189+ possible_orders = sorted(possible_orders,
190+ key=lambda order: -('python2' in order) - ('sdl2' in order))
191+
192+
193+
194+ return possible_orders
195+
196+
118197def get_recipe_order_and_bootstrap(ctx, names, bs=None):
119198 '''Takes a list of recipe names and (optionally) a bootstrap. Then
120199 works out the dependency graph (including bootstrap recipes if
@@ -129,7 +208,9 @@ def get_recipe_order_and_bootstrap(ctx, names, bs=None):
129208 recipes_to_load = list(recipes_to_load)
130209 recipe_loaded = []
131210 python_modules = []
211+ print('recipes_to_load', recipes_to_load)
132212 while recipes_to_load:
213+ info('Current recipes to load: {}'.format(', '.join(map(str, recipes_to_load))))
133214 name = recipes_to_load.pop(0)
134215 if name in recipe_loaded or isinstance(name, (list, tuple)):
135216 continue
0 commit comments