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

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#----------------------------------------------------------------------------- 

10 

11import re 

12import shlex 

13import sys 

14from pathlib import Path 

15 

16from IPython.core.magic import Magics, magics_class, line_magic 

17 

18 

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() 

23 

24 

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) 

32 

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"] 

43 

44 # Fallback: assume conda is available on the system path. 

45 return "conda" 

46 

47 

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'} 

56 

57 

58@magics_class 

59class PackagingMagics(Magics): 

60 """Magics related to packaging & installation""" 

61 

62 @line_magic 

63 def pip(self, line): 

64 """Run the pip package manager within the current kernel. 

65 

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) 

74 

75 self.shell.system(" ".join([python, "-m", "pip", line])) 

76 

77 print("Note: you may need to restart the kernel to use updated packages.") 

78 

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() 

91 args = shlex.split(line) 

92 command = args[0] if len(args) > 0 else "" 

93 args = args[1:] if len(args) > 1 else [""] 

94 

95 extra_args = [] 

96 

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") 

104 

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]) 

110 

111 self.shell.system(' '.join([conda, command] + extra_args + args)) 

112 print("\nNote: you may need to restart the kernel to use updated packages.")