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'
|
__license__ = 'GPL'
|
||||||
|
|
||||||
import logging, os, sys
|
import logging, os, sys
|
||||||
|
|
||||||
if sys.version_info >= (3,2): # pragma: no cover
|
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
|
else: # pragma: no cover
|
||||||
from ConfigParser import SafeConfigParser
|
from ConfigParser import SafeConfigParser
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
# Gets the instance of the logger.
|
||||||
logSys = logging.getLogger(__name__)
|
logSys = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
__all__ = ['SafeConfigParserWithIncludes']
|
||||||
|
|
||||||
class SafeConfigParserWithIncludes(SafeConfigParser):
|
class SafeConfigParserWithIncludes(SafeConfigParser):
|
||||||
"""
|
"""
|
||||||
Class adds functionality to SafeConfigParser to handle included
|
Class adds functionality to SafeConfigParser to handle included
|
||||||
|
@ -68,6 +98,14 @@ after = 1.conf
|
||||||
|
|
||||||
SECTION_NAME = "INCLUDES"
|
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
|
#@staticmethod
|
||||||
def getIncludes(resource, seen = []):
|
def getIncludes(resource, seen = []):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -21,7 +21,7 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
import os, shutil, tempfile, unittest
|
import os, shutil, sys, tempfile, unittest
|
||||||
|
|
||||||
from fail2ban.client.configreader import ConfigReader
|
from fail2ban.client.configreader import ConfigReader
|
||||||
from fail2ban.client.jailreader import JailReader
|
from fail2ban.client.jailreader import JailReader
|
||||||
|
@ -47,7 +47,7 @@ class ConfigReaderTest(unittest.TestCase):
|
||||||
"""Call after every test case."""
|
"""Call after every test case."""
|
||||||
shutil.rmtree(self.d)
|
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
|
# verify if we don't need to create .d directory
|
||||||
if os.path.sep in fname:
|
if os.path.sep in fname:
|
||||||
d = os.path.dirname(fname)
|
d = os.path.dirname(fname)
|
||||||
|
@ -55,10 +55,13 @@ class ConfigReaderTest(unittest.TestCase):
|
||||||
if not os.path.exists(d_):
|
if not os.path.exists(d_):
|
||||||
os.makedirs(d_)
|
os.makedirs(d_)
|
||||||
f = open("%s/%s" % (self.d, fname), "w")
|
f = open("%s/%s" % (self.d, fname), "w")
|
||||||
f.write("""
|
if value is not None:
|
||||||
|
f.write("""
|
||||||
[section]
|
[section]
|
||||||
option = %s
|
option = %s
|
||||||
""" % value)
|
""" % value)
|
||||||
|
if content is not None:
|
||||||
|
f.write(content)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
def _remove(self, fname):
|
def _remove(self, fname):
|
||||||
|
@ -105,6 +108,28 @@ option = %s
|
||||||
self._remove("c.local")
|
self._remove("c.local")
|
||||||
self.assertEqual(self._getoption(), 1)
|
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):
|
class JailReaderTest(unittest.TestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue