diff options
author | Ludovico Cavedon <cavedon@debian.org> | 2010-06-12 16:34:16 -0700 |
---|---|---|
committer | Ludovico Cavedon <cavedon@debian.org> | 2010-06-12 16:34:16 -0700 |
commit | b58ade97bde0f26271ebbccf6959bfc5a30a88d2 (patch) | |
tree | 3d296c03823ea4806febf3d0d9becb8a90e57671 /iniparse | |
parent | 60b2e5ebf0b074436aaec91409d9863d015b9a73 (diff) |
Imported Upstream version 0.4
Diffstat (limited to 'iniparse')
-rw-r--r-- | iniparse/__init__.py | 3 | ||||
-rw-r--r-- | iniparse/compat.py | 44 | ||||
-rw-r--r-- | iniparse/config.py | 43 | ||||
-rw-r--r-- | iniparse/ini.py | 49 | ||||
-rw-r--r-- | iniparse/utils.py | 47 |
5 files changed, 101 insertions, 85 deletions
diff --git a/iniparse/__init__.py b/iniparse/__init__.py index 1a267e6..8de756f 100644 --- a/iniparse/__init__.py +++ b/iniparse/__init__.py @@ -3,9 +3,10 @@ # Copyright (c) 2007 Tim Lauridsen <tla@rasmil.dk> # All Rights Reserved. See LICENSE-PSF & LICENSE for details. -from ini import INIConfig, tidy, change_comment_syntax +from ini import INIConfig, change_comment_syntax from config import BasicConfig, ConfigNamespace from compat import RawConfigParser, ConfigParser, SafeConfigParser +from utils import tidy from ConfigParser import DuplicateSectionError, \ NoSectionError, NoOptionError, \ diff --git a/iniparse/compat.py b/iniparse/compat.py index 3de6148..db89ed8 100644 --- a/iniparse/compat.py +++ b/iniparse/compat.py @@ -68,17 +68,13 @@ class RawConfigParser(object): 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 @@ class RawConfigParser(object): 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 @@ class RawConfigParser(object): 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 @@ class RawConfigParser(object): 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): diff --git a/iniparse/config.py b/iniparse/config.py index 508dac2..5cfa2ea 100644 --- a/iniparse/config.py +++ b/iniparse/config.py @@ -17,7 +17,7 @@ class ConfigNamespace(object): # 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 @@ class ConfigNamespace(object): 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,10 +51,18 @@ class ConfigNamespace(object): # 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 return Undefined(name, self) def __setattr__(self, name, value): @@ -63,9 +79,10 @@ class ConfigNamespace(object): except AttributeError: self.__delitem__(name) - def __getstate__(self): - return self.__dict__ - + # 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) @@ -85,6 +102,10 @@ class Undefined(object): 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 @@ -164,7 +185,7 @@ class BasicConfig(ConfigNamespace): def __init__(self): self._data = {} - def __getitem__(self, key): + def _getitem(self, key): return self._data[key] def __setitem__(self, key, value): @@ -215,11 +236,11 @@ class BasicConfig(ConfigNamespace): 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 @@ -259,11 +280,11 @@ def update_config(target, source): 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: diff --git a/iniparse/ini.py b/iniparse/ini.py index f0e7ec2..408354d 100644 --- a/iniparse/ini.py +++ b/iniparse/ini.py @@ -45,7 +45,6 @@ import re from ConfigParser import DEFAULTSECT, ParsingError, MissingSectionHeaderError import config -import compat class LineType(object): line = None @@ -352,7 +351,7 @@ class INISection(config.ConfigNamespace): 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) @@ -474,7 +473,7 @@ class INIConfig(config.ConfigNamespace): _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) @@ -642,47 +641,3 @@ class INIConfig(config.ConfigNamespace): raise exc -def tidy(cfg): - """Clean up blank lines. - - This functions makes the configuration look clean and - handwritten - consecutive empty lines and empty lines at - the start of the file are removed, and one is guaranteed - to be at the end of the file. - """ - - if isinstance(cfg, compat.RawConfigParser): - cfg = cfg.data - cont = cfg._data.contents - i = 1 - while i < len(cont): - if isinstance(cont[i], LineContainer): - tidy_section(cont[i]) - i += 1 - elif (isinstance(cont[i-1], EmptyLine) and - isinstance(cont[i], EmptyLine)): - del cont[i] - else: - i += 1 - - # Remove empty first line - if cont and isinstance(cont[0], EmptyLine): - del cont[0] - - # Ensure a last line - if cont and not isinstance(cont[-1], EmptyLine): - cont.append(EmptyLine()) - -def tidy_section(lc): - cont = lc.contents - i = 1 - while i < len(cont): - if (isinstance(cont[i-1], EmptyLine) and - isinstance(cont[i], EmptyLine)): - del cont[i] - else: - i += 1 - - # Remove empty first line - if len(cont) > 1 and isinstance(cont[1], EmptyLine): - del cont[1] diff --git a/iniparse/utils.py b/iniparse/utils.py new file mode 100644 index 0000000..829fc28 --- /dev/null +++ b/iniparse/utils.py @@ -0,0 +1,47 @@ +import compat +from ini import LineContainer, EmptyLine + +def tidy(cfg): + """Clean up blank lines. + + This functions makes the configuration look clean and + handwritten - consecutive empty lines and empty lines at + the start of the file are removed, and one is guaranteed + to be at the end of the file. + """ + + if isinstance(cfg, compat.RawConfigParser): + cfg = cfg.data + cont = cfg._data.contents + i = 1 + while i < len(cont): + if isinstance(cont[i], LineContainer): + tidy_section(cont[i]) + i += 1 + elif (isinstance(cont[i-1], EmptyLine) and + isinstance(cont[i], EmptyLine)): + del cont[i] + else: + i += 1 + + # Remove empty first line + if cont and isinstance(cont[0], EmptyLine): + del cont[0] + + # Ensure a last line + if cont and not isinstance(cont[-1], EmptyLine): + cont.append(EmptyLine()) + +def tidy_section(lc): + cont = lc.contents + i = 1 + while i < len(cont): + if (isinstance(cont[i-1], EmptyLine) and + isinstance(cont[i], EmptyLine)): + del cont[i] + else: + i += 1 + + # Remove empty first line + if len(cont) > 1 and isinstance(cont[1], EmptyLine): + del cont[1] |