class Problem(object):
    """
    A problem report. Each time a Check finds a problem, it creates
    a Problem instance to report it.
    """
    def __init__(self, msg):
        self.msg = msg

class CheckBase(object):
    """
    Base of all CheckXxx classes. These are individual checks; each
    covers a certain type of security problem.
    """
    name = None
    
    def do_check(self):
        """
        Performs the actual verification; returns a list of Problem instances
        (an empty list means "no problems")
        """
        raise NotImplemented('You must override do_check in subclasses of CheckBase')

class CheckRunner(object):
    """
    Container for a set of Checks. Runs them on demand and reports the
    problems they find.
    """
    def __init__(self):
        self.checks = []
    
    def add(self, check):
        """
        Add a Check object to the list
        """
        self.checks.append(check)
    
    def run(self):
        """
        Runs the checks. Returns a string reporting a summary
        of the check runs.
        """
        problems = []
        ok_count = 0
        for check in self.checks:
            check_out = check.do_check()
            if check_out:
                problems += ((check, problem) for problem in check_out)
            else:
                ok_count += 1
        
        output = 'ran %d chekcs\n' % len(self.checks)
        if problems:
            output += '%d problems\n' % len(problems)
            for (check, problem) in problems:
                output += '    %s: "%s"\n' % (check.name, problem.msg)
            output += '%d of %d checks ok\n' % (ok_count, len(self.checks))
        else:
            output += 'all checks ok\n'
        
        return output
    
class NewCheckRunner(object):
    def __init__(self):
        self.checks = []
    
    def add(self, check):
        """
        Add a Check object to the list
        """
        self.checks.append(check)
    
    def runTests(self):
        problems = []
        for check in self.checks:
            check_out = check.do_check()
            if check_out:
                problems += ((check, problem) for problem in check_out)
        
        return problems    