# ==================================================================== # Provides a with-style resource handler for optionally-None resources # ==================================================================== class optional_with(object): # pylint: disable=too-few-public-methods # This is a wrapper - it is not meant to provide any extra methods. """Provides a wrapper for objects supporting "with", allowing None. This lets a user use the "with object" syntax for resource usage (e.g. locks) even when the wrapped with object is None. e.g. wrapped_lock = optional_with(thread.Lock()) with wrapped_lock: # Do something while the lock is obtained. pass might_be_none = None wrapped_none = optional_with(might_be_none) with wrapped_none: # This code here still works. pass This prevents having to write code like this when a lock is optional: if lock: lock.acquire() try: code_fragment_always_run() finally: if lock: lock.release() And I'd posit it is safer, as it becomes impossible to forget the try/finally using optional_with(), since the with syntax can be used. """ def __init__(self, wrapped_object): self.wrapped_object = wrapped_object def __enter__(self): if self.wrapped_object is not None: return self.wrapped_object.__enter__() else: return self def __exit__(self, the_type, value, traceback): if self.wrapped_object is not None: return self.wrapped_object.__exit__(the_type, value, traceback) else: # Don't suppress any exceptions return False