|
|
|
@ -16,43 +16,48 @@ |
|
|
|
|
This takes the list of libs, node_modules, and targets from our |
|
|
|
|
yaml dictionary, and adds to each the transitive closure |
|
|
|
|
of the list of dependencies. |
|
|
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_lib(libs, name): |
|
|
|
|
try: |
|
|
|
|
return next(lib for lib in libs if lib['name'] == name) |
|
|
|
|
except StopIteration: |
|
|
|
|
return None |
|
|
|
|
def transitive_deps(lib_map, node): |
|
|
|
|
"""Returns a list of transitive dependencies from node. |
|
|
|
|
|
|
|
|
|
Recursively iterate all dependent node in a depth-first fashion and |
|
|
|
|
list a result using a topological sorting. |
|
|
|
|
""" |
|
|
|
|
result = [] |
|
|
|
|
seen = set() |
|
|
|
|
start = node |
|
|
|
|
|
|
|
|
|
def recursive_helper(node): |
|
|
|
|
if node is None: |
|
|
|
|
return |
|
|
|
|
for dep in node.get("deps", []): |
|
|
|
|
if dep not in seen: |
|
|
|
|
seen.add(dep) |
|
|
|
|
next_node = lib_map.get(dep) |
|
|
|
|
recursive_helper(next_node) |
|
|
|
|
if node is not start: |
|
|
|
|
result.insert(0, node["name"]) |
|
|
|
|
|
|
|
|
|
def transitive_deps(lib, libs): |
|
|
|
|
if lib is not None and 'deps' in lib: |
|
|
|
|
# Recursively call transitive_deps on each dependency, and take the union |
|
|
|
|
return set.union( |
|
|
|
|
set(lib['deps']), *[ |
|
|
|
|
set(transitive_deps(get_lib(libs, dep), libs)) |
|
|
|
|
for dep in lib['deps'] |
|
|
|
|
]) |
|
|
|
|
else: |
|
|
|
|
return set() |
|
|
|
|
recursive_helper(node) |
|
|
|
|
return result |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def mako_plugin(dictionary): |
|
|
|
|
"""The exported plugin code for transitive_dependencies. |
|
|
|
|
|
|
|
|
|
Iterate over each list and check each item for a deps list. We add a |
|
|
|
|
transitive_deps property to each with the transitive closure of those |
|
|
|
|
dependency lists. |
|
|
|
|
""" |
|
|
|
|
libs = dictionary.get('libs') |
|
|
|
|
Iterate over each list and check each item for a deps list. We add a |
|
|
|
|
transitive_deps property to each with the transitive closure of those |
|
|
|
|
dependency lists. The result list is sorted in a topological ordering. |
|
|
|
|
""" |
|
|
|
|
lib_map = {lib['name']: lib for lib in dictionary.get('libs')} |
|
|
|
|
|
|
|
|
|
for target_name, target_list in dictionary.items(): |
|
|
|
|
for target in target_list: |
|
|
|
|
if isinstance(target, dict) and 'deps' in target: |
|
|
|
|
target['transitive_deps'] = transitive_deps(target, libs) |
|
|
|
|
target['transitive_deps'] = transitive_deps(lib_map, target) |
|
|
|
|
|
|
|
|
|
python_dependencies = dictionary.get('python_dependencies') |
|
|
|
|
python_dependencies['transitive_deps'] = (transitive_deps( |
|
|
|
|
python_dependencies, libs)) |
|
|
|
|
python_dependencies['transitive_deps'] = transitive_deps( |
|
|
|
|
lib_map, python_dependencies) |
|
|
|
|