Merge 'github_kwirk_fail2ban/warnings-fix' into 0.9: warnings + tests

* github_kwirk_fail2ban/warnings-fix:
  BF+TST: Correctly reset time in tearDownMyTime
  ENH: Reimplement warning suppression of setup.py test --quiet
  BF: Remove warnings handler which breaks setup.py python2<2.7 and python3<3.2
  ENH: For python3.2+ use ConfigPaser which replaces SafeConfigParser
  TST: Change depreciated unittest assertEquals method to assertEqual
  TST: Ensure files are closed in tests to remove ResourceWarnings
  BF: Change logging instance logSys `warn` method to `warning`
pull/185/head
Yaroslav Halchenko 2013-04-21 22:57:37 -04:00
commit 28f00161c9
14 changed files with 49 additions and 34 deletions

View File

@ -102,7 +102,7 @@ class Fail2banClient:
def __sigTERMhandler(self, signum, frame): def __sigTERMhandler(self, signum, frame):
# Print a new line because we probably come from wait # Print a new line because we probably come from wait
print print
logSys.warn("Caught signal %d. Exiting" % signum) logSys.warning("Caught signal %d. Exiting" % signum)
sys.exit(-1) sys.exit(-1)
def __getCmdLineOptions(self, optList): def __getCmdLineOptions(self, optList):

View File

@ -133,7 +133,7 @@ class Beautifier:
c += 1 c += 1
msg = msg + "`- [" + str(c) + "]: " + response[len(response)-1] msg = msg + "`- [" + str(c) + "]: " + response[len(response)-1]
except Exception: except Exception:
logSys.warn("Beautifier error. Please report the error") logSys.warning("Beautifier error. Please report the error")
logSys.error("Beautify " + `response` + " with " + `self.__inputCmd` + logSys.error("Beautify " + `response` + " with " + `self.__inputCmd` +
" failed") " failed")
msg = msg + `response` msg = msg + `response`

View File

@ -27,8 +27,12 @@ __date__ = '$Date$'
__copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko' __copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko'
__license__ = 'GPL' __license__ = 'GPL'
import logging, os import logging, os, sys
from ConfigParser import SafeConfigParser if sys.version_info >= (3,2): # pragma: no cover
# SafeConfigParser deprecitated from python 3.2 (renamed ConfigParser)
from configparser import ConfigParser as SafeConfigParser
else: # pragma: no cover
from ConfigParser import SafeConfigParser
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = logging.getLogger(__name__)

View File

@ -70,7 +70,7 @@ class ConfigReader(SafeConfigParserWithIncludes):
# files must carry .conf suffix as well # files must carry .conf suffix as well
config_files += sorted(glob.glob('%s/*.conf' % config_dir)) config_files += sorted(glob.glob('%s/*.conf' % config_dir))
else: else:
logSys.warn("%s exists but not a directory or not accessible" logSys.warning("%s exists but not a directory or not accessible"
% config_dir) % config_dir)
# check if files are accessible, warn if any is not accessible # check if files are accessible, warn if any is not accessible
@ -80,7 +80,7 @@ class ConfigReader(SafeConfigParserWithIncludes):
if os.access(f, os.R_OK): if os.access(f, os.R_OK):
config_files_accessible.append(f) config_files_accessible.append(f)
else: else:
logSys.warn("%s exists but not accessible - skipping" % f) logSys.warning("%s exists but not accessible - skipping" % f)
if len(config_files_accessible): if len(config_files_accessible):
# at least one config exists and accessible # at least one config exists and accessible
@ -122,11 +122,11 @@ class ConfigReader(SafeConfigParserWithIncludes):
values[option[1]] = option[2] values[option[1]] = option[2]
except NoOptionError: except NoOptionError:
if not option[2] == None: if not option[2] == None:
logSys.warn("'%s' not defined in '%s'. Using default one: %r" logSys.warning("'%s' not defined in '%s'. Using default one: %r"
% (option[1], sec, option[2])) % (option[1], sec, option[2]))
values[option[1]] = option[2] values[option[1]] = option[2]
except ValueError: except ValueError:
logSys.warn("Wrong value for '" + option[1] + "' in '" + sec + logSys.warning("Wrong value for '" + option[1] + "' in '" + sec +
"'. Using default one: '" + `option[2]` + "'") "'. Using default one: '" + `option[2]` + "'")
values[option[1]] = option[2] values[option[1]] = option[2]
return values return values

