Skip to content

Commit dca5468

Browse files
committed
Added intial alternative dependency support
1 parent a61c641 commit dca5468

File tree

1 file changed

+57
-12
lines changed

1 file changed

+57
-12
lines changed

pythonforandroid/toolchain.py

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import imp
2626
import contextlib
2727
import logging
28+
from copy import deepcopy
2829
from functools import wraps
2930
from datetime import datetime
3031
from distutils.spawn import find_executable
@@ -414,38 +415,75 @@ class ArchAndroid(Arch):
414415

415416
class Graph(object):
416417
# Taken from the old python-for-android/depsort
418+
# Modified to include alternative dependencies
417419
def __init__(self):
418420
# `graph`: dict that maps each package to a set of its dependencies.
419-
self.graph = {}
421+
self.graphs = [{}]
422+
# self.graph = {}
423+
424+
def remove_redundant_graphs(self):
425+
'''Removes possible graphs if they are equivalent to others.'''
426+
graphs = self.graphs
427+
initial_num_graphs = len(graphs)
428+
# Walk the list backwards so that popping elements doesn't mess up indexing
429+
for i in range(len(graphs) - 1):
430+
graph = graphs[initial_num_graphs - 1 - i]
431+
for j in range(1, len(graphs)):
432+
comparison_graph = graphs[initial_num_graphs - 1 - j]
433+
if set(comparison_graph.keys()) == set(graph.keys()):
434+
graphs.pop([initial_num_graphs - 1 - i])
435+
break
420436

421437
def add(self, dependent, dependency):
422438
"""Add a dependency relationship to the graph"""
423-
self.graph.setdefault(dependent, set())
424-
self.graph.setdefault(dependency, set())
439+
if isinstance(dependency, (tuple, list)):
440+
for graph in self.graphs:
441+
self._add(graph, dependent, dependency[0])
442+
for dep in dependency[1:]:
443+
new_graph = deepcopy(graph)
444+
self._add(new_graph, dependent, dep)
445+
self.graphs.append(new_graph)
446+
else:
447+
for graph in self.graphs:
448+
self._add(graph, dependent, dependency)
449+
self.remove_redundant_graphs()
450+
451+
def _add(self, graph, dependent, dependency):
452+
'''Add a dependency relationship to a specific graph, where dependency
453+
must be a single dependency, not a list or tuple.
454+
'''
455+
graph.setdefault(dependent, set())
456+
graph.setdefault(dependency, set())
425457
if dependent != dependency:
426-
self.graph[dependent].add(dependency)
458+
graph[dependent].add(dependency)
427459

428460
def conflicts(self, conflict):
429-
if conflict in self.graph:
430-
return True
431-
return False
461+
graphs = self.graphs
462+
for i in range(len(graphs)):
463+
graph = graphs[len(graphs) - 1 - i]
464+
if conflict in graph:
465+
print('conflict in graph', conflict, graph)
466+
graphs.pop([len(graphs) - 1 - i])
467+
return len(graphs) == 0
432468

433469
def add_optional(self, dependent, dependency):
434470
"""Add an optional (ordering only) dependency relationship to the graph
435471
436472
Only call this after all mandatory requirements are added
437473
"""
438-
if dependent in self.graph and dependency in self.graph:
439-
self.add(dependent, dependency)
474+
for graph in self.graphs:
475+
if dependent in graph and dependency in graph:
476+
self._add(graph, dependent, dependency)
440477

441-
def find_order(self):
478+
def find_order(self, index=0):
442479
"""Do a topological sort on a dependency graph
443480
444481
:Parameters:
445482
:Returns:
446483
iterator, sorted items form first to last
447484
"""
448-
graph = dict((k, set(v)) for k, v in self.graph.items())
485+
graph = self.graphs[index]
486+
graph = dict((k, set(v)) for k, v in graph.items())
449487
while graph:
450488
# Find all items without a parent
451489
leftmost = [l for l, s in graph.items() if not s]
@@ -1913,7 +1951,14 @@ def build_recipes(names, ctx):
19131951
warning('Due to this conflict the build cannot continue, exiting.')
19141952
exit(1)
19151953
recipe_loaded.append(name)
1916-
build_order = list(graph.find_order())
1954+
if len(graph.graphs) > 1:
1955+
info('Found multiple valid recipe sets:')
1956+
for graph in graph.graphs:
1957+
info(' {}'.format(graph.keys()))
1958+
info_notify('Using the first of these: {}'.format(graph.graphs[0].keys()))
1959+
else:
1960+
info('Found a single valid recipe set (this is good)')
1961+
build_order = list(graph.find_order(0))
19171962
info_notify("Recipe build order is {}".format(build_order))
19181963
if python_modules:
19191964
info_notify(('The requirements ({}) were not found as recipes, they will be '

0 commit comments

Comments
 (0)