Say you have a configuration class (like Django's settings.py
style settings) that gets set up when an application is started. You load it like so.
from myapp import config
CONF = config.CONF
You want to use some variable from this configuration as a decorator argument, like so.
@decorators.mydecorator(run_timeout=CONF.timeout)
def run_stuff_once():
# blah, blah, blah...
@decorators.mydecorator(interval=CONF.interval)
def run_stuff_periodically():
# blah, blah, blah...
If you run this, the configuration variables are loaded at runtime and never change. We can see this happening even without the use of decorators.
>>> class Config(object):
... x = 5
...
>>> config = Config()
>>>
>>> def func(param=config.x):
... print(param)
...
>>> func()
5
>>> config.x = 9
>>> func()
5
This causes two issues:
- If the configuration for that configuration variable is loaded after the file where this function is contained, the function uses the original value of the variable.
- Regardless of import order, it is not possible to change configuration dynamically once the file has been loaded.
Can this be resolved? Were I talking about "normal functions", I would adopt a solution similar to resolving PyLint's W0102 warning, i.e.
>>> def func2(param=None):
... if param is None:
... param = config.x
... print(param)
...
>>> func2()
9
>>> config.x = 5
>>> func2()
5
However, it is not possible to do this for the decorator as, as seen above, the value passed to the decorator can change. I'm stumped as to a resolution for this case.