Source code for fmeTestSupport.Context

# Copyright (c) Fraunhofer MEVIS, Germany. All rights reserved.
# **InsertLicense** code

from contextlib import contextmanager
import os
from typing import Callable, ContextManager, Dict, Union, TypeVar, MutableMapping

YieldType = TypeVar("YieldType")
MemoryType = TypeVar("MemoryType")

[docs]@contextmanager def Context( doAction:Union[ Callable[ [], YieldType], Callable[ [MemoryType], YieldType] ], undoAction:Union[ Callable[ [YieldType], None], Callable[ [YieldType, MemoryType], None] ], undoOnError:bool=True, memory:MemoryType=None ) -> ContextManager[YieldType]: """Generic context manager to temporarily do something, and then undo it on exit, but (optionally) only if no exception has occurred in between. :param doAction: Callback to be called before yielding :param undoAction: Callback to be called on exit :param undoOnError: If set, the undoAction is NOT executed if an exception occurred within the context manager body :param memory: Optional mutable object (e.g. a dict) that doAction can use to remember stuff required by undoAction. \ If provided, it is passed to both functions as first/second parameter. :yields: The return value of doAction """ undo = True v = doAction() if memory is None else doAction( memory ) try: yield v except: undo = undoOnError raise finally: if undo: undoAction( v ) if memory is None else undoAction( v, memory )
[docs]@contextmanager def TemporaryItems( dictionary:MutableMapping, additionalItems:dict, unsetOnError:bool=True ): """ Contextmanager that temporarily extends a dictionary with additional items. If the provided additionalItems overwrite pre-existing ones, the original valus will be restored afterwards. :param dictionary: Target dictionary to be extended. :param additionalItems: Source dictionary to be used to extend the given target dictionary. :param unsetOnError: If set, the variables are NOT unset if an exception occurred within the context manager body. :yields: None """ orig_values = {} def ___do(): for variableName, value in additionalItems.items(): if variableName in dictionary: orig_values[ variableName ] = dictionary[ variableName ] dictionary[ variableName ] = value def ___undo( _ ): for variableName in additionalItems: if variableName in orig_values: dictionary[ variableName ] = orig_values[ variableName ] else: del dictionary[ variableName ] # with Context( ___do, ___undo, undoOnError=unsetOnError ): yield
[docs]@contextmanager def EnvironmentVariables( additionalItems:Dict[str,str], unsetOnError:bool=True ): """ Context manager to temporarily set environment variables. Internally uses AdditionalItems(). :param additionalItems: Dictionary to be used to extend environment variables. :param unsetOnError: If set, the variables are NOT unset if an exception occurred within the context manager body. :yields: None """ with TemporaryItems( os.environ, additionalItems, unsetOnError=unsetOnError ): yield