login page
This commit is contained in:
155
Lib/site-packages/virtualenv/discovery/builtin.py
Normal file
155
Lib/site-packages/virtualenv/discovery/builtin.py
Normal file
@@ -0,0 +1,155 @@
|
||||
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):
|
||||
""""""
|
||||
Reference in New Issue
Block a user