diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/planemo/lib/python3.7/site-packages/virtualenv/discovery/builtin.py	Fri Jul 31 00:32:28 2020 -0400
@@ -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):
+    """"""