# Copyright 2016 gRPC authors.
#
# 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.

import os
import os.path
import shutil
import sys
import tempfile

try:
    from setuptools.errors import CompileError
except ImportError:
    # CompileError only exist for setuptools>=59.0.1, which becomes standard library
    # after Python 3.10.6.
    # TODO(xuanwn): Remove this once Python version floor is higher than 3.10.
    from distutils.errors import CompileError

import commands

C_PYTHON_DEV = """
#include <Python.h>
int main(int argc, char **argv) { return 0; }
"""
C_PYTHON_DEV_ERROR_MESSAGE = """
Could not find <Python.h>. This could mean the following:
  * You're on Ubuntu and haven't run `apt-get install <PY_REPR>-dev`.
  * You're on RHEL/Fedora and haven't run `yum install <PY_REPR>-devel` or
    `dnf install <PY_REPR>-devel` (make sure you also have redhat-rpm-config
    installed)
  * You're on Mac OS X and the usual Python framework was somehow corrupted
    (check your environment variables or try re-installing?)
  * You're on Windows and your Python installation was somehow corrupted
    (check your environment variables or try re-installing?)
"""
if sys.version_info[0] == 2:
    PYTHON_REPRESENTATION = "python"
elif sys.version_info[0] == 3:
    PYTHON_REPRESENTATION = "python3"
else:
    raise NotImplementedError("Unsupported Python version: %s" % sys.version)

C_CHECKS = {
    C_PYTHON_DEV: C_PYTHON_DEV_ERROR_MESSAGE.replace(
        "<PY_REPR>", PYTHON_REPRESENTATION
    ),
}


def _compile(compiler, source_string):
    tempdir = tempfile.mkdtemp()
    cpath = os.path.join(tempdir, "a.c")
    with open(cpath, "w") as cfile:
        cfile.write(source_string)
    try:
        compiler.compile([cpath])
    except CompileError as error:
        return error
    finally:
        shutil.rmtree(tempdir)


def _expect_compile(compiler, source_string, error_message):
    if _compile(compiler, source_string) is not None:
        sys.stderr.write(error_message)
        raise commands.CommandError(
            "Diagnostics found a compilation environment issue:\n{}".format(
                error_message
            )
        )


def diagnose_compile_error(build_ext, error):
    """Attempt to diagnose an error during compilation."""
    for c_check, message in C_CHECKS.items():
        _expect_compile(build_ext.compiler, c_check, message)
    python_sources = [
        source
        for source in build_ext.get_source_files()
        if source.startswith("./src/python") and source.endswith("c")
    ]
    for source in python_sources:
        if not os.path.isfile(source):
            raise commands.CommandError(
                (
                    "Diagnostics found a missing Python extension source"
                    " file:\n{}\n\nThis is usually because the Cython sources"
                    " haven't been transpiled into C yet and you're building"
                    " from source.\nTry setting the environment variable"
                    " `GRPC_PYTHON_BUILD_WITH_CYTHON=1` when invoking"
                    " `setup.py` or when using `pip`, e.g.:\n\npip install"
                    " -rrequirements.txt\nGRPC_PYTHON_BUILD_WITH_CYTHON=1 pip"
                    " install ."
                ).format(source)
            )


def diagnose_attribute_error(build_ext, error):
    if any("_needs_stub" in arg for arg in error.args):
        raise commands.CommandError(
            "We expect a missing `_needs_stub` attribute from older versions of"
            " setuptools. Consider upgrading setuptools."
        )


_ERROR_DIAGNOSES = {
    CompileError: diagnose_compile_error,
    AttributeError: diagnose_attribute_error,
}


def diagnose_build_ext_error(build_ext, error, formatted):
    diagnostic = _ERROR_DIAGNOSES.get(type(error))
    if diagnostic is None:
        raise commands.CommandError(
            "\n\nWe could not diagnose your build failure with type {}. If you are unable to"
            " proceed, please file an issue at http://www.github.com/grpc/grpc"
            " with `[Python install]` in the title; please attach the whole log"
            " (including everything that may have appeared above the Python"
            " backtrace).\n\n{}".format(type(error), formatted)
        )
    else:
        diagnostic(build_ext, error)
