def test_flatten_walk(): walk = [{'e': 1, 'a': 2}, [{'e': 1, 'z': 5}, {'e': 2}, [{'x': 50}]]] flat = flatten_walk(walk, ['e', 'x']) assert_equal(flat, {'e': set((1, 2)), 'x': set([50])})
def collect_dependencies(self, obj, dependencies=['build', 'runtime'], ids=[], caller=None): """ Build a dict of dependencies for a given obj. NB : This assumes the obj has a walk method similar to the one found in ComplexTask Parameters ---------- obj : object with a walk method Obj for which dependencies should be computed. dependencies : {['build'], ['runtime'], ['build', 'runtime']} Kind of dependencies which should be gathered. ids : list, optional List of dependencies ids to use when collecting. caller : optional Calling plugin. Used for some runtime dependencies needing to know the ressource owner. Returns ------- result : bool Flag indicating the success of the operation. dependencies : dict In case of success: - Dicts holding all the classes or other dependencies to build, run or build and run a task without any access to the workbench. If a single kind of dependencies is requested a single dict is returned otherwise two are returned one for the build ones and one for the runtime ones Otherwise: - dict holding the id of the dependencie and the asssociated error message. """ # Use a set to avoid collecting several times the same entry, which # could happen if an entry is both a build and a runtime dependency. members = set() callables = {} if 'runtime' in dependencies and caller is None: raise RuntimeError( cleandoc('''Cannot collect runtime dependencies without knowing the caller plugin''')) if 'build' in dependencies: if ids: b = self.build_collectors build_deps = [dep for id, dep in b.iteritems() if id in ids] else: build_deps = self.build_collectors.values() for build_dep in build_deps: members.update(set(build_dep.walk_members)) if 'runtime' in dependencies: if ids: r = self.runtime_collectors runtime_deps = [dep for id, dep in r.iteritems() if id in ids] else: runtime_deps = self.runtime_collectors.values() for runtime_dep in runtime_deps: members.update(set(runtime_dep.walk_members)) callables.update(runtime_dep.walk_callables) walk = obj.walk(members, callables) flat_walk = flatten_walk(walk, list(members) + callables.keys()) deps = ({}, {}) errors = {} if 'build' in dependencies: for build_dep in self.build_collectors.values(): try: deps[0].update(build_dep.collect(self.workbench, flat_walk)) except ValueError as e: errors[build_dep.id] = e.message if 'runtime' in dependencies: for runtime_dep in self.runtime_collectors.values(): try: deps[1].update( runtime_dep.collect(self.workbench, flat_walk, caller)) except ValueError as e: errors[runtime_dep.id] = e.message if errors: return False, errors if 'build' in dependencies and 'runtime' in dependencies: return True, deps[0], deps[1] elif 'build' in dependencies: return True, deps[0] else: return True, deps[1]
def collect_dependencies(self, obj, dependencies=['build', 'runtime'], ids=[], caller=None): """ Build a dict of dependencies for a given obj. NB : This assumes the obj has a walk method similar to the one found in ComplexTask Parameters ---------- obj : object with a walk method Obj for which dependencies should be computed. dependencies : {['build'], ['runtime'], ['build', 'runtime']} Kind of dependencies which should be gathered. ids : list, optional List of dependencies ids to use when collecting. caller : optional Calling plugin. Used for some runtime dependencies needing to know the ressource owner. Returns ------- result : bool Flag indicating the success of the operation. dependencies : dict In case of success: - Dicts holding all the classes or other dependencies to build, run or build and run a task without any access to the workbench. If a single kind of dependencies is requested a single dict is returned otherwise two are returned one for the build ones and one for the runtime ones Otherwise: - dict holding the id of the dependencie and the asssociated error message. """ # Use a set to avoid collecting several times the same entry, which # could happen if an entry is both a build and a runtime dependency. members = set() callables = {} if 'runtime' in dependencies and caller is None: raise RuntimeError(cleandoc('''Cannot collect runtime dependencies without knowing the caller plugin''')) if 'build' in dependencies: if ids: b = self.build_collectors build_deps = [dep for id, dep in b.iteritems() if id in ids] else: build_deps = self.build_collectors.values() for build_dep in build_deps: members.update(set(build_dep.walk_members)) if 'runtime' in dependencies: if ids: r = self.runtime_collectors runtime_deps = [dep for id, dep in r.iteritems() if id in ids] else: runtime_deps = self.runtime_collectors.values() for runtime_dep in runtime_deps: members.update(set(runtime_dep.walk_members)) callables.update(runtime_dep.walk_callables) walk = obj.walk(members, callables) flat_walk = flatten_walk(walk, list(members) + callables.keys()) deps = ({}, {}) errors = {} if 'build' in dependencies: for build_dep in self.build_collectors.values(): try: deps[0].update(build_dep.collect(self.workbench, flat_walk)) except ValueError as e: errors[build_dep.id] = e.message if 'runtime' in dependencies: for runtime_dep in self.runtime_collectors.values(): try: deps[1].update(runtime_dep.collect(self.workbench, flat_walk, caller)) except ValueError as e: errors[runtime_dep.id] = e.message if errors: return False, errors if 'build' in dependencies and 'runtime' in dependencies: return True, deps[0], deps[1] elif 'build' in dependencies: return True, deps[0] else: return True, deps[1]