##// END OF EJS Templates
Implement magic for mamba and micromamba
Samuel Gaist -
Show More
@@ -1,16 +1,15 b''
1 1 # See https://pre-commit.com for more information
2 2 # See https://pre-commit.com/hooks.html for more hooks
3 3 repos:
4 4 - repo: https://github.com/pre-commit/pre-commit-hooks
5 rev: v3.2.0
5 rev: v4.4.0
6 6 hooks:
7 7 - id: trailing-whitespace
8 8 - id: end-of-file-fixer
9 9 - id: check-yaml
10 10 - id: check-added-large-files
11 11
12 12 - repo: https://github.com/akaihola/darker
13 rev: 1.3.1
13 rev: 1.7.2
14 14 hooks:
15 15 - id: darker
16
@@ -1,112 +1,151 b''
1 1 """Implementation of packaging-related magic functions.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2018 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 import functools
11 12 import re
12 13 import shlex
13 14 import sys
14 15 from pathlib import Path
15 16
16 17 from IPython.core.magic import Magics, magics_class, line_magic
17 18
18 19
19 def _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()
20 def is_conda_environment(func):
21 @functools.wraps(func)
22 def wrapper(*args, **kwargs):
23 """Return True if the current Python executable is in a conda env"""
24 # TODO: does this need to change on windows?
25 if not Path(sys.prefix, "conda-meta", "history").exists():
26 raise ValueError(
27 "The python kernel does not appear to be a conda environment. "
28 "Please use ``%pip install`` instead."
29 )
30 return func(*args, **kwargs)
23 31
32 return wrapper
24 33
25 def _get_conda_executable():
26 """Find the path to the conda executable"""
34
35 def _get_conda_like_executable(command):
36 """Find the path to the given executable
37
38 Parameters
39 ----------
40
41 executable: string
42 Value should be: conda, mamba or micromamba
43 """
27 44 # Check if there is a conda executable in the same directory as the Python executable.
28 45 # 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)
46 executable = Path(sys.executable).parent / command
47 if executable.is_file():
48 return str(executable)
32 49
33 50 # Otherwise, attempt to extract the executable from conda history.
34 51 # This applies in any conda environment.
35 52 history = Path(sys.prefix, "conda-meta", "history").read_text(encoding="utf-8")
36 53 match = re.search(
37 r"^#\s*cmd:\s*(?P<command>.*conda)\s[create|install]",
54 rf"^#\s*cmd:\s*(?P<command>.*{executable})\s[create|install]",
38 55 history,
39 56 flags=re.MULTILINE,
40 57 )
41 58 if match:
42 59 return match.groupdict()["command"]
43 60
44 # Fallback: assume conda is available on the system path.
45 return "conda"
61 # Fallback: assume the executable is available on the system path.
62 return command
46 63
47 64
48 65 CONDA_COMMANDS_REQUIRING_PREFIX = {
49 66 'install', 'list', 'remove', 'uninstall', 'update', 'upgrade',
50 67 }
51 68 CONDA_COMMANDS_REQUIRING_YES = {
52 69 'install', 'remove', 'uninstall', 'update', 'upgrade',
53 70 }
54 71 CONDA_ENV_FLAGS = {'-p', '--prefix', '-n', '--name'}
55 72 CONDA_YES_FLAGS = {'-y', '--y'}
56 73
57 74
58 75 @magics_class
59 76 class PackagingMagics(Magics):
60 77 """Magics related to packaging & installation"""
61 78
62 79 @line_magic
63 80 def pip(self, line):
64 81 """Run the pip package manager within the current kernel.
65 82
66 83 Usage:
67 84 %pip install [pkgs]
68 85 """
69 86 python = sys.executable
70 87 if sys.platform == "win32":
71 88 python = '"' + python + '"'
72 89 else:
73 90 python = shlex.quote(python)
74 91
75 92 self.shell.system(" ".join([python, "-m", "pip", line]))
76 93
77 94 print("Note: you may need to restart the kernel to use updated packages.")
78 95
79 @line_magic
80 def conda(self, line):
81 """Run the conda package manager within the current kernel.
82
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.")
89
90 conda = _get_conda_executable()
96 def _run_command(self, cmd, line):
91 97 args = shlex.split(line)
92 98 command = args[0] if len(args) > 0 else ""
93 99 args = args[1:] if len(args) > 1 else [""]
94 100
95 101 extra_args = []
96 102
97 103 # When the subprocess does not allow us to respond "yes" during the installation,
98 104 # we need to insert --yes in the argument list for some commands
99 105 stdin_disabled = getattr(self.shell, 'kernel', None) is not None
100 106 needs_yes = command in CONDA_COMMANDS_REQUIRING_YES
101 107 has_yes = set(args).intersection(CONDA_YES_FLAGS)
102 108 if stdin_disabled and needs_yes and not has_yes:
103 109 extra_args.append("--yes")
104 110
105 111 # Add --prefix to point conda installation to the current environment
106 112 needs_prefix = command in CONDA_COMMANDS_REQUIRING_PREFIX
107 113 has_prefix = set(args).intersection(CONDA_ENV_FLAGS)
108 114 if needs_prefix and not has_prefix:
109 115 extra_args.extend(["--prefix", sys.prefix])
110 116
111 self.shell.system(' '.join([conda, command] + extra_args + args))
117 self.shell.system(" ".join([cmd, command] + extra_args + args))
112 118 print("\nNote: you may need to restart the kernel to use updated packages.")
119
120 @line_magic
121 @is_conda_environment
122 def conda(self, line):
123 """Run the conda package manager within the current kernel.
124
125 Usage:
126 %conda install [pkgs]
127 """
128 conda = _get_conda_like_executable("conda")
129 self._run_command(conda, line)
130
131 @line_magic
132 @is_conda_environment
133 def mamba(self, line):
134 """Run the mamba package manager within the current kernel.
135
136 Usage:
137 %mamba install [pkgs]
138 """
139 mamba = _get_conda_like_executable("mamba")
140 self._run_command(mamba, line)
141
142 @line_magic
143 @is_conda_environment
144 def micromamba(self, line):
145 """Run the conda package manager within the current kernel.
146
147 Usage:
148 %micromamba install [pkgs]
149 """
150 micromamba = _get_conda_like_executable("micromamba")
151 self._run_command(micromamba, line)
General Comments 0
You need to be logged in to leave comments. Login now