You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Enso-Bot/venv/Lib/site-packages/virtualenv/discovery/builtin.py

156 lines
5.0 KiB
Python

from __future__ import absolute_import, unicode_literals
import logging
import os
import sys
from virtualenv.info import IS_WIN
from virtualenv.util.six import ensure_str, ensure_text
from .discover import Discover
from .py_info import PythonInfo
from .py_spec import PythonSpec
class Builtin(Discover):
def __init__(self, options):
super(Builtin, self).__init__(options)
self.python_spec = options.python
self.app_data = options.app_data
@classmethod
def add_parser_arguments(cls, parser):
parser.add_argument(
"-p",
"--python",
dest="python",
metavar="py",
help="target interpreter for which to create a virtual (either absolute path or identifier string)",
default=sys.executable,
)
def run(self):
return get_interpreter(self.python_spec, self.app_data)
def __repr__(self):
return ensure_str(self.__unicode__())
def __unicode__(self):
return "{} discover of python_spec={!r}".format(self.__class__.__name__, self.python_spec)
def get_interpreter(key, app_data=None):
spec = PythonSpec.from_string_spec(key)
logging.info("find interpreter for spec %r", spec)
proposed_paths = set()
for interpreter, impl_must_match in propose_interpreters(spec, app_data):
key = interpreter.system_executable, impl_must_match
if key in proposed_paths:
continue
logging.info("proposed %s", interpreter)
if interpreter.satisfies(spec, impl_must_match):
logging.debug("accepted %s", interpreter)
return interpreter
proposed_paths.add(key)
def propose_interpreters(spec, app_data):
# 1. if it's a path and exists
if spec.path is not None:
try:
os.lstat(spec.path) # Windows Store Python does not work with os.path.exists, but does for os.lstat
except OSError:
if spec.is_abs:
raise
else:
yield PythonInfo.from_exe(os.path.abspath(spec.path), app_data), True
if spec.is_abs:
return
else:
# 2. otherwise try with the current
yield PythonInfo.current_system(app_data), True
# 3. otherwise fallback to platform default logic
if IS_WIN:
from .windows import propose_interpreters
for interpreter in propose_interpreters(spec, app_data):
yield interpreter, True
# finally just find on path, the path order matters (as the candidates are less easy to control by end user)
paths = get_paths()
tested_exes = set()
for pos, path in enumerate(paths):
path = ensure_text(path)
logging.debug(LazyPathDump(pos, path))
for candidate, match in possible_specs(spec):
found = check_path(candidate, path)
if found is not None:
exe = os.path.abspath(found)
if exe not in tested_exes:
tested_exes.add(exe)
interpreter = PathPythonInfo.from_exe(exe, app_data, raise_on_error=False)
if interpreter is not None:
yield interpreter, match
def get_paths():
path = os.environ.get(str("PATH"), None)
if path is None:
try:
path = os.confstr("CS_PATH")
except (AttributeError, ValueError):
path = os.defpath
if not path:
paths = []
else:
paths = [p for p in path.split(os.pathsep) if os.path.exists(p)]
return paths
class LazyPathDump(object):
def __init__(self, pos, path):
self.pos = pos
self.path = path
def __repr__(self):
return ensure_str(self.__unicode__())
def __unicode__(self):
content = "discover PATH[{}]={}".format(self.pos, self.path)
if os.environ.get(str("_VIRTUALENV_DEBUG")): # this is the over the board debug
content += " with =>"
for file_name in os.listdir(self.path):
try:
file_path = os.path.join(self.path, file_name)
if os.path.isdir(file_path) or not os.access(file_path, os.X_OK):
continue
except OSError:
pass
content += " "
content += file_name
return content
def check_path(candidate, path):
_, ext = os.path.splitext(candidate)
if sys.platform == "win32" and ext != ".exe":
candidate = candidate + ".exe"
if os.path.isfile(candidate):
return candidate
candidate = os.path.join(path, candidate)
if os.path.isfile(candidate):
return candidate
return None
def possible_specs(spec):
# 4. then maybe it's something exact on PATH - if it was direct lookup implementation no longer counts
yield spec.str_spec, False
# 5. or from the spec we can deduce a name on path that matches
for exe, match in spec.generate_names():
yield exe, match
class PathPythonInfo(PythonInfo):
""""""