Issue 25 in iniparse: config.section.key fails rather than returning Undefined for undefined section

2 views
Skip to first unread message

inip...@googlecode.com

unread,
Nov 13, 2010, 7:30:33 AM11/13/10
to iniparse...@googlegroups.com
Status: New
Owner: ----
Labels: Type-Defect Priority-Medium

New issue 25 by chris.morganiser: config.section.key fails rather than
returning Undefined for undefined section
http://code.google.com/p/iniparse/issues/detail?id=25

Long summary: An INIConfig provides a nice Undefined object for undefined
sections so that you can set values directly. Unfortunately, this Undefined
does not provide magic __getitem__ or __getattr__ methods, so undefined
values raise an AttributeError.

I use a simple function, ``ini_defined``, for some things on INI files for
setting and validation of some INI files in a set format, where the
sections and keys may or may not exist::

from iniparse.config import Undefined

def ini_defined(val):
return not isinstance(val, Undefined)

I may add I think this would be helpful in ``iniparse.utils``.

On to the issue. Here is the current behaviour::

>>> import iniparse
>>> config = iniparse.INIConfig()
>>> config.section
<iniparse.config.Undefined object at 0x7fcfaeff9190>
>>> config.section.key
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Undefined' object has no attribute 'key'
>>> config.section.key = 'value'
>>> config.section.key2
<iniparse.config.Undefined object at 0x7fcfaeff9350>

When the section is defined, an undefined key works, so that I can do
``ini_defined(config.section.key2)``. However,
``ini_defined(config.section2.key)`` will raise an AttributeError, so I've
taken to doing ``ini_defined(config.section2) and
ini_defined(config.section2.key)`` when the section may not exist. Not neat.

Here is a patch which provides __getitem__ and __getattr__ for the
Undefined object, returning another Undefined object. There is one
side-effect to it which I've identified; the getter can then go to any
number of levels. But the setter will fail, so I think it's alright::

>>> # New behaviour; foo.section2 is not a defined section
>>> foo.section2.key
<iniparse.config.Undefined object at 0x7f3d7ab63a50>
>>> foo.section2.key.subkey
<iniparse.config.Undefined object at 0x7f3d7ab63bd0>
>>> foo.section2.key.subkey = 'value'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "iniparse/config.py", line 108, in __setattr__
obj =
object.__getattribute__(self, 'namespace')._new_namespace(self.name)
TypeError: 'Undefined' object is not callable
>>> foo.section2.key.subkey.subkey
<iniparse.config.Undefined object at 0x7f3d7ab63b50>
>>> foo.section2.key.subkey.subkey = 'value'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "iniparse/config.py", line 108, in __setattr__
obj =
object.__getattribute__(self, 'namespace')._new_namespace(self.name)
TypeError: 'Undefined' object is not callable

I don't think it would be worth while "fixing" this getter behaviour with
another Undefined subclass. Note that this is a different exception from
the Exception: ('No sub-sections allowed', 'key3') you get if the section
is defined but the key is not - e.g. ``foo.section.key3.subkey``. If it
matters I can fix it up.

Side note: defining __getattribute__ instead of __getattr__ and using
object.__getattribute__ locally (a decorator could switch self for a magic
thing which would use object.__getattribute__ instead of
self.__getattribute__) would remove the possibility of name clashes
entirely. But I think I'll create another bug and patch for that. May take
a while, though.

Attachments:
get-undefined.patch 975 bytes

inip...@googlecode.com

unread,
Nov 23, 2010, 4:39:51 PM11/23/10
to iniparse...@googlegroups.com

Comment #1 on issue 25 by chris.morganiser: config.section.key fails rather
than returning Undefined for undefined section
http://code.google.com/p/iniparse/issues/detail?id=25

I discovered an issue with this; rather than having ``'key' in
iniconfig.UndefinedSection`` or ``list(iniconfig.UndefinedSection)`` raise
an error as they currently do, it triggers a race condition, getting items
0, 1, 2, etc.

I discussed this at
http://stackoverflow.com/questions/4256357/how-to-override-python-listiterator-behaviour
and came up with the following solution.

The solution is overriding __iter__ in the Undefined class::

def __iter__(self):
"""Simple iterator which produces no output."""
return
yield

This makes ``list(iniconfig.UndefinedSection)`` return [] and makes ``'key'
in iniconfig.UndefinedSection`` return False as expected.

Reply all
Reply to author
Forward
0 new messages