summaryrefslogtreecommitdiff
path: root/src/virtualenv/run
diff options
context:
space:
mode:
authorBernát Gábor <bgabor8@bloomberg.net>2020-01-21 12:20:43 +0000
committerGitHub <noreply@github.com>2020-01-21 12:20:43 +0000
commit886ba275110f0a1f4777445dab4757b90f7ac6da (patch)
treed2d65198ee8cda7cd42b6033e84a8879adf00277 /src/virtualenv/run
parent8d6af57d76edcf425beab6d53d4c14f1e49f7ca5 (diff)
downloadvirtualenv-886ba275110f0a1f4777445dab4757b90f7ac6da.tar.gz
separate describe/create - check upfront if can create (#1502)
* start Signed-off-by: Bernat Gabor <bgabor8@bloomberg.net> * test for Windows Signed-off-by: Bernat Gabor <bgabor8@bloomberg.net> * test for Windows Signed-off-by: Bernat Gabor <bgabor8@bloomberg.net> * fix Windows symlink cache
Diffstat (limited to 'src/virtualenv/run')
-rw-r--r--src/virtualenv/run/plugin/activators.py6
-rw-r--r--src/virtualenv/run/plugin/base.py15
-rw-r--r--src/virtualenv/run/plugin/creators.py55
-rw-r--r--src/virtualenv/run/plugin/seeders.py3
4 files changed, 50 insertions, 29 deletions
diff --git a/src/virtualenv/run/plugin/activators.py b/src/virtualenv/run/plugin/activators.py
index 56ee316..8fb5a6b 100644
--- a/src/virtualenv/run/plugin/activators.py
+++ b/src/virtualenv/run/plugin/activators.py
@@ -1,6 +1,7 @@
from __future__ import absolute_import, unicode_literals
from argparse import ArgumentTypeError
+from collections import OrderedDict
from .base import ComponentBuilder
@@ -8,7 +9,10 @@ from .base import ComponentBuilder
class ActivationSelector(ComponentBuilder):
def __init__(self, interpreter, parser):
self.default = None
- super(ActivationSelector, self).__init__(interpreter, parser, "virtualenv.activate", "activators", True)
+ possible = OrderedDict(
+ (k, v) for k, v in self.options("virtualenv.activate").items() if v.supports(interpreter)
+ )
+ super(ActivationSelector, self).__init__(interpreter, parser, "activators", possible)
self.active = None
def add_selector_arg_parse(self, name, choices):
diff --git a/src/virtualenv/run/plugin/base.py b/src/virtualenv/run/plugin/base.py
index 5232b39..e3230e7 100644
--- a/src/virtualenv/run/plugin/base.py
+++ b/src/virtualenv/run/plugin/base.py
@@ -25,14 +25,11 @@ class PluginLoader(object):
class ComponentBuilder(PluginLoader):
- def __init__(self, interpreter, parser, key, name, needs_support):
+ def __init__(self, interpreter, parser, name, possible):
self.interpreter = interpreter
self.name = name
self._impl_class = None
- opts = self.options(key)
- self.possible = self._build_options(
- OrderedDict((k, v) for k, v in opts.items() if v.supports(interpreter)) if needs_support else opts
- )
+ self.possible = possible
self.parser = parser.add_argument_group("{} options".format(name))
self.add_selector_arg_parse(name, list(self.possible))
@@ -45,16 +42,16 @@ class ComponentBuilder(PluginLoader):
def add_selector_arg_parse(self, name, choices):
raise NotImplementedError
- def _build_options(self, options):
- return options
-
def handle_selected_arg_parse(self, options):
selected = getattr(options, self.name)
if selected not in self.possible:
raise RuntimeError("No implementation for {}".format(self.interpreter))
self._impl_class = self.possible[selected]
- self._impl_class.add_parser_arguments(self.parser, self.interpreter)
+ self.populate_selected_argparse(selected)
return selected
+ def populate_selected_argparse(self, selected):
+ self._impl_class.add_parser_arguments(self.parser, self.interpreter)
+
def create(self, options):
return self._impl_class(options, self.interpreter)
diff --git a/src/virtualenv/run/plugin/creators.py b/src/virtualenv/run/plugin/creators.py
index a6d3cd3..558144f 100644
--- a/src/virtualenv/run/plugin/creators.py
+++ b/src/virtualenv/run/plugin/creators.py
@@ -1,24 +1,41 @@
from __future__ import absolute_import, unicode_literals
-from virtualenv.interpreters.create.venv import Venv
+from collections import OrderedDict, namedtuple
+
+from virtualenv.create.describe import Describe
+from virtualenv.create.via_global_ref.builtin.builtin_way import VirtualenvBuiltin
from .base import ComponentBuilder
+CreatorInfo = namedtuple("CreatorInfo", ["key_to_class", "key_to_meta", "describe", "builtin_key"])
+
class CreatorSelector(ComponentBuilder):
def __init__(self, interpreter, parser):
- super(CreatorSelector, self).__init__(interpreter, parser, "virtualenv.create", "creator", True)
-
- def _build_options(self, options):
- if not options:
- raise RuntimeError("No virtualenv implementation for {}".format(self.interpreter))
-
- from virtualenv.interpreters.create.builtin_way import VirtualenvBuiltin
-
- self.builtin_way = next((i for i, v in options.items() if issubclass(v, VirtualenvBuiltin)), None)
- if self.builtin_way is not None:
- options["builtin"] = options[self.builtin_way] # make the first builtin method the builtin alias
- return options
+ creators, self.key_to_meta, self.describe, self.builtin_key = self.for_interpreter(interpreter)
+ if not creators:
+ raise RuntimeError("No virtualenv implementation for {}".format(interpreter))
+ super(CreatorSelector, self).__init__(interpreter, parser, "creator", creators)
+
+ @classmethod
+ def for_interpreter(cls, interpreter):
+ key_to_class, key_to_meta, builtin_key, describe = OrderedDict(), {}, None, None
+ for key, creator_class in cls.options("virtualenv.create").items():
+ if key == "builtin":
+ raise RuntimeError("builtin creator is a reserved name")
+ meta = creator_class.can_create(interpreter)
+ if meta:
+ if "builtin" not in key_to_class and issubclass(creator_class, VirtualenvBuiltin):
+ builtin_key = key
+ key_to_class["builtin"] = creator_class
+ key_to_meta["builtin"] = meta
+ key_to_class[key] = creator_class
+ key_to_meta[key] = meta
+ if describe is None and issubclass(creator_class, Describe) and creator_class.can_describe(interpreter):
+ describe = creator_class
+ return CreatorInfo(
+ key_to_class=key_to_class, key_to_meta=key_to_meta, describe=describe, builtin_key=builtin_key
+ )
def add_selector_arg_parse(self, name, choices):
# prefer the built-in venv if present, otherwise fallback to first defined type
@@ -29,13 +46,15 @@ class CreatorSelector(ComponentBuilder):
default=next(iter(choices)),
required=False,
help="create environment via{}".format(
- "" if self.builtin_way is None else " (builtin = {})".format(self.builtin_way)
+ "" if self.builtin_key is None else " (builtin = {})".format(self.builtin_key)
),
)
+ def populate_selected_argparse(self, selected):
+ self._impl_class.add_parser_arguments(self.parser, self.interpreter, self.key_to_meta[selected])
+
def create(self, options):
- if issubclass(self._impl_class, Venv):
- options.builtin_way = (
- None if self.builtin_way is None else self.possible[self.builtin_way](options, self.interpreter)
- )
+ options.meta = self.key_to_meta[getattr(options, self.name)]
+ if not issubclass(self._impl_class, Describe):
+ options.describe = self.describe(options, self.interpreter)
return super(CreatorSelector, self).create(options)
diff --git a/src/virtualenv/run/plugin/seeders.py b/src/virtualenv/run/plugin/seeders.py
index 75cfad8..2bd7070 100644
--- a/src/virtualenv/run/plugin/seeders.py
+++ b/src/virtualenv/run/plugin/seeders.py
@@ -5,7 +5,8 @@ from .base import ComponentBuilder
class SeederSelector(ComponentBuilder):
def __init__(self, interpreter, parser):
- super(SeederSelector, self).__init__(interpreter, parser, "virtualenv.seed", "seeder", False)
+ possible = self.options("virtualenv.seed")
+ super(SeederSelector, self).__init__(interpreter, parser, "seeder", possible)
def add_selector_arg_parse(self, name, choices):
self.parser.add_argument(