#!/usr/bin/env python
#     Copyright 2013, Kay Hayen, mailto:kay.hayen@gmail.com
#
#     Part of "Nuitka", an optimizing Python compiler that is compatible and
#     integrates with CPython, but also works on its own.
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.
#

# Disabled globally:
#
# W0232: Class has no __init__ method
# Who cares, I am using overrides that don't need to change object init a lot
# and I rarely ever made a mistake with forgetting to call __init__ of the
# parent.
#
# I0011: Locally disabling W....
# Strange one anyway, I want to locally disable stuff. And that just makes it
# a different warning. Amazing. Luckily I can decide to ignore that globally
# then.

import sys, os, subprocess

# Go its own directory, to have it easy with path knowledge.
os.chdir( os.path.dirname( os.path.abspath( __file__ ) ) )
os.chdir( ".." )

pylint_options = """
--rcfile=/dev/null
--include-ids=y
--disable=I0011,W0232
--reports=no
--persistent=no
--method-rgx=[a-z_][a-zA-Z0-9_]{2,40}$
--module-rgx=.*
--function-rgx=.*
--variable-rgx=.*
--argument-rgx=.*
--const-rgx=.*
--max-line-length=120
--no-docstring-rgx=.*
--max-module-lines=5000
--min-public-methods=0
--max-public-methods=100
--max-args=10
--max-parents=9
""".split()


from optparse import OptionParser


parser = OptionParser()

parser.add_option(
    "--hide-todos", "--no-todos",
    action  = "store_true",
    dest    = "no_todos",
    default = False,
    help    = """\
    Default is %default."""
)

parser.add_option(
    "--emacs",
    action  = "store_true",
    dest    = "emacs",
    default = False,
    help    = """\
    Default is %default."""
)


options, positional_args = parser.parse_args()

if os.environ.get( "TODO", 0 ) or options.no_todos:
    pylint_options.append( "--notes=" )

blacklist = (
    "oset.py",
    "odict.py",
    "SyntaxHighlighting.py",
    "TreeDisplay.py"
)

def executePyLint( filename ):
    command = "pylint %s %s %s" % (
        " ".join( pylint_options ),
        os.environ.get( "PYLINT_EXTRA_OPTIONS", "" ),
        filename
    )

    process = subprocess.Popen(
        args   = command,
        stdout = subprocess.PIPE,
        stderr = subprocess.STDOUT,
        shell  = True
    )

    stdout, _stderr = process.communicate()
    exit_code = process.returncode

    assert not _stderr
    if stdout:
        for line in stdout.split( b"\n" ):
            output = line.decode()

            if options.emacs and ":" in output:
                parts = output.split( ":" )
                output = filename + ":" + parts[1].split(",")[0].strip() + ": " + \
                         parts[0] + " " + ":".join( parts[2:] )

                sys.stderr.write( output + "\n" )
            else:
                print( output )

    sys.stdout.flush()

if "PYTHONPATH" not in os.environ:
    os.environ[ "PYTHONPATH" ] = "."

if positional_args:
    for positional_arg in positional_args:
        executePyLint( positional_arg )
else:
    executePyLint( "bin/nuitka" )

    for dirpath, dirnames, filenames in os.walk( "nuitka" ):
        dirnames.sort()

        if "inline_copy" in dirnames:
            dirnames.remove( "inline_copy" )

        filenames.sort()

        for filename in filenames:
            if not filename.endswith( ".py" ):
                continue

            # Skip temporary files from flymake mode of Emacs.
            if filename.endswith( "_flymake.py" ):
                continue

            # Skip temporary files from unsaved files of Emacs.
            if filename.startswith( ".#" ):
                continue

            if filename not in blacklist:
                executePyLint( os.path.join( dirpath, filename ) )
