#!/usr/bin/env python

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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 sys
try:
    from setuptools import setup, Extension
except Exception:
    from distutils.core import setup, Extension

from setuptools.command.build_ext import build_ext
from setuptools.errors import CCompilerError, ExecError, PlatformError

# Fix to build sdist under vagrant
import os
if 'vagrant' in str(os.environ):
    try:
        del os.link
    except AttributeError:
        pass

include_dirs = ['src']
if sys.platform == 'win32':
    include_dirs.append('compat/win32')
    ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError, IOError)
else:
    ext_errors = (CCompilerError, ExecError, PlatformError)


class BuildFailed(Exception):
    pass


class ve_build_ext(build_ext):
    def run(self):
        try:
            build_ext.run(self)
        except PlatformError:
            raise BuildFailed()

    def build_extension(self, ext):
        try:
            build_ext.build_extension(self, ext)
        except ext_errors:
            raise BuildFailed()


def read_file(path):
    """
    Return the contents of a file

    Arguments:
      - path: path to the file

    Returns:
      - contents of the file
    """
    with open(path, "r") as desc_file:
        return desc_file.read().rstrip()


def run_setup(with_binary):
    if with_binary:
        extensions = dict(
            ext_modules=[
                Extension('thrift.protocol.fastbinary',
                          extra_compile_args=['-std=c++11'],
                          sources=[
                              'src/ext/module.cpp',
                              'src/ext/types.cpp',
                              'src/ext/binary.cpp',
                              'src/ext/compact.cpp',
                          ],
                          include_dirs=include_dirs,
                          )
            ],
            cmdclass=dict(build_ext=ve_build_ext)
        )
    else:
        extensions = dict()

    ssl_deps = []
    if sys.hexversion < 0x03050000:
        ssl_deps.append('backports.ssl_match_hostname>=3.5')
    tornado_deps = ['tornado>=4.0']
    twisted_deps = ['twisted']

    setup(name='thrift',
          version='0.23.0',
          description='Python bindings for the Apache Thrift RPC system',
          long_description=read_file("README.md"),
          long_description_content_type="text/markdown",
          author='Apache Thrift Developers',
          author_email='dev@thrift.apache.org',
          url='http://thrift.apache.org',
          license='Apache License 2.0',
          extras_require={
              'ssl': ssl_deps,
              'tornado': tornado_deps,
              'twisted': twisted_deps,
              'all': ssl_deps + tornado_deps + twisted_deps,
          },
          packages=[
              'thrift',
              'thrift.protocol',
              'thrift.transport',
              'thrift.server',
          ],
          package_dir={'thrift': 'src'},
          classifiers=[
              'Development Status :: 5 - Production/Stable',
              'Environment :: Console',
              'Intended Audience :: Developers',
              'Programming Language :: Python',
              'Programming Language :: Python :: 3',
              'Topic :: Software Development :: Libraries',
              'Topic :: System :: Networking'
          ],
          zip_safe=False,
          **extensions
          )


try:
    with_binary = True
    run_setup(with_binary)
except BuildFailed:
    print()
    print('*' * 80)
    print("An error occurred while trying to compile with the C extension enabled")
    print("Attempting to build without the extension now")
    print('*' * 80)
    print()

    run_setup(False)