View File

@ -105,7 +105,7 @@ class JailReader(ConfigReader):
logSys.debug("Caught exception: %s" % (e,)) logSys.debug("Caught exception: %s" % (e,))
return False return False
if not len(self.__actions): if not len(self.__actions):
logSys.warn("No actions were defined for %s" % self.__name) logSys.warning("No actions were defined for %s" % self.__name)
return True return True
def convert(self): def convert(self):

View File

@ -177,7 +177,7 @@ class Actions(JailThread):
aInfo["time"] = bTicket.getTime() aInfo["time"] = bTicket.getTime()
aInfo["matches"] = "".join(bTicket.getMatches()) aInfo["matches"] = "".join(bTicket.getMatches())
if self.__banManager.addBanTicket(bTicket): if self.__banManager.addBanTicket(bTicket):
logSys.warn("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"])) logSys.warning("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"]))
for action in self.__actions: for action in self.__actions:
action.execActionBan(aInfo) action.execActionBan(aInfo)
return True return True
@ -217,7 +217,7 @@ class Actions(JailThread):
aInfo["failures"] = ticket.getAttempt() aInfo["failures"] = ticket.getAttempt()
aInfo["time"] = ticket.getTime() aInfo["time"] = ticket.getTime()
aInfo["matches"] = "".join(ticket.getMatches()) aInfo["matches"] = "".join(ticket.getMatches())
logSys.warn("[%s] Unban %s" % (self.jail.getName(), aInfo["ip"])) logSys.warning("[%s] Unban %s" % (self.jail.getName(), aInfo["ip"]))
for action in self.__actions: for action in self.__actions:
action.execActionUnban(aInfo) action.execActionUnban(aInfo)

View File

@ -135,7 +135,7 @@ class AsyncServer(asyncore.dispatcher):
if os.path.exists(sock): if os.path.exists(sock):
logSys.error("Fail2ban seems to be already running") logSys.error("Fail2ban seems to be already running")
if force: if force:
logSys.warn("Forcing execution of the server") logSys.warning("Forcing execution of the server")
os.remove(sock) os.remove(sock)
else: else:
raise AsyncServerException("Server already running") raise AsyncServerException("Server already running")

View File

@ -632,7 +632,7 @@ class FileContainer:
try: try:
line = line.decode(self.getEncoding(), 'strict') line = line.decode(self.getEncoding(), 'strict')
except UnicodeDecodeError: except UnicodeDecodeError:
logSys.warn("Error decoding line from '%s' with '%s': %s" % logSys.warning("Error decoding line from '%s' with '%s': %s" %
(self.getFileName(), self.getEncoding(), `line`)) (self.getFileName(), self.getEncoding(), `line`))
if sys.version_info >= (3,): # In python3, must be decoded if sys.version_info >= (3,): # In python3, must be decoded
line = line.decode(self.getEncoding(), 'ignore') line = line.decode(self.getEncoding(), 'ignore')
@ -668,11 +668,11 @@ class DNSUtils:
try: try:
return socket.gethostbyname_ex(dns)[2] return socket.gethostbyname_ex(dns)[2]
except socket.gaierror: except socket.gaierror:
logSys.warn("Unable to find a corresponding IP address for %s" logSys.warning("Unable to find a corresponding IP address for %s"
% dns) % dns)
return list() return list()
except socket.error, e: except socket.error, e:
logSys.warn("Socket error raised trying to resolve hostname %s: %s" logSys.warning("Socket error raised trying to resolve hostname %s: %s"
% (dns, e)) % (dns, e))
return list() return list()
dnsToIp = staticmethod(dnsToIp) dnsToIp = staticmethod(dnsToIp)

