~ubuntu-branches/ubuntu/saucy/fail2ban/saucy

« back to all changes in this revision

Viewing changes to testcases/utils.py

  • Committer: Package Import Robot
  • Author(s): Yaroslav Halchenko
  • Date: 2013-05-13 11:58:56 UTC
  • mfrom: (1.1.15) (10.2.13 sid)
  • Revision ID: package-import@ubuntu.com-20130513115856-x7six9p53qcie0vl
Tags: 0.8.9-1
* New upstream release
  - significant improvements in documentation (Closes: #400416)
  - roundcube auth filter (Closes: #699442)
  - enforces C locale for dates (Closes: #686341)
  - provides bash_completion.d/fail2ban
* debian/jail.conf:
  - added findtime and documentation on those basic options from jail.conf
    (Closes: #704568)
  - added new sample jails definitions for ssh-route, ssh-iptables-ipset{4,6},
    roundcube-auth, sogo-auth, mysqld-auth
* debian/control:
  - suggest system-log-daemon (Closes: #691001)
  - boost policy compliance to 3.9.4
* debian/rules:
  - run fail2ban's unittests at build time but ignore the failures
    (there are still some known issues to fix up to guarantee robust testing
    in clean chroots etc).
    Only pyinotify was added to build-depends since gamin might still be
    buggy on older releases and get stuck, which would complicate
    backporting

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
 
2
# vi: set ft=python sts=4 ts=4 sw=4 noet :
 
3
 
 
4
# This file is part of Fail2Ban.
 
5
#
 
6
# Fail2Ban is free software; you can redistribute it and/or modify
 
7
# it under the terms of the GNU General Public License as published by
 
8
# the Free Software Foundation; either version 2 of the License, or
 
9
# (at your option) any later version.
 
10
#
 
11
# Fail2Ban is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with Fail2Ban; if not, write to the Free Software
 
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 
 
20
 
 
21
__author__ = "Yaroslav Halchenko"
 
22
__copyright__ = "Copyright (c) 2013 Yaroslav Halchenko"
 
23
__license__ = "GPL"
 
24
 
 
25
import logging, os, re, traceback
 
26
from os.path import basename, dirname
 
27
 
 
28
#
 
29
# Following "traceback" functions are adopted from PyMVPA distributed
 
30
# under MIT/Expat and copyright by PyMVPA developers (i.e. me and
 
31
# Michael).  Hereby I re-license derivative work on these pieces under GPL
 
32
# to stay in line with the main Fail2Ban license
 
33
#
 
34
def mbasename(s):
 
35
        """Custom function to include directory name if filename is too common
 
36
 
 
37
        Also strip .py at the end
 
38
        """
 
39
        base = basename(s)
 
40
        if base.endswith('.py'):
 
41
                base = base[:-3]
 
42
        if base in set(['base', '__init__']):
 
43
                base = basename(dirname(s)) + '.' + base
 
44
        return base
 
45
 
 
46
class TraceBack(object):
 
47
        """Customized traceback to be included in debug messages
 
48
        """
 
49
 
 
50
        def __init__(self, compress=False):
 
51
                """Initialize TrackBack metric
 
52
 
 
53
                Parameters
 
54
                ----------
 
55
                compress : bool
 
56
                  if True then prefix common with previous invocation gets
 
57
                  replaced with ...
 
58
                """
 
59
                self.__prev = ""
 
60
                self.__compress = compress
 
61
 
 
62
        def __call__(self):
 
63
                ftb = traceback.extract_stack(limit=100)[:-2]
 
64
                entries = [[mbasename(x[0]), dirname(x[0]), str(x[1])] for x in ftb]
 
65
                entries = [ [e[0], e[2]] for e in entries
 
66
                                        if not (e[0] in ['unittest', 'logging.__init__']
 
67
                                                        or e[1].endswith('/unittest'))]
 
68
 
 
69
                # lets make it more concise
 
70
                entries_out = [entries[0]]
 
71
                for entry in entries[1:]:
 
72
                        if entry[0] == entries_out[-1][0]:
 
73
                                entries_out[-1][1] += ',%s' % entry[1]
 
74
                        else:
 
75
                                entries_out.append(entry)
 
76
                sftb = '>'.join(['%s:%s' % (mbasename(x[0]),
 
77
                                                                        x[1]) for x in entries_out])
 
78
                if self.__compress:
 
79
                        # lets remove part which is common with previous invocation
 
80
                        prev_next = sftb
 
81
                        common_prefix = os.path.commonprefix((self.__prev, sftb))
 
82
                        common_prefix2 = re.sub('>[^>]*$', '', common_prefix)
 
83
 
 
84
                        if common_prefix2 != "":
 
85
                                sftb = '...' + sftb[len(common_prefix2):]
 
86
                        self.__prev = prev_next
 
87
 
 
88
                return sftb
 
89
 
 
90
class FormatterWithTraceBack(logging.Formatter):
 
91
        """Custom formatter which expands %(tb) and %(tbc) with tracebacks
 
92
 
 
93
        TODO: might need locking in case of compressed tracebacks
 
94
        """
 
95
        def __init__(self, fmt, *args, **kwargs):
 
96
                logging.Formatter.__init__(self, fmt=fmt, *args, **kwargs)
 
97
                compress = '%(tbc)s' in fmt
 
98
                self._tb = TraceBack(compress=compress)
 
99
 
 
100
        def format(self, record):
 
101
                record.tbc = record.tb = self._tb()
 
102
                return logging.Formatter.format(self, record)