class StepContext(object): """Encapsulates external state and the details of creating Nodes. This avoids giving Nodes direct access to the task list or subject set. """ def __init__(self, node_builder, project_tree, node_states, inline_nodes): self._node_builder = node_builder self.project_tree = project_tree self._node_states = dict(node_states) self._parents = OrderedSet() self._inline_nodes = inline_nodes def get(self, node): """Given a Node and computed node_states, gets the current state for the Node. Optionally inlines execution of inlineable dependencies if `inline_nodes=True`. """ state = self._node_states.get(node, None) if state is not None: return state if self._inline_nodes and node.is_inlineable: if node in self._parents: return Noop.cycle(list(self._parents)[-1], node) self._parents.add(node) state = self._node_states[node] = node.step(self) self._parents.remove(node) return state else: return Waiting([node]) def gen_nodes(self, subject, product, variants): """Yields Node instances which might be able to provide a value for the given inputs.""" return self._node_builder.gen_nodes(subject, product, variants) def select_node(self, selector, subject, variants): """Constructs a Node for the given Selector and the given Subject/Variants. This method is decoupled from Selector classes in order to allow the `selector` package to not need a dependency on the `nodes` package. """ selector_type = type(selector) if selector_type is Select: return SelectNode(subject, selector.product, variants, None) elif selector_type is SelectVariant: return SelectNode(subject, selector.product, variants, selector.variant_key) elif selector_type is SelectDependencies: return DependenciesNode(subject, selector.product, variants, selector.deps_product, selector.field) elif selector_type is SelectProjection: return ProjectionNode(subject, selector.product, variants, selector.projected_subject, selector.fields, selector.input_product) elif selector_type is SelectLiteral: # NB: Intentionally ignores subject parameter to provide a literal subject. return SelectNode(selector.subject, selector.product, variants, None) else: raise ValueError('Unrecognized Selector type "{}" for: {}'.format( selector_type, selector))
class StepContext(object): """Encapsulates external state and the details of creating Nodes. This avoids giving Nodes direct access to the task list or subject set. """ def __init__(self, node_builder, project_tree, node_states, inline_nodes): self._node_builder = node_builder self.project_tree = project_tree self._node_states = dict(node_states) self._parents = OrderedSet() self._inline_nodes = inline_nodes self.snapshot_archive_root = os.path.join(project_tree.build_root, '.snapshots') def get(self, node): """Given a Node and computed node_states, gets the current state for the Node. Optionally inlines execution of inlineable dependencies if `inline_nodes=True`. """ state = self._node_states.get(node, None) if state is not None: return state if self._inline_nodes and node.is_inlineable: if node in self._parents: return Noop.cycle(list(self._parents)[-1], node) self._parents.add(node) state = self._node_states[node] = node.step(self) self._parents.remove(node) return state else: return Waiting([node]) def gen_nodes(self, subject, product, variants): """Yields Node instances which might be able to provide a value for the given inputs.""" return self._node_builder.gen_nodes(subject, product, variants) def select_node(self, selector, subject, variants): """Constructs a Node for the given Selector and the given Subject/Variants. This method is decoupled from Selector classes in order to allow the `selector` package to not need a dependency on the `nodes` package. """ selector_type = type(selector) if selector_type is Select: return SelectNode(subject, selector.product, variants, None) elif selector_type is SelectVariant: return SelectNode(subject, selector.product, variants, selector.variant_key) elif selector_type is SelectDependencies: return DependenciesNode(subject, selector.product, variants, selector.deps_product, selector.field) elif selector_type is SelectProjection: return ProjectionNode(subject, selector.product, variants, selector.projected_subject, selector.fields, selector.input_product) elif selector_type is SelectLiteral: # NB: Intentionally ignores subject parameter to provide a literal subject. return SelectNode(selector.subject, selector.product, variants, None) else: raise ValueError('Unrecognized Selector type "{}" for: {}'.format(selector_type, selector))
class StepContext(object): """Encapsulates external state and the details of creating Nodes. This avoids giving Nodes direct access to the task list or subject set. """ def __init__(self, node_builder, project_tree, node_states, inline_nodes): self._node_builder = node_builder self.project_tree = project_tree self._node_states = dict(node_states) self._parents = OrderedSet() self._inline_nodes = inline_nodes self.snapshot_archive_root = os.path.join(project_tree.build_root, '.snapshots') def get(self, node): """Given a Node and computed node_states, gets the current state for the Node. Optionally inlines execution of inlineable dependencies if `inline_nodes=True`. """ state = self._node_states.get(node, None) if state is not None: return state if self._inline_nodes and node.is_inlineable: if node in self._parents: return Noop.cycle(list(self._parents)[-1], node) self._parents.add(node) state = self._node_states[node] = node.step(self) self._parents.remove(node) return state else: return Waiting([node]) def gen_nodes(self, subject, product, variants): """Yields Node instances which might be able to provide a value for the given inputs.""" return self._node_builder.gen_nodes(subject, product, variants) def select_node(self, selector, subject, variants): """Constructs a Node for the given Selector and the given Subject/Variants. This method is decoupled from Selector classes in order to allow the `selector` package to not need a dependency on the `nodes` package. """ return self._node_builder.select_node(selector, subject, variants)
class StepContext(object): """Encapsulates external state and the details of creating Nodes. This avoids giving Nodes direct access to the task list or subject set. """ def __init__(self, node_builder, project_tree, node_states, inline_nodes): self._node_builder = node_builder self.project_tree = project_tree self._node_states = dict(node_states) self._parents = OrderedSet() self._inline_nodes = inline_nodes self.snapshot_archive_root = os.path.join(project_tree.build_root, '.snapshots') def get(self, node): """Given a Node and computed node_states, gets the current state for the Node. Optionally inlines execution of inlineable dependencies if `inline_nodes=True`. """ state = self._node_states.get(node, None) if state is not None: return state if self._inline_nodes and node.is_inlineable: if node in self._parents: return Noop.cycle(list(self._parents)[-1], node) self._parents.add(node) state = self._node_states[node] = node.step(self) self._parents.remove(node) return state else: return Waiting([node]) def get_nodes_and_states_for(self, subject, product, variants): for node in self._node_builder.gen_nodes(subject, product, variants): state = self.get(node) yield node, state def select_for(self, selector, subject, variants): """Returns the state for selecting a product via the provided selector.""" dep_node = self._node_builder.select_node(selector, subject, variants) return self.get(dep_node)