View File

@ -131,10 +131,10 @@ class FilterPoll(FileFilter):
% (filename, e)) % (filename, e))
self.__file404Cnt[filename] += 1 self.__file404Cnt[filename] += 1
if self.__file404Cnt[filename] > 2: if self.__file404Cnt[filename] > 2:
logSys.warn("Too many errors. Setting the jail idle") logSys.warning("Too many errors. Setting the jail idle")
if self.jail: if self.jail:
self.jail.setIdle(True) self.jail.setIdle(True)
else: else:
logSys.warn("No jail is assigned to %s" % self) logSys.warning("No jail is assigned to %s" % self)
self.__file404Cnt[filename] = 0 self.__file404Cnt[filename] = 0
return False return False

View File

@ -55,7 +55,7 @@ class Transmitter:
ret = self.__commandHandler(command) ret = self.__commandHandler(command)
ack = 0, ret ack = 0, ret
except Exception, e: except Exception, e:
logSys.warn("Command %r has failed. Received %r" logSys.warning("Command %r has failed. Received %r"
% (command, e)) % (command, e))
ack = 1, e ack = 1, e
return ack return ack

View File

@ -53,10 +53,12 @@ class ConfigReaderTest(unittest.TestCase):
d_ = os.path.join(self.d, d) d_ = os.path.join(self.d, d)
if not os.path.exists(d_): if not os.path.exists(d_):
os.makedirs(d_) os.makedirs(d_)
open("%s/%s" % (self.d, fname), "w").write(""" f = open("%s/%s" % (self.d, fname), "w")
f.write("""
[section] [section]
option = %s option = %s
""" % value) """ % value)
f.close()
def _remove(self, fname): def _remove(self, fname):
os.unlink("%s/%s" % (self.d, fname)) os.unlink("%s/%s" % (self.d, fname))
@ -116,7 +118,7 @@ class JailReaderTest(unittest.TestCase):
action = "mail-whois[name=SSH]" action = "mail-whois[name=SSH]"
expected = ['mail-whois', {'name': 'SSH'}] expected = ['mail-whois', {'name': 'SSH'}]
result = JailReader.splitAction(action) result = JailReader.splitAction(action)
self.assertEquals(expected, result) self.assertEqual(expected, result)
class FilterReaderTest(unittest.TestCase): class FilterReaderTest(unittest.TestCase):
@ -148,7 +150,7 @@ class FilterReaderTest(unittest.TestCase):
# Add sort as configreader uses dictionary and therefore order # Add sort as configreader uses dictionary and therefore order
# is unreliable # is unreliable
self.assertEquals(sorted(filterReader.convert()), sorted(output)) self.assertEqual(sorted(filterReader.convert()), sorted(output))
class JailsReaderTest(unittest.TestCase): class JailsReaderTest(unittest.TestCase):

View File

