comparison planemo/lib/python3.7/site-packages/virtualenv/discovery/builtin.py @ 1:56ad4e20f292 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:32:28 -0400
parents
children
comparison
equal deleted inserted replaced
0:d30785e31577 1:56ad4e20f292
1 from __future__ import absolute_import, unicode_literals
2
3 import logging
4 import os
5 import sys
6
7 from virtualenv.info import IS_WIN
8 from virtualenv.util.six import ensure_str, ensure_text
9
10 from .discover import Discover
11 from .py_info import PythonInfo
12 from .py_spec import PythonSpec
13
14
15 class Builtin(Discover):
16 def __init__(self, options):
17 super(Builtin, self).__init__(options)
18 self.python_spec = options.python
19 self.app_data = options.app_data
20
21 @classmethod
22 def add_parser_arguments(cls, parser):
23 parser.add_argument(
24 "-p",
25 "--python",
26 dest="python",
27 metavar="py",
28 help="target interpreter for which to create a virtual (either absolute path or identifier string)",
29 default=sys.executable,
30 )
31
32 def run(self):
33 return get_interpreter(self.python_spec, self.app_data)
34
35 def __repr__(self):
36 return ensure_str(self.__unicode__())
37
38 def __unicode__(self):
39 return "{} discover of python_spec={!r}".format(self.__class__.__name__, self.python_spec)
40
41
42 def get_interpreter(key, app_data=None):
43 spec = PythonSpec.from_string_spec(key)
44 logging.info("find interpreter for spec %r", spec)
45 proposed_paths = set()
46 for interpreter, impl_must_match in propose_interpreters(spec, app_data):
47 key = interpreter.system_executable, impl_must_match
48 if key in proposed_paths:
49 continue
50 logging.info("proposed %s", interpreter)
51 if interpreter.satisfies(spec, impl_must_match):
52 logging.debug("accepted %s", interpreter)
53 return interpreter
54 proposed_paths.add(key)
55
56
57 def propose_interpreters(spec, app_data):
58 # 1. if it's a path and exists
59 if spec.path is not None:
60 try:
61 os.lstat(spec.path) # Windows Store Python does not work with os.path.exists, but does for os.lstat
62 except OSError:
63 if spec.is_abs:
64 raise
65 else:
66 yield PythonInfo.from_exe(os.path.abspath(spec.path), app_data), True
67 if spec.is_abs:
68 return
69 else:
70 # 2. otherwise try with the current
71 yield PythonInfo.current_system(app_data), True
72
73 # 3. otherwise fallback to platform default logic
74 if IS_WIN:
75 from .windows import propose_interpreters
76
77 for interpreter in propose_interpreters(spec, app_data):
78 yield interpreter, True
79 # finally just find on path, the path order matters (as the candidates are less easy to control by end user)
80 paths = get_paths()
81 tested_exes = set()
82 for pos, path in enumerate(paths):
83 path = ensure_text(path)
84 logging.debug(LazyPathDump(pos, path))
85 for candidate, match in possible_specs(spec):
86 found = check_path(candidate, path)
87 if found is not None:
88 exe = os.path.abspath(found)
89 if exe not in tested_exes:
90 tested_exes.add(exe)
91 interpreter = PathPythonInfo.from_exe(exe, app_data, raise_on_error=False)
92 if interpreter is not None:
93 yield interpreter, match
94
95
96 def get_paths():
97 path = os.environ.get(str("PATH"), None)
98 if path is None:
99 try:
100 path = os.confstr("CS_PATH")
101 except (AttributeError, ValueError):
102 path = os.defpath
103 if not path:
104 paths = []
105 else:
106 paths = [p for p in path.split(os.pathsep) if os.path.exists(p)]
107 return paths
108
109
110 class LazyPathDump(object):
111 def __init__(self, pos, path):
112 self.pos = pos
113 self.path = path
114
115 def __repr__(self):
116 return ensure_str(self.__unicode__())
117
118 def __unicode__(self):
119 content = "discover PATH[{}]={}".format(self.pos, self.path)
120 if os.environ.get(str("_VIRTUALENV_DEBUG")): # this is the over the board debug
121 content += " with =>"
122 for file_name in os.listdir(self.path):
123 try:
124 file_path = os.path.join(self.path, file_name)
125 if os.path.isdir(file_path) or not os.access(file_path, os.X_OK):
126 continue
127 except OSError:
128 pass
129 content += " "
130 content += file_name
131 return content
132
133
134 def check_path(candidate, path):
135 _, ext = os.path.splitext(candidate)
136 if sys.platform == "win32" and ext != ".exe":
137 candidate = candidate + ".exe"
138 if os.path.isfile(candidate):
139 return candidate
140 candidate = os.path.join(path, candidate)
141 if os.path.isfile(candidate):
142 return candidate
143 return None
144
145
146 def possible_specs(spec):
147 # 4. then maybe it's something exact on PATH - if it was direct lookup implementation no longer counts
148 yield spec.str_spec, False
149 # 5. or from the spec we can deduce a name on path that matches
150 for exe, match in spec.generate_names():
151 yield exe, match
152
153
154 class PathPythonInfo(PythonInfo):
155 """"""