It is not ugly, it is better - dot notation means there is probably some custom class' object within another custom class' object. The more feasible way is to use dictionaries (that use bracket notation).
But if you insist, you can probably translate the code like that:
def config2object(config):
"""
Convert dictionary into instance allowing access to dictionary keys using
dot notation (attributes).
"""
class ConfigObject(dict):
"""
Represents configuration options' group, works like a dict
"""
def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs)
def __getattr__(self, name):
return self[name]
def __setattr__(self, name, val):
self[name] = val
if isinstance(config, dict):
result = ConfigObject()
for key in config:
result[key] = config2object(config[key])
return result
else:
return config
And the tests show the expected results:
>>> c1 = {
'conf1': {
'key1': 'aaa',
'key2': 12321,
'key3': False,
},
'conf2': 'bbbb',
}
>>> c1
{'conf2': 'bbbb', 'conf1': {'key3': False, 'key2': 12321, 'key1': 'aaa'}}
>>> c2 = config2object(c1)
>>> c2.conf1
{'key3': False, 'key2': 12321, 'key1': 'aaa'}
>>> c2.conf1.key1
'aaa'
>>> c2.conf1.key3
False
>>> c2.conf2
'bbbb'
EDIT: Sven Marnach noted that Config('config.ini')
is some custom class instance. It is not a dictionary, it has some custom methods that could be quite useful, but could make some configuration options inaccessible (when there is name conflict). Therefore the preferred approach is not to use the solution I mentioned, but to use bracket notation to access configuration options.