2016-04-19 12:20:35 +08:00
|
|
|
# ====================================================================
|
|
|
|
# Provides a with-style resource handler for optionally-None resources
|
|
|
|
# ====================================================================
|
2015-09-30 06:19:06 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-04-19 12:20:35 +08:00
|
|
|
class optional_with(object):
|
2015-09-30 06:19:06 +08:00
|
|
|
# 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.
|
|
|
|
|
2016-04-19 12:20:35 +08:00
|
|
|
wrapped_lock = optional_with(thread.Lock())
|
2015-09-30 06:19:06 +08:00
|
|
|
with wrapped_lock:
|
|
|
|
# Do something while the lock is obtained.
|
|
|
|
pass
|
|
|
|
|
|
|
|
might_be_none = None
|
2016-04-19 12:20:35 +08:00
|
|
|
wrapped_none = optional_with(might_be_none)
|
2015-09-30 06:19:06 +08:00
|
|
|
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:
|
2016-04-19 12:20:35 +08:00
|
|
|
code_fragment_always_run()
|
2015-09-30 06:19:06 +08:00
|
|
|
finally:
|
|
|
|
if lock:
|
|
|
|
lock.release()
|
|
|
|
|
|
|
|
And I'd posit it is safer, as it becomes impossible to
|
2016-04-19 12:20:35 +08:00
|
|
|
forget the try/finally using optional_with(), since
|
2015-09-30 06:19:06 +08:00
|
|
|
the with syntax can be used.
|
|
|
|
"""
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-09-30 06:19:06 +08:00
|
|
|
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
|