# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

import os
import sys
from textwrap import dedent

import pytest

from pex.interpreter import PythonInterpreter
from pex.interpreter_constraints import UnsatisfiableInterpreterConstraintsError
from pex.pex_bootstrapper import iter_compatible_interpreters
from pex.testing import PY27, PY35, PY36, ensure_python_interpreter


def find_interpreters(path, *constraints):
    return [
        interp.binary
        for interp in iter_compatible_interpreters(
            path=os.pathsep.join(path), compatibility_constraints=constraints
        )
    ]


def test_find_compatible_interpreters():
    py27 = ensure_python_interpreter(PY27)
    py35 = ensure_python_interpreter(PY35)
    py36 = ensure_python_interpreter(PY36)
    path = [py27, py35, py36]

    assert [py35, py36] == find_interpreters(path, ">3")
    assert [py27] == find_interpreters(path, "<3")

    assert [py36] == find_interpreters(path, ">{}".format(PY35))
    assert [py35] == find_interpreters(path, ">{}, <{}".format(PY27, PY36))
    assert [py36] == find_interpreters(path, ">=3.6")

    with pytest.raises(UnsatisfiableInterpreterConstraintsError):
        find_interpreters(path, "<2")

    with pytest.raises(UnsatisfiableInterpreterConstraintsError):
        find_interpreters(path, ">4")

    with pytest.raises(UnsatisfiableInterpreterConstraintsError):
        find_interpreters(path, ">{}, <{}".format(PY27, PY35))

    # All interpreters on PATH including whatever interpreter is currently running.
    all_known_interpreters = set(PythonInterpreter.all())
    all_known_interpreters.add(PythonInterpreter.get())

    interpreters = set(iter_compatible_interpreters(compatibility_constraints=["<3"]))
    i_rendered = "\n      ".join(sorted(map(repr, interpreters)))
    aki_rendered = "\n      ".join(sorted(map(repr, all_known_interpreters)))
    assert interpreters.issubset(all_known_interpreters), dedent(
        """
        interpreters '<3':
          {interpreters}
        
        all known interpreters:
          {all_known_interpreters}
        """.format(
            interpreters=i_rendered, all_known_interpreters=aki_rendered
        )
    )


def test_find_compatible_interpreters_bias_current():
    py36 = ensure_python_interpreter(PY36)
    assert [os.path.realpath(sys.executable), py36] == find_interpreters([py36, sys.executable])
    assert [os.path.realpath(sys.executable), py36] == find_interpreters([sys.executable, py36])
