euporie 2.8.6__py3-none-any.whl → 2.8.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- euporie/console/app.py +2 -0
- euporie/console/tabs/console.py +27 -17
- euporie/core/__init__.py +2 -2
- euporie/core/app/_commands.py +4 -21
- euporie/core/app/app.py +13 -7
- euporie/core/bars/command.py +9 -6
- euporie/core/bars/search.py +43 -2
- euporie/core/border.py +7 -2
- euporie/core/comm/base.py +2 -2
- euporie/core/comm/ipywidgets.py +3 -3
- euporie/core/commands.py +44 -8
- euporie/core/completion.py +14 -6
- euporie/core/convert/datum.py +7 -7
- euporie/core/data_structures.py +20 -1
- euporie/core/filters.py +8 -0
- euporie/core/ft/html.py +47 -40
- euporie/core/graphics.py +11 -3
- euporie/core/history.py +15 -5
- euporie/core/inspection.py +16 -9
- euporie/core/kernel/__init__.py +53 -1
- euporie/core/kernel/base.py +571 -0
- euporie/core/kernel/{client.py → jupyter.py} +173 -430
- euporie/core/kernel/{manager.py → jupyter_manager.py} +4 -3
- euporie/core/kernel/local.py +694 -0
- euporie/core/key_binding/bindings/basic.py +6 -3
- euporie/core/keys.py +26 -25
- euporie/core/layout/cache.py +31 -7
- euporie/core/layout/containers.py +88 -13
- euporie/core/layout/scroll.py +45 -148
- euporie/core/log.py +1 -1
- euporie/core/style.py +2 -1
- euporie/core/suggest.py +155 -74
- euporie/core/tabs/__init__.py +10 -0
- euporie/core/tabs/_commands.py +76 -0
- euporie/core/tabs/_settings.py +16 -0
- euporie/core/tabs/base.py +22 -8
- euporie/core/tabs/kernel.py +81 -35
- euporie/core/tabs/notebook.py +14 -22
- euporie/core/utils.py +1 -1
- euporie/core/validation.py +8 -8
- euporie/core/widgets/_settings.py +19 -2
- euporie/core/widgets/cell.py +31 -31
- euporie/core/widgets/cell_outputs.py +10 -1
- euporie/core/widgets/dialog.py +30 -75
- euporie/core/widgets/forms.py +71 -59
- euporie/core/widgets/inputs.py +7 -4
- euporie/core/widgets/layout.py +281 -93
- euporie/core/widgets/menu.py +55 -15
- euporie/core/widgets/palette.py +3 -1
- euporie/core/widgets/tree.py +86 -76
- euporie/notebook/app.py +35 -16
- euporie/notebook/tabs/edit.py +4 -4
- euporie/notebook/tabs/json.py +6 -2
- euporie/notebook/tabs/notebook.py +26 -8
- euporie/preview/tabs/notebook.py +17 -13
- euporie/web/tabs/web.py +22 -3
- euporie/web/widgets/webview.py +3 -0
- {euporie-2.8.6.dist-info → euporie-2.8.7.dist-info}/METADATA +1 -1
- {euporie-2.8.6.dist-info → euporie-2.8.7.dist-info}/RECORD +64 -61
- {euporie-2.8.6.dist-info → euporie-2.8.7.dist-info}/entry_points.txt +1 -1
- {euporie-2.8.6.dist-info → euporie-2.8.7.dist-info}/licenses/LICENSE +1 -1
- {euporie-2.8.6.data → euporie-2.8.7.data}/data/share/applications/euporie-console.desktop +0 -0
- {euporie-2.8.6.data → euporie-2.8.7.data}/data/share/applications/euporie-notebook.desktop +0 -0
- {euporie-2.8.6.dist-info → euporie-2.8.7.dist-info}/WHEEL +0 -0
@@ -0,0 +1,571 @@
|
|
1
|
+
"""Base class for euporie kernels."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
import asyncio
|
6
|
+
import concurrent
|
7
|
+
import logging
|
8
|
+
import threading
|
9
|
+
from abc import ABC, abstractmethod
|
10
|
+
from typing import TYPE_CHECKING, NamedTuple, TypedDict, overload
|
11
|
+
|
12
|
+
if TYPE_CHECKING:
|
13
|
+
from collections.abc import Callable, Coroutine
|
14
|
+
from typing import Any, Literal, Protocol, TypeVar, Unpack
|
15
|
+
|
16
|
+
from euporie.core.tabs.kernel import KernelTab
|
17
|
+
|
18
|
+
class KernelFactory(Protocol):
|
19
|
+
"""Type for kernel factory functions."""
|
20
|
+
|
21
|
+
def __call__(
|
22
|
+
self,
|
23
|
+
kernel_tab: KernelTab,
|
24
|
+
default_callbacks: MsgCallbacks | None = None,
|
25
|
+
allow_stdin: bool = False,
|
26
|
+
**kwargs: Any,
|
27
|
+
) -> BaseKernel:
|
28
|
+
"""Signature for creating a new Kernel instance."""
|
29
|
+
|
30
|
+
T = TypeVar("T")
|
31
|
+
|
32
|
+
log = logging.getLogger(__name__)
|
33
|
+
|
34
|
+
_THREAD: list[threading.Thread | None] = [None]
|
35
|
+
_LOOP: list[asyncio.AbstractEventLoop | None] = [None]
|
36
|
+
|
37
|
+
|
38
|
+
class KernelInfo(NamedTuple):
|
39
|
+
"""Named tuple representing a launchable kernel."""
|
40
|
+
|
41
|
+
name: str
|
42
|
+
display_name: str
|
43
|
+
type: type[BaseKernel]
|
44
|
+
kind: Literal["new", "existing"]
|
45
|
+
factory: KernelFactory
|
46
|
+
|
47
|
+
|
48
|
+
class MsgCallbacks(TypedDict, total=False):
|
49
|
+
"""Typed dictionary for named message callbacks."""
|
50
|
+
|
51
|
+
get_input: Callable[[str, bool], None] | None
|
52
|
+
set_execution_count: Callable[[int], None] | None
|
53
|
+
add_output: Callable[[dict[str, Any], bool], None] | None
|
54
|
+
add_input: Callable[[dict[str, Any], bool], None] | None
|
55
|
+
clear_output: Callable[[bool], None] | None
|
56
|
+
done: Callable[[dict[str, Any]], None] | None
|
57
|
+
set_metadata: Callable[[tuple[str, ...], Any], None] | None
|
58
|
+
set_status: Callable[[str], None] | None
|
59
|
+
set_kernel_info: Callable[[dict[str, Any]], None] | None
|
60
|
+
completeness_status: Callable[[dict[str, Any]], None] | None
|
61
|
+
dead: Callable[[], None] | None
|
62
|
+
# Payloads
|
63
|
+
page: Callable[[list[dict], int], None] | None
|
64
|
+
set_next_input: Callable[[str, bool], None] | None
|
65
|
+
edit_magic: Callable[[str, int], None] | None
|
66
|
+
ask_exit: Callable[[bool], None] | None
|
67
|
+
|
68
|
+
|
69
|
+
def get_loop() -> asyncio.AbstractEventLoop:
|
70
|
+
"""Create or return the conversion IO loop.
|
71
|
+
|
72
|
+
The loop will be running on a separate thread.
|
73
|
+
"""
|
74
|
+
if _LOOP[0] is None:
|
75
|
+
loop = asyncio.new_event_loop()
|
76
|
+
_LOOP[0] = loop
|
77
|
+
thread = threading.Thread(
|
78
|
+
target=loop.run_forever, name="EuporieKernelLoop", daemon=True
|
79
|
+
)
|
80
|
+
thread.start()
|
81
|
+
_THREAD[0] = thread
|
82
|
+
assert _LOOP[0] is not None
|
83
|
+
# Check we are not already in the conversion event loop
|
84
|
+
try:
|
85
|
+
running_loop = asyncio.get_running_loop()
|
86
|
+
except RuntimeError:
|
87
|
+
running_loop = None
|
88
|
+
if _LOOP[0] is running_loop:
|
89
|
+
raise NotImplementedError("Cannot nest event loop access")
|
90
|
+
return _LOOP[0]
|
91
|
+
|
92
|
+
|
93
|
+
class BaseKernel(ABC):
|
94
|
+
"""Abstract base class for euporie kernels."""
|
95
|
+
|
96
|
+
@classmethod
|
97
|
+
def variants(cls) -> list[KernelInfo]:
|
98
|
+
"""Return a list of parameterized variants of this kernel."""
|
99
|
+
return []
|
100
|
+
|
101
|
+
def __init__(
|
102
|
+
self,
|
103
|
+
kernel_tab: KernelTab,
|
104
|
+
default_callbacks: MsgCallbacks | None = None,
|
105
|
+
allow_stdin: bool = False,
|
106
|
+
**kwargs: Any,
|
107
|
+
) -> None:
|
108
|
+
"""Initialize the kernel.
|
109
|
+
|
110
|
+
Args:
|
111
|
+
kernel_tab: The notebook this kernel belongs to
|
112
|
+
allow_stdin: Whether the kernel is allowed to request input
|
113
|
+
default_callbacks: The default callbacks to use on receipt of a message
|
114
|
+
**kwargs: Additional keyword arguments passed to parent classes
|
115
|
+
"""
|
116
|
+
self.loop = get_loop()
|
117
|
+
self.kernel_tab = kernel_tab
|
118
|
+
self.allow_stdin = allow_stdin
|
119
|
+
self._status = "stopped"
|
120
|
+
self.error: Exception | None = None
|
121
|
+
self.dead = False
|
122
|
+
self.status_change_event = asyncio.Event()
|
123
|
+
self.coros: dict[str, concurrent.futures.Future] = {}
|
124
|
+
self.msg_id_callbacks: dict[str, MsgCallbacks] = {}
|
125
|
+
self.threaded = False
|
126
|
+
|
127
|
+
self.default_callbacks = MsgCallbacks(
|
128
|
+
{
|
129
|
+
"get_input": None,
|
130
|
+
"set_execution_count": None,
|
131
|
+
"add_output": None,
|
132
|
+
"clear_output": None,
|
133
|
+
"done": None,
|
134
|
+
"set_metadata": None,
|
135
|
+
"set_status": None,
|
136
|
+
}
|
137
|
+
)
|
138
|
+
if default_callbacks is not None:
|
139
|
+
self.default_callbacks.update(default_callbacks)
|
140
|
+
|
141
|
+
@property
|
142
|
+
@abstractmethod
|
143
|
+
def spec(self) -> dict[str, str]:
|
144
|
+
"""The kernelspec metadata for the current kernel instance."""
|
145
|
+
|
146
|
+
@overload
|
147
|
+
def _aodo(
|
148
|
+
self,
|
149
|
+
coro: Coroutine[Any, Any, T],
|
150
|
+
wait: Literal[True] = True,
|
151
|
+
callback: Callable | None = None,
|
152
|
+
timeout: int | float | None = None,
|
153
|
+
single: bool = False,
|
154
|
+
) -> T | None: ...
|
155
|
+
@overload
|
156
|
+
def _aodo(
|
157
|
+
self,
|
158
|
+
coro: Coroutine[Any, Any, T],
|
159
|
+
wait: Literal[False] = False,
|
160
|
+
callback: Callable | None = None,
|
161
|
+
timeout: int | float | None = None,
|
162
|
+
single: bool = False,
|
163
|
+
) -> concurrent.futures.Future: ...
|
164
|
+
@overload
|
165
|
+
def _aodo(
|
166
|
+
self,
|
167
|
+
coro: Coroutine[Any, Any, T],
|
168
|
+
wait: bool = False,
|
169
|
+
callback: Callable | None = None,
|
170
|
+
timeout: int | float | None = None,
|
171
|
+
single: bool = False,
|
172
|
+
) -> T | None | concurrent.futures.Future: ...
|
173
|
+
def _aodo(self, coro, wait=False, callback=None, timeout=None, single=False):
|
174
|
+
"""Schedule a coroutine in the kernel's event loop.
|
175
|
+
|
176
|
+
Optionally waits for the results (blocking the main thread). Optionally
|
177
|
+
schedules a callback to run when the coroutine has completed or timed out.
|
178
|
+
|
179
|
+
Args:
|
180
|
+
coro: The coroutine to run
|
181
|
+
wait: If :py:const:`True`, block until the kernel has started
|
182
|
+
callback: A function to run when the coroutine completes. The result from
|
183
|
+
the coroutine will be passed as an argument
|
184
|
+
timeout: The number of seconds to allow the coroutine to run if waiting
|
185
|
+
single: If :py:const:`True`, any futures for previous instances of the
|
186
|
+
coroutine will be cancelled
|
187
|
+
|
188
|
+
Returns:
|
189
|
+
The result of the coroutine
|
190
|
+
|
191
|
+
"""
|
192
|
+
future = asyncio.run_coroutine_threadsafe(coro, self.loop)
|
193
|
+
|
194
|
+
# Cancel previous future instances if required
|
195
|
+
if single and self.coros.get(coro.__name__):
|
196
|
+
self.coros[coro.__name__].cancel()
|
197
|
+
self.coros[coro.__name__] = future
|
198
|
+
|
199
|
+
if wait:
|
200
|
+
result = None
|
201
|
+
try:
|
202
|
+
result = future.result(timeout)
|
203
|
+
except concurrent.futures.TimeoutError:
|
204
|
+
log.error("Operation '%s' timed out", coro)
|
205
|
+
future.cancel()
|
206
|
+
return result
|
207
|
+
finally:
|
208
|
+
if callable(callback):
|
209
|
+
callback(result)
|
210
|
+
return result
|
211
|
+
else:
|
212
|
+
if callable(callback):
|
213
|
+
future.add_done_callback(lambda f: callback(f.result()))
|
214
|
+
return future
|
215
|
+
|
216
|
+
@property
|
217
|
+
def status(self) -> str:
|
218
|
+
"""Retrieve the current kernel status.
|
219
|
+
|
220
|
+
Returns:
|
221
|
+
The kernel status
|
222
|
+
|
223
|
+
"""
|
224
|
+
return self._status
|
225
|
+
|
226
|
+
@status.setter
|
227
|
+
def status(self, value: str) -> None:
|
228
|
+
"""Set the kernel status."""
|
229
|
+
self.status_change_event.set()
|
230
|
+
self._status = value
|
231
|
+
self.status_change_event.clear()
|
232
|
+
|
233
|
+
def wait_for_status(self, status: str = "idle") -> None:
|
234
|
+
"""Block until the kernel reaches a given status value."""
|
235
|
+
if self.status != status:
|
236
|
+
|
237
|
+
async def _wait() -> None:
|
238
|
+
while self.status != status:
|
239
|
+
await asyncio.wait_for(
|
240
|
+
self.status_change_event.wait(), timeout=None
|
241
|
+
)
|
242
|
+
|
243
|
+
self._aodo(_wait(), wait=True)
|
244
|
+
|
245
|
+
def start(
|
246
|
+
self, cb: Callable | None = None, wait: bool = False, timeout: int = 10
|
247
|
+
) -> None:
|
248
|
+
"""Start the kernel.
|
249
|
+
|
250
|
+
Args:
|
251
|
+
cb: An optional callback to run after the kernel has started
|
252
|
+
wait: If :py:const:`True`, block until the kernel has started
|
253
|
+
timeout: How long to wait until failure is assumed
|
254
|
+
|
255
|
+
"""
|
256
|
+
self._aodo(
|
257
|
+
self.start_async(),
|
258
|
+
timeout=timeout,
|
259
|
+
wait=wait,
|
260
|
+
callback=cb,
|
261
|
+
)
|
262
|
+
|
263
|
+
@abstractmethod
|
264
|
+
async def start_async(self) -> None:
|
265
|
+
"""Start the kernel."""
|
266
|
+
|
267
|
+
def stop(self, cb: Callable | None = None, wait: bool = False) -> None:
|
268
|
+
"""Stop the kernel."""
|
269
|
+
log.debug("Stopping kernel %s (wait=%s)", self.id, wait)
|
270
|
+
if not wait:
|
271
|
+
self.interrupt()
|
272
|
+
self._aodo(self.stop_async(), callback=cb, wait=wait)
|
273
|
+
|
274
|
+
async def stop_async(self, cb: Callable | None = None) -> None:
|
275
|
+
"""Stop the kernel asynchronously."""
|
276
|
+
self.stop(cb)
|
277
|
+
|
278
|
+
def run(
|
279
|
+
self,
|
280
|
+
source: str,
|
281
|
+
wait: bool = False,
|
282
|
+
callback: Callable[..., None] | None = None,
|
283
|
+
**callbacks: Callable[..., Any],
|
284
|
+
) -> None:
|
285
|
+
"""Execute code in the kernel."""
|
286
|
+
self._aodo(
|
287
|
+
self.run_async(source, **callbacks),
|
288
|
+
wait=wait,
|
289
|
+
callback=callback,
|
290
|
+
)
|
291
|
+
|
292
|
+
@abstractmethod
|
293
|
+
async def run_async(
|
294
|
+
self, source: str, **local_callbacks: Unpack[MsgCallbacks]
|
295
|
+
) -> None:
|
296
|
+
"""Execute code in the kernel asynchronously."""
|
297
|
+
|
298
|
+
def complete(self, source: str, cursor_pos: int) -> list[dict]:
|
299
|
+
"""Request code completions from the kernel.
|
300
|
+
|
301
|
+
Args:
|
302
|
+
source: The code string to retrieve completions for
|
303
|
+
cursor_pos: The position of the cursor in the code string
|
304
|
+
|
305
|
+
Returns:
|
306
|
+
A list of dictionaries defining completion entries. The dictionaries
|
307
|
+
contain ``text`` (the completion text), ``start_position`` (the stating
|
308
|
+
position of the completion text), and optionally ``display_meta``
|
309
|
+
(a string containing additional data about the completion type)
|
310
|
+
|
311
|
+
"""
|
312
|
+
return (
|
313
|
+
self._aodo(
|
314
|
+
self.complete_async(source, cursor_pos),
|
315
|
+
wait=True,
|
316
|
+
single=True,
|
317
|
+
)
|
318
|
+
or []
|
319
|
+
)
|
320
|
+
|
321
|
+
@abstractmethod
|
322
|
+
async def complete_async(self, source: str, cursor_pos: int) -> list[dict]:
|
323
|
+
"""Get code completions asynchronously."""
|
324
|
+
|
325
|
+
def history(
|
326
|
+
self, pattern: str = "", n: int = 1, hist_access_type: str = "search"
|
327
|
+
) -> list[tuple[int, int, str]] | None:
|
328
|
+
"""Retrieve history from the kernel.
|
329
|
+
|
330
|
+
Args:
|
331
|
+
pattern: The pattern to search for
|
332
|
+
n: the number of history items to return
|
333
|
+
hist_access_type: How to access the history ('range', 'tail' or 'search')
|
334
|
+
|
335
|
+
Returns:
|
336
|
+
A list of history items, consisting of tuples (session, line_number, input)
|
337
|
+
|
338
|
+
"""
|
339
|
+
return self._aodo(
|
340
|
+
self.history_async(pattern, n, hist_access_type),
|
341
|
+
wait=True,
|
342
|
+
single=True,
|
343
|
+
)
|
344
|
+
|
345
|
+
async def history_async(
|
346
|
+
self,
|
347
|
+
pattern: str = "",
|
348
|
+
n: int = 1,
|
349
|
+
hist_access_type: str = "search",
|
350
|
+
timeout: int = 1,
|
351
|
+
) -> list[tuple[int, int, str]] | None:
|
352
|
+
"""Retrieve history from the kernel asynchronously."""
|
353
|
+
return []
|
354
|
+
|
355
|
+
def inspect(
|
356
|
+
self,
|
357
|
+
source: str,
|
358
|
+
cursor_pos: int,
|
359
|
+
detail_level: int = 0,
|
360
|
+
timeout: int = 2,
|
361
|
+
callback: Callable[[dict[str, Any]], None] | None = None,
|
362
|
+
) -> dict[str, Any]:
|
363
|
+
"""Request code inspection from the kernel.
|
364
|
+
|
365
|
+
Args:
|
366
|
+
source: The code string to retrieve completions for
|
367
|
+
cursor_pos: The position of the cursor in the code string
|
368
|
+
detail_level: Level of detail for the inspection (0-2)
|
369
|
+
timeout: Number of seconds to wait for inspection results
|
370
|
+
callback: A function to run when the inspection result arrives. The result
|
371
|
+
is passed as an argument.
|
372
|
+
|
373
|
+
Returns:
|
374
|
+
A string containing useful information about the code at the current cursor
|
375
|
+
position
|
376
|
+
|
377
|
+
"""
|
378
|
+
return (
|
379
|
+
self._aodo(
|
380
|
+
self.inspect_async(source, cursor_pos, detail_level),
|
381
|
+
wait=True,
|
382
|
+
callback=callback,
|
383
|
+
single=True,
|
384
|
+
)
|
385
|
+
or {}
|
386
|
+
)
|
387
|
+
|
388
|
+
@abstractmethod
|
389
|
+
async def inspect_async(
|
390
|
+
self,
|
391
|
+
source: str,
|
392
|
+
cursor_pos: int,
|
393
|
+
detail_level: int = 0,
|
394
|
+
timeout: int = 2,
|
395
|
+
) -> dict[str, Any]:
|
396
|
+
"""Get code inspection/documentation asynchronously."""
|
397
|
+
|
398
|
+
def is_complete(
|
399
|
+
self,
|
400
|
+
source: str,
|
401
|
+
timeout: int | float = 0.1,
|
402
|
+
callback: Callable[[dict[str, Any]], None] | None = None,
|
403
|
+
) -> dict[str, Any]:
|
404
|
+
"""Request code completeness status from the kernel.
|
405
|
+
|
406
|
+
Args:
|
407
|
+
source: The code string to check the completeness status of
|
408
|
+
timeout: How long to wait for a kernel response
|
409
|
+
wait: Whether to wait for the response
|
410
|
+
callback: A function to run when the inspection result arrives. The result
|
411
|
+
is passed as an argument.
|
412
|
+
|
413
|
+
Returns:
|
414
|
+
A string describing the completeness status
|
415
|
+
|
416
|
+
"""
|
417
|
+
return (
|
418
|
+
self._aodo(
|
419
|
+
self.is_complete_async(source, timeout), wait=True, callback=callback
|
420
|
+
)
|
421
|
+
or {}
|
422
|
+
)
|
423
|
+
|
424
|
+
@abstractmethod
|
425
|
+
async def is_complete_async(
|
426
|
+
self,
|
427
|
+
source: str,
|
428
|
+
timeout: int | float = 0.1,
|
429
|
+
) -> dict[str, Any]:
|
430
|
+
"""Check if code is complete asynchronously."""
|
431
|
+
|
432
|
+
@abstractmethod
|
433
|
+
def input(self, text: str) -> None:
|
434
|
+
"""Send input to the kernel."""
|
435
|
+
|
436
|
+
@abstractmethod
|
437
|
+
def interrupt(self) -> None:
|
438
|
+
"""Interrupt the kernel."""
|
439
|
+
|
440
|
+
def restart(self, wait: bool = False, cb: Callable | None = None) -> None:
|
441
|
+
"""Restart the current kernel."""
|
442
|
+
self._aodo(
|
443
|
+
self.restart_async(),
|
444
|
+
wait=wait,
|
445
|
+
callback=cb,
|
446
|
+
)
|
447
|
+
|
448
|
+
@abstractmethod
|
449
|
+
async def restart_async(self) -> None:
|
450
|
+
"""Restart the kernel asynchronously."""
|
451
|
+
|
452
|
+
def shutdown(self, wait: bool = False, cb: Callable | None = None) -> None:
|
453
|
+
"""Shutdown the kernel.
|
454
|
+
|
455
|
+
This is intended to be run when the notebook is closed: the
|
456
|
+
:py:class:`~euporie.core.kernel.base.BaseKernel` cannot be restarted after this.
|
457
|
+
|
458
|
+
Args:
|
459
|
+
wait: Whether to block until shutdown completes
|
460
|
+
cb: Callback run after shutdown completes
|
461
|
+
|
462
|
+
"""
|
463
|
+
self._aodo(self.shutdown_async(), wait=wait, callback=cb)
|
464
|
+
|
465
|
+
@abstractmethod
|
466
|
+
async def shutdown_async(self) -> None:
|
467
|
+
"""Shutdown the kernel asynchronously."""
|
468
|
+
|
469
|
+
@property
|
470
|
+
@abstractmethod
|
471
|
+
def missing(self) -> bool:
|
472
|
+
"""Return whether the kernel is missing."""
|
473
|
+
|
474
|
+
@property
|
475
|
+
@abstractmethod
|
476
|
+
def id(self) -> str | None:
|
477
|
+
"""Return the kernel ID."""
|
478
|
+
|
479
|
+
@abstractmethod
|
480
|
+
def info(
|
481
|
+
self,
|
482
|
+
set_kernel_info: Callable[[dict[str, Any]], None] | None = None,
|
483
|
+
set_status: Callable[[str], None] | None = None,
|
484
|
+
) -> None:
|
485
|
+
"""Request information about the kernel."""
|
486
|
+
|
487
|
+
def kc_comm(self, comm_id: str, data: dict[str, Any]) -> str:
|
488
|
+
"""By default kernels do not implement COMM communication."""
|
489
|
+
log.warning("The %s kernel does not implement COMMs", self.__class__.__name__)
|
490
|
+
return "" # TODO - raise NotImplementedError
|
491
|
+
|
492
|
+
def comm_info(self, target_name: str | None = None) -> None:
|
493
|
+
"""Request information about the current comms.
|
494
|
+
|
495
|
+
Does nothing by default.
|
496
|
+
"""
|
497
|
+
|
498
|
+
|
499
|
+
class NoKernel(BaseKernel):
|
500
|
+
"""A `None` kernel."""
|
501
|
+
|
502
|
+
@property
|
503
|
+
def spec(self) -> dict[str, str]:
|
504
|
+
"""The kernelspec metadata for the current kernel instance."""
|
505
|
+
raise NotImplementedError()
|
506
|
+
|
507
|
+
async def start_async(self) -> None:
|
508
|
+
"""Start the kernel."""
|
509
|
+
raise NotImplementedError()
|
510
|
+
|
511
|
+
async def run_async(
|
512
|
+
self, source: str, **local_callbacks: Unpack[MsgCallbacks]
|
513
|
+
) -> None:
|
514
|
+
"""Execute code in the kernel asynchronously."""
|
515
|
+
raise NotImplementedError()
|
516
|
+
|
517
|
+
async def is_complete_async(
|
518
|
+
self,
|
519
|
+
source: str,
|
520
|
+
timeout: int | float = 0.1,
|
521
|
+
) -> dict[str, Any]:
|
522
|
+
"""Check if code is complete asynchronously."""
|
523
|
+
raise NotImplementedError()
|
524
|
+
|
525
|
+
async def complete_async(self, source: str, cursor_pos: int) -> list[dict]:
|
526
|
+
"""Get code completions asynchronously."""
|
527
|
+
raise NotImplementedError()
|
528
|
+
|
529
|
+
async def inspect_async(
|
530
|
+
self,
|
531
|
+
source: str,
|
532
|
+
cursor_pos: int,
|
533
|
+
detail_level: int = 0,
|
534
|
+
timeout: int = 2,
|
535
|
+
) -> dict[str, Any]:
|
536
|
+
"""Get code inspection/documentation asynchronously."""
|
537
|
+
raise NotImplementedError()
|
538
|
+
|
539
|
+
def input(self, text: str) -> None:
|
540
|
+
"""Send input to the kernel."""
|
541
|
+
# Do nothing
|
542
|
+
|
543
|
+
def interrupt(self) -> None:
|
544
|
+
"""Interrupt the kernel."""
|
545
|
+
# Do nothing
|
546
|
+
|
547
|
+
async def restart_async(self) -> None:
|
548
|
+
"""Restart the kernel asynchronously."""
|
549
|
+
# Do nothing
|
550
|
+
|
551
|
+
async def shutdown_async(self) -> None:
|
552
|
+
"""Shutdown the kernel asynchronously."""
|
553
|
+
# Do nothing
|
554
|
+
|
555
|
+
@property
|
556
|
+
def missing(self) -> bool:
|
557
|
+
"""Return whether the kernel is missing."""
|
558
|
+
raise NotImplementedError()
|
559
|
+
|
560
|
+
@property
|
561
|
+
def id(self) -> str | None:
|
562
|
+
"""Return the kernel ID."""
|
563
|
+
raise NotImplementedError()
|
564
|
+
|
565
|
+
def info(
|
566
|
+
self,
|
567
|
+
set_kernel_info: Callable[[dict[str, Any]], None] | None = None,
|
568
|
+
set_status: Callable[[str], None] | None = None,
|
569
|
+
) -> None:
|
570
|
+
"""Request information about the kernel."""
|
571
|
+
raise NotImplementedError()
|