summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBernát Gábor <bgabor8@bloomberg.net>2020-02-04 14:51:00 +0000
committerGitHub <noreply@github.com>2020-02-04 14:51:00 +0000
commit7a5d03fe15f1d467f7b224c528b95eccc080b2c1 (patch)
tree7d1ccccac7eb588221fd3aa26c9d9227293ba179 /src
parent786c3d0addb5d6b155dc73f8bd444bde00877045 (diff)
downloadvirtualenv-7a5d03fe15f1d467f7b224c528b95eccc080b2c1.tar.gz
rewrite the documentation (#1519)
Diffstat (limited to 'src')
-rw-r--r--src/virtualenv/activation/activator.py29
-rw-r--r--src/virtualenv/config/cli/parser.py6
-rw-r--r--src/virtualenv/create/creator.py40
-rw-r--r--src/virtualenv/discovery/builtin.py2
-rw-r--r--src/virtualenv/discovery/discover.py25
-rw-r--r--src/virtualenv/run/__init__.py42
-rw-r--r--src/virtualenv/run/plugin/activators.py2
-rw-r--r--src/virtualenv/run/plugin/base.py3
-rw-r--r--src/virtualenv/run/plugin/creators.py8
-rw-r--r--src/virtualenv/run/plugin/discovery.py10
-rw-r--r--src/virtualenv/run/plugin/seeders.py13
-rw-r--r--src/virtualenv/seed/embed/base_embed.py8
-rw-r--r--src/virtualenv/seed/embed/pip_invoke.py2
-rw-r--r--src/virtualenv/seed/none.py15
-rw-r--r--src/virtualenv/seed/seeder.py19
-rw-r--r--src/virtualenv/seed/via_app_data/via_app_data.py4
16 files changed, 163 insertions, 65 deletions
diff --git a/src/virtualenv/activation/activator.py b/src/virtualenv/activation/activator.py
index 7e69aa7..728fa7e 100644
--- a/src/virtualenv/activation/activator.py
+++ b/src/virtualenv/activation/activator.py
@@ -7,17 +7,38 @@ import six
@six.add_metaclass(ABCMeta)
class Activator(object):
+ """Generates an activate script for the virtual environment"""
+
def __init__(self, options):
- self.flag_prompt = options.prompt
+ """Create a new activator generator.
- @classmethod
- def add_parser_arguments(cls, parser, interpreter):
- """add activator options"""
+ :param options: the parsed options as defined within :meth:`add_parser_arguments`
+ """
+ self.flag_prompt = options.prompt
@classmethod
def supports(cls, interpreter):
+ """Check if the activation script is supported in the given interpreter.
+
+ :param interpreter: the interpreter we need to support
+ :return: ``True`` if supported, ``False`` otherwise
+ """
return True
+ @classmethod
+ def add_parser_arguments(cls, parser, interpreter):
+ """
+ Add CLI arguments for this activation script.
+
+ :param parser: the CLI parser
+ :param interpreter: the interpreter this virtual environment is based of
+ """
+
@abstractmethod
def generate(self, creator):
+ """Generate the activate script for the given creator.
+
+ :param creator: the creator (based of :class:`virtualenv.create.creator.Creator`) we used to create this \
+ virtual environment
+ """
raise NotImplementedError
diff --git a/src/virtualenv/config/cli/parser.py b/src/virtualenv/config/cli/parser.py
index e817a42..67c63fb 100644
--- a/src/virtualenv/config/cli/parser.py
+++ b/src/virtualenv/config/cli/parser.py
@@ -20,6 +20,10 @@ class VirtualEnvConfigParser(ArgumentParser):
kwargs["prog"] = "virtualenv"
super(VirtualEnvConfigParser, self).__init__(*args, **kwargs)
self._fixed = set()
+ self._elements = None
+ self._verbosity = None
+ self._options = None
+ self._interpreter = None
def _fix_defaults(self):
for action in self._actions:
@@ -52,7 +56,7 @@ class VirtualEnvConfigParser(ArgumentParser):
class HelpFormatter(ArgumentDefaultsHelpFormatter):
def __init__(self, prog):
- super(HelpFormatter, self).__init__(prog, max_help_position=37, width=240)
+ super(HelpFormatter, self).__init__(prog, max_help_position=35, width=240)
def _get_help_string(self, action):
# noinspection PyProtectedMember
diff --git a/src/virtualenv/create/creator.py b/src/virtualenv/create/creator.py
index 11e0deb..7965bd0 100644
--- a/src/virtualenv/create/creator.py
+++ b/src/virtualenv/create/creator.py
@@ -28,7 +28,14 @@ DEBUG_SCRIPT = HERE / "debug.py"
@add_metaclass(ABCMeta)
class Creator(object):
+ """A class that given a python Interpreter creates a virtual environment"""
+
def __init__(self, options, interpreter):
+ """Construct a new virtual environment creator.
+
+ :param options: the CLI option as parsed from :meth:`add_parser_arguments`
+ :param interpreter: the interpreter to create virtual environment from
+ """
self.interpreter = interpreter
self._debug = None
self.dest = Path(options.dest)
@@ -48,7 +55,23 @@ class Creator(object):
]
@classmethod
+ def can_create(cls, interpreter):
+ """Determine if we can create a virtual environment.
+
+ :param interpreter: the interpreter in question
+ :return: ``None`` if we can't create, any other object otherwise that will be forwarded to \
+ :meth:`add_parser_arguments`
+ """
+ return True
+
+ @classmethod
def add_parser_arguments(cls, parser, interpreter, meta):
+ """Add CLI arguments for the creator.
+
+ :param parser: the CLI parser
+ :param interpreter: the interpreter we're asked to create virtual environment for
+ :param meta: value as returned by :meth:`can_create`
+ """
parser.add_argument(
"dest", help="directory to create virtualenv at", type=cls.validate_dest, default="venv", nargs="?",
)
@@ -60,6 +83,11 @@ class Creator(object):
default=False,
)
+ @abstractmethod
+ def create(self):
+ """Perform the virtual environment creation."""
+ raise NotImplementedError
+
@classmethod
def validate_dest(cls, raw_value):
"""No path separator in the path, valid chars and must be write-able"""
@@ -132,15 +160,6 @@ class Creator(object):
self.create()
self.set_pyenv_cfg()
- @abstractmethod
- def create(self):
- raise NotImplementedError
-
- @classmethod
- def can_create(cls, interpreter):
- """Default is that we can"""
- return True
-
def set_pyenv_cfg(self):
self.pyenv_cfg.content = OrderedDict()
self.pyenv_cfg["home"] = self.interpreter.system_exec_prefix
@@ -150,6 +169,9 @@ class Creator(object):
@property
def debug(self):
+ """
+ :return: debug information about the virtual environment (only valid after :meth:`create` has run)
+ """
if self._debug is None and self.exe is not None:
self._debug = get_env_debug_info(self.exe, self.debug_script())
return self._debug
diff --git a/src/virtualenv/discovery/builtin.py b/src/virtualenv/discovery/builtin.py
index e4e0ea0..c5f4883 100644
--- a/src/virtualenv/discovery/builtin.py
+++ b/src/virtualenv/discovery/builtin.py
@@ -15,7 +15,7 @@ from .py_spec import PythonSpec
class Builtin(Discover):
def __init__(self, options):
- super(Builtin, self).__init__()
+ super(Builtin, self).__init__(options)
self.python_spec = options.python
@classmethod
diff --git a/src/virtualenv/discovery/discover.py b/src/virtualenv/discovery/discover.py
index 13e258f..17d404e 100644
--- a/src/virtualenv/discovery/discover.py
+++ b/src/virtualenv/discovery/discover.py
@@ -7,20 +7,39 @@ import six
@six.add_metaclass(ABCMeta)
class Discover(object):
- def __init__(self):
- self._has_run = False
- self._interpreter = None
+ """Discover and provide the requested Python interpreter"""
@classmethod
def add_parser_arguments(cls, parser):
+ """Add CLI arguments for this discovery mechanisms.
+
+ :param parser: the CLI parser
+ """
raise NotImplementedError
+ # noinspection PyUnusedLocal
+ def __init__(self, options):
+ """Create a new discovery mechanism.
+
+ :param options: the parsed options as defined within :meth:`add_parser_arguments`
+ """
+ self._has_run = False
+ self._interpreter = None
+
@abstractmethod
def run(self):
+ """Discovers an interpreter.
+
+
+ :return: the interpreter ready to use for virtual environment creation
+ """
raise NotImplementedError
@property
def interpreter(self):
+ """
+ :return: the interpreter as returned by :meth:`run`, cached
+ """
if self._has_run is False:
self._interpreter = self.run()
self._has_run = True
diff --git a/src/virtualenv/run/__init__.py b/src/virtualenv/run/__init__.py
index 45a9662..7d0776b 100644
--- a/src/virtualenv/run/__init__.py
+++ b/src/virtualenv/run/__init__.py
@@ -23,41 +23,53 @@ def run_via_cli(args):
return session
+# noinspection PyProtectedMember
def session_via_cli(args):
+ parser = build_parser(args)
+ parser.parse_args(args, namespace=parser._options)
+ creator, seeder, activators = tuple(e.create(parser._options) for e in parser._elements) # create types
+ session = Session(parser._verbosity, parser._interpreter, creator, seeder, activators)
+ return session
+
+
+# noinspection PyProtectedMember
+def build_parser(args=None):
parser = VirtualEnvConfigParser()
add_version_flag(parser)
- options, verbosity = _do_report_setup(parser, args)
- discover = get_discover(parser, args, options)
- interpreter = discover.interpreter
+ parser._options, parser._verbosity = _do_report_setup(parser, args)
+ discover = get_discover(parser, args, parser._options)
+ parser._interpreter = interpreter = discover.interpreter
if interpreter is None:
raise RuntimeError("failed to find interpreter for {}".format(discover))
- elements = [
+ parser._elements = [
CreatorSelector(interpreter, parser),
SeederSelector(interpreter, parser),
ActivationSelector(interpreter, parser),
]
- parser.parse_known_args(args, namespace=options)
- for element in elements:
- element.handle_selected_arg_parse(options)
+ parser.parse_known_args(args, namespace=parser._options)
+ for element in parser._elements:
+ element.handle_selected_arg_parse(parser._options)
parser.enable_help()
- parser.parse_args(args, namespace=options)
- creator, seeder, activators = tuple(e.create(options) for e in elements) # create types
- session = Session(verbosity, interpreter, creator, seeder, activators)
- return session
+ return parser
def add_version_flag(parser):
import virtualenv
parser.add_argument(
- "--version", action="version", version="%(prog)s {} from {}".format(__version__, virtualenv.__file__)
+ "--version",
+ action="version",
+ version="%(prog)s {} from {}".format(__version__, virtualenv.__file__),
+ help="display the version of the virtualenv package and it's location, then exit",
)
def _do_report_setup(parser, args):
- level_map = ", ".join("{}:{}".format(c, logging.getLevelName(l)) for c, l in sorted(list(LEVELS.items())))
- msg = "verbosity = verbose - quiet, default {}, count mapping = {{{}}}"
- verbosity_group = parser.add_argument_group(msg.format(logging.getLevelName(LEVELS[3]), level_map))
+ 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)
diff --git a/src/virtualenv/run/plugin/activators.py b/src/virtualenv/run/plugin/activators.py
index 8fb5a6b..69b3050 100644
--- a/src/virtualenv/run/plugin/activators.py
+++ b/src/virtualenv/run/plugin/activators.py
@@ -13,11 +13,11 @@ class ActivationSelector(ComponentBuilder):
(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,
diff --git a/src/virtualenv/run/plugin/base.py b/src/virtualenv/run/plugin/base.py
index e3230e7..8aa4206 100644
--- a/src/virtualenv/run/plugin/base.py
+++ b/src/virtualenv/run/plugin/base.py
@@ -30,7 +30,7 @@ class ComponentBuilder(PluginLoader):
self.name = name
self._impl_class = None
self.possible = possible
- self.parser = parser.add_argument_group("{} options".format(name))
+ self.parser = parser.add_argument_group(title=name)
self.add_selector_arg_parse(name, list(self.possible))
@classmethod
@@ -51,6 +51,7 @@ class ComponentBuilder(PluginLoader):
return selected
def populate_selected_argparse(self, selected):
+ self.parser.description = "options for {} {}".format(self.name, selected)
self._impl_class.add_parser_arguments(self.parser, self.interpreter)
def create(self, options):
diff --git a/src/virtualenv/run/plugin/creators.py b/src/virtualenv/run/plugin/creators.py
index 946b87a..7c8132d 100644
--- a/src/virtualenv/run/plugin/creators.py
+++ b/src/virtualenv/run/plugin/creators.py
@@ -40,17 +40,23 @@ class CreatorSelector(ComponentBuilder):
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=next(iter(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):
+ self.parser.description = "options for {} {}".format(self.name, selected)
self._impl_class.add_parser_arguments(self.parser, self.interpreter, self.key_to_meta[selected])
def create(self, options):
diff --git a/src/virtualenv/run/plugin/discovery.py b/src/virtualenv/run/plugin/discovery.py
index aaed452..8890150 100644
--- a/src/virtualenv/run/plugin/discovery.py
+++ b/src/virtualenv/run/plugin/discovery.py
@@ -9,10 +9,12 @@ class Discovery(PluginLoader):
def get_discover(parser, args, options):
discover_types = Discovery.entry_points_for("virtualenv.discovery")
- discovery_parser = parser.add_argument_group("target interpreter identifier")
+ discovery_parser = parser.add_argument_group(
+ title="discovery", description="discover and provide a target interpreter"
+ )
discovery_parser.add_argument(
"--discovery",
- choices=list(discover_types.keys()),
+ choices=_get_default_discovery(discover_types),
default=next(i for i in discover_types.keys()),
required=False,
help="interpreter discovery method",
@@ -23,3 +25,7 @@ def get_discover(parser, args, options):
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())
diff --git a/src/virtualenv/run/plugin/seeders.py b/src/virtualenv/run/plugin/seeders.py
index 2bd7070..26a3385 100644
--- a/src/virtualenv/run/plugin/seeders.py
+++ b/src/virtualenv/run/plugin/seeders.py
@@ -12,20 +12,19 @@ class SeederSelector(ComponentBuilder):
self.parser.add_argument(
"--{}".format(name),
choices=choices,
- default="app-data",
+ default=self._get_default(),
required=False,
help="seed packages install method",
)
self.parser.add_argument(
- "--without-pip",
- help="if set forces the none seeder, used for compatibility with venv",
- action="store_true",
- dest="without_pip",
+ "--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):
- if options.without_pip is True:
- setattr(options, self.name, "none")
return super(SeederSelector, self).handle_selected_arg_parse(options)
def create(self, options):
diff --git a/src/virtualenv/seed/embed/base_embed.py b/src/virtualenv/seed/embed/base_embed.py
index 28490b8..b93fff6 100644
--- a/src/virtualenv/seed/embed/base_embed.py
+++ b/src/virtualenv/seed/embed/base_embed.py
@@ -14,7 +14,7 @@ class BaseEmbed(Seeder):
packages = ["pip", "setuptools", "wheel"]
def __init__(self, options):
- super(BaseEmbed, self).__init__(options, enabled=options.without_pip is False)
+ super(BaseEmbed, self).__init__(options, enabled=options.no_seed is False)
self.download = options.download
self.extra_search_dir = [i.resolve() for i in options.extra_search_dir if i.exists()]
@@ -41,7 +41,7 @@ class BaseEmbed(Seeder):
"--download",
dest="download",
action="store_true",
- help="download latest {} from PyPI".format("/".join(cls.packages)),
+ help="pass to enable download of the latest {} from PyPI".format("/".join(cls.packages)),
default=False,
)
group.add_argument(
@@ -49,7 +49,7 @@ class BaseEmbed(Seeder):
"--never-download",
dest="download",
action="store_false",
- help="download latest {} from PyPI".format("/".join(cls.packages)),
+ help="pass to disable download of the latest {} from PyPI".format("/".join(cls.packages)),
default=True,
)
parser.add_argument(
@@ -57,7 +57,7 @@ class BaseEmbed(Seeder):
metavar="d",
type=Path,
nargs="+",
- help="a location containing wheels candidates to install from",
+ help="a path containing wheels the seeder may also use beside bundled (can be set 1+ times)",
default=[],
)
for package in cls.packages:
diff --git a/src/virtualenv/seed/embed/pip_invoke.py b/src/virtualenv/seed/embed/pip_invoke.py
index 0e9ac8c..4b35ee5 100644
--- a/src/virtualenv/seed/embed/pip_invoke.py
+++ b/src/virtualenv/seed/embed/pip_invoke.py
@@ -21,6 +21,8 @@ class PipInvoke(BaseEmbed):
super(PipInvoke, self).__init__(options)
def run(self, creator):
+ if not self.enabled:
+ return
with self.get_pip_install_cmd(creator.exe, creator.interpreter.version_release_str) as cmd:
with pip_wheel_env_run(creator.interpreter.version_release_str) as env:
logging.debug("pip seed by running: %s", LogCmd(cmd, env))
diff --git a/src/virtualenv/seed/none.py b/src/virtualenv/seed/none.py
deleted file mode 100644
index 0bd12e4..0000000
--- a/src/virtualenv/seed/none.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import absolute_import, unicode_literals
-
-from virtualenv.seed.seeder import Seeder
-
-
-class NoneSeeder(Seeder):
- def __init__(self, options):
- super(NoneSeeder, self).__init__(options, False)
-
- @classmethod
- def add_parser_arguments(cls, parser, interpreter):
- pass
-
- def run(self, creator):
- pass
diff --git a/src/virtualenv/seed/seeder.py b/src/virtualenv/seed/seeder.py
index a679f03..52b065d 100644
--- a/src/virtualenv/seed/seeder.py
+++ b/src/virtualenv/seed/seeder.py
@@ -7,13 +7,32 @@ import six
@six.add_metaclass(ABCMeta)
class Seeder(object):
+ """A seeder will install some seed packages into a virtual environment."""
+
+ # noinspection PyUnusedLocal
def __init__(self, options, enabled):
+ """
+
+ :param options: the parsed options as defined within :meth:`add_parser_arguments`
+ :param enabled: a flag weather the seeder is enabled or not
+ """
self.enabled = enabled
@classmethod
def add_parser_arguments(cls, parser, interpreter):
+ """
+ Add CLI arguments for this seed mechanisms.
+
+ :param parser: the CLI parser
+ :param interpreter: the interpreter this virtual environment is based of
+ """
raise NotImplementedError
@abstractmethod
def run(self, creator):
+ """Perform the seed operation.
+
+ :param creator: the creator (based of :class:`virtualenv.create.creator.Creator`) we used to create this \
+ virtual environment
+ """
raise NotImplementedError
diff --git a/src/virtualenv/seed/via_app_data/via_app_data.py b/src/virtualenv/seed/via_app_data/via_app_data.py
index c0e28e5..069a9c1 100644
--- a/src/virtualenv/seed/via_app_data/via_app_data.py
+++ b/src/virtualenv/seed/via_app_data/via_app_data.py
@@ -30,11 +30,13 @@ class FromAppData(BaseEmbed):
"--clear-app-data",
dest="clear_app_data",
action="store_true",
- help="clear the app data folder",
+ help="clear the app data folder of seed images ({})".format((default_data_dir() / "seed-v1").path),
default=False,
)
def run(self, creator):
+ if not self.enabled:
+ return
base_cache = self.app_data_dir / creator.interpreter.version_release_str
with self._get_seed_wheels(creator, base_cache) as name_to_whl:
pip_version = name_to_whl["pip"].stem.split("-")[1]