@ -123,7 +123,7 @@ def _assert_correct_last_attempt(utest, filter_, output, count=None):
_assert_equal_entries(utest, found, output, count) _assert_equal_entries(utest, found, output, count)
def _copy_lines_between_files(fin, fout, n=None, skip=0, mode='a', terminal_line=""): def _copy_lines_between_files(in_, fout, n=None, skip=0, mode='a', terminal_line=""):
"""Copy lines from one file to another (which might be already open) """Copy lines from one file to another (which might be already open)
Returns open fout Returns open fout
@ -132,8 +132,10 @@ def _copy_lines_between_files(fin, fout, n=None, skip=0, mode='a', terminal_line
# on old Python st_mtime is int, so we should give at least 1 sec so # on old Python st_mtime is int, so we should give at least 1 sec so
# polling filter could detect the change # polling filter could detect the change
time.sleep(1) time.sleep(1)
if isinstance(fin, str): # pragma: no branch - only used with str in test cases if isinstance(in_, str): # pragma: no branch - only used with str in test cases
fin = open(fin, 'r') fin = open(in_, 'r')
else:
fin = in_
# Skip # Skip
for i in xrange(skip): for i in xrange(skip):
_ = fin.readline() _ = fin.readline()
@ -151,6 +153,9 @@ def _copy_lines_between_files(fin, fout, n=None, skip=0, mode='a', terminal_line
fout = open(fout, mode) fout = open(fout, mode)
fout.write('\n'.join(lines)) fout.write('\n'.join(lines))
fout.flush() fout.flush()
if isinstance(in_, str): # pragma: no branch - only used with str in test cases
# Opened earlier, therefore must close it
fin.close()
# to give other threads possibly some time to crunch # to give other threads possibly some time to crunch
time.sleep(0.1) time.sleep(0.1)
return fout return fout
@ -291,7 +296,7 @@ class LogFileMonitor(unittest.TestCase):
# #
# if we rewrite the file at once # if we rewrite the file at once
self.file.close() self.file.close()
_copy_lines_between_files(GetFailures.FILENAME_01, self.name) _copy_lines_between_files(GetFailures.FILENAME_01, self.name).close()
self.filter.getFailures(self.name) self.filter.getFailures(self.name)
_assert_correct_last_attempt(self, self.filter, GetFailures.FAILURES_01) _assert_correct_last_attempt(self, self.filter, GetFailures.FAILURES_01)
@ -308,6 +313,7 @@ class LogFileMonitor(unittest.TestCase):
def testNewChangeViaGetFailures_move(self): def testNewChangeViaGetFailures_move(self):
# #
# if we move file into a new location while it has been open already # if we move file into a new location while it has been open already
self.file.close()
self.file = _copy_lines_between_files(GetFailures.FILENAME_01, self.name, self.file = _copy_lines_between_files(GetFailures.FILENAME_01, self.name,
n=14, mode='w') n=14, mode='w')
self.filter.getFailures(self.name) self.filter.getFailures(self.name)
@ -316,7 +322,7 @@ class LogFileMonitor(unittest.TestCase):
# move aside, but leaving the handle still open... # move aside, but leaving the handle still open...
os.rename(self.name, self.name + '.bak') os.rename(self.name, self.name + '.bak')
_copy_lines_between_files(GetFailures.FILENAME_01, self.name, skip=14) _copy_lines_between_files(GetFailures.FILENAME_01, self.name, skip=14).close()
self.filter.getFailures(self.name) self.filter.getFailures(self.name)
_assert_correct_last_attempt(self, self.filter, GetFailures.FAILURES_01) _assert_correct_last_attempt(self, self.filter, GetFailures.FAILURES_01)
self.assertEqual(self.filter.failManager.getFailTotal(), 3) self.assertEqual(self.filter.failManager.getFailTotal(), 3)
@ -454,7 +460,7 @@ def get_monitor_failures_testcase(Filter_):
def test_rewrite_file(self): def test_rewrite_file(self):
# if we rewrite the file at once # if we rewrite the file at once
self.file.close() self.file.close()
_copy_lines_between_files(GetFailures.FILENAME_01, self.name) _copy_lines_between_files(GetFailures.FILENAME_01, self.name).close()
self.assert_correct_last_attempt(GetFailures.FAILURES_01) self.assert_correct_last_attempt(GetFailures.FAILURES_01)
# What if file gets overridden # What if file gets overridden
@ -468,6 +474,7 @@ def get_monitor_failures_testcase(Filter_):
def test_move_file(self): def test_move_file(self):
# if we move file into a new location while it has been open already # if we move file into a new location while it has been open already
self.file.close()
self.file = _copy_lines_between_files(GetFailures.FILENAME_01, self.name, self.file = _copy_lines_between_files(GetFailures.FILENAME_01, self.name,
n=14, mode='w') n=14, mode='w')
# Poll might need more time # Poll might need more time
@ -477,25 +484,25 @@ def get_monitor_failures_testcase(Filter_):
# move aside, but leaving the handle still open... # move aside, but leaving the handle still open...
os.rename(self.name, self.name + '.bak') os.rename(self.name, self.name + '.bak')
_copy_lines_between_files(GetFailures.FILENAME_01, self.name, skip=14) _copy_lines_between_files(GetFailures.FILENAME_01, self.name, skip=14).close()
self.assert_correct_last_attempt(GetFailures.FAILURES_01) self.assert_correct_last_attempt(GetFailures.FAILURES_01)
self.assertEqual(self.filter.failManager.getFailTotal(), 3) self.assertEqual(self.filter.failManager.getFailTotal(), 3)
# now remove the moved file # now remove the moved file
_killfile(None, self.name + '.bak') _killfile(None, self.name + '.bak')
_copy_lines_between_files(GetFailures.FILENAME_01, self.name, n=100) _copy_lines_between_files(GetFailures.FILENAME_01, self.name, n=100).close()
self.assert_correct_last_attempt(GetFailures.FAILURES_01) self.assert_correct_last_attempt(GetFailures.FAILURES_01)
self.assertEqual(self.filter.failManager.getFailTotal(), 6) self.assertEqual(self.filter.failManager.getFailTotal(), 6)
def test_new_bogus_file(self): def test_new_bogus_file(self):
# to make sure that watching whole directory does not effect # to make sure that watching whole directory does not effect
_copy_lines_between_files(GetFailures.FILENAME_01, self.name, n=100) _copy_lines_between_files(GetFailures.FILENAME_01, self.name, n=100).close()
self.assert_correct_last_attempt(GetFailures.FAILURES_01) self.assert_correct_last_attempt(GetFailures.FAILURES_01)
# create a bogus file in the same directory and see if that doesn't affect # create a bogus file in the same directory and see if that doesn't affect
open(self.name + '.bak2', 'w').write('') open(self.name + '.bak2', 'w').close()
_copy_lines_between_files(GetFailures.FILENAME_01, self.name, n=100) _copy_lines_between_files(GetFailures.FILENAME_01, self.name, n=100).close()
self.assert_correct_last_attempt(GetFailures.FAILURES_01) self.assert_correct_last_attempt(GetFailures.FAILURES_01)
self.assertEqual(self.filter.failManager.getFailTotal(), 6) self.assertEqual(self.filter.failManager.getFailTotal(), 6)
_killfile(None, self.name + '.bak2') _killfile(None, self.name + '.bak2')

View File

@ -118,6 +118,7 @@ def tearDownMyTime():
if old_TZ: if old_TZ:
os.environ['TZ'] = old_TZ os.environ['TZ'] = old_TZ
time.tzset() time.tzset()
MyTime.myTime = None
from fail2ban.tests import banmanagertestcase from fail2ban.tests import banmanagertestcase
from fail2ban.tests import clientreadertestcase from fail2ban.tests import clientreadertestcase

View File

@ -39,7 +39,7 @@ except ImportError:
from distutils.command.build_py import build_py from distutils.command.build_py import build_py
from distutils.command.build_scripts import build_scripts from distutils.command.build_scripts import build_scripts
from os.path import isfile, join, isdir from os.path import isfile, join, isdir
import sys import sys, warnings
from glob import glob from glob import glob
if setuptools and "test" in sys.argv: if setuptools and "test" in sys.argv:
@ -51,7 +51,8 @@ if setuptools and "test" in sys.argv:
logSys.addHandler(hdlr) logSys.addHandler(hdlr)
if set(["-q", "--quiet"]) & set(sys.argv): if set(["-q", "--quiet"]) & set(sys.argv):
logSys.setLevel(logging.FATAL) logSys.setLevel(logging.FATAL)
logging.captureWarnings(True) warnings.simplefilter("ignore")
sys.warnoptions.append("ignore")
elif set(["-v", "--verbose"]) & set(sys.argv): elif set(["-v", "--verbose"]) & set(sys.argv):
logSys.setLevel(logging.DEBUG) logSys.setLevel(logging.DEBUG)
else: else: