Let us walk on the 3-isogeny graph
Loading...
Searching...
No Matches
configuration.py
Go to the documentation of this file.
1import logging
2import os
3import subprocess
4from optparse import Values
5from typing import Any, List, Optional
6
7from pip._internal.cli.base_command import Command
8from pip._internal.cli.status_codes import ERROR, SUCCESS
10 Configuration,
11 Kind,
12 get_configuration_files,
13 kinds,
14)
15from pip._internal.exceptions import PipError
16from pip._internal.utils.logging import indent_log
17from pip._internal.utils.misc import get_prog, write_output
18
19logger = logging.getLogger(__name__)
20
21
23 """
24 Manage local and global configuration.
25
26 Subcommands:
27
28 - list: List the active configuration (or from the file specified)
29 - edit: Edit the configuration file in an editor
30 - get: Get the value associated with command.option
31 - set: Set the command.option=value
32 - unset: Unset the value associated with command.option
33 - debug: List the configuration files and values defined under them
34
35 Configuration keys should be dot separated command and option name,
36 with the special prefix "global" affecting any command. For example,
37 "pip config set global.index-url https://example.org/" would configure
38 the index url for all commands, but "pip config set download.timeout 10"
39 would configure a 10 second timeout only for "pip download" commands.
40
41 If none of --user, --global and --site are passed, a virtual
42 environment configuration file is used if one is active and the file
43 exists. Otherwise, all modifications happen to the user file by
44 default.
45 """
46
47 ignore_require_venv = True
48 usage = """
49 %prog [<file-option>] list
50 %prog [<file-option>] [--editor <editor-path>] edit
51
52 %prog [<file-option>] get command.option
53 %prog [<file-option>] set command.option value
54 %prog [<file-option>] unset command.option
55 %prog [<file-option>] debug
56 """
57
58 def add_options(self) -> None:
60 "--editor",
61 dest="editor",
62 action="store",
63 default=None,
64 help=(
65 "Editor to use to edit the file. Uses VISUAL or EDITOR "
66 "environment variables if not provided."
67 ),
68 )
69
71 "--global",
72 dest="global_file",
73 action="store_true",
74 default=False,
75 help="Use the system-wide configuration file only",
76 )
77
79 "--user",
80 dest="user_file",
81 action="store_true",
82 default=False,
83 help="Use the user configuration file only",
84 )
85
87 "--site",
88 dest="site_file",
89 action="store_true",
90 default=False,
91 help="Use the current environment configuration file only",
92 )
93
94 self.parser.insert_option_group(0, self.cmd_optscmd_opts)
95
96 def run(self, options: Values, args: List[str]) -> int:
97 handlers = {
100 "get": self.get_nameget_name,
102 "unset": self.unset_nameunset_name,
104 }
105
106 # Determine action
107 if not args or args[0] not in handlers:
109 "Need an action (%s) to perform.",
110 ", ".join(sorted(handlers)),
111 )
112 return ERROR
113
114 action = args[0]
115
116 # Determine which configuration files are to be loaded
117 # Depends on whether the command is modifying.
118 try:
119 load_only = self._determine_file(
120 options, need_value=(action in ["get", "set", "unset", "edit"])
121 )
122 except PipError as e:
124 return ERROR
125
126 # Load a new configuration
128 isolated=options.isolated_mode, load_only=load_only
129 )
130 self.configuration.load()
131
132 # Error handling happens here, not in the action-handlers.
133 try:
134 handlers[action](options, args[1:])
135 except PipError as e:
137 return ERROR
138
139 return SUCCESS
140
141 def _determine_file(self, options: Values, need_value: bool) -> Optional[Kind]:
142 file_options = [
143 key
144 for key, value in (
148 )
149 if value
150 ]
151
152 if not file_options:
153 if not need_value:
154 return None
155 # Default to user, unless there's a site file.
156 elif any(
157 os.path.exists(site_config_file)
158 for site_config_file in get_configuration_files()[kinds.SITE]
159 ):
160 return kinds.SITE
161 else:
162 return kinds.USER
163 elif len(file_options) == 1:
164 return file_options[0]
165
166 raise PipError(
167 "Need exactly one file to operate upon "
168 "(--user, --site, --global) to perform."
169 )
170
171 def list_values(self, options: Values, args: List[str]) -> None:
172 self._get_n_args(args, "list", n=0)
173
174 for key, value in sorted(self.configuration.items()):
175 write_output("%s=%r", key, value)
176
177 def get_name(self, options: Values, args: List[str]) -> None:
178 key = self._get_n_args(args, "get [name]", n=1)
179 value = self.configuration.get_value(key)
180
181 write_output("%s", value)
182
183 def set_name_value(self, options: Values, args: List[str]) -> None:
184 key, value = self._get_n_args(args, "set [name] [value]", n=2)
185 self.configuration.set_value(key, value)
186
188
189 def unset_name(self, options: Values, args: List[str]) -> None:
190 key = self._get_n_args(args, "unset [name]", n=1)
191 self.configuration.unset_value(key)
192
194
195 def list_config_values(self, options: Values, args: List[str]) -> None:
196 """List config key-value pairs across different config files"""
197 self._get_n_args(args, "debug", n=0)
198
200 # Iterate over config files and print if they exist, and the
201 # key-value pairs present in them if they do
202 for variant, files in sorted(self.configuration.iter_config_files()):
203 write_output("%s:", variant)
204 for fname in files:
205 with indent_log():
206 file_exists = os.path.exists(fname)
207 write_output("%s, exists: %r", fname, file_exists)
208 if file_exists:
209 self.print_config_file_values(variant)
210
211 def print_config_file_values(self, variant: Kind) -> None:
212 """Get key-value pairs from the file of a variant"""
213 for name, value in self.configuration.get_values_in_config(variant).items():
214 with indent_log():
215 write_output("%s: %s", name, value)
216
217 def print_env_var_values(self) -> None:
218 """Get key-values pairs present as environment variables"""
219 write_output("%s:", "env_var")
220 with indent_log():
221 for key, value in sorted(self.configuration.get_environ_vars()):
222 env_var = f"PIP_{key.upper()}"
223 write_output("%s=%r", env_var, value)
224
225 def open_in_editor(self, options: Values, args: List[str]) -> None:
226 editor = self._determine_editor(options)
227
228 fname = self.configuration.get_file_to_edit()
229 if fname is None:
230 raise PipError("Could not determine appropriate file.")
231 elif '"' in fname:
232 # This shouldn't happen, unless we see a username like that.
233 # If that happens, we'd appreciate a pull request fixing this.
234 raise PipError(
235 f'Can not open an editor for a file name containing "\n{fname}'
236 )
237
238 try:
239 subprocess.check_call(f'{editor} "{fname}"', shell=True)
240 except FileNotFoundError as e:
241 if not e.filename:
242 e.filename = editor
243 raise
245 raise PipError(
246 "Editor Subprocess exited with exit code {}".format(e.returncode)
247 )
248
249 def _get_n_args(self, args: List[str], example: str, n: int) -> Any:
250 """Helper to make sure the command got the right number of arguments"""
251 if len(args) != n:
252 msg = (
253 "Got unexpected number of arguments, expected {}. "
254 '(example: "{} config {}")'
255 ).format(n, get_prog(), example)
256 raise PipError(msg)
257
258 if n == 1:
259 return args[0]
260 else:
261 return args
262
263 def _save_configuration(self) -> None:
264 # We successfully ran a modifying command. Need to save the
265 # configuration.
266 try:
267 self.configuration.save()
268 except Exception:
270 "Unable to save configuration. Please report this as a bug."
271 )
272 raise PipError("Internal Error.")
273
274 def _determine_editor(self, options: Values) -> str:
275 if options.editor is not None:
276 return options.editor
277 elif "VISUAL" in os.environ:
278 return os.environ["VISUAL"]
279 elif "EDITOR" in os.environ:
280 return os.environ["EDITOR"]
281 else:
282 raise PipError("Could not determine editor to use.")
Any _get_n_args(self, List[str] args, str example, int n)
None get_name(self, Values options, List[str] args)
None set_name_value(self, Values options, List[str] args)
None unset_name(self, Values options, List[str] args)
None open_in_editor(self, Values options, List[str] args)
None list_config_values(self, Values options, List[str] args)
Optional[Kind] _determine_file(self, Values options, bool need_value)
int run(self, Values options, List[str] args)
None list_values(self, Values options, List[str] args)
for i