Skip to content

loop

loop #

cg.while_repeat — collect a block into a ProcedureWhile.

The block is the loop body; the yielded folder is a fresh array_path element that each iteration appends and caches into. Do-while semantics: the body runs, then condition is evaluated, and while it is true (and max_iterations is not reached) the body runs again.

condition and array_path are built by the caller (before the with), so they are recorded in the enclosing context and caught by the ProcedureWhile. The yielded folder (a PathAppend on array_path) is built inside the block, so the body's per-iteration nodes descend from it and reduce to the loop body. On the device the body and condition are cloned per iteration; the loop-invariant array_path and max_iterations are referenced once.

DEFAULT_MAX_ITERATIONS = 1000 module-attribute #

Iteration cap when while_repeat is called without max_iterations.

The condition drives normal termination; this only bounds a runaway loop.

WhileContext #

Bases: ProcedureContext

Reduce a block's roots to the body of a ProcedureWhile.

Source code in capturegraph-lib/capturegraph/procedures/procedure/authoring/contexts/loop.py
class WhileContext(ProcedureContext):
    """Reduce a block's roots to the body of a ``ProcedureWhile``."""

    def __init__(
        self,
        condition: Procedure[Bool],
        array_path: Procedure[Path],
        max_iterations: Procedure[Number] | int,
    ) -> None:
        """Reduce the block into the loop body appending into ``array_path``."""
        super().__init__()
        self._condition = condition
        self._array_path = array_path
        self._max_iterations = max_iterations

    def _finish(self) -> None:
        from capturegraph.procedures.nodes.process.structural import (
            ProcedureSequence,
            ProcedureWhile,
        )

        ProcedureWhile(
            body=ProcedureSequence(procedures=self._step_roots()),
            condition=self._condition,
            array_path=self._array_path,
            max_iterations=self._max_iterations,
        )

__init__(condition, array_path, max_iterations) #

Reduce the block into the loop body appending into array_path.

Source code in capturegraph-lib/capturegraph/procedures/procedure/authoring/contexts/loop.py
def __init__(
    self,
    condition: Procedure[Bool],
    array_path: Procedure[Path],
    max_iterations: Procedure[Number] | int,
) -> None:
    """Reduce the block into the loop body appending into ``array_path``."""
    super().__init__()
    self._condition = condition
    self._array_path = array_path
    self._max_iterations = max_iterations

while_repeat(condition, array_path, *, max_iterations=DEFAULT_MAX_ITERATIONS) #

Repeat the with block, appending one array_path element per iteration.

Yields the freshly appended element's Path (folder); cache into it with |= / &= like any path. Do-while: the body runs, then condition is evaluated, and while it is true (and max_iterations is not reached) the body runs again.

Parameters:

Name Type Description Default
condition Procedure[Bool]

Boolean procedure evaluated after each iteration; the loop continues while it is true. Built before the block, so it is a loop-level decision (e.g. cg.UserInputBool(label="Another?")), not a reference to data captured in the current iteration.

required
array_path Procedure[Path]

The Path to the Array each iteration appends into.

required
max_iterations Procedure[Number] | int

Hard iteration cap (a safety bound; the condition drives normal termination). A raw int lifts to a Constant.

DEFAULT_MAX_ITERATIONS
Example
@cg.procedure(MyTarget)
def capture(root):
    session = root.sessions[cg.CaptureTime()]
    with cg.while_repeat(cg.UserInputBool(label="Another?"), session.extras) as item:
        item &= cg.CaptureImage(label="Extra photo")
Source code in capturegraph-lib/capturegraph/procedures/procedure/authoring/contexts/loop.py
@contextmanager
def while_repeat(
    condition: Procedure[Bool],
    array_path: Procedure[Path],
    *,
    max_iterations: Procedure[Number] | int = DEFAULT_MAX_ITERATIONS,
) -> Iterator[Procedure[Path]]:
    """Repeat the ``with`` block, appending one ``array_path`` element per iteration.

    Yields the freshly appended element's ``Path`` (``folder``); cache into it with
    ``|=`` / ``&=`` like any path. Do-while: the body runs, then ``condition`` is
    evaluated, and while it is true (and ``max_iterations`` is not reached) the body
    runs again.

    Args:
        condition: Boolean procedure evaluated after each iteration; the loop
            continues while it is true. Built before the block, so it is a
            loop-level decision (e.g. ``cg.UserInputBool(label="Another?")``), not a
            reference to data captured in the current iteration.
        array_path: The ``Path`` to the ``Array`` each iteration appends into.
        max_iterations: Hard iteration cap (a safety bound; the condition drives
            normal termination). A raw ``int`` lifts to a ``Constant``.

    Example:
        ```python
        @cg.procedure(MyTarget)
        def capture(root):
            session = root.sessions[cg.CaptureTime()]
            with cg.while_repeat(cg.UserInputBool(label="Another?"), session.extras) as item:
                item &= cg.CaptureImage(label="Extra photo")
        ```
    """
    from capturegraph.procedures.nodes.destination.access import (
        PathAppend,
    )

    with WhileContext(condition, array_path, max_iterations).collect():
        yield PathAppend(source=array_path)