login page
This commit is contained in:
151
Lib/site-packages/virtualenv/run/__init__.py
Normal file
151
Lib/site-packages/virtualenv/run/__init__.py
Normal file
@@ -0,0 +1,151 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import logging
|
||||
|
||||
from ..app_data import AppDataAction, AppDataDisabled, TempAppData
|
||||
from ..config.cli.parser import VirtualEnvConfigParser
|
||||
from ..report import LEVELS, setup_report
|
||||
from ..run.session import Session
|
||||
from ..seed.wheels.periodic_update import manual_upgrade
|
||||
from ..version import __version__
|
||||
from .plugin.activators import ActivationSelector
|
||||
from .plugin.creators import CreatorSelector
|
||||
from .plugin.discovery import get_discover
|
||||
from .plugin.seeders import SeederSelector
|
||||
|
||||
|
||||
def cli_run(args, options=None, setup_logging=True):
|
||||
"""
|
||||
Create a virtual environment given some command line interface arguments.
|
||||
|
||||
:param args: the command line arguments
|
||||
:param options: passing in a ``VirtualEnvOptions`` object allows return of the parsed options
|
||||
:param setup_logging: ``True`` if setup logging handlers, ``False`` to use handlers already registered
|
||||
:return: the session object of the creation (its structure for now is experimental and might change on short notice)
|
||||
"""
|
||||
of_session = session_via_cli(args, options, setup_logging)
|
||||
with of_session:
|
||||
of_session.run()
|
||||
return of_session
|
||||
|
||||
|
||||
def session_via_cli(args, options=None, setup_logging=True):
|
||||
"""
|
||||
Create a virtualenv session (same as cli_run, but this does not perform the creation). Use this if you just want to
|
||||
query what the virtual environment would look like, but not actually create it.
|
||||
|
||||
:param args: the command line arguments
|
||||
:param options: passing in a ``VirtualEnvOptions`` object allows return of the parsed options
|
||||
:param setup_logging: ``True`` if setup logging handlers, ``False`` to use handlers already registered
|
||||
:return: the session object of the creation (its structure for now is experimental and might change on short notice)
|
||||
"""
|
||||
parser, elements = build_parser(args, options, setup_logging)
|
||||
options = parser.parse_args(args)
|
||||
creator, seeder, activators = tuple(e.create(options) for e in elements) # create types
|
||||
of_session = Session(options.verbosity, options.app_data, parser._interpreter, creator, seeder, activators) # noqa
|
||||
return of_session
|
||||
|
||||
|
||||
def build_parser(args=None, options=None, setup_logging=True):
|
||||
parser = VirtualEnvConfigParser(options)
|
||||
add_version_flag(parser)
|
||||
parser.add_argument(
|
||||
"--with-traceback",
|
||||
dest="with_traceback",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="on failure also display the stacktrace internals of virtualenv",
|
||||
)
|
||||
_do_report_setup(parser, args, setup_logging)
|
||||
options = load_app_data(args, parser, options)
|
||||
handle_extra_commands(options)
|
||||
|
||||
discover = get_discover(parser, args)
|
||||
parser._interpreter = interpreter = discover.interpreter
|
||||
if interpreter is None:
|
||||
raise RuntimeError("failed to find interpreter for {}".format(discover))
|
||||
elements = [
|
||||
CreatorSelector(interpreter, parser),
|
||||
SeederSelector(interpreter, parser),
|
||||
ActivationSelector(interpreter, parser),
|
||||
]
|
||||
options, _ = parser.parse_known_args(args)
|
||||
for element in elements:
|
||||
element.handle_selected_arg_parse(options)
|
||||
parser.enable_help()
|
||||
return parser, elements
|
||||
|
||||
|
||||
def build_parser_only(args=None):
|
||||
"""Used to provide a parser for the doc generation"""
|
||||
return build_parser(args)[0]
|
||||
|
||||
|
||||
def handle_extra_commands(options):
|
||||
if options.upgrade_embed_wheels:
|
||||
result = manual_upgrade(options.app_data)
|
||||
raise SystemExit(result)
|
||||
|
||||
|
||||
def load_app_data(args, parser, options):
|
||||
# here we need a write-able application data (e.g. the zipapp might need this for discovery cache)
|
||||
default_app_data = AppDataAction.default()
|
||||
parser.add_argument(
|
||||
"--app-data",
|
||||
dest="app_data",
|
||||
action=AppDataAction,
|
||||
default="<temp folder>" if isinstance(default_app_data, AppDataDisabled) else default_app_data,
|
||||
help="a data folder used as cache by the virtualenv",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--reset-app-data",
|
||||
dest="reset_app_data",
|
||||
action="store_true",
|
||||
help="start with empty app data folder",
|
||||
default=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--upgrade-embed-wheels",
|
||||
dest="upgrade_embed_wheels",
|
||||
action="store_true",
|
||||
help="trigger a manual update of the embedded wheels",
|
||||
default=False,
|
||||
)
|
||||
options, _ = parser.parse_known_args(args, namespace=options)
|
||||
if options.app_data == "<temp folder>":
|
||||
options.app_data = TempAppData()
|
||||
if options.reset_app_data:
|
||||
options.app_data.reset()
|
||||
return options
|
||||
|
||||
|
||||
def add_version_flag(parser):
|
||||
import virtualenv
|
||||
|
||||
parser.add_argument(
|
||||
"--version",
|
||||
action="version",
|
||||
version="%(prog)s {} from {}".format(__version__, virtualenv.__file__),
|
||||
help="display the version of the virtualenv package and its location, then exit",
|
||||
)
|
||||
|
||||
|
||||
def _do_report_setup(parser, args, setup_logging):
|
||||
level_map = ", ".join("{}={}".format(logging.getLevelName(l), c) for c, l in sorted(list(LEVELS.items())))
|
||||
msg = "verbosity = verbose - quiet, default {}, mapping => {}"
|
||||
verbosity_group = parser.add_argument_group(
|
||||
title="verbosity",
|
||||
description=msg.format(logging.getLevelName(LEVELS[3]), level_map),
|
||||
)
|
||||
verbosity = verbosity_group.add_mutually_exclusive_group()
|
||||
verbosity.add_argument("-v", "--verbose", action="count", dest="verbose", help="increase verbosity", default=2)
|
||||
verbosity.add_argument("-q", "--quiet", action="count", dest="quiet", help="decrease verbosity", default=0)
|
||||
option, _ = parser.parse_known_args(args)
|
||||
if setup_logging:
|
||||
setup_report(option.verbosity)
|
||||
|
||||
|
||||
__all__ = (
|
||||
"cli_run",
|
||||
"session_via_cli",
|
||||
)
|
||||
Binary file not shown.
Binary file not shown.
0
Lib/site-packages/virtualenv/run/plugin/__init__.py
Normal file
0
Lib/site-packages/virtualenv/run/plugin/__init__.py
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
53
Lib/site-packages/virtualenv/run/plugin/activators.py
Normal file
53
Lib/site-packages/virtualenv/run/plugin/activators.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from argparse import ArgumentTypeError
|
||||
from collections import OrderedDict
|
||||
|
||||
from .base import ComponentBuilder
|
||||
|
||||
|
||||
class ActivationSelector(ComponentBuilder):
|
||||
def __init__(self, interpreter, parser):
|
||||
self.default = None
|
||||
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.parser.description = "options for activation scripts"
|
||||
self.active = None
|
||||
|
||||
def add_selector_arg_parse(self, name, choices):
|
||||
self.default = ",".join(choices)
|
||||
self.parser.add_argument(
|
||||
"--{}".format(name),
|
||||
default=self.default,
|
||||
metavar="comma_sep_list",
|
||||
required=False,
|
||||
help="activators to generate - default is all supported",
|
||||
type=self._extract_activators,
|
||||
)
|
||||
|
||||
def _extract_activators(self, entered_str):
|
||||
elements = [e.strip() for e in entered_str.split(",") if e.strip()]
|
||||
missing = [e for e in elements if e not in self.possible]
|
||||
if missing:
|
||||
raise ArgumentTypeError("the following activators are not available {}".format(",".join(missing)))
|
||||
return elements
|
||||
|
||||
def handle_selected_arg_parse(self, options):
|
||||
selected_activators = (
|
||||
self._extract_activators(self.default) if options.activators is self.default else options.activators
|
||||
)
|
||||
self.active = {k: v for k, v in self.possible.items() if k in selected_activators}
|
||||
self.parser.add_argument(
|
||||
"--prompt",
|
||||
dest="prompt",
|
||||
metavar="prompt",
|
||||
help="provides an alternative prompt prefix for this environment",
|
||||
default=None,
|
||||
)
|
||||
for activator in self.active.values():
|
||||
activator.add_parser_arguments(self.parser, self.interpreter)
|
||||
|
||||
def create(self, options):
|
||||
return [activator_class(options) for activator_class in self.active.values()]
|
||||
58
Lib/site-packages/virtualenv/run/plugin/base.py
Normal file
58
Lib/site-packages/virtualenv/run/plugin/base.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import sys
|
||||
from collections import OrderedDict
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from importlib.metadata import entry_points
|
||||
else:
|
||||
from importlib_metadata import entry_points
|
||||
|
||||
|
||||
class PluginLoader(object):
|
||||
_OPTIONS = None
|
||||
_ENTRY_POINTS = None
|
||||
|
||||
@classmethod
|
||||
def entry_points_for(cls, key):
|
||||
return OrderedDict((e.name, e.load()) for e in cls.entry_points().get(key, {}))
|
||||
|
||||
@staticmethod
|
||||
def entry_points():
|
||||
if PluginLoader._ENTRY_POINTS is None:
|
||||
PluginLoader._ENTRY_POINTS = entry_points()
|
||||
return PluginLoader._ENTRY_POINTS
|
||||
|
||||
|
||||
class ComponentBuilder(PluginLoader):
|
||||
def __init__(self, interpreter, parser, name, possible):
|
||||
self.interpreter = interpreter
|
||||
self.name = name
|
||||
self._impl_class = None
|
||||
self.possible = possible
|
||||
self.parser = parser.add_argument_group(title=name)
|
||||
self.add_selector_arg_parse(name, list(self.possible))
|
||||
|
||||
@classmethod
|
||||
def options(cls, key):
|
||||
if cls._OPTIONS is None:
|
||||
cls._OPTIONS = cls.entry_points_for(key)
|
||||
return cls._OPTIONS
|
||||
|
||||
def add_selector_arg_parse(self, name, choices):
|
||||
raise NotImplementedError
|
||||
|
||||
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.populate_selected_argparse(selected, options.app_data)
|
||||
return selected
|
||||
|
||||
def populate_selected_argparse(self, selected, app_data):
|
||||
self.parser.description = "options for {} {}".format(self.name, selected)
|
||||
self._impl_class.add_parser_arguments(self.parser, self.interpreter, app_data)
|
||||
|
||||
def create(self, options):
|
||||
return self._impl_class(options, self.interpreter)
|
||||
77
Lib/site-packages/virtualenv/run/plugin/creators.py
Normal file
77
Lib/site-packages/virtualenv/run/plugin/creators.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from collections import OrderedDict, defaultdict, 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):
|
||||
creators, self.key_to_meta, self.describe, self.builtin_key = self.for_interpreter(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
|
||||
errors = defaultdict(list)
|
||||
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 meta.error:
|
||||
errors[meta.error].append(creator_class)
|
||||
else:
|
||||
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
|
||||
if not key_to_meta:
|
||||
if errors:
|
||||
rows = ["{} for creators {}".format(k, ", ".join(i.__name__ for i in v)) for k, v in errors.items()]
|
||||
raise RuntimeError("\n".join(rows))
|
||||
else:
|
||||
raise RuntimeError("No virtualenv implementation for {}".format(interpreter))
|
||||
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
|
||||
choices = sorted(choices, key=lambda a: 0 if a == "builtin" else 1)
|
||||
default_value = self._get_default(choices)
|
||||
self.parser.add_argument(
|
||||
"--{}".format(name),
|
||||
choices=choices,
|
||||
default=default_value,
|
||||
required=False,
|
||||
help="create environment via{}".format(
|
||||
"" if self.builtin_key is None else " (builtin = {})".format(self.builtin_key),
|
||||
),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _get_default(choices):
|
||||
return next(iter(choices))
|
||||
|
||||
def populate_selected_argparse(self, selected, app_data):
|
||||
self.parser.description = "options for {} {}".format(self.name, selected)
|
||||
self._impl_class.add_parser_arguments(self.parser, self.interpreter, self.key_to_meta[selected], app_data)
|
||||
|
||||
def create(self, options):
|
||||
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)
|
||||
32
Lib/site-packages/virtualenv/run/plugin/discovery.py
Normal file
32
Lib/site-packages/virtualenv/run/plugin/discovery.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from .base import PluginLoader
|
||||
|
||||
|
||||
class Discovery(PluginLoader):
|
||||
""""""
|
||||
|
||||
|
||||
def get_discover(parser, args):
|
||||
discover_types = Discovery.entry_points_for("virtualenv.discovery")
|
||||
discovery_parser = parser.add_argument_group(
|
||||
title="discovery",
|
||||
description="discover and provide a target interpreter",
|
||||
)
|
||||
discovery_parser.add_argument(
|
||||
"--discovery",
|
||||
choices=_get_default_discovery(discover_types),
|
||||
default=next(i for i in discover_types.keys()),
|
||||
required=False,
|
||||
help="interpreter discovery method",
|
||||
)
|
||||
options, _ = parser.parse_known_args(args)
|
||||
discover_class = discover_types[options.discovery]
|
||||
discover_class.add_parser_arguments(discovery_parser)
|
||||
options, _ = parser.parse_known_args(args, namespace=options)
|
||||
discover = discover_class(options)
|
||||
return discover
|
||||
|
||||
|
||||
def _get_default_discovery(discover_types):
|
||||
return list(discover_types.keys())
|
||||
35
Lib/site-packages/virtualenv/run/plugin/seeders.py
Normal file
35
Lib/site-packages/virtualenv/run/plugin/seeders.py
Normal file
@@ -0,0 +1,35 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from .base import ComponentBuilder
|
||||
|
||||
|
||||
class SeederSelector(ComponentBuilder):
|
||||
def __init__(self, interpreter, parser):
|
||||
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(
|
||||
"--{}".format(name),
|
||||
choices=choices,
|
||||
default=self._get_default(),
|
||||
required=False,
|
||||
help="seed packages install method",
|
||||
)
|
||||
self.parser.add_argument(
|
||||
"--no-seed",
|
||||
"--without-pip",
|
||||
help="do not install seed packages",
|
||||
action="store_true",
|
||||
dest="no_seed",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _get_default():
|
||||
return "app-data"
|
||||
|
||||
def handle_selected_arg_parse(self, options):
|
||||
return super(SeederSelector, self).handle_selected_arg_parse(options)
|
||||
|
||||
def create(self, options):
|
||||
return self._impl_class(options)
|
||||
91
Lib/site-packages/virtualenv/run/session.py
Normal file
91
Lib/site-packages/virtualenv/run/session.py
Normal file
@@ -0,0 +1,91 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
from virtualenv.util.six import ensure_text
|
||||
|
||||
|
||||
class Session(object):
|
||||
"""Represents a virtual environment creation session"""
|
||||
|
||||
def __init__(self, verbosity, app_data, interpreter, creator, seeder, activators):
|
||||
self._verbosity = verbosity
|
||||
self._app_data = app_data
|
||||
self._interpreter = interpreter
|
||||
self._creator = creator
|
||||
self._seeder = seeder
|
||||
self._activators = activators
|
||||
|
||||
@property
|
||||
def verbosity(self):
|
||||
"""The verbosity of the run"""
|
||||
return self._verbosity
|
||||
|
||||
@property
|
||||
def interpreter(self):
|
||||
"""Create a virtual environment based on this reference interpreter"""
|
||||
return self._interpreter
|
||||
|
||||
@property
|
||||
def creator(self):
|
||||
"""The creator used to build the virtual environment (must be compatible with the interpreter)"""
|
||||
return self._creator
|
||||
|
||||
@property
|
||||
def seeder(self):
|
||||
"""The mechanism used to provide the seed packages (pip, setuptools, wheel)"""
|
||||
return self._seeder
|
||||
|
||||
@property
|
||||
def activators(self):
|
||||
"""Activators used to generate activations scripts"""
|
||||
return self._activators
|
||||
|
||||
def run(self):
|
||||
self._create()
|
||||
self._seed()
|
||||
self._activate()
|
||||
self.creator.pyenv_cfg.write()
|
||||
|
||||
def _create(self):
|
||||
logging.info("create virtual environment via %s", ensure_text(str(self.creator)))
|
||||
self.creator.run()
|
||||
logging.debug(_DEBUG_MARKER)
|
||||
logging.debug("%s", _Debug(self.creator))
|
||||
|
||||
def _seed(self):
|
||||
if self.seeder is not None and self.seeder.enabled:
|
||||
logging.info("add seed packages via %s", self.seeder)
|
||||
self.seeder.run(self.creator)
|
||||
|
||||
def _activate(self):
|
||||
if self.activators:
|
||||
logging.info(
|
||||
"add activators for %s",
|
||||
", ".join(type(i).__name__.replace("Activator", "") for i in self.activators),
|
||||
)
|
||||
for activator in self.activators:
|
||||
activator.generate(self.creator)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self._app_data.close()
|
||||
|
||||
|
||||
_DEBUG_MARKER = "=" * 30 + " target debug " + "=" * 30
|
||||
|
||||
|
||||
class _Debug(object):
|
||||
"""lazily populate debug"""
|
||||
|
||||
def __init__(self, creator):
|
||||
self.creator = creator
|
||||
|
||||
def __unicode__(self):
|
||||
return ensure_text(repr(self))
|
||||
|
||||
def __repr__(self):
|
||||
return json.dumps(self.creator.debug, indent=2)
|
||||
Reference in New Issue
Block a user