1from __future__ import absolute_import, unicode_literals
2
3import abc
4
5from six import add_metaclass
6
7from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest, RefMust, RefWhen
8from virtualenv.util.path import Path
9
10from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin
11
12
13@add_metaclass(abc.ABCMeta)
14class PyPy(ViaGlobalRefVirtualenvBuiltin):
15    @classmethod
16    def can_describe(cls, interpreter):
17        return interpreter.implementation == "PyPy" and super(PyPy, cls).can_describe(interpreter)
18
19    @classmethod
20    def _executables(cls, interpreter):
21        host = Path(interpreter.system_executable)
22        targets = sorted("{}{}".format(name, PyPy.suffix) for name in cls.exe_names(interpreter))
23        must = RefMust.COPY if interpreter.version_info.major == 2 else RefMust.NA
24        yield host, targets, must, RefWhen.ANY
25
26    @classmethod
27    def exe_names(cls, interpreter):
28        return {
29            cls.exe_stem(),
30            "python",
31            "python{}".format(interpreter.version_info.major),
32            "python{}.{}".format(*interpreter.version_info),
33        }
34
35    @classmethod
36    def sources(cls, interpreter):
37        for src in super(PyPy, cls).sources(interpreter):
38            yield src
39        for host in cls._add_shared_libs(interpreter):
40            yield PathRefToDest(host, dest=lambda self, s: self.bin_dir / s.name)
41
42    @classmethod
43    def _add_shared_libs(cls, interpreter):
44        # https://bitbucket.org/pypy/pypy/issue/1922/future-proofing-virtualenv
45        python_dir = Path(interpreter.system_executable).resolve().parent
46        for libname in cls._shared_libs():
47            src = python_dir / libname
48            if src.exists():
49                yield src
50
51    @classmethod
52    def _shared_libs(cls):
53        raise NotImplementedError
54