[iniparse] r141 committed - Accessing non-existing sections using the container notation...

1 view
Skip to first unread message

inip...@googlecode.com

unread,
May 8, 2010, 3:59:37 PM5/8/10
to iniparse...@googlegroups.com
Revision: 141
Author: psoberoi
Date: Sat May 8 12:58:40 2010
Log: Accessing non-existing sections using the container notation
(i.e. cfg['foo']['bar']) will auto-create the sections. This
has always been the behavior for dotted access, but so far
container access used to raise a KeyError exception.

http://code.google.com/p/iniparse/source/detail?r=141

Modified:
/trunk/iniparse/compat.py
/trunk/iniparse/config.py
/trunk/iniparse/ini.py
/trunk/tests/test_ini.py

=======================================
--- /trunk/iniparse/compat.py Sun Feb 22 13:35:19 2009
+++ /trunk/iniparse/compat.py Sat May 8 12:58:40 2010
@@ -68,17 +68,13 @@

The DEFAULT section is not acknowledged.
"""
- try:
- self.data[section]
- return True
- except KeyError:
- return False
+ return (section in self.data)

def options(self, section):
"""Return a list of option names for the given section name."""
- try:
+ if section in self.data:
return list(self.data[section])
- except KeyError:
+ else:
raise NoSectionError(section)

def read(self, filenames):
@@ -119,19 +115,20 @@
raise NoSectionError(section)
if vars is not None and option in vars:
value = vars[option]
- try:
- sec = self.data[section]
+
+ sec = self.data[section]
+ if option in sec:
return sec._compat_get(option)
- except KeyError:
+ else:
raise NoOptionError(option, section)

def items(self, section):
- try:
+ if section in self.data:
ans = []
for opt in self.data[section]:
ans.append((opt, self.get(section, opt)))
return ans
- except KeyError:
+ else:
raise NoSectionError(section)

def getint(self, section, option):
@@ -151,21 +148,17 @@

def has_option(self, section, option):
"""Check for the existence of a given option in a given section."""
- try:
+ if section in self.data:
sec = self.data[section]
- except KeyError:
+ else:
raise NoSectionError(section)
- try:
- sec[option]
- return True
- except KeyError:
- return False
+ return (option in sec)

def set(self, section, option, value):
"""Set an option."""
- try:
+ if section in self.data:
self.data[section][option] = value
- except KeyError:
+ else:
raise NoSectionError(section)

def write(self, fp):
@@ -174,15 +167,14 @@

def remove_option(self, section, option):
"""Remove an option."""
- try:
+ if section in self.data:
sec = self.data[section]
- except KeyError:
+ else:
raise NoSectionError(section)
- try:
- sec[option]
+ if option in sec:
del sec[option]
return 1
- except KeyError:
+ else:
return 0

def remove_section(self, section):
=======================================
--- /trunk/iniparse/config.py Fri May 7 09:04:34 2010
+++ /trunk/iniparse/config.py Sat May 8 12:58:40 2010
@@ -17,7 +17,7 @@

# Methods that must be implemented by subclasses

- def __getitem__(self, key):
+ def _getitem(self, key):
return NotImplementedError(key)

def __setitem__(self, key, value):
@@ -32,7 +32,15 @@
def _new_namespace(self, name):
raise NotImplementedError(name)

- # Machinery for converting dotted access into contained access
+ def __contains__(self, key):
+ try:
+ self._getitem(key)
+ except KeyError:
+ return False
+ return True
+
+ # Machinery for converting dotted access into container access,
+ # and automatically creating new sections/namespaces.
#
# To distinguish between accesses of class members and namespace
# keys, we first call object.__getattribute__(). If that succeeds,
@@ -43,9 +51,15 @@
# not just in the __init__() function. See BasicNamespace for
# an example.

+ def __getitem__(self, key):
+ try:
+ return self._getitem(key)
+ except KeyError:
+ return Undefined(key, self)
+
def __getattr__(self, name):
try:
- return self.__getitem__(name)
+ return self._getitem(name)
except KeyError:
if name.startswith('__') and name.endswith('__'):
raise AttributeError
@@ -65,10 +79,10 @@
except AttributeError:
self.__delitem__(name)

- # During unpickling, __getattr__/__getitem__ raise exceptions since
- # the data dicts have not been initialized yet. So, the attribute
- # lookup for __setstate__ gets a non-AttributeError exception. Thus
- # we need to define it explicitly.
+ # During unpickling, Python checks if the class has a __setstate__
+ # method. But, the data dicts have not been initialised yet, which
+ # leads to _getitem and hence __getattr__ raising an exception. So
+ # we explicitly impement default __setstate__ behavior.
def __setstate__(self, state):
self.__dict__.update(state)

@@ -88,6 +102,10 @@
obj = self.namespace._new_namespace(self.name)
obj[name] = value

+ def __setitem__(self, name, value):
+ obj = self.namespace._new_namespace(self.name)
+ obj[name] = value
+

# ---- Basic implementation of a ConfigNamespace

@@ -167,7 +185,7 @@
def __init__(self):
self._data = {}

- def __getitem__(self, key):
+ def _getitem(self, key):
return self._data[key]

def __setitem__(self, key, value):
@@ -218,11 +236,11 @@
name_components = name.split('.')
ns = self
for n in name_components[:-1]:
- try:
+ if n in ns:
ns = ns[n]
if not isinstance(ns, ConfigNamespace):
raise TypeError('value-namespace conflict', n)
- except KeyError:
+ else:
ns = ns._new_namespace(n)
ns[name_components[-1]] = value

@@ -262,11 +280,11 @@
for name in source:
value = source[name]
if isinstance(value, ConfigNamespace):
- try:
+ if name in target:
myns = target[name]
if not isinstance(myns, ConfigNamespace):
raise TypeError('value-namespace conflict')
- except KeyError:
+ else:
myns = target._new_namespace(name)
update_config(myns, value)
else:
=======================================
--- /trunk/iniparse/ini.py Sat May 8 00:00:44 2010
+++ /trunk/iniparse/ini.py Sat May 8 12:58:40 2010
@@ -351,7 +351,7 @@
value = re.sub('\n+', '\n', value)
return value

- def __getitem__(self, key):
+ def _getitem(self, key):
if key == '__name__':
return self._lines[-1].name
if self._optionxform: key = self._optionxform(key)
@@ -473,7 +473,7 @@
_optionxform = _make_xform_property('_optionxform', 'optionxform')
_sectionxform = _make_xform_property('_sectionxform', 'optionxform')

- def __getitem__(self, key):
+ def _getitem(self, key):
if key == DEFAULTSECT:
return self._defaults
if self._sectionxform: key = self._sectionxform(key)
=======================================
--- /trunk/tests/test_ini.py Sat Apr 17 11:30:31 2010
+++ /trunk/tests/test_ini.py Sat May 8 12:58:40 2010
@@ -223,8 +223,14 @@
p = ini.INIConfig(sio)
p.new1.created = 1
setattr(getattr(p, 'new2'), 'created', 1)
+ p.new3['created'] = 1
+ p['new4'].created = 1
+ p['new5']['created'] = 1
self.assertEqual(p.new1.created, 1)
self.assertEqual(p.new2.created, 1)
+ self.assertEqual(p.new3.created, 1)
+ self.assertEqual(p.new4.created, 1)
+ self.assertEqual(p.new5.created, 1)

def test_order(self):
sio = StringIO(self.s1)

--
To post to this group, send email to iniparse...@googlegroups.com
To unsubscribe from this group, send email to iniparse-commi...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/iniparse-commits?hl=en
Reply all
Reply to author
Forward
0 new messages