summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgrabner <pjg.github@ubergrabner.net>2016-12-14 11:44:40 -0500
committergrabner <pjg.github@ubergrabner.net>2016-12-14 11:44:40 -0500
commitcfcc9cefcdd74670e2871a869d0eceb364d89366 (patch)
treebc2f0f6741e0476fe599cda02d8fbbc39d385b4a
parent0bbdcee2745a7dc7208063e779275c49fb079545 (diff)
downloadiniherit-cfcc9cefcdd74670e2871a869d0eceb364d89366.tar.gz
added "%(ENV)s" interpolation support
-rw-r--r--iniherit/parser.py16
-rw-r--r--iniherit/test.py45
2 files changed, 61 insertions, 0 deletions
diff --git a/iniherit/parser.py b/iniherit/parser.py
index a186cfe..ed5c5be 100644
--- a/iniherit/parser.py
+++ b/iniherit/parser.py
@@ -8,6 +8,8 @@
import io
import os.path
+import warnings
+
import six
from six.moves import configparser as CP
from six.moves import urllib
@@ -20,6 +22,8 @@ except ImportError:
# be overridden as well...
# TODO: should `ConfigParser.set()` be checked for option==INHERITTAG?...
+from . import interpolation
+
__all__ = (
'Loader', 'IniheritMixin', 'RawConfigParser',
'ConfigParser', 'SafeConfigParser',
@@ -174,6 +178,18 @@ class IniheritMixin(object):
else:
_real_RawConfigParser.set(dst, dstsect, option, value)
+ #----------------------------------------------------------------------------
+ # todo: yikes! overriding a private method!...
+ def _interpolate(self, section, option, rawval, vars):
+ return interpolation.interpolate(
+ self, _real_ConfigParser._interpolate, section, option, rawval, vars)
+ if not hasattr(_real_ConfigParser, '_interpolate'):
+ warnings.warn(
+ 'ConfigParser did not have a "_interpolate" method...'
+ ' iniherit may be broken on this platform',
+ RuntimeWarning)
+
+
#------------------------------------------------------------------------------
# todo: i'm a little worried about the diamond inheritance here...
class RawConfigParser(IniheritMixin, _real_RawConfigParser):
diff --git a/iniherit/test.py b/iniherit/test.py
index fddd93a..fef1bbd 100644
--- a/iniherit/test.py
+++ b/iniherit/test.py
@@ -213,6 +213,51 @@ class TestIniherit(unittest.TestCase):
output.getvalue(),
'[s3]\ns3v = b3\n\n[s2]\ns2v = o2\n\n[s1]\ns1v = b1\n\n')
+ #----------------------------------------------------------------------------
+ def test_interpolation_env(self):
+ import os
+ from six.moves.configparser import InterpolationDepthError
+ from iniherit import InterpolationMissingEnvError
+ files = {k: textwrap.dedent(v) for k, v in {
+ 'config.ini' : '''\
+ [section]
+ key1 = %(ENV:INIHERIT_TEST_EXIST)s
+ key2 = %(ENV:INIHERIT_TEST_EXIST:-default-value)s
+ key3 = %(ENV:INIHERIT_TEST_NOEXIST)s
+ key4 = %(ENV:INIHERIT_TEST_NOEXIST:-default-value)s
+ key5 = %(ENV:INIHERIT_TEST_INFLOOP)s
+ ''',
+ }.items()}
+ files = {k: textwrap.dedent(v) for k, v in files.items()}
+ parser = ConfigParser(loader=ByteLoader(files))
+ parser.read('config.ini')
+ # note: setting envvar's *after* reading to ensure that interpolation
+ # occurs on-demand, i.e. lazy-eval
+ os.environ.pop('INIHERIT_TEST_NOEXIST', None)
+ os.environ['INIHERIT_TEST_EXIST'] = 'this-value'
+ os.environ['INIHERIT_TEST_INFLOOP'] = '%(ENV:INIHERIT_TEST_INFLOOP)s'
+ self.assertEqual(parser.get('section', 'key1'), 'this-value')
+ self.assertEqual(parser.get('section', 'key2'), 'this-value')
+ self.assertEqual(parser.get('section', 'key4'), 'default-value')
+ with self.assertRaises(InterpolationMissingEnvError) as cm:
+ parser.get('section', 'key3')
+ self.assertMultiLineEqual(str(cm.exception), textwrap.dedent('''\
+ Bad value substitution:
+ \tsection: [section]
+ \toption : key3
+ \tkey : INIHERIT_TEST_NOEXIST
+ \trawval : %(ENV:INIHERIT_TEST_NOEXIST)s
+ '''))
+ with self.assertRaises(InterpolationDepthError) as cm:
+ parser.get('section', 'key5')
+ self.assertMultiLineEqual(str(cm.exception), textwrap.dedent('''\
+ Value interpolation too deeply recursive:
+ \tsection: [section]
+ \toption : key5
+ \trawval : %(ENV:INIHERIT_TEST_INFLOOP)s
+ '''))
+
+
#------------------------------------------------------------------------------
# end of $Id$
# $ChangeLog$