codebind 0.6.7__py3-none-any.whl → 0.6.8__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.
- codebind/execution.py +9 -4
- codebind/extension.py +37 -0
- codebind/terminal.py +152 -8
- {codebind-0.6.7.dist-info → codebind-0.6.8.dist-info}/METADATA +2 -2
- {codebind-0.6.7.dist-info → codebind-0.6.8.dist-info}/RECORD +14 -14
- {codebind-0.6.7.data → codebind-0.6.8.data}/data/share/jupyter/labextensions/codebind-jupyterlab/install.json +0 -0
- {codebind-0.6.7.data → codebind-0.6.8.data}/data/share/jupyter/labextensions/codebind-jupyterlab/package.json +0 -0
- {codebind-0.6.7.data → codebind-0.6.8.data}/data/share/jupyter/labextensions/codebind-jupyterlab/static/590.dae4561c5427a855.js +0 -0
- {codebind-0.6.7.data → codebind-0.6.8.data}/data/share/jupyter/labextensions/codebind-jupyterlab/static/remoteEntry.c10098fb6e87897c.js +0 -0
- {codebind-0.6.7.data → codebind-0.6.8.data}/data/share/jupyter/labextensions/codebind-jupyterlab/static/style.js +0 -0
- {codebind-0.6.7.data → codebind-0.6.8.data}/data/share/jupyter/labextensions/codebind-jupyterlab/static/third-party-licenses.json +0 -0
- {codebind-0.6.7.dist-info → codebind-0.6.8.dist-info}/WHEEL +0 -0
- {codebind-0.6.7.dist-info → codebind-0.6.8.dist-info}/entry_points.txt +0 -0
- {codebind-0.6.7.dist-info → codebind-0.6.8.dist-info}/licenses/LICENSE +0 -0
codebind/execution.py
CHANGED
|
@@ -16,7 +16,7 @@ from IPython.utils.capture import capture_output
|
|
|
16
16
|
from .display import display_cell
|
|
17
17
|
from .images import PreparedImage, prepare_mime_image
|
|
18
18
|
from .jupyter import JupyterLabBridge
|
|
19
|
-
from .terminal import record_tool_output, show_input
|
|
19
|
+
from .terminal import preview_tool_output, record_tool_output, show_input
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
_MAXIMUM_IMAGES_PER_REPORT = 32
|
|
@@ -219,9 +219,11 @@ class IPythonExecutor:
|
|
|
219
219
|
|
|
220
220
|
if self.bridge is None and isinstance(self.shell, TerminalInteractiveShell):
|
|
221
221
|
show_input(self.shell, cell)
|
|
222
|
-
with record_tool_output(self.shell):
|
|
222
|
+
with preview_tool_output() as preview, record_tool_output(self.shell):
|
|
223
223
|
result = self.shell.run_cell(cell, store_history=True)
|
|
224
|
-
|
|
224
|
+
report = self._native_report(result)
|
|
225
|
+
preview.show_notice(result.execution_count, report.error)
|
|
226
|
+
return report
|
|
225
227
|
|
|
226
228
|
bridge = self.bridge
|
|
227
229
|
cell_id = bridge.start_code_cell(cell) if bridge is not None else None
|
|
@@ -260,6 +262,7 @@ class IPythonExecutor:
|
|
|
260
262
|
transformed = self.shell.transform_cell(cell)
|
|
261
263
|
result = None
|
|
262
264
|
with (
|
|
265
|
+
preview_tool_output() as preview,
|
|
263
266
|
record_tool_output(self.shell),
|
|
264
267
|
self.shell._tee(channel="stdout"),
|
|
265
268
|
self.shell._tee(channel="stderr"),
|
|
@@ -273,7 +276,9 @@ class IPythonExecutor:
|
|
|
273
276
|
finally:
|
|
274
277
|
self.shell.events.trigger("post_execute")
|
|
275
278
|
self.shell.events.trigger("post_run_cell", result)
|
|
276
|
-
|
|
279
|
+
report = self._native_report(result)
|
|
280
|
+
preview.show_notice(result.execution_count, report.error)
|
|
281
|
+
return report
|
|
277
282
|
|
|
278
283
|
bridge = self.bridge
|
|
279
284
|
cell_id = bridge.start_code_cell(cell) if bridge is not None else None
|
codebind/extension.py
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
|
+
import sys
|
|
6
7
|
from typing import Any
|
|
7
8
|
|
|
8
9
|
from IPython.core.interactiveshell import InteractiveShell
|
|
10
|
+
from IPython.core.page import page
|
|
9
11
|
from IPython.terminal.interactiveshell import TerminalInteractiveShell
|
|
10
12
|
from langchain_core.language_models import BaseChatModel
|
|
11
13
|
|
|
@@ -20,6 +22,9 @@ _STATE_ATTRIBUTE = "_codebind_extension_state"
|
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
def _close_state(state: dict[str, Any]) -> None:
|
|
25
|
+
restore_output_magic = state.get("restore_output_magic")
|
|
26
|
+
if callable(restore_output_magic):
|
|
27
|
+
restore_output_magic()
|
|
23
28
|
terminal_history = state.get("terminal_history")
|
|
24
29
|
if isinstance(terminal_history, TerminalCellHistory):
|
|
25
30
|
terminal_history.close()
|
|
@@ -89,6 +94,7 @@ def load_ipython_extension(ipython: InteractiveShell) -> None:
|
|
|
89
94
|
"restore_terminal_display": None,
|
|
90
95
|
"restore_terminal_question_mode": None,
|
|
91
96
|
"terminal_history": None,
|
|
97
|
+
"restore_output_magic": None,
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
if manager is None:
|
|
@@ -104,6 +110,37 @@ def load_ipython_extension(ipython: InteractiveShell) -> None:
|
|
|
104
110
|
)
|
|
105
111
|
state["restore_terminal_display"] = install_markdown_renderer(ipython)
|
|
106
112
|
state["restore_terminal_question_mode"] = install_question_mode(ipython)
|
|
113
|
+
|
|
114
|
+
line_magics = ipython.magics_manager.magics["line"]
|
|
115
|
+
previous_output_magic = line_magics.get("output")
|
|
116
|
+
|
|
117
|
+
def output_magic(line: str) -> None:
|
|
118
|
+
number_text = line.strip()
|
|
119
|
+
if not number_text.isdecimal() or int(number_text) < 1:
|
|
120
|
+
raise ValueError("Usage: %output <cell number>")
|
|
121
|
+
terminal_history = state["terminal_history"]
|
|
122
|
+
if not isinstance(terminal_history, TerminalCellHistory):
|
|
123
|
+
raise RuntimeError("Terminal history is unavailable")
|
|
124
|
+
number = int(number_text)
|
|
125
|
+
try:
|
|
126
|
+
full_output = terminal_history.output_text(number)
|
|
127
|
+
except KeyError as error:
|
|
128
|
+
raise ValueError(f"No recorded cell In [{number}]") from error
|
|
129
|
+
if full_output:
|
|
130
|
+
page(f"\x1b[90m{full_output}\x1b[0m" if sys.stdout.isatty() else full_output)
|
|
131
|
+
else:
|
|
132
|
+
print(f"In [{number}] has no text output.")
|
|
133
|
+
|
|
134
|
+
ipython.register_magic_function(output_magic, "line", "output")
|
|
135
|
+
|
|
136
|
+
def restore_output_magic() -> None:
|
|
137
|
+
if line_magics.get("output") is output_magic:
|
|
138
|
+
if previous_output_magic is None:
|
|
139
|
+
line_magics.pop("output", None)
|
|
140
|
+
else:
|
|
141
|
+
line_magics["output"] = previous_output_magic
|
|
142
|
+
|
|
143
|
+
state["restore_output_magic"] = restore_output_magic
|
|
107
144
|
else:
|
|
108
145
|
|
|
109
146
|
def accept_comm(comm: Any, message: dict[str, Any]) -> None:
|
codebind/terminal.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import ast
|
|
6
|
+
import shutil
|
|
6
7
|
import sys
|
|
7
8
|
from collections.abc import Callable, Iterator
|
|
8
9
|
from contextlib import contextmanager
|
|
@@ -13,7 +14,7 @@ from IPython.terminal.interactiveshell import IPythonPTLexer, TerminalInteractiv
|
|
|
13
14
|
from prompt_toolkit.enums import DEFAULT_BUFFER
|
|
14
15
|
from prompt_toolkit.filters import Condition, has_focus
|
|
15
16
|
from prompt_toolkit.document import Document
|
|
16
|
-
from prompt_toolkit.formatted_text import FormattedText, PygmentsTokens
|
|
17
|
+
from prompt_toolkit.formatted_text import ANSI, FormattedText, PygmentsTokens, to_formatted_text
|
|
17
18
|
from prompt_toolkit.shortcuts import print_formatted_text
|
|
18
19
|
from prompt_toolkit.styles import DynamicStyle, Style, merge_styles
|
|
19
20
|
from rich.console import Console
|
|
@@ -22,10 +23,15 @@ from rich.markdown import Markdown
|
|
|
22
23
|
|
|
23
24
|
_MISSING = object()
|
|
24
25
|
_IMAGE_FORMATS = ("image/png", "image/jpeg", "image/svg+xml")
|
|
26
|
+
_MAXIMUM_VISIBLE_OUTPUT_LINES = 10
|
|
25
27
|
|
|
26
28
|
|
|
27
|
-
def
|
|
28
|
-
""
|
|
29
|
+
def _plain_ansi(value: str) -> str:
|
|
30
|
+
return "".join(text for _, text in to_formatted_text(ANSI(value)))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _magic_input(transformed: str) -> tuple[str, str] | None:
|
|
34
|
+
"""Recognize a complete IPython magic call in transformed history."""
|
|
29
35
|
try:
|
|
30
36
|
statements = ast.parse(transformed).body
|
|
31
37
|
except SyntaxError:
|
|
@@ -42,14 +48,14 @@ def _question_text(transformed: str) -> str | None:
|
|
|
42
48
|
and call.func.value.func.id == "get_ipython"
|
|
43
49
|
and bool(call.args)
|
|
44
50
|
and isinstance(call.args[0], ast.Constant)
|
|
45
|
-
and call.args[0].value
|
|
51
|
+
and isinstance(call.args[0].value, str)
|
|
46
52
|
):
|
|
47
53
|
return None
|
|
48
54
|
text_index = 2 if call.func.attr == "run_cell_magic" else 1
|
|
49
55
|
if len(call.args) <= text_index or not isinstance(call.args[text_index], ast.Constant):
|
|
50
56
|
return None
|
|
51
57
|
text = call.args[text_index].value
|
|
52
|
-
return text.strip() if isinstance(text, str) else None
|
|
58
|
+
return (call.args[0].value, text.strip()) if isinstance(text, str) else None
|
|
53
59
|
|
|
54
60
|
|
|
55
61
|
def _history_cell(
|
|
@@ -63,9 +69,11 @@ def _history_cell(
|
|
|
63
69
|
return None
|
|
64
70
|
history = shell.history_manager
|
|
65
71
|
identifier = f"terminal-{number}"
|
|
66
|
-
|
|
67
|
-
if
|
|
68
|
-
return {"id": identifier, "type": "markdown", "source":
|
|
72
|
+
magic = _magic_input(transformed)
|
|
73
|
+
if magic is not None and magic[0] == "question":
|
|
74
|
+
return {"id": identifier, "type": "markdown", "source": magic[1]}
|
|
75
|
+
if magic is not None and magic[0] == "output":
|
|
76
|
+
return {"id": identifier, "type": "raw", "source": source}
|
|
69
77
|
|
|
70
78
|
outputs: list[dict[str, object]] = []
|
|
71
79
|
for record in history.outputs.get(number, ()):
|
|
@@ -139,10 +147,145 @@ class TerminalCellHistory:
|
|
|
139
147
|
def snapshot(self) -> list[dict[str, object]]:
|
|
140
148
|
return [deepcopy(self._cells[number]) for number in sorted(self._cells)]
|
|
141
149
|
|
|
150
|
+
def output_text(self, number: int) -> str:
|
|
151
|
+
"""Format one completed cell's recorded output for IPython's pager."""
|
|
152
|
+
cell = self._cells.get(number)
|
|
153
|
+
if cell is None:
|
|
154
|
+
raise KeyError(number)
|
|
155
|
+
parts: list[str] = []
|
|
156
|
+
for output in cell.get("outputs", []):
|
|
157
|
+
kind = output["output_type"]
|
|
158
|
+
if kind == "stream":
|
|
159
|
+
parts.append(output["text"])
|
|
160
|
+
elif kind in {"execute_result", "display_data"}:
|
|
161
|
+
data = output["data"]
|
|
162
|
+
text = data.get("text/plain", data.get("text/markdown"))
|
|
163
|
+
if text is None:
|
|
164
|
+
continue
|
|
165
|
+
prefix = f"Out[{number}]: " if kind == "execute_result" else ""
|
|
166
|
+
parts.append(prefix + str(text) + "\n")
|
|
167
|
+
elif kind == "error":
|
|
168
|
+
traceback = output.get("traceback") or [
|
|
169
|
+
f"{output.get('ename', 'Error')}: {output.get('evalue', '')}"
|
|
170
|
+
]
|
|
171
|
+
parts.append("\n".join(traceback) + "\n")
|
|
172
|
+
return _plain_ansi("".join(parts))
|
|
173
|
+
|
|
142
174
|
def close(self) -> None:
|
|
143
175
|
self.shell.events.unregister("post_run_cell", self._callback)
|
|
144
176
|
|
|
145
177
|
|
|
178
|
+
class _OutputPreview:
|
|
179
|
+
"""Limit only terminal painting; IPython still records every written byte."""
|
|
180
|
+
|
|
181
|
+
def __init__(self, maximum_lines: int, maximum_characters: int) -> None:
|
|
182
|
+
self.maximum_lines = maximum_lines
|
|
183
|
+
self.maximum_characters = maximum_characters
|
|
184
|
+
self.visible_lines = 0
|
|
185
|
+
self.visible_characters = 0
|
|
186
|
+
self.hidden_line_breaks = 0
|
|
187
|
+
self.hidden_has_tail = False
|
|
188
|
+
self.hidden_characters = 0
|
|
189
|
+
self.truncated = False
|
|
190
|
+
self.visible_ends_line = True
|
|
191
|
+
|
|
192
|
+
def _hide(self, data: str) -> None:
|
|
193
|
+
self.truncated = True
|
|
194
|
+
self.hidden_characters += len(data)
|
|
195
|
+
self.hidden_line_breaks += data.count("\n") + data.count("\r") - data.count("\r\n")
|
|
196
|
+
self.hidden_has_tail = not data.endswith(("\n", "\r"))
|
|
197
|
+
|
|
198
|
+
def write(self, stream, data: str) -> int:
|
|
199
|
+
for piece in data.splitlines(keepends=True):
|
|
200
|
+
remaining = self.maximum_characters - self.visible_characters
|
|
201
|
+
if self.truncated or self.visible_lines >= self.maximum_lines or remaining <= 0:
|
|
202
|
+
self._hide(piece)
|
|
203
|
+
continue
|
|
204
|
+
visible = piece[:remaining]
|
|
205
|
+
if len(visible) < len(piece) and "\x1b" in visible:
|
|
206
|
+
# Never leave a partially printed ANSI escape sequence on screen.
|
|
207
|
+
visible = ""
|
|
208
|
+
if visible:
|
|
209
|
+
if stream.isatty():
|
|
210
|
+
stream.write("\x1b[90m")
|
|
211
|
+
stream.write(visible)
|
|
212
|
+
if stream.isatty():
|
|
213
|
+
stream.write("\x1b[0m")
|
|
214
|
+
self.visible_characters += len(visible)
|
|
215
|
+
self.visible_ends_line = visible.endswith(("\n", "\r"))
|
|
216
|
+
if self.visible_ends_line:
|
|
217
|
+
self.visible_lines += 1
|
|
218
|
+
if len(visible) < len(piece):
|
|
219
|
+
self._hide(piece[len(visible) :])
|
|
220
|
+
return len(data)
|
|
221
|
+
|
|
222
|
+
def show_notice(self, number: int, error: dict[str, str] | None = None) -> None:
|
|
223
|
+
if not self.hidden_characters:
|
|
224
|
+
return
|
|
225
|
+
if sys.stdout.isatty():
|
|
226
|
+
sys.stdout.write("\x1b[0m")
|
|
227
|
+
if not self.visible_ends_line:
|
|
228
|
+
sys.stdout.write("\n")
|
|
229
|
+
hidden_lines = self.hidden_line_breaks + int(self.hidden_has_tail)
|
|
230
|
+
label = "line" if hidden_lines == 1 else "lines"
|
|
231
|
+
sys.stdout.write(
|
|
232
|
+
f"… {hidden_lines:,} more output {label}. Run %output {number} to view all.\n"
|
|
233
|
+
)
|
|
234
|
+
if error is not None:
|
|
235
|
+
if sys.stdout.isatty():
|
|
236
|
+
sys.stdout.write("\x1b[90m")
|
|
237
|
+
sys.stdout.write(f"{error['type']}: {error['message']}\n")
|
|
238
|
+
if sys.stdout.isatty():
|
|
239
|
+
sys.stdout.write("\x1b[0m")
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class _PreviewStream:
|
|
243
|
+
def __init__(self, stream, preview: _OutputPreview) -> None:
|
|
244
|
+
self.stream = stream
|
|
245
|
+
self.preview = preview
|
|
246
|
+
self.pending = ""
|
|
247
|
+
|
|
248
|
+
def write(self, data: str) -> int:
|
|
249
|
+
self.pending += data
|
|
250
|
+
lines = self.pending.splitlines(keepends=True)
|
|
251
|
+
if lines and not lines[-1].endswith(("\n", "\r")):
|
|
252
|
+
self.pending = lines.pop()
|
|
253
|
+
else:
|
|
254
|
+
self.pending = ""
|
|
255
|
+
for line in lines:
|
|
256
|
+
self.preview.write(self.stream, _plain_ansi(line))
|
|
257
|
+
return len(data)
|
|
258
|
+
|
|
259
|
+
def flush(self) -> None:
|
|
260
|
+
if self.pending:
|
|
261
|
+
self.preview.write(self.stream, _plain_ansi(self.pending))
|
|
262
|
+
self.pending = ""
|
|
263
|
+
self.stream.flush()
|
|
264
|
+
|
|
265
|
+
def __getattr__(self, name: str):
|
|
266
|
+
return getattr(self.stream, name)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@contextmanager
|
|
270
|
+
def preview_tool_output(
|
|
271
|
+
maximum_lines: int = _MAXIMUM_VISIBLE_OUTPUT_LINES,
|
|
272
|
+
) -> Iterator[_OutputPreview]:
|
|
273
|
+
"""Show a compact preview while keeping the tool cell's complete native output."""
|
|
274
|
+
columns = shutil.get_terminal_size(fallback=(80, 24)).columns
|
|
275
|
+
preview = _OutputPreview(maximum_lines, maximum_lines * max(20, columns))
|
|
276
|
+
stdout, stderr = sys.stdout, sys.stderr
|
|
277
|
+
preview_stdout = _PreviewStream(stdout, preview)
|
|
278
|
+
preview_stderr = _PreviewStream(stderr, preview)
|
|
279
|
+
sys.stdout = preview_stdout
|
|
280
|
+
sys.stderr = preview_stderr
|
|
281
|
+
try:
|
|
282
|
+
yield preview
|
|
283
|
+
finally:
|
|
284
|
+
preview_stdout.flush()
|
|
285
|
+
preview_stderr.flush()
|
|
286
|
+
sys.stdout, sys.stderr = stdout, stderr
|
|
287
|
+
|
|
288
|
+
|
|
146
289
|
def install_question_mode(shell: TerminalInteractiveShell) -> Callable[[], None]:
|
|
147
290
|
"""Let Shift+Tab switch the terminal prompt between Python and questions."""
|
|
148
291
|
prompt_session = shell.pt_app
|
|
@@ -305,6 +448,7 @@ __all__ = [
|
|
|
305
448
|
"TerminalCellHistory",
|
|
306
449
|
"install_markdown_renderer",
|
|
307
450
|
"install_question_mode",
|
|
451
|
+
"preview_tool_output",
|
|
308
452
|
"record_tool_output",
|
|
309
453
|
"show_input",
|
|
310
454
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codebind
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.8
|
|
4
4
|
Summary: A frontend-neutral model loop for persistent IPython sessions.
|
|
5
5
|
Keywords: ai,ipython,llm,repl,agents
|
|
6
6
|
Author: Giovanni Gravili
|
|
@@ -75,7 +75,7 @@ Inspect this project and tell me what to implement first.
|
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
Terminal conversations remain live for the current IPython process. Previous terminal inputs and outputs, including Python cells you ran yourself, enter the model's context when you ask a question. Durable automatic resumption belongs to notebooks, where the notebook file provides an unambiguous conversation identity.
|
|
78
|
-
Model-executed cells appear with IPython's native input counter, syntax highlighting, output prompts, streams, and tracebacks. Assistant Markdown is rendered through IPython's terminal MIME renderer. A terminal is a stream rather than a notebook document, so these displays are not editable notebook cells.
|
|
78
|
+
Model-executed cells appear with IPython's native input counter, syntax highlighting, output prompts, streams, and tracebacks. To keep terminal scrollback usable, Codebind shows at most 10 gray lines of each model-executed cell's output, then displays a notice such as `… 990 more output lines. Run %output 8 to view all.` The complete output remains available to the model and in IPython history; `%output 8` opens its full text in IPython's pager. User-entered Python cells keep IPython's normal display behavior. Assistant Markdown is rendered through IPython's terminal MIME renderer. A terminal is a stream rather than a notebook document, so these displays are not editable notebook cells.
|
|
79
79
|
|
|
80
80
|
## JupyterLab
|
|
81
81
|
|
|
@@ -3,22 +3,22 @@ codebind/cli.py,sha256=9LOR1L3P8sPsOOgsnpbOsA1PNUZdAj1Z9ROFKeo3EV8,423
|
|
|
3
3
|
codebind/configuration.py,sha256=b9ux-MiepzAFfRhorZp4w2pdLLs44necescIGg_IKfo,1828
|
|
4
4
|
codebind/conversation.py,sha256=nFMe2QgFkFOA2GYInN-cO_jhA9010LpM6_Ij2g4Q2BA,17500
|
|
5
5
|
codebind/display.py,sha256=IpxcElyNcr5olRIatEduN_d-sRwpsMlaq1UtrOXocQA,494
|
|
6
|
-
codebind/execution.py,sha256=
|
|
7
|
-
codebind/extension.py,sha256=
|
|
6
|
+
codebind/execution.py,sha256=0G3WZ5HkXCdr-PavhRcvjKOjW70-iHGM2Xp9KkZ6WIc,16562
|
|
7
|
+
codebind/extension.py,sha256=DRT0-Syn8yQ4ib46Mb-Yvxhw1fXz9OINr2bCS7oR-uE,8953
|
|
8
8
|
codebind/images.py,sha256=9bJHjXc75_YRBFTAqAWiknRTCjs8ApyGVVSxC_S5lio,4342
|
|
9
9
|
codebind/instructions.md,sha256=_8CVGEuKgPRLmxfPnJMP0sNGg_Nh_o6z5iuKHKj57RM,3768
|
|
10
10
|
codebind/jupyter.py,sha256=07H_S9G3iyyUtWRzlvFr5-5X6CuLBXVficu5Fz8jpVw,8652
|
|
11
11
|
codebind/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
codebind/session.py,sha256=b8fEFOFdZn4h1wIr9RE2K5SPWmoVyro5pRhGUr4rI6c,23722
|
|
13
|
-
codebind/terminal.py,sha256=
|
|
14
|
-
codebind-0.6.
|
|
15
|
-
codebind-0.6.
|
|
16
|
-
codebind-0.6.
|
|
17
|
-
codebind-0.6.
|
|
18
|
-
codebind-0.6.
|
|
19
|
-
codebind-0.6.
|
|
20
|
-
codebind-0.6.
|
|
21
|
-
codebind-0.6.
|
|
22
|
-
codebind-0.6.
|
|
23
|
-
codebind-0.6.
|
|
24
|
-
codebind-0.6.
|
|
13
|
+
codebind/terminal.py,sha256=YcaHvl8L9P0vNfsS7YEhhkXXJJOTZ1QUeprzEE6pabg,16979
|
|
14
|
+
codebind-0.6.8.dist-info/licenses/LICENSE,sha256=ujX46e0LFBIBTnCDY0u3Q7LV363B7CiI7QJZxIkEXlk,1073
|
|
15
|
+
codebind-0.6.8.data/data/share/jupyter/labextensions/codebind-jupyterlab/install.json,sha256=78rEThkfrk1pXtekX5WrG9_Y0lJYi5XBEm8n9athpFE,164
|
|
16
|
+
codebind-0.6.8.data/data/share/jupyter/labextensions/codebind-jupyterlab/package.json,sha256=hawl8ZytgxN-WbUjgbzdIVemPPczzmSFoc2HwDxtgIc,1192
|
|
17
|
+
codebind-0.6.8.data/data/share/jupyter/labextensions/codebind-jupyterlab/static/590.dae4561c5427a855.js,sha256=lMbXilytbQEc_kzyVkgzhKZxU_zgdNLTz4uLJfC7APY,16141
|
|
18
|
+
codebind-0.6.8.data/data/share/jupyter/labextensions/codebind-jupyterlab/static/remoteEntry.c10098fb6e87897c.js,sha256=U0JBoOwkRkzPct8MzcUO1pc2XeVGvxgztXBMtJMg2b4,11794
|
|
19
|
+
codebind-0.6.8.data/data/share/jupyter/labextensions/codebind-jupyterlab/static/style.js,sha256=Opy15wyuR_ABqsrk-cOcOj2yZtvtq0r36aDkErnloD0,113
|
|
20
|
+
codebind-0.6.8.data/data/share/jupyter/labextensions/codebind-jupyterlab/static/third-party-licenses.json,sha256=MNToQfru1YnHAie-2Virp23yWsc5co3qG0IzrO6SEfw,20
|
|
21
|
+
codebind-0.6.8.dist-info/WHEEL,sha256=7hzKWg-J8I3Buqyw5tBii5z_MmAVsDYXXijd_QAtNZ8,81
|
|
22
|
+
codebind-0.6.8.dist-info/entry_points.txt,sha256=GiPcU63sULDlywJSKigAS4M3vaziYIrubXOb3fAg2_c,48
|
|
23
|
+
codebind-0.6.8.dist-info/METADATA,sha256=BqNK8lXq6yyfeisTOEM6B2q2p8kMweQs5cOKYs0hIVQ,7716
|
|
24
|
+
codebind-0.6.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|