[openstack-dev] [nova][oslo] oslo.config and import chains
Doug Hellmann
doug at doughellmann.com
Thu Aug 7 18:58:30 UTC 2014
On Aug 7, 2014, at 12:39 PM, Kevin L. Mitchell <kevin.mitchell at rackspace.com> wrote:
> On Thu, 2014-08-07 at 17:27 +0100, Matthew Booth wrote:
>> On 07/08/14 16:27, Kevin L. Mitchell wrote:
>>> On Thu, 2014-08-07 at 12:15 +0100, Matthew Booth wrote:
>>>> A (the?) solution is to register_opts() in foo before importing any
>>>> modules which might also use oslo.config.
>>>
>>> Actually, I disagree. The real problem here is the definition of
>>> bar_func(). The default value of the parameter "arg" will likely always
>>> be the default value of foo_opt, rather than the configured value,
>>> because "CONF.foo_opt" will be evaluated at module load time. The way
>>> bar_func() should be defined would be:
>>>
>>> def bar_func(arg=None):
>>> if not arg:
>>> arg = CONF.foo_opt
>>> …
>>>
>>> That ensures that arg will be the configured value, and should also
>>> solve the import conflict.
>>
>> That's different behaviour, because you can no longer pass arg=None. The
>> fix isn't to change the behaviour of the code.
>
> Well, the point is that the code as written is incorrect. And if 'None'
> is an input you want to allow, then use an incantation like:
>
> _unset = object()
>
> def bar_func(arg=_unset):
> if arg is _unset:
> arg = CONF.foo_opt
> …
>
> In any case, the operative point is that CONF.<attribute> must always be
> evaluated inside run-time code, never at module load time.
It would be even better to take the extra step of registering the option at runtime at the point it is about to be used by calling register_opt() inside bar_func() instead of when bar is imported. That avoids import order concerns, and re-enforces the idea that options should be declared local to the code that uses them and their values should be passed to other code, rather than having 2 modules tightly bound together through a global configuration value.
Doug
More information about the OpenStack-dev
mailing list