pynteract 0.1.0__tar.gz
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.
- pynteract-0.1.0/LICENSE +21 -0
- pynteract-0.1.0/MANIFEST.in +8 -0
- pynteract-0.1.0/PKG-INFO +386 -0
- pynteract-0.1.0/README.md +371 -0
- pynteract-0.1.0/pynteract/__init__.py +6 -0
- pynteract-0.1.0/pynteract/builtin_magics.py +260 -0
- pynteract-0.1.0/pynteract/cli.py +112 -0
- pynteract-0.1.0/pynteract/collector.py +109 -0
- pynteract-0.1.0/pynteract/context.py +35 -0
- pynteract-0.1.0/pynteract/future_utils.py +60 -0
- pynteract-0.1.0/pynteract/magics.py +229 -0
- pynteract-0.1.0/pynteract/namespace_utils.py +142 -0
- pynteract-0.1.0/pynteract/ptk.py +484 -0
- pynteract-0.1.0/pynteract/shell.py +822 -0
- pynteract-0.1.0/pynteract/streams.py +461 -0
- pynteract-0.1.0/pynteract/traceback_utils.py +168 -0
- pynteract-0.1.0/pynteract/user_config.py +32 -0
- pynteract-0.1.0/pynteract/utils.py +37 -0
- pynteract-0.1.0/pynteract.egg-info/PKG-INFO +386 -0
- pynteract-0.1.0/pynteract.egg-info/SOURCES.txt +39 -0
- pynteract-0.1.0/pynteract.egg-info/dependency_links.txt +1 -0
- pynteract-0.1.0/pynteract.egg-info/entry_points.txt +2 -0
- pynteract-0.1.0/pynteract.egg-info/requires.txt +7 -0
- pynteract-0.1.0/pynteract.egg-info/top_level.txt +1 -0
- pynteract-0.1.0/pyproject.toml +29 -0
- pynteract-0.1.0/setup.cfg +4 -0
- pynteract-0.1.0/tests/conftest.py +9 -0
- pynteract-0.1.0/tests/test_builtin_magics_autoregister.py +11 -0
- pynteract-0.1.0/tests/test_cli.py +29 -0
- pynteract-0.1.0/tests/test_display.py +44 -0
- pynteract-0.1.0/tests/test_dynamic_stream_hooks.py +24 -0
- pynteract-0.1.0/tests/test_history_and_filenames.py +39 -0
- pynteract-0.1.0/tests/test_hooks.py +74 -0
- pynteract-0.1.0/tests/test_ipython_magics.py +59 -0
- pynteract-0.1.0/tests/test_magics.py +155 -0
- pynteract-0.1.0/tests/test_reset.py +18 -0
- pynteract-0.1.0/tests/test_run_hooks_and_capture_context.py +69 -0
- pynteract-0.1.0/tests/test_run_magic.py +43 -0
- pynteract-0.1.0/tests/test_shell.py +57 -0
- pynteract-0.1.0/tests/test_stream_compat.py +60 -0
- pynteract-0.1.0/tests/test_system_commands.py +40 -0
pynteract-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Baptiste
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pynteract-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pynteract
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Lightweight embedded, cell-oriented Python shell (notebooks/agents) with minimal dependencies.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: asttokens>=2.4
|
|
10
|
+
Provides-Extra: terminal
|
|
11
|
+
Requires-Dist: prompt-toolkit>=3.0; extra == "terminal"
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# Pynteract
|
|
17
|
+
|
|
18
|
+
Pynteract is a lightweight, dependency-minimal, embeddable Python “cell shell” with IPython-style ergonomics:
|
|
19
|
+
magics (`%`, `%%`), system commands (`!`, `!!`), per-cell filenames for better tracebacks, and a hookable execution pipeline.
|
|
20
|
+
|
|
21
|
+
It is designed to be used inside notebooks, web apps, AI agents, CLIs, and other embedded environments where you want:
|
|
22
|
+
deterministic execution, controllable IO, and rich integration points.
|
|
23
|
+
|
|
24
|
+
## Table of contents
|
|
25
|
+
|
|
26
|
+
- [Install](#install)
|
|
27
|
+
- [Quick start](#quick-start)
|
|
28
|
+
- [Core concepts](#core-concepts)
|
|
29
|
+
- [Execution + display](#execution--display)
|
|
30
|
+
- [Namespaces + filenames](#namespaces--filenames)
|
|
31
|
+
- [History](#history)
|
|
32
|
+
- [Magics and system commands](#magics-and-system-commands)
|
|
33
|
+
- [Registering magics](#registering-magics)
|
|
34
|
+
- [Magic forms](#magic-forms)
|
|
35
|
+
- [Templates](#templates)
|
|
36
|
+
- [System commands](#system-commands)
|
|
37
|
+
- [Built-in magics](#built-in-magics)
|
|
38
|
+
- [Hooks](#hooks)
|
|
39
|
+
- [Interactive terminal mode](#interactive-terminal-mode)
|
|
40
|
+
- [Persistent history](#persistent-history)
|
|
41
|
+
- [Startup script](#startup-script)
|
|
42
|
+
- [Restarting a session](#restarting-a-session)
|
|
43
|
+
- [CLI](#cli)
|
|
44
|
+
- [Threads and late output routing](#threads-and-late-output-routing)
|
|
45
|
+
- [API reference](#api-reference)
|
|
46
|
+
- [`Shell`](#shell)
|
|
47
|
+
- [`ShellResponse`](#shellresponse)
|
|
48
|
+
- [`RunContext` and context capture](#runcontext-and-context-capture)
|
|
49
|
+
- [Hook reference](#hook-reference)
|
|
50
|
+
- [Configuration files](#configuration-files)
|
|
51
|
+
- [Development](#development)
|
|
52
|
+
- [License](#license)
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install pynteract
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Optional terminal interactive mode (adds prompt_toolkit):
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install "pynteract[terminal]"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Quick start
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from pynteract import Shell
|
|
70
|
+
|
|
71
|
+
shell = Shell(display_mode="none")
|
|
72
|
+
resp = shell.run("x = 41 + 1\nx")
|
|
73
|
+
|
|
74
|
+
assert resp.result == 42
|
|
75
|
+
assert resp.stdout == ""
|
|
76
|
+
assert resp.stderr == ""
|
|
77
|
+
assert resp.exception is None
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Core concepts
|
|
81
|
+
|
|
82
|
+
### Execution + display
|
|
83
|
+
|
|
84
|
+
- Code is executed node-by-node (AST-level), enabling pre/post hooks per statement/expression.
|
|
85
|
+
- `display_mode` controls what expression results are displayed:
|
|
86
|
+
- `"last"` (default): display only the last expression value
|
|
87
|
+
- `"all"`: display every expression value
|
|
88
|
+
- `"none"`: never display expression values
|
|
89
|
+
- A semicolon after an expression suppresses display, mirroring IPython: `x;`.
|
|
90
|
+
|
|
91
|
+
### Namespaces + filenames
|
|
92
|
+
|
|
93
|
+
Pynteract runs in a module-backed namespace by default (good `__module__` behavior, better tracebacks).
|
|
94
|
+
|
|
95
|
+
You can embed it in an existing namespace:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
import sys
|
|
99
|
+
from pynteract import Shell
|
|
100
|
+
|
|
101
|
+
shell = Shell(module_name="__main__", namespace=sys.modules["__main__"].__dict__)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Each `run()` is assigned a synthetic filename like `<shell-input-3>` (or a custom one via `filename=...`).
|
|
105
|
+
This filename is used for:
|
|
106
|
+
|
|
107
|
+
- tracebacks
|
|
108
|
+
- `Shell.history` keys
|
|
109
|
+
- hook routing via `RunContext.name` (handy in notebook-like UIs)
|
|
110
|
+
|
|
111
|
+
### History
|
|
112
|
+
|
|
113
|
+
`Shell.history` is an `OrderedDict` of recent `ShellResponse` objects keyed by synthetic/custom filename.
|
|
114
|
+
The size is capped by `history_size`.
|
|
115
|
+
|
|
116
|
+
## Magics and system commands
|
|
117
|
+
|
|
118
|
+
### Registering magics
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from pynteract import Shell
|
|
122
|
+
|
|
123
|
+
shell = Shell(display_mode="none")
|
|
124
|
+
|
|
125
|
+
@shell.register_magic(name="caps", mode="both") # "line" | "cell" | "both"
|
|
126
|
+
def caps(text: str) -> str:
|
|
127
|
+
return text.upper()
|
|
128
|
+
|
|
129
|
+
assert shell.run("%caps hello").result == "HELLO"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Magic forms
|
|
133
|
+
|
|
134
|
+
- Line magic: `%name rest of line`
|
|
135
|
+
- Cell magic: `%%name` on the first line; the remaining cell body is passed as a string
|
|
136
|
+
- Inline magic: `x = %name rest of line` (also works after `;`)
|
|
137
|
+
|
|
138
|
+
### Templates
|
|
139
|
+
|
|
140
|
+
Inside magics and system commands, `{expr}` is evaluated in the current namespace and replaced with `str(value)`.
|
|
141
|
+
|
|
142
|
+
- Escape literal braces with `{{` / `}}`.
|
|
143
|
+
|
|
144
|
+
### System commands
|
|
145
|
+
|
|
146
|
+
- `!cmd ...` runs a system command and streams stdout/stderr into the captured streams.
|
|
147
|
+
- `!!cmd ...` runs a system command, captures stdout, and returns it as the cell result (stderr still streams).
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
shell = Shell(display_mode="none")
|
|
151
|
+
shell.run('!python3 -c "print(123)"').stdout
|
|
152
|
+
shell.run('!!python3 -c "print(456)"').result
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Built-in magics
|
|
156
|
+
|
|
157
|
+
Pynteract ships a small set of “IPython-like” convenience magics (registered automatically by `Shell.ensure_builtins()`):
|
|
158
|
+
|
|
159
|
+
- `%pwd`, `%cd [path|-]`, `%ls [path]`
|
|
160
|
+
- `%env`, `%env KEY`, `%env KEY=value`, `%env -u KEY`
|
|
161
|
+
- `%who`, `%whos`
|
|
162
|
+
- `%run [-i] script.py [args...]`
|
|
163
|
+
- `%time <code>`, `%timeit [-n N] [-r R] <code>`
|
|
164
|
+
- `%%bash`
|
|
165
|
+
|
|
166
|
+
## Hooks
|
|
167
|
+
|
|
168
|
+
Hooks are stored in `shell.hooks` (a dict) and are looked up dynamically during execution. Updating a hook
|
|
169
|
+
while the shell is running takes effect immediately.
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
from pynteract import Shell
|
|
173
|
+
|
|
174
|
+
def stdout_hook(data: str, buffer: str) -> None:
|
|
175
|
+
print("STDOUT:", data, end="")
|
|
176
|
+
|
|
177
|
+
shell = Shell(display_mode="none", stdout_hook=stdout_hook)
|
|
178
|
+
shell.hooks["stdout_hook"] = stdout_hook # can be swapped dynamically
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Hooks may optionally accept a final `ctx` argument (`RunContext`) for routing. `ctx.name` matches the synthetic/custom
|
|
182
|
+
`filename` of the current run (or another routing name if you override it).
|
|
183
|
+
|
|
184
|
+
## Interactive terminal mode
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
from pynteract import Shell
|
|
188
|
+
Shell().interact()
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Persistent history
|
|
192
|
+
|
|
193
|
+
Interactive sessions store prompt histories under `~/.pynteract/` (or `PYNTERACT_CONFIG_DIR`):
|
|
194
|
+
|
|
195
|
+
- `history_python.txt`: interactive `>>>` input history
|
|
196
|
+
- `history_text.txt`: stdin “text” history used for `input()` reads
|
|
197
|
+
|
|
198
|
+
### Startup script
|
|
199
|
+
|
|
200
|
+
If present and non-empty, `~/.pynteract/startup.py` is executed at the start of interactive sessions.
|
|
201
|
+
|
|
202
|
+
- The startup file is executed via `Shell.run(..., silent=True)` so magics/system commands are supported.
|
|
203
|
+
- If the startup fails, Pynteract prints the enriched traceback and exits (non-zero status in the CLI).
|
|
204
|
+
- When using `pynteract -i script.py`, the startup script runs before the script (same namespace kept for the REPL).
|
|
205
|
+
|
|
206
|
+
### Restarting a session
|
|
207
|
+
|
|
208
|
+
In interactive mode, you can reset the namespace and rerun startup:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
__shell__.restart_session()
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## CLI
|
|
215
|
+
|
|
216
|
+
Installing the package provides a `pynteract` executable.
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Interactive session
|
|
220
|
+
pynteract
|
|
221
|
+
|
|
222
|
+
# Run a script (similar to `python script.py`)
|
|
223
|
+
pynteract path/to/script.py [args...]
|
|
224
|
+
|
|
225
|
+
# Run a script, then enter interactive mode with the same namespace
|
|
226
|
+
pynteract -i path/to/script.py [args...]
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Threads and late output routing
|
|
230
|
+
|
|
231
|
+
To keep output from background threads routed to the originating cell/run, call `shell.enable_stdio_proxy()` once,
|
|
232
|
+
then capture and propagate a `contextvars.Context`:
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
import threading, time
|
|
236
|
+
from pynteract import Shell
|
|
237
|
+
|
|
238
|
+
shell = Shell(display_mode="none")
|
|
239
|
+
shell.enable_stdio_proxy()
|
|
240
|
+
|
|
241
|
+
def worker():
|
|
242
|
+
for i in range(3):
|
|
243
|
+
print(f"tick {i}")
|
|
244
|
+
time.sleep(0.1)
|
|
245
|
+
|
|
246
|
+
shell.run("print('cell start')", filename="<cell-1>")
|
|
247
|
+
ctx = shell.capture_context() # captures ctx.name == "<cell-1>"
|
|
248
|
+
threading.Thread(target=lambda: ctx.run(worker), daemon=True).start()
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Notebook-style “late streaming” example
|
|
252
|
+
|
|
253
|
+
In a notebook UI, you typically want each cell to own its own stdout/stderr widget, and you want background threads
|
|
254
|
+
spawned by a cell to keep streaming into that same widget even after the cell finished.
|
|
255
|
+
|
|
256
|
+
Use the run `filename=` (exposed as `ctx.name` to hooks) as your routing key:
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
from pynteract import Shell
|
|
260
|
+
|
|
261
|
+
cell_widgets = {} # e.g. {"cell-42": StdoutTextArea(...)}
|
|
262
|
+
|
|
263
|
+
def cell_id_from_ctx(ctx) -> str:
|
|
264
|
+
return ctx.name.split(":")[1] # e.g. "<nb:cell-42:run-7>" -> "cell-42"
|
|
265
|
+
|
|
266
|
+
def stdout_router(data: str, _buffer: str, ctx) -> None:
|
|
267
|
+
cell_widgets[cell_id_from_ctx(ctx)].append(data)
|
|
268
|
+
|
|
269
|
+
shell = Shell(display_mode="none", stdout_hook=stdout_router)
|
|
270
|
+
shell.enable_stdio_proxy()
|
|
271
|
+
|
|
272
|
+
def run_cell(cell_id: str, run_no: int, code: str) -> None:
|
|
273
|
+
shell.run(code, filename=f"<nb:{cell_id}:run-{run_no}>")
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## API reference
|
|
277
|
+
|
|
278
|
+
### `Shell`
|
|
279
|
+
|
|
280
|
+
Constructor:
|
|
281
|
+
|
|
282
|
+
```python
|
|
283
|
+
Shell(
|
|
284
|
+
namespace: dict | None = None,
|
|
285
|
+
module_name: str | None = None,
|
|
286
|
+
ensure_cwd_on_syspath: bool = True,
|
|
287
|
+
display_mode: Literal["all", "last", "none"] = "last",
|
|
288
|
+
history_size: int = 200,
|
|
289
|
+
**hooks,
|
|
290
|
+
)
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Key methods:
|
|
294
|
+
|
|
295
|
+
| Method | Signature | Notes |
|
|
296
|
+
| --- | --- | --- |
|
|
297
|
+
| Execute | `run(code, globals=None, locals=None, silent=False, filename=None) -> ShellResponse` | `silent=True` suppresses stdout/stderr hooks (output still captured). |
|
|
298
|
+
| Interactive | `interact() -> int` | Terminal REPL; returns process-like exit code. |
|
|
299
|
+
| Restart | `restart_session(rerun_startup=True, announce=True) -> int` | Resets namespace and (optionally) reruns startup. |
|
|
300
|
+
| Namespace | `update_namespace(**kwargs)` | Adds symbols to the execution namespace. |
|
|
301
|
+
| Namespace | `set_namespace(namespace: dict)` | Switches to a different dict namespace. |
|
|
302
|
+
| Namespace | `reset_namespace()` | Clears user symbols and resets `__future__` flags. |
|
|
303
|
+
| Magics | `register_magic(func=None, *, name=None, mode="both")` | Decorator or direct call; mode `"line"|"cell"|"both"`. |
|
|
304
|
+
| Threads | `enable_stdio_proxy()` | Installs a routing proxy on `sys.stdout`/`sys.stderr` for late-thread capture. |
|
|
305
|
+
| Threads | `capture_context(name=None) -> contextvars.Context` | Capture routing context for another thread. |
|
|
306
|
+
| Builtins | `ensure_builtins()` | (Re)adds `__shell__`, `__magics__`, `display`, and built-in magics. |
|
|
307
|
+
|
|
308
|
+
Important public attributes:
|
|
309
|
+
|
|
310
|
+
| Attribute | Type | Meaning |
|
|
311
|
+
| --- | --- | --- |
|
|
312
|
+
| `namespace` | `dict` | Module-backed execution namespace. |
|
|
313
|
+
| `hooks` | `dict[str, Any]` | Hook registry; updated dynamically. |
|
|
314
|
+
| `magics` | `dict[str, Any]` | Registered magics. |
|
|
315
|
+
| `history` | `OrderedDict[str, ShellResponse]` | Recent run history keyed by filename. |
|
|
316
|
+
| `last_result` | `Any` | Last expression value. |
|
|
317
|
+
|
|
318
|
+
### `ShellResponse`
|
|
319
|
+
|
|
320
|
+
Returned by `Shell.run(...)`.
|
|
321
|
+
|
|
322
|
+
| Field | Type | Meaning |
|
|
323
|
+
| --- | --- | --- |
|
|
324
|
+
| `input` | `str` | Original source string. |
|
|
325
|
+
| `processed_input` | `str` | Expanded source (magics/system commands). |
|
|
326
|
+
| `stdout` / `stderr` | `str` | Captured output for the run. |
|
|
327
|
+
| `result` | `Any` | Last expression value (depending on `display_mode`). |
|
|
328
|
+
| `exception` | `Exception | None` | Exception instance, with enriched traceback attached (when available). |
|
|
329
|
+
|
|
330
|
+
### `RunContext` and context capture
|
|
331
|
+
|
|
332
|
+
Hooks may receive a `RunContext` object (`ctx`) with:
|
|
333
|
+
|
|
334
|
+
- `ctx.name`: routing name (by default the synthetic/custom `filename` of the current `run()`).
|
|
335
|
+
|
|
336
|
+
Use `shell.capture_context()` to propagate routing/capture context to a new thread:
|
|
337
|
+
|
|
338
|
+
```python
|
|
339
|
+
ctx = shell.capture_context()
|
|
340
|
+
threading.Thread(target=lambda: ctx.run(worker)).start()
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Hook reference
|
|
344
|
+
|
|
345
|
+
All hooks are optional. Hook keys live in `shell.hooks` and are passed to `Shell(...)` via `**hooks` (kwargs must end with `_hook`).
|
|
346
|
+
Most hooks may optionally accept a final `ctx: RunContext`.
|
|
347
|
+
|
|
348
|
+
| Hook key | Signature | When it runs |
|
|
349
|
+
| --- | --- | --- |
|
|
350
|
+
| `input_hook` | `input_hook(code: str[, ctx]) -> None` | Before parsing. |
|
|
351
|
+
| `pre_run_hook` | `pre_run_hook(code: str[, ctx]) -> str` | Before tokenization/execution; can rewrite source. |
|
|
352
|
+
| `code_block_hook` | `code_block_hook(code_block: str[, ctx]) -> None` | For each executed AST block. |
|
|
353
|
+
| `pre_execute_hook` | `pre_execute_hook(node, source[, ctx]) -> ast.AST` | Before compiling a node. |
|
|
354
|
+
| `post_execute_hook` | `post_execute_hook(node, result[, ctx]) -> None` | After a node executes. |
|
|
355
|
+
| `display_hook` | `display_hook(obj, **kwargs)` or `display_hook(obj, ctx, **kwargs)` | When displaying expression values. |
|
|
356
|
+
| `stdout_hook` | `stdout_hook(data: str, buffer: str[, ctx]) -> None` | As stdout is flushed. |
|
|
357
|
+
| `stderr_hook` | `stderr_hook(data: str, buffer: str[, ctx]) -> None` | As stderr is flushed. |
|
|
358
|
+
| `stdin_hook` | `stdin_hook([ctx]) -> str | None` | For stdin reads (`None` = EOF). |
|
|
359
|
+
| `exception_hook` | `exception_hook(exc: Exception[, ctx]) -> None` | When a run finishes with an error. |
|
|
360
|
+
| `namespace_change_hook` | `namespace_change_hook(old, new, locals[, ctx]) -> None` | After a run, with before/after namespaces. |
|
|
361
|
+
| `post_run_hook` | `post_run_hook(resp: ShellResponse[, ctx]) -> ShellResponse` | Final response override/hook. |
|
|
362
|
+
|
|
363
|
+
### Configuration files
|
|
364
|
+
|
|
365
|
+
Pynteract stores user-facing state under `~/.pynteract/` (override with `PYNTERACT_CONFIG_DIR`):
|
|
366
|
+
|
|
367
|
+
- `startup.py`: optional startup file (interactive + `-i` only)
|
|
368
|
+
- `history_python.txt`: persistent REPL history
|
|
369
|
+
- `history_text.txt`: persistent stdin history
|
|
370
|
+
|
|
371
|
+
## Development
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
pip install -e ".[dev]"
|
|
375
|
+
pytest -q
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
To develop terminal interactive mode:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
pip install -e ".[dev,terminal]"
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## License
|
|
385
|
+
|
|
386
|
+
MIT. See `LICENSE` file.
|