Source code for cobra.util.context

"""Context manager for the package."""

from functools import partial
from typing import TYPE_CHECKING, Any, Callable, Optional


if TYPE_CHECKING:
    from cobra import Object


[docs]class HistoryManager: """ Define a base context manager. It records a list of actions to be taken at a later time. This is used to implement context managers that allow temporary changes to a `cobra.core.Model`. """ def __init__(self, **kwargs) -> None: """Initialize the class.""" super().__init__(**kwargs) # this acts like a stack self._history = []
[docs] def __call__(self, operation: Callable[[Any], Any]) -> None: """Add the corresponding operation to the history stack. Parameters ---------- operation : callable A function to be called at a later time. """ self._history.append(operation)
[docs] def reset(self) -> None: """Trigger executions for all items in the stack in reverse order.""" while self._history: entry = self._history.pop() entry()
[docs] def size(self) -> int: """Calculate number of operations on the stack.""" return len(self._history)
[docs]def get_context(obj: "Object") -> Optional[HistoryManager]: """Search for a context manager. Parameters ---------- obj: cobra.Object The cobra.Object for which to search context manager. Returns ------- HistoryManager or None HistoryManager instance, or None if no context manager is found. Raises ------ AttributeError If no context manager is found. IndexError If no context manager is found. """ # works for cobra.core.Model objects try: return obj._contexts[-1] except (AttributeError, IndexError): pass # works for objects other than cobra.core.Model try: return obj._model._contexts[-1] except (AttributeError, IndexError): pass
[docs]def resettable(func: Callable[[Any], Any]) -> Callable[[Any], Any]: """ Simplify the context management of simple object attributes. It gets the value of the attribute prior to setting it, and stores a function to set the value to the old value in the `cobra.util.HistoryManager`. Parameters ---------- func: callable The function to decorate. Returns ------- callable The decorated function. """ def wrapper(self, new_value): context = get_context(self) if context: old_value = getattr(self, func.__name__) # Don't clutter the context with unchanged variables if old_value == new_value: return context(partial(func, self, old_value)) func(self, new_value) return wrapper