mirror of https://github.com/fail2ban/fail2ban
PY3(BF): config reader -- handle __name__ interpolation
parent
d05e7a5746
commit
203ddb370a
|
@ -28,15 +28,45 @@ __copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko'
|
|||
__license__ = 'GPL'
|
||||
|
||||
import logging, os, sys
|
||||
|
||||
if sys.version_info >= (3,2): # pragma: no cover
|
||||
# SafeConfigParser deprecitated from python 3.2 (renamed ConfigParser)
|
||||
from configparser import ConfigParser as SafeConfigParser
|
||||
|
||||
# SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser)
|
||||
from configparser import ConfigParser as SafeConfigParser, \
|
||||
BasicInterpolation
|
||||
|
||||
# And interpolation of __name__ was simply removed, thus we need to
|
||||
# decorate default interpolator to handle it
|
||||
class BasicInterpolationWithName(BasicInterpolation):
|
||||
"""Decorator to bring __name__ interpolation back.
|
||||
|
||||
Original handling of __name__ was removed because of
|
||||
functional deficiencies: http://bugs.python.org/issue10489
|
||||
|
||||
commit v3.2a4-105-g61f2761
|
||||
Author: Lukasz Langa <lukasz@langa.pl>
|
||||
Date: Sun Nov 21 13:41:35 2010 +0000
|
||||
|
||||
Issue #10489: removed broken `__name__` support from configparser
|
||||
|
||||
But should be fine to reincarnate for our use case
|
||||
"""
|
||||
def _interpolate_some(self, parser, option, accum, rest, section, map,
|
||||
depth):
|
||||
if section and not (__name__ in map):
|
||||
map = map.copy() # just to be safe
|
||||
map['__name__'] = section
|
||||
return super(BasicInterpolationWithName, self)._interpolate_some(
|
||||
parser, option, accum, rest, section, map, depth)
|
||||
|
||||
else: # pragma: no cover
|
||||
from ConfigParser import SafeConfigParser
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger(__name__)
|
||||
|
||||
__all__ = ['SafeConfigParserWithIncludes']
|
||||
|
||||
class SafeConfigParserWithIncludes(SafeConfigParser):
|
||||
"""
|
||||
Class adds functionality to SafeConfigParser to handle included
|
||||
|
@ -68,6 +98,14 @@ after = 1.conf
|
|||
|
||||
SECTION_NAME = "INCLUDES"
|
||||
|
||||
if sys.version_info >= (3,2):
|
||||
# overload constructor only for fancy new Python3's
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs = kwargs.copy()
|
||||
kwargs['interpolation'] = BasicInterpolationWithName()
|
||||
super(SafeConfigParserWithIncludes, self).__init__(
|
||||
*args, **kwargs)
|
||||
|
||||
#@staticmethod
|
||||
def getIncludes(resource, seen = []):
|
||||
"""
|
||||
|
|
|
@ -21,7 +21,7 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
|
|||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
|
||||
__license__ = "GPL"
|
||||
|
||||
import os, shutil, tempfile, unittest
|
||||
import os, shutil, sys, tempfile, unittest
|
||||
|
||||
from fail2ban.client.configreader import ConfigReader
|
||||
from fail2ban.client.jailreader import JailReader
|
||||
|
@ -47,7 +47,7 @@ class ConfigReaderTest(unittest.TestCase):
|
|||
"""Call after every test case."""
|
||||
shutil.rmtree(self.d)
|
||||
|
||||
def _write(self, fname, value):
|
||||
def _write(self, fname, value=None, content=None):
|
||||
# verify if we don't need to create .d directory
|
||||
if os.path.sep in fname:
|
||||
d = os.path.dirname(fname)
|
||||
|
@ -55,10 +55,13 @@ class ConfigReaderTest(unittest.TestCase):
|
|||
if not os.path.exists(d_):
|
||||
os.makedirs(d_)
|
||||
f = open("%s/%s" % (self.d, fname), "w")
|
||||
f.write("""
|
||||
if value is not None:
|
||||
f.write("""
|
||||
[section]
|
||||
option = %s
|
||||
""" % value)
|
||||
""" % value)
|
||||
if content is not None:
|
||||
f.write(content)
|
||||
f.close()
|
||||
|
||||
def _remove(self, fname):
|
||||
|
@ -105,6 +108,28 @@ option = %s
|
|||
self._remove("c.local")
|
||||
self.assertEqual(self._getoption(), 1)
|
||||
|
||||
def testInterpolations(self):
|
||||
self.assertFalse(self.c.read('i')) # nothing is there yet
|
||||
self._write("i.conf", value=None, content="""
|
||||
[DEFAULT]
|
||||
b = a
|
||||
zz = the%(__name__)s
|
||||
|
||||
[section]
|
||||
y = 4%(b)s
|
||||
e = 5${b}
|
||||
z = %(__name__)s
|
||||
|
||||
[section2]
|
||||
z = 3%(__name__)s
|
||||
""")
|
||||
self.assertTrue(self.c.read('i'))
|
||||
self.assertEqual(self.c.sections(), ['section', 'section2'])
|
||||
self.assertEqual(self.c.get('section', 'y'), '4a') # basic interpolation works
|
||||
self.assertEqual(self.c.get('section', 'e'), '5${b}') # no extended interpolation
|
||||
self.assertEqual(self.c.get('section', 'z'), 'section') # __name__ works
|
||||
self.assertEqual(self.c.get('section', 'zz'), 'thesection') # __name__ works even 'delayed'
|
||||
self.assertEqual(self.c.get('section2', 'z'), '3section2') # and differs per section ;)
|
||||
|
||||
class JailReaderTest(unittest.TestCase):
|
||||
|
||||
|
|
Loading…
Reference in New Issue