ini-parser cannot handle empty keys
Closed this issue · 5 comments
providing a missing key (such as "Foo" in the following example):
ini.parse('[Section]\nFoo = \nBar = Baz\n')
will cause an IndexError:
In [4]: ini.parse('[Section]\nFoo = \nBar = Baz\n')
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-4-f5daad03ff17> in <module>
----> 1 ini.parse('[Section]\nFoo = \nBar = Baz\n')
~/open_source/ini-parser/ini/__init__.py in decode(string)
78 continue
79 key = unsafe(match[2])
---> 80 value = _parse_value(unsafe(match[4])) if match[3] else True
81 if value in ('true', 'True'):
82 value = True
~/open_source/ini-parser/ini/__init__.py in unsafe(val)
140 def unsafe(val):
141 val = (val or '').strip()
--> 142 if _is_quoted(val):
143 # remove the single quotes before calling JSON.parse
144 if val[0] == "'":
~/open_source/ini-parser/ini/__init__.py in _is_quoted(val)
125
126 def _is_quoted(val):
--> 127 return (val[0] == '"' and val[-1] == '"') or (val[0] == "'" and val[-1] == "'")
128
129
IndexError: string index out of range
since it's sometimes desirable to explicitly fail and in other times it's desirable to have a default value (see the discussion regarding ConfigParser on SO), IMO decode()
should define a new keyword parameter on_empty_key
to be implemented as followed:
def decode(string, on_empty_key = object):
...
[__init__.py:80] if match[4].strip():
[__init__.py:81] value = _parse_value(unsafe(match[4])) if match[3] else True
[__init__.py:82] elif on_empty_key == object:
[__init__.py:83] raise ValueError(match[2].strip())
[__init__.py:84] else:
[__init__.py:85] value = on_empty_key
with the proposed fix:
In [1]: import ini
In [2]: ini.parse('[Section]\nFoo = \nBar = Baz\n', on_empty_key=None)
Out[2]: {'Section': {'Foo': None, 'Bar': 'Baz'}}
In [3]: ini.parse('[Section]\nFoo = \nBar = Baz\n')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-3-f5daad03ff17> in <module>
----> 1 ini.parse('[Section]\nFoo = \nBar = Baz\n')
~/open_source/ini-parser/ini/__init__.py in decode(string, on_empty_key)
84 value = _parse_value(unsafe(match[4])) if match[3] else True
85 elif on_empty_key == EMPTY_KEY_SENTINEL:
---> 86 raise ValueError(key)
87 else:
88 value = on_empty_key
ValueError: Foo
In [4]:
I don't see why this is necessary. Why would you have an empty key?
hi andrew,
a quick search on google found this ini example showing an ini with an empty value.
generally speaking, I opted to use ini-parser over ConfigParser because of its simplicity, but not supporting empty values is a major drawback when comparing the two (since I need it to parse arbitrary ini files the user providers). while not part of the official format, many parsers allow such flexibility.
finally, since the default behavior (raising an exception) is kept (in a more user friendly manner IMO), I see no reason not to include this feature.
Hmm, thanks for the info. I'll review the PR later :)