summaryrefslogtreecommitdiff
path: root/src/tox/interpreters/py_spec.py
blob: a1d3055a70730856b7cdddf5d14f8eddc1b0d34a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from __future__ import unicode_literals

import os
import re
import sys

import six

import tox


class PythonSpec(object):
    def __init__(self, name, major, minor, architecture, path, args=None):
        self.name = name
        self.major = major
        self.minor = minor
        self.architecture = architecture
        self.path = path
        self.args = args

    def __repr__(self):
        return (
            "{0.__class__.__name__}(name={0.name!r}, major={0.major!r}, minor={0.minor!r}, "
            "architecture={0.architecture!r}, path={0.path!r}, args={0.args!r})"
        ).format(self)

    def __str__(self):
        msg = repr(self)
        return msg.encode("utf-8") if six.PY2 else msg

    def satisfies(self, req):
        if req.is_abs and self.is_abs and self.path != req.path:
            return False
        if req.name is not None and req.name != self.name:
            return False
        if req.architecture is not None and req.architecture != self.architecture:
            return False
        if req.major is not None and req.major != self.major:
            return False
        if req.minor is not None and req.minor != self.minor:
            return False
        if req.major is None and req.minor is not None:
            return False
        return True

    @property
    def is_abs(self):
        return self.path is not None and os.path.isabs(self.path)

    @classmethod
    def from_name(cls, base_python):
        name, major, minor, architecture, path = None, None, None, None, None
        if os.path.isabs(base_python):
            path = base_python
        else:
            match = re.match(r"(python|pypy|jython)(\d)?(?:\.(\d+))?(-(32|64))?$", base_python)
            if match:
                groups = match.groups()
                name = groups[0]
                major = int(groups[1]) if len(groups) >= 2 and groups[1] is not None else None
                minor = int(groups[2]) if len(groups) >= 3 and groups[2] is not None else None
                architecture = (
                    int(groups[3]) if len(groups) >= 4 and groups[3] is not None else None
                )
            else:
                path = base_python
        return cls(name, major, minor, architecture, path)


CURRENT = PythonSpec(
    "pypy" if tox.constants.INFO.IS_PYPY else "python",
    sys.version_info[0],
    sys.version_info[1],
    64 if sys.maxsize > 2 ** 32 else 32,
    sys.executable,
)