1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
from __future__ import annotations
import logging
import os
from functools import partial
from ..app_data import make_app_data
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, env=None):
"""
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
:param env: environment variables to use
:return: the session object of the creation (its structure for now is experimental and might change on short notice)
"""
env = os.environ if env is None else env
of_session = session_via_cli(args, options, setup_logging, env)
with of_session:
of_session.run()
return of_session
def session_via_cli(args, options=None, setup_logging=True, env=None):
"""
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
:param env: environment variables to use
:return: the session object of the creation (its structure for now is experimental and might change on short notice)
"""
env = os.environ if env is None else env
parser, elements = build_parser(args, options, setup_logging, env)
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)
return of_session
def build_parser(args=None, options=None, setup_logging=True, env=None):
parser = VirtualEnvConfigParser(options, os.environ if env is None else env)
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(f"failed to find interpreter for {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, options.env)
raise SystemExit(result)
def load_app_data(args, parser, options):
parser.add_argument(
"--read-only-app-data",
action="store_true",
help="use app data folder in read-only mode (write operations will fail with error)",
)
options, _ = parser.parse_known_args(args, namespace=options)
# here we need a write-able application data (e.g. the zipapp might need this for discovery cache)
parser.add_argument(
"--app-data",
help="a data folder used as cache by the virtualenv",
type=partial(make_app_data, read_only=options.read_only_app_data, env=options.env),
default=make_app_data(None, read_only=options.read_only_app_data, env=options.env),
)
parser.add_argument(
"--reset-app-data",
action="store_true",
help="start with empty app data folder",
)
parser.add_argument(
"--upgrade-embed-wheels",
action="store_true",
help="trigger a manual update of the embedded wheels",
)
options, _ = parser.parse_known_args(args, namespace=options)
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=f"%(prog)s {__version__} from {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(f"{logging.getLevelName(l)}={c}" for c, l in sorted(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",
]
|