def test_walk_sequence(): # Test walking a pulse sequence. root = RootSequence() context = BaseContext() root.context = context root.external_vars = {'a': 1.5} pulse1 = Pulse(def_1='1.0', def_2='{a}') pulse2 = Pulse(def_1='{a} + 1.0', def_2='3.0') pulse3 = Pulse(def_1='{2_stop} + 0.5', def_2='10', kind='Analogical', shape=SquareShape()) seq = Sequence(items=[Pulse(def_1='{2_stop} + 0.5', def_2='10', kind='Analogical', shape=SquareShape())]) root.items.extend([pulse1, pulse2, pulse3, seq]) walk = root.walk(['item_class', 'shape_class'], {}) flat = flatten_walk(walk, ['item_class', 'shape_class']) assert_in('item_class', flat) assert_equal(flat['item_class'], set(['Pulse', 'RootSequence', 'Sequence'])) assert_in('shape_class', flat) assert_equal(flat['shape_class'], set(['SquareShape']))
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 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])})