Suppose I have some kind of context manager (from a third-party library) that I am using like so:
with freeze_time(test_dt):
lines_of_code_1
lines_of_code_2
lines_of_code_3
But, suppose if there is no value for test_dt, the context manager should not run, but all of the remaining code should run, like so:
if test_dt:
with freeze_time(test_dt):
lines_of_code_1
lines_of_code_2
lines_of_code_3
else:
lines_of_code_1
lines_of_code_2
lines_of_code_3
Assume that lines_of_code
here is 2-3 lines of code which are exactly identical, is there a cleaner way of writing this? I'm aware that I could write something like this:
def do_thing():
lines_of_code_1
lines_of_code_2
lines_of_code_3
if test_dt:
with freeze_time(test_dt):
do_thing()
else:
do_thing()
But I'm not crazy about this formatting. Also, I don't want to have to litter this pattern all over my code.
There is one final possibility, but I'm not certain it will work: subclassing the context manager and skipping the __enter__
and __exit__
functions if the test_dt given is empty, like so:
class optional_freeze_time(object):
def __init__(self, test_dt=None):
if test_dt:
self.ctx_manager = freeze_time(test_dt)
else:
self.ctx_manager = None
def __enter__(self, *args, **kwargs):
if self.ctx_manager:
self.ctx_manager.__enter__(*args, **kwargs)
def __exit__(self, *args, **kwargs):
if self.ctx_manager:
self.ctx_manager.__exit__(*args, **kwargs)
I tested it out with a blank context manager class, and it seemed to behave correctly. However, I'm worried whether a real context manager will behave correctly if I do this (I'm not very familiar with the internals of how it works).
Here's an easy way to wrap around an existing context manager without even using any classes:
Output: