comparison env/lib/python3.9/site-packages/virtualenv/discovery/py_spec.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """A Python specification is an abstract requirement definition of a interpreter"""
2 from __future__ import absolute_import, unicode_literals
3
4 import os
5 import re
6 import sys
7 from collections import OrderedDict
8
9 from virtualenv.info import fs_is_case_sensitive
10 from virtualenv.util.six import ensure_str
11
12 PATTERN = re.compile(r"^(?P<impl>[a-zA-Z]+)?(?P<version>[0-9.]+)?(?:-(?P<arch>32|64))?$")
13 IS_WIN = sys.platform == "win32"
14
15
16 class PythonSpec(object):
17 """Contains specification about a Python Interpreter"""
18
19 def __init__(self, str_spec, implementation, major, minor, micro, architecture, path):
20 self.str_spec = str_spec
21 self.implementation = implementation
22 self.major = major
23 self.minor = minor
24 self.micro = micro
25 self.architecture = architecture
26 self.path = path
27
28 @classmethod
29 def from_string_spec(cls, string_spec):
30 impl, major, minor, micro, arch, path = None, None, None, None, None, None
31 if os.path.isabs(string_spec):
32 path = string_spec
33 else:
34 ok = False
35 match = re.match(PATTERN, string_spec)
36 if match:
37
38 def _int_or_none(val):
39 return None if val is None else int(val)
40
41 try:
42 groups = match.groupdict()
43 version = groups["version"]
44 if version is not None:
45 versions = tuple(int(i) for i in version.split(".") if i)
46 if len(versions) > 3:
47 raise ValueError
48 if len(versions) == 3:
49 major, minor, micro = versions
50 elif len(versions) == 2:
51 major, minor = versions
52 elif len(versions) == 1:
53 version_data = versions[0]
54 major = int(str(version_data)[0]) # first digit major
55 if version_data > 9:
56 minor = int(str(version_data)[1:])
57 ok = True
58 except ValueError:
59 pass
60 else:
61 impl = groups["impl"]
62 if impl == "py" or impl == "python":
63 impl = "CPython"
64 arch = _int_or_none(groups["arch"])
65
66 if not ok:
67 path = string_spec
68
69 return cls(string_spec, impl, major, minor, micro, arch, path)
70
71 def generate_names(self):
72 impls = OrderedDict()
73 if self.implementation:
74 # first consider implementation as it is
75 impls[self.implementation] = False
76 if fs_is_case_sensitive():
77 # for case sensitive file systems consider lower and upper case versions too
78 # trivia: MacBooks and all pre 2018 Windows-es were case insensitive by default
79 impls[self.implementation.lower()] = False
80 impls[self.implementation.upper()] = False
81 impls["python"] = True # finally consider python as alias, implementation must match now
82 version = self.major, self.minor, self.micro
83 try:
84 version = version[: version.index(None)]
85 except ValueError:
86 pass
87 for impl, match in impls.items():
88 for at in range(len(version), -1, -1):
89 cur_ver = version[0:at]
90 spec = "{}{}".format(impl, ".".join(str(i) for i in cur_ver))
91 yield spec, match
92
93 @property
94 def is_abs(self):
95 return self.path is not None and os.path.isabs(self.path)
96
97 def satisfies(self, spec):
98 """called when there's a candidate metadata spec to see if compatible - e.g. PEP-514 on Windows"""
99 if spec.is_abs and self.is_abs and self.path != spec.path:
100 return False
101 if spec.implementation is not None and spec.implementation.lower() != self.implementation.lower():
102 return False
103 if spec.architecture is not None and spec.architecture != self.architecture:
104 return False
105
106 for our, req in zip((self.major, self.minor, self.micro), (spec.major, spec.minor, spec.micro)):
107 if req is not None and our is not None and our != req:
108 return False
109 return True
110
111 def __unicode__(self):
112 return "{}({})".format(
113 type(self).__name__,
114 ", ".join(
115 "{}={}".format(k, getattr(self, k))
116 for k in ("implementation", "major", "minor", "micro", "architecture", "path")
117 if getattr(self, k) is not None
118 ),
119 )
120
121 def __repr__(self):
122 return ensure_str(self.__unicode__())