To create a temporary setup for pytest, you may think fixtures. But my case isn't like yours.
I needed to change tempolarly a value in the middle of my test so I could get faster results.
We will use the with
statement. It will make a dedicated "scope" to that temporary setup. I'm sure that you already used them to open files. It is particularly powerful as it creates a context manager, which increases readibility, and protects developers from themselves.
Why do clean? Because it's an addiction since I discovered C++ destructors, but above all, Rust drop trait.
The goal is to have the save
and restore
code as close as each over to avoid irrelevant variables of saved state.
We need to create a class using the __enter__
and __exit__
method defined. We will use __init__
method
to define those functions.
""" Quick save and restore context manager (by TheRolf) """
class SaveAndRestore(object):
def __init__(self, save_fct, restore_fct):
self.save_fct = save_fct
self.saved = None
self.restore_fct = restore_fct
def __enter__(self):
self.saved = self.save_fct()
return self.saved
def __exit__(self, *_):
self.restore_fct(self.saved)
Wow so complicated! My god, this is pure genius! /s
You will ask me: This is useless?, we still have to make a function and lambda are very limited. That is where lamba functions come useful. You can write some "anonymous" functions and define on the fly save and restore operations.
With Python 3.8+, you can even make it kinda multiline and local binding!
To use this, you can simply make your with
statement and make your best code. If you want you can use the saved value but it is not mandatory:
with SaveAndRestore(
lambda: "value", # save function
lambda saved: print("Value saved was: " + str(saved)) # restore function
) as saved:
print("This is the saved value: " + str(saved))
We can read and interpret this as a human:
- [Reading the class name] The following code with save and restore values.
- [Reading the save lambda] Okay I save this value.
- [Reading the restore lambda] and after it will be restored like that.
- [Reading inside the with block] Meanwhile, these operations occur.
Now let your imagination do whatever you want. You can use array or tuple return values to save more data and/or extract some inside the scope.
Only sad part, we cannot have a return value for the with statement for even better lexical code. However you can still use an external variable.
Thanks for reading, hit me on social networks and give me your best feedback or improvements!
TheRolf
We could add a new parameter set_fct
to the constructor so that change the place where the saved value is stored.
And we can get an even cleaner code:
""" Quick save and restore context manager (by TheRolf) """
class SaveAndRestore(object):
def __init__(self, save_fct, restore_fct, set_fct = lambda: None):
self.save_fct = save_fct
self.saved = None
self.set_fct = set_fct
self.restore_fct = restore_fct
def __enter__(self):
self.saved = self.save_fct()
self.set_fct()
return self.saved
def __exit__(self, *_):
self.restore_fct(self.saved)