Loading buildstream/sandbox/sandbox.py +62 −12 Original line number Diff line number Diff line Loading @@ -29,7 +29,8 @@ See also: :ref:`sandboxing`. """ import os from collections import namedtuple from collections import deque, namedtuple from contextlib import contextmanager from .._exceptions import ImplError, BstError from ..storage._filebaseddirectory import FileBasedDirectory Loading Loading @@ -73,6 +74,22 @@ class SandboxFlags(): """ # _QueueEntryType() # # A type for sandbox queue entries. # class _QueueEntryType(): # A queued command. COMMAND = 1 # A queued context manager enter. CONTEXT_MANAGER_ENTER = 2 # A queued context manager exit. CONTEXT_MANAGER_EXIT = 3 class Sandbox(): """Sandbox() Loading Loading @@ -265,7 +282,8 @@ class Sandbox(): *Since: 1.4* """ entry = namedtuple('QueueEntry', ['command', 'cwd', 'env', 'start_callback', 'complete_callback']) entry = namedtuple('QueueEntry', ['type', 'command', 'cwd', 'env', 'start_callback', 'complete_callback']) entry.type = _QueueEntryType.COMMAND entry.command = command entry.cwd = self._get_work_directory(cwd=cwd) entry.env = self._get_environment(cwd=cwd, env=env) Loading @@ -273,6 +291,24 @@ class Sandbox(): entry.complete_callback = complete_callback self._queue.append(entry) @contextmanager def queue_context_manager(self, cm): """Queue entering and exiting a context manager Args: cm: A context manager *Since: 1.4* """ entry = namedtuple('QueueEntry', ['type', 'cm']) entry.type = _QueueEntryType.CONTEXT_MANAGER_ENTER entry.cm = cm self._queue.append(entry) yield entry = namedtuple('QueueEntry', ['type']) entry.type = _QueueEntryType.CONTEXT_MANAGER_EXIT self._queue.append(entry) def run_queue(self, flags): """Run a command in the sandbox. Loading @@ -289,7 +325,11 @@ class Sandbox(): queue = self._queue self._queue = [] # Stack of pending context manager exit methods exit_stack = deque() try: for entry in queue: if entry.type == _QueueEntryType.COMMAND: if entry.start_callback: entry.start_callback() if entry.command: Loading @@ -299,6 +339,16 @@ class Sandbox(): entry.complete_callback(exit_code) if exit_code != 0: break elif entry.type == _QueueEntryType.CONTEXT_MANAGER_ENTER: entry.cm.__enter__() exit_stack.append(entry.cm.__exit__) elif entry.type == _QueueEntryType.CONTEXT_MANAGER_EXIT: exit_cb = exit_stack.pop() exit_cb(None, None, None) finally: while exit_stack: exit_cb = exit_stack.pop() exit_cb(None, None, None) ################################################ # Private methods # Loading Loading
buildstream/sandbox/sandbox.py +62 −12 Original line number Diff line number Diff line Loading @@ -29,7 +29,8 @@ See also: :ref:`sandboxing`. """ import os from collections import namedtuple from collections import deque, namedtuple from contextlib import contextmanager from .._exceptions import ImplError, BstError from ..storage._filebaseddirectory import FileBasedDirectory Loading Loading @@ -73,6 +74,22 @@ class SandboxFlags(): """ # _QueueEntryType() # # A type for sandbox queue entries. # class _QueueEntryType(): # A queued command. COMMAND = 1 # A queued context manager enter. CONTEXT_MANAGER_ENTER = 2 # A queued context manager exit. CONTEXT_MANAGER_EXIT = 3 class Sandbox(): """Sandbox() Loading Loading @@ -265,7 +282,8 @@ class Sandbox(): *Since: 1.4* """ entry = namedtuple('QueueEntry', ['command', 'cwd', 'env', 'start_callback', 'complete_callback']) entry = namedtuple('QueueEntry', ['type', 'command', 'cwd', 'env', 'start_callback', 'complete_callback']) entry.type = _QueueEntryType.COMMAND entry.command = command entry.cwd = self._get_work_directory(cwd=cwd) entry.env = self._get_environment(cwd=cwd, env=env) Loading @@ -273,6 +291,24 @@ class Sandbox(): entry.complete_callback = complete_callback self._queue.append(entry) @contextmanager def queue_context_manager(self, cm): """Queue entering and exiting a context manager Args: cm: A context manager *Since: 1.4* """ entry = namedtuple('QueueEntry', ['type', 'cm']) entry.type = _QueueEntryType.CONTEXT_MANAGER_ENTER entry.cm = cm self._queue.append(entry) yield entry = namedtuple('QueueEntry', ['type']) entry.type = _QueueEntryType.CONTEXT_MANAGER_EXIT self._queue.append(entry) def run_queue(self, flags): """Run a command in the sandbox. Loading @@ -289,7 +325,11 @@ class Sandbox(): queue = self._queue self._queue = [] # Stack of pending context manager exit methods exit_stack = deque() try: for entry in queue: if entry.type == _QueueEntryType.COMMAND: if entry.start_callback: entry.start_callback() if entry.command: Loading @@ -299,6 +339,16 @@ class Sandbox(): entry.complete_callback(exit_code) if exit_code != 0: break elif entry.type == _QueueEntryType.CONTEXT_MANAGER_ENTER: entry.cm.__enter__() exit_stack.append(entry.cm.__exit__) elif entry.type == _QueueEntryType.CONTEXT_MANAGER_EXIT: exit_cb = exit_stack.pop() exit_cb(None, None, None) finally: while exit_stack: exit_cb = exit_stack.pop() exit_cb(None, None, None) ################################################ # Private methods # Loading