#!/usr/bin/python

# pylint-wrapper: Script to wrap pylint output
#
# Author: Rodney Dawes <rodney.dawes@canonical.com>
#
# Copyright 2009 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify it 
# under the terms of the GNU General Public License version 3, as published 
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but 
# WITHOUT ANY WARRANTY; without even the implied warranties of 
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
# PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along 
# with this program.  If not, see <http://www.gnu.org/licenses/>.
"""Wrapper script for pylint command"""

import ConfigParser
import os
import subprocess

try:
    SRCDIR = os.environ['SRCDIR']
except KeyError:
    SRCDIR = os.getcwd()

def _read_pylintrc_ignored():
    """Get the ignored files list from pylintrc"""
    config = ConfigParser.ConfigParser()
    config.read([os.path.join(SRCDIR, 'pylintrc')])

    try:
        return config.get("MASTER", "ignore").split(",")
    except ConfigParser.NoOptionError:
        return None

def _group_lines_by_file(data):
    """Format file:line:message output as lines grouped by file."""
    failed = False
    outputs = []
    filename = ""
    for line in data.splitlines():
        current = line.split(":", 3)
        if line.startswith("    "):
            outputs.append("    " + current[0] + "")
        elif line.startswith("build/") or len(current) < 3:
            pass
        elif filename == current[0]:
            # pylint warning W0511 is a custom note
            if not "[W0511]" in current[2]:
                failed = True
            outputs.append("    " + current[1] + ": " + current[2])
        elif filename != current[0]:
            filename = current[0]
            outputs.append("")
            outputs.append(filename + ":")
            # pylint warning W0511 is a custom note
            if not "[W0511]" in current[2]:
                failed = True
            outputs.append("    " + current[1] + ": " + current[2])

    return (failed, "\n".join(outputs))

def _find_files():
    """Find all Python files under the current tree."""
    pyfiles = []
    # pylint: disable-msg=W0612
    for root, dirs, files in os.walk(SRCDIR, topdown=False):
        for file in files:
            path = "%s/" % root
            if file.endswith(".py") or path.endswith("bin/"):
                pyfiles.append(os.path.join(root, file))

    pyfiles.sort()
    return pyfiles


failed = False

ignored = _read_pylintrc_ignored()

# So that we can match the path correctly
moreignores = [os.path.join(SRCDIR, item) for item in ignored]
ignored.extend(moreignores)
if os.environ.get('USE_PYFLAKES'):
    pylint_args = ["pyflakes"]
else:
    pylint_args = ["pylint",
                   "--output-format=parseable",
                   "--include-ids=yes",
                   "--rcfile=" + os.path.join(SRCDIR, "pylintrc"),]
    

for path in _find_files():
    if path not in ignored and not path.startswith(os.path.join(SRCDIR,
                                                                "_build")):
        pylint_args.append(path)

p = subprocess.Popen(pylint_args,
                     bufsize=4096, stdout=subprocess.PIPE)
notices = p.stdout

output = "".join(notices.readlines())
if output != "":
    print "== Python Lint Notices =="
    (failed, grouped) = _group_lines_by_file(output)
    print grouped
    print ""

returncode = p.wait()
if returncode != 0:
    exit(returncode)

if failed:
    exit(1)
