import ctypes
import ctypes.util
import os
import sys
from setuptools import setup, Extension, find_packages

VERSION = "1.4.1"  # Also in `mbedtls.__init__.py`.
MBEDTLS_VERSION = "2.16.8"
DOWNLOAD_URL = "https://github.com/Synss/python-mbedtls/tarball/%s" % VERSION


__mbedtls_version_info__ = tuple(map(int, MBEDTLS_VERSION.split(".")))
__mbedtls_url__ = "https://tls.mbed.org"


if "--with-coverage" in sys.argv:
    sys.argv.remove("--with-coverage")
    COVERAGE = True
else:
    COVERAGE = False


setup_requires = [
    # Setuptools 18.0 properly handles Cython extensions.
    "setuptools >= 18.0",
    # Cython 0.28 handles const memoryviews.
    "cython >= 0.28.0",
]
install_requires = [
    "certifi",
    'contextlib2; python_version < "3.0"',
    'enum34 != 1.1.8; python_version < "3.0"',
    'pathlib2; python_version < "3.0"',
]
tests_require = [
    "readme_renderer",
    'contextlib2; python_version < "3.0"',
]


def mbedtls_version(lib):
    null = b"\0"
    output = 18 * null
    output_p = ctypes.c_char_p(output)
    lib.mbedtls_version_get_string_full(output_p)
    return output.strip(null).decode("ascii")


def mbedtls_version_info(lib):
    version = lib.mbedtls_version_get_number()
    return tuple(version >> shift & 0xFF for shift in (24, 16, 8))


def check_mbedtls_support(version, url):
    library = ctypes.util.find_library("mbedtls")
    if not library:
        sys.stderr.write("  Library not found{sep}".format(sep=os.linesep))
    try:
        lib = ctypes.cdll.LoadLibrary(library)
        sys.stdout.write(
            "  loading: {!r}\n".format(lib._name)
        )
        sys.stdout.write(
            "  mbedtls version: {!s}{sep}".format(
                mbedtls_version(lib), sep=os.linesep
            )
        )
        sys.stdout.write("  python-mbedtls version: {0}".format(VERSION))
    except OSError as exc:
        lib = None
        sys.stderr.write("  {exc!s}{sep}".format(exc=exc, sep=os.linesep))
    if lib and mbedtls_version_info(lib) < version[:2]:
        message = (
            "  python-mbedtls requires at least mbedtls {major}.{minor}".format(
                major=version[0], minor=version[1]
            ),
            "  The latest version of mbedtls may be obtained from {url}.".format(
                url=url
            ),
            "",
        )
        sys.stderr.writelines(os.linesep.join(message))
        sys.exit(1)


def extensions(coverage=False):
    for dirpath, dirnames, filenames in os.walk("src"):
        for fn in filenames:
            root, ext = os.path.splitext(fn)
            if ext != ".pyx":
                continue
            mod = ".".join(dirpath.split(os.sep)[1:] + [root])
            extension = Extension(
                mod,
                [os.path.join(dirpath, fn)],
                library_dirs=os.environ.get("LIBRARY_PATH", "").split(":"),
                libraries=["mbedcrypto", "mbedtls", "mbedx509"],
                define_macros=[
                    ("CYTHON_TRACE", "1"),
                    ("CYTHON_TRACE_NOGIL", "1"),
                ]
                if coverage
                else [],
            )
            extension.cython_directives = {"language_level": "3str"}
            if coverage:
                extension.cython_directives["linetrace"] = True
            yield extension


def options(coverage=False):
    if coverage:
        return {}

    return {
        "build": {
            "build_base": os.sep.join(
                ("build", "%i.%i.%i" % sys.version_info[:3])
            )
        },
        "build_ext": {"cython_c_in_temp": True},
    }


def readme():
    with open("README.rst") as f:
        return f.read().replace(":math:", "")


if len(sys.argv) > 1 and any(
    (sys.argv[1].startswith("build"), sys.argv[1].startswith("bdist"))
):
    check_mbedtls_support(
        version=__mbedtls_version_info__, url=__mbedtls_url__
    )


setup(
    name="python-mbedtls",
    version=VERSION,
    description=(
        "hash, hmac, RSA, ECC, X.509, TLS, DTLS, handshakes, and secrets "
        "with an mbed TLS back end"
    ),
    long_description=readme(),
    long_description_content_type="text/x-rst",
    author="Mathias Laurin",
    author_email="Mathias.Laurin@github.com",
    license="MIT License",
    url="https://github.com/Synss/python-mbedtls",
    download_url=DOWNLOAD_URL,
    ext_modules=list(extensions(COVERAGE)),
    options=options(COVERAGE),
    package_dir={"": "src"},
    packages=find_packages("src"),
    setup_requires=setup_requires,
    install_requires=install_requires,
    tests_require=tests_require,
    classifiers=[
        "Development Status :: 5 - Production/Stable",
        "Programming Language :: Cython",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "License :: OSI Approved :: MIT License",
        "Topic :: Security :: Cryptography",
    ],
)

@@ -47,16 +47,26 @@
 ort sys%0A
+import re%0A
 from set
@@ -117,46 +117,183 @@
 es%0A%0A
-VERSION = %221.4.1%22  # Also in %60
+%0Adef _get_version():%0A    pattern = re.compile('%5E__version__ = %5B%22%5D(%5B.%5Cw%5D+?)%5B%22%5D')%0A    with open(%0A        os.path.join(%0A            os.path.dirname(__file__), %22src%22, %22
 mbedtls
-.
+%22, %22
 __in
@@ -303,10 +303,228 @@
 _.py
-%60.
+%22%0A        )%0A    ) as f:%0A        for line in f:%0A            match = pattern.match(line)%0A            if match:%0A                return match.group(1)%0A        else:%0A            raise RuntimeError()%0A%0A%0AVERSION = _get_version()
 %0AMBE
@@ -1911,29 +1911,16 @@
 t.write(
-%0A            
 %22  loadi
@@ -1948,25 +1948,16 @@
 b._name)
-%0A        
 )%0A      

Read version from `__init__`