Over the weekend, I wanted to implement something that acted as both a class and
function decorator, but could also be used as a context manager. I needed this
flexibility for overriding configuration values making it easier to write tests.
I wanted to use it in the following ways:
-
as a function decorator:
@config_override(DEBUG='False')
def test_something():
...
-
as a class decorator that would decorate all methods that start with
test_:
@config_override(DEBUG='False')
class TestSomething:
def test_something(self):
...
-
as a context manager that allowed for multiple layer of overriding:
def test_something():
with config_override(DEBUG='False'):
with config_override(SOMETHING_ELSE='ou812'):
...
This kind of need comes up periodically, but infrequently enough that I forget
how I wrote it the last time around.
This post walks through how I structured it.
Read more…