Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/IPython/core/magics/packaging.py: 34%
50 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1"""Implementation of packaging-related magic functions.
2"""
3#-----------------------------------------------------------------------------
4# Copyright (c) 2018 The IPython Development Team.
5#
6# Distributed under the terms of the Modified BSD License.
7#
8# The full license is in the file COPYING.txt, distributed with this software.
9#-----------------------------------------------------------------------------
11import re
12import shlex
13import sys
14from pathlib import Path
16from IPython.core.magic import Magics, magics_class, line_magic
19def _is_conda_environment():
20 """Return True if the current Python executable is in a conda env"""
21 # TODO: does this need to change on windows?
22 return Path(sys.prefix, "conda-meta", "history").exists()
25def _get_conda_executable():
26 """Find the path to the conda executable"""
27 # Check if there is a conda executable in the same directory as the Python executable.
28 # This is the case within conda's root environment.
29 conda = Path(sys.executable).parent / "conda"
30 if conda.is_file():
31 return str(conda)
33 # Otherwise, attempt to extract the executable from conda history.
34 # This applies in any conda environment.
35 history = Path(sys.prefix, "conda-meta", "history").read_text(encoding="utf-8")
36 match = re.search(
37 r"^#\s*cmd:\s*(?P<command>.*conda)\s[create|install]",
38 history,
39 flags=re.MULTILINE,
40 )
41 if match:
42 return match.groupdict()["command"]
44 # Fallback: assume conda is available on the system path.
45 return "conda"
48CONDA_COMMANDS_REQUIRING_PREFIX = {
49 'install', 'list', 'remove', 'uninstall', 'update', 'upgrade',
50}
51CONDA_COMMANDS_REQUIRING_YES = {
52 'install', 'remove', 'uninstall', 'update', 'upgrade',
53}
54CONDA_ENV_FLAGS = {'-p', '--prefix', '-n', '--name'}
55CONDA_YES_FLAGS = {'-y', '--y'}
58@magics_class
59class PackagingMagics(Magics):
60 """Magics related to packaging & installation"""
62 @line_magic
63 def pip(self, line):
64 """Run the pip package manager within the current kernel.
66 Usage:
67 %pip install [pkgs]
68 """
69 python = sys.executable
70 if sys.platform == "win32":
71 python = '"' + python + '"'
72 else:
73 python = shlex.quote(python)
75 self.shell.system(" ".join([python, "-m", "pip", line]))
77 print("Note: you may need to restart the kernel to use updated packages.")
79 @line_magic
80 def conda(self, line):
81 """Run the conda package manager within the current kernel.
83 Usage:
84 %conda install [pkgs]
85 """
86 if not _is_conda_environment():
87 raise ValueError("The python kernel does not appear to be a conda environment. "
88 "Please use ``%pip install`` instead.")
90 conda = _get_conda_executable()
91 args = shlex.split(line)
92 command = args[0] if len(args) > 0 else ""
93 args = args[1:] if len(args) > 1 else [""]
95 extra_args = []
97 # When the subprocess does not allow us to respond "yes" during the installation,
98 # we need to insert --yes in the argument list for some commands
99 stdin_disabled = getattr(self.shell, 'kernel', None) is not None
100 needs_yes = command in CONDA_COMMANDS_REQUIRING_YES
101 has_yes = set(args).intersection(CONDA_YES_FLAGS)
102 if stdin_disabled and needs_yes and not has_yes:
103 extra_args.append("--yes")
105 # Add --prefix to point conda installation to the current environment
106 needs_prefix = command in CONDA_COMMANDS_REQUIRING_PREFIX
107 has_prefix = set(args).intersection(CONDA_ENV_FLAGS)
108 if needs_prefix and not has_prefix:
109 extra_args.extend(["--prefix", sys.prefix])
111 self.shell.system(' '.join([conda, command] + extra_args + args))
112 print("\nNote: you may need to restart the kernel to use updated packages.")