##// END OF EJS Templates
Add env to the kernelspec __init__...
Jason Grout -
Show More
@@ -1,202 +1,202 b''
1 1 import io
2 2 import json
3 3 import os
4 4 import shutil
5 5 import sys
6 6
7 7 pjoin = os.path.join
8 8
9 9 from IPython.utils.path import get_ipython_dir
10 10 from IPython.utils.py3compat import PY3
11 11 from IPython.utils.traitlets import HasTraits, List, Unicode, Dict
12 12
13 13 if os.name == 'nt':
14 14 programdata = os.environ.get('PROGRAMDATA', None)
15 15 if programdata:
16 16 SYSTEM_KERNEL_DIRS = [pjoin(programdata, 'ipython', 'kernels')]
17 17 else: # PROGRAMDATA is not defined by default on XP.
18 18 SYSTEM_KERNEL_DIRS = []
19 19 else:
20 20 SYSTEM_KERNEL_DIRS = ["/usr/share/ipython/kernels",
21 21 "/usr/local/share/ipython/kernels",
22 22 ]
23 23
24 24 NATIVE_KERNEL_NAME = 'python3' if PY3 else 'python2'
25 25
26 26 def _pythonfirst(s):
27 27 "Sort key function that will put strings starting with 'python' first."
28 28 if s == NATIVE_KERNEL_NAME:
29 29 return ' ' + s # Two spaces to sort this first of all
30 30 elif s.startswith('python'):
31 31 # Space is not valid in kernel names, so this should sort first
32 32 return ' ' + s
33 33 return s
34 34
35 35 class KernelSpec(HasTraits):
36 36 argv = List()
37 37 display_name = Unicode()
38 38 language = Unicode()
39 39 codemirror_mode = None
40 40 env = Dict()
41 41
42 42 resource_dir = Unicode()
43 43
44 44 def __init__(self, resource_dir, argv, display_name, language,
45 codemirror_mode=None):
45 codemirror_mode=None, env=None):
46 46 super(KernelSpec, self).__init__(resource_dir=resource_dir, argv=argv,
47 47 display_name=display_name, language=language,
48 codemirror_mode=codemirror_mode)
48 codemirror_mode=codemirror_mode, env=env)
49 49 if not self.codemirror_mode:
50 50 self.codemirror_mode = self.language
51 51
52 52 @classmethod
53 53 def from_resource_dir(cls, resource_dir):
54 54 """Create a KernelSpec object by reading kernel.json
55 55
56 56 Pass the path to the *directory* containing kernel.json.
57 57 """
58 58 kernel_file = pjoin(resource_dir, 'kernel.json')
59 59 with io.open(kernel_file, 'r', encoding='utf-8') as f:
60 60 kernel_dict = json.load(f)
61 61 return cls(resource_dir=resource_dir, **kernel_dict)
62 62
63 63 def to_dict(self):
64 64 return dict(argv=self.argv,
65 65 env=self.env,
66 66 display_name=self.display_name,
67 67 language=self.language,
68 68 codemirror_mode=self.codemirror_mode,
69 69 )
70 70
71 71 def to_json(self):
72 72 return json.dumps(self.to_dict())
73 73
74 74 def _is_kernel_dir(path):
75 75 """Is ``path`` a kernel directory?"""
76 76 return os.path.isdir(path) and os.path.isfile(pjoin(path, 'kernel.json'))
77 77
78 78 def _list_kernels_in(dir):
79 79 """Return a mapping of kernel names to resource directories from dir.
80 80
81 81 If dir is None or does not exist, returns an empty dict.
82 82 """
83 83 if dir is None or not os.path.isdir(dir):
84 84 return {}
85 85 return {f.lower(): pjoin(dir, f) for f in os.listdir(dir)
86 86 if _is_kernel_dir(pjoin(dir, f))}
87 87
88 88 class NoSuchKernel(KeyError):
89 89 def __init__(self, name):
90 90 self.name = name
91 91
92 92 class KernelSpecManager(HasTraits):
93 93 ipython_dir = Unicode()
94 94 def _ipython_dir_default(self):
95 95 return get_ipython_dir()
96 96
97 97 user_kernel_dir = Unicode()
98 98 def _user_kernel_dir_default(self):
99 99 return pjoin(self.ipython_dir, 'kernels')
100 100
101 101 kernel_dirs = List(
102 102 help="List of kernel directories to search. Later ones take priority over earlier."
103 103 )
104 104 def _kernel_dirs_default(self):
105 105 return SYSTEM_KERNEL_DIRS + [
106 106 self.user_kernel_dir,
107 107 ]
108 108
109 109 def _make_native_kernel_dir(self):
110 110 """Makes a kernel directory for the native kernel.
111 111
112 112 The native kernel is the kernel using the same Python runtime as this
113 113 process. This will put its informatino in the user kernels directory.
114 114 """
115 115 path = pjoin(self.user_kernel_dir, NATIVE_KERNEL_NAME)
116 116 os.makedirs(path, mode=0o755)
117 117 with open(pjoin(path, 'kernel.json'), 'w') as f:
118 118 json.dump({'argv':[NATIVE_KERNEL_NAME, '-c',
119 119 'from IPython.kernel.zmq.kernelapp import main; main()',
120 120 '-f', '{connection_file}'],
121 121 'display_name': 'IPython (Python %d)' % (3 if PY3 else 2),
122 122 'language': 'python',
123 123 'codemirror_mode': {'name': 'ipython',
124 124 'version': sys.version_info[0]},
125 125 },
126 126 f, indent=1)
127 127 # TODO: Copy icons into directory
128 128 return path
129 129
130 130 def find_kernel_specs(self):
131 131 """Returns a dict mapping kernel names to resource directories."""
132 132 d = {}
133 133 for kernel_dir in self.kernel_dirs:
134 134 d.update(_list_kernels_in(kernel_dir))
135 135
136 136 if NATIVE_KERNEL_NAME not in d:
137 137 d[NATIVE_KERNEL_NAME] = self._make_native_kernel_dir()
138 138 return d
139 139 # TODO: Caching?
140 140
141 141 def get_kernel_spec(self, kernel_name):
142 142 """Returns a :class:`KernelSpec` instance for the given kernel_name.
143 143
144 144 Raises :exc:`NoSuchKernel` if the given kernel name is not found.
145 145 """
146 146 if kernel_name == 'python':
147 147 kernel_name = NATIVE_KERNEL_NAME
148 148 d = self.find_kernel_specs()
149 149 try:
150 150 resource_dir = d[kernel_name.lower()]
151 151 except KeyError:
152 152 raise NoSuchKernel(kernel_name)
153 153 return KernelSpec.from_resource_dir(resource_dir)
154 154
155 155 def install_kernel_spec(self, source_dir, kernel_name=None, system=False,
156 156 replace=False):
157 157 """Install a kernel spec by copying its directory.
158 158
159 159 If ``kernel_name`` is not given, the basename of ``source_dir`` will
160 160 be used.
161 161
162 162 If ``system`` is True, it will attempt to install into the systemwide
163 163 kernel registry. If the process does not have appropriate permissions,
164 164 an :exc:`OSError` will be raised.
165 165
166 166 If ``replace`` is True, this will replace an existing kernel of the same
167 167 name. Otherwise, if the destination already exists, an :exc:`OSError`
168 168 will be raised.
169 169 """
170 170 if not kernel_name:
171 171 kernel_name = os.path.basename(source_dir)
172 172 kernel_name = kernel_name.lower()
173 173
174 174 if system:
175 175 if SYSTEM_KERNEL_DIRS:
176 176 destination = os.path.join(SYSTEM_KERNEL_DIRS[-1], kernel_name)
177 177 else:
178 178 raise EnvironmentError("No system kernel directory is available")
179 179 else:
180 180 destination = os.path.join(self.user_kernel_dir, kernel_name)
181 181
182 182 if replace and os.path.isdir(destination):
183 183 shutil.rmtree(destination)
184 184
185 185 shutil.copytree(source_dir, destination)
186 186
187 187 def find_kernel_specs():
188 188 """Returns a dict mapping kernel names to resource directories."""
189 189 return KernelSpecManager().find_kernel_specs()
190 190
191 191 def get_kernel_spec(kernel_name):
192 192 """Returns a :class:`KernelSpec` instance for the given kernel_name.
193 193
194 194 Raises KeyError if the given kernel name is not found.
195 195 """
196 196 return KernelSpecManager().get_kernel_spec(kernel_name)
197 197
198 198 def install_kernel_spec(source_dir, kernel_name=None, system=False, replace=False):
199 199 return KernelSpecManager().install_kernel_spec(source_dir, kernel_name,
200 200 system, replace)
201 201
202 202 install_kernel_spec.__doc__ = KernelSpecManager.install_kernel_spec.__doc__
General Comments 0
You need to be logged in to leave comments. Login now