euporie 2.8.5__tar.gz → 2.8.7__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.
- {euporie-2.8.5 → euporie-2.8.7}/.gitignore +1 -142
- {euporie-2.8.5 → euporie-2.8.7}/LICENSE +1 -1
- {euporie-2.8.5 → euporie-2.8.7}/PKG-INFO +4 -2
- {euporie-2.8.5 → euporie-2.8.7}/README.rst +3 -1
- {euporie-2.8.5 → euporie-2.8.7}/euporie/console/app.py +2 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/console/tabs/console.py +27 -17
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/__init__.py +2 -2
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/__main__.py +2 -2
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/_settings.py +7 -2
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/app/_commands.py +20 -12
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/app/_settings.py +34 -4
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/app/app.py +31 -18
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/bars/command.py +53 -27
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/bars/search.py +43 -2
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/border.py +7 -2
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/comm/base.py +2 -2
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/comm/ipywidgets.py +3 -3
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/commands.py +44 -24
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/completion.py +14 -6
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/datum.py +7 -7
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/data_structures.py +20 -1
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/filters.py +40 -9
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/format.py +2 -3
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/ft/html.py +47 -40
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/graphics.py +199 -31
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/history.py +15 -5
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/inspection.py +16 -9
- euporie-2.8.7/euporie/core/kernel/__init__.py +53 -0
- euporie-2.8.7/euporie/core/kernel/base.py +571 -0
- euporie-2.8.5/euporie/core/kernel/client.py → euporie-2.8.7/euporie/core/kernel/jupyter.py +173 -430
- euporie-2.8.5/euporie/core/kernel/manager.py → euporie-2.8.7/euporie/core/kernel/jupyter_manager.py +4 -3
- euporie-2.8.7/euporie/core/kernel/local.py +694 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/bindings/basic.py +6 -3
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/keys.py +26 -25
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/layout/cache.py +31 -7
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/layout/containers.py +88 -13
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/layout/scroll.py +69 -170
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/log.py +2 -5
- euporie-2.8.7/euporie/core/path.py +127 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/style.py +2 -1
- euporie-2.8.7/euporie/core/suggest.py +241 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/tabs/__init__.py +12 -4
- euporie-2.8.7/euporie/core/tabs/_commands.py +76 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/tabs/_settings.py +16 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/tabs/base.py +89 -9
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/tabs/kernel.py +83 -38
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/tabs/notebook.py +28 -76
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/utils.py +2 -19
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/validation.py +8 -8
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/_settings.py +19 -2
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/cell.py +32 -32
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/cell_outputs.py +10 -1
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/dialog.py +60 -76
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/display.py +2 -2
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/forms.py +71 -59
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/inputs.py +7 -4
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/layout.py +281 -93
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/menu.py +56 -16
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/palette.py +3 -1
- euporie-2.8.7/euporie/core/widgets/tree.py +119 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/app.py +35 -16
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/tabs/display.py +2 -2
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/tabs/edit.py +11 -46
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/tabs/json.py +8 -4
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/tabs/notebook.py +26 -8
- {euporie-2.8.5 → euporie-2.8.7}/euporie/preview/tabs/notebook.py +17 -13
- euporie-2.8.7/euporie/web/__init__.py +1 -0
- euporie-2.8.7/euporie/web/tabs/__init__.py +14 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/web/tabs/web.py +30 -5
- euporie-2.8.7/euporie/web/widgets/__init__.py +1 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/web/widgets/webview.py +5 -4
- {euporie-2.8.5 → euporie-2.8.7}/pyproject.toml +10 -9
- euporie-2.8.5/euporie/core/kernel/__init__.py +0 -1
- euporie-2.8.5/euporie/core/path.py +0 -79
- euporie-2.8.5/euporie/core/suggest.py +0 -160
- euporie-2.8.5/euporie/core/widgets/tree.py +0 -109
- {euporie-2.8.5 → euporie-2.8.7}/euporie/console/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/console/__main__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/console/_commands.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/console/_settings.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/console/py.typed +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/console/tabs/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/app/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/app/base.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/app/current.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/app/cursor.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/app/dummy.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/app/launch.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/bars/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/bars/menu.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/bars/status.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/clipboard.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/comm/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/comm/registry.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/config.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/ansi.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/base64.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/common.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/ft.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/html.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/jpeg.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/markdown.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/pdf.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/pil.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/png.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/rich.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/sixel.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/formats/svg.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/mime.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/registry.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/convert/utils.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/diagnostics.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/ft/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/ft/ansi.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/ft/table.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/ft/utils.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/io.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/bindings/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/bindings/completion.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/bindings/micro.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/bindings/mouse.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/bindings/page_navigation.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/bindings/terminal.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/bindings/vi.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/key_processor.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/micro_state.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/registry.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/utils.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/key_binding/vi_state.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/layout/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/layout/controls.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/layout/decor.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/layout/mouse.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/layout/print.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/layout/screen.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/lexers.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/lsp.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/margins.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/processors.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/py.typed +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/pygments.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/reference.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/renderer.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/decor.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/file_browser.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/formatted_text_area.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/logo.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/core/widgets/pager.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/data/desktop/euporie-console.desktop +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/data/desktop/euporie-notebook.desktop +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/hub/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/hub/__main__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/hub/app.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/hub/py.typed +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/__main__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/_commands.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/_settings.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/current.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/enums.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/filters.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/py.typed +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/tabs/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/tabs/_commands.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/tabs/_settings.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/tabs/log.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/widgets/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/widgets/_commands.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/widgets/_settings.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/notebook/widgets/side_bar.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/preview/__init__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/preview/__main__.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/preview/_settings.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/preview/app.py +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/preview/py.typed +0 -0
- {euporie-2.8.5 → euporie-2.8.7}/euporie/preview/tabs/__init__.py +0 -0
@@ -2,9 +2,6 @@
|
|
2
2
|
/media
|
3
3
|
/examples
|
4
4
|
|
5
|
-
# Python version specifier file
|
6
|
-
.python-version
|
7
|
-
|
8
5
|
# AI tools
|
9
6
|
.aider*
|
10
7
|
|
@@ -97,7 +94,7 @@ ipython_config.py
|
|
97
94
|
# pyenv
|
98
95
|
# For a library or package, you might want to ignore these files since the code is
|
99
96
|
# intended to run in multiple environments; otherwise, check them in:
|
100
|
-
|
97
|
+
.python-version
|
101
98
|
|
102
99
|
# pipenv
|
103
100
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
@@ -151,141 +148,3 @@ dmypy.json
|
|
151
148
|
|
152
149
|
# Cython debug symbols
|
153
150
|
cython_debug/
|
154
|
-
# Byte-compiled / optimized / DLL files
|
155
|
-
__pycache__/
|
156
|
-
*.py[cod]
|
157
|
-
*$py.class
|
158
|
-
|
159
|
-
# C extensions
|
160
|
-
*.so
|
161
|
-
|
162
|
-
# Distribution / packaging
|
163
|
-
.Python
|
164
|
-
build/
|
165
|
-
develop-eggs/
|
166
|
-
dist/
|
167
|
-
downloads/
|
168
|
-
eggs/
|
169
|
-
.eggs/
|
170
|
-
lib/
|
171
|
-
lib64/
|
172
|
-
parts/
|
173
|
-
sdist/
|
174
|
-
var/
|
175
|
-
wheels/
|
176
|
-
share/python-wheels/
|
177
|
-
*.egg-info/
|
178
|
-
.installed.cfg
|
179
|
-
*.egg
|
180
|
-
MANIFEST
|
181
|
-
|
182
|
-
# PyInstaller
|
183
|
-
# Usually these files are written by a python script from a template
|
184
|
-
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
185
|
-
*.manifest
|
186
|
-
*.spec
|
187
|
-
|
188
|
-
# Installer logs
|
189
|
-
pip-log.txt
|
190
|
-
pip-delete-this-directory.txt
|
191
|
-
|
192
|
-
# Unit test / coverage reports
|
193
|
-
htmlcov/
|
194
|
-
.tox/
|
195
|
-
.nox/
|
196
|
-
.coverage
|
197
|
-
.coverage.*
|
198
|
-
.cache
|
199
|
-
nosetests.xml
|
200
|
-
coverage.xml
|
201
|
-
*.cover
|
202
|
-
*.py,cover
|
203
|
-
.hypothesis/
|
204
|
-
.pytest_cache/
|
205
|
-
cover/
|
206
|
-
|
207
|
-
# Translations
|
208
|
-
*.mo
|
209
|
-
*.pot
|
210
|
-
|
211
|
-
# Django stuff:
|
212
|
-
*.log
|
213
|
-
local_settings.py
|
214
|
-
db.sqlite3
|
215
|
-
db.sqlite3-journal
|
216
|
-
|
217
|
-
# Flask stuff:
|
218
|
-
instance/
|
219
|
-
.webassets-cache
|
220
|
-
|
221
|
-
# Scrapy stuff:
|
222
|
-
.scrapy
|
223
|
-
|
224
|
-
# Sphinx documentation
|
225
|
-
docs/_build/
|
226
|
-
|
227
|
-
# PyBuilder
|
228
|
-
.pybuilder/
|
229
|
-
target/
|
230
|
-
|
231
|
-
# Jupyter Notebook
|
232
|
-
.ipynb_checkpoints
|
233
|
-
|
234
|
-
# IPython
|
235
|
-
profile_default/
|
236
|
-
ipython_config.py
|
237
|
-
|
238
|
-
# pyenv
|
239
|
-
# For a library or package, you might want to ignore these files since the code is
|
240
|
-
# intended to run in multiple environments; otherwise, check them in:
|
241
|
-
# .python-version
|
242
|
-
|
243
|
-
# pipenv
|
244
|
-
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
245
|
-
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
246
|
-
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
247
|
-
# install all needed dependencies.
|
248
|
-
#Pipfile.lock
|
249
|
-
|
250
|
-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
251
|
-
__pypackages__/
|
252
|
-
|
253
|
-
# Celery stuff
|
254
|
-
celerybeat-schedule
|
255
|
-
celerybeat.pid
|
256
|
-
|
257
|
-
# SageMath parsed files
|
258
|
-
*.sage.py
|
259
|
-
|
260
|
-
# Environments
|
261
|
-
.env
|
262
|
-
.venv
|
263
|
-
env/
|
264
|
-
venv/
|
265
|
-
ENV/
|
266
|
-
env.bak/
|
267
|
-
venv.bak/
|
268
|
-
|
269
|
-
# Spyder project settings
|
270
|
-
.spyderproject
|
271
|
-
.spyproject
|
272
|
-
|
273
|
-
# Rope project settings
|
274
|
-
.ropeproject
|
275
|
-
|
276
|
-
# mkdocs documentation
|
277
|
-
/site
|
278
|
-
|
279
|
-
# mypy
|
280
|
-
.mypy_cache/
|
281
|
-
.dmypy.json
|
282
|
-
dmypy.json
|
283
|
-
|
284
|
-
# Pyre type checker
|
285
|
-
.pyre/
|
286
|
-
|
287
|
-
# pytype static type analyzer
|
288
|
-
.pytype/
|
289
|
-
|
290
|
-
# Cython debug symbols
|
291
|
-
cython_debug/
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: euporie
|
3
|
-
Version: 2.8.
|
3
|
+
Version: 2.8.7
|
4
4
|
Summary: Euporie is a suite of terminal applications for interacting with Jupyter kernels
|
5
5
|
Project-URL: Documentation, https://euporie.readthedocs.io/en/latest
|
6
6
|
Project-URL: Issues, https://github.com/joouha/euporie/issues
|
@@ -85,10 +85,12 @@ If you're working with Jupyter notebooks in a terminal only environment, like an
|
|
85
85
|
Install
|
86
86
|
*******
|
87
87
|
|
88
|
-
You can install euporie with `pipx <https://pipxproject.github.io/>`_
|
88
|
+
You can install euporie with `uv <https://docs.astral.sh/uv/>`_ (recommended), or with `pipx <https://pipxproject.github.io/>`_ or ``pip``):
|
89
89
|
|
90
90
|
.. code-block:: console
|
91
91
|
|
92
|
+
$ uv tool install euporie
|
93
|
+
$ # OR
|
92
94
|
$ pipx install euporie
|
93
95
|
$ # OR
|
94
96
|
$ python -m pip install --user euporie
|
@@ -38,10 +38,12 @@ If you're working with Jupyter notebooks in a terminal only environment, like an
|
|
38
38
|
Install
|
39
39
|
*******
|
40
40
|
|
41
|
-
You can install euporie with `pipx <https://pipxproject.github.io/>`_
|
41
|
+
You can install euporie with `uv <https://docs.astral.sh/uv/>`_ (recommended), or with `pipx <https://pipxproject.github.io/>`_ or ``pip``):
|
42
42
|
|
43
43
|
.. code-block:: console
|
44
44
|
|
45
|
+
$ uv tool install euporie
|
46
|
+
$ # OR
|
45
47
|
$ pipx install euporie
|
46
48
|
$ # OR
|
47
49
|
$ python -m pip install --user euporie
|
@@ -32,6 +32,7 @@ from euporie.core.filters import has_dialog
|
|
32
32
|
from euporie.core.layout.mouse import DisableMouseOnScroll
|
33
33
|
from euporie.core.widgets.dialog import (
|
34
34
|
AboutDialog,
|
35
|
+
ConfirmDialog,
|
35
36
|
NoKernelsDialog,
|
36
37
|
SaveAsDialog,
|
37
38
|
SelectKernelDialog,
|
@@ -112,6 +113,7 @@ class ConsoleApp(BaseApp):
|
|
112
113
|
self.dialogs["no-kernels"] = NoKernelsDialog(self)
|
113
114
|
self.dialogs["change-kernel"] = SelectKernelDialog(self)
|
114
115
|
self.dialogs["shortcuts"] = ShortcutsDialog(self)
|
116
|
+
self.dialogs["confirm"] = ConfirmDialog(self)
|
115
117
|
|
116
118
|
return FloatContainer(
|
117
119
|
DisableMouseOnScroll(
|
@@ -40,7 +40,7 @@ from euporie.core.filters import (
|
|
40
40
|
)
|
41
41
|
from euporie.core.format import LspFormatter
|
42
42
|
from euporie.core.io import edit_in_editor
|
43
|
-
from euporie.core.kernel.
|
43
|
+
from euporie.core.kernel.base import MsgCallbacks
|
44
44
|
from euporie.core.key_binding.registry import (
|
45
45
|
load_registered_bindings,
|
46
46
|
register_bindings,
|
@@ -137,10 +137,7 @@ class Console(KernelTab):
|
|
137
137
|
|
138
138
|
self.container = self.load_container()
|
139
139
|
|
140
|
-
self.kernel.start(cb=self.kernel_started, wait=False)
|
141
|
-
|
142
140
|
self.app.before_render += self.render_outputs
|
143
|
-
|
144
141
|
self.on_advance = Event(self)
|
145
142
|
|
146
143
|
async def load_lsps(self) -> None:
|
@@ -162,9 +159,26 @@ class Console(KernelTab):
|
|
162
159
|
|
163
160
|
lsp.on_exit += lsp_unload
|
164
161
|
|
162
|
+
def post_init_kernel(self) -> None:
|
163
|
+
"""Start the kernel after if has been loaded."""
|
164
|
+
# Load container
|
165
|
+
super().post_init_kernel()
|
166
|
+
|
167
|
+
# Start kernel
|
168
|
+
if self.kernel._status == "stopped":
|
169
|
+
self.kernel.start(cb=self.kernel_started, wait=False)
|
170
|
+
|
165
171
|
def kernel_died(self) -> None:
|
166
|
-
"""Call
|
172
|
+
"""Call if the kernel dies."""
|
167
173
|
log.error("The kernel has died")
|
174
|
+
if confirm := self.app.dialogs.get("confirm"):
|
175
|
+
confirm.show(
|
176
|
+
title="Kernel connection lost",
|
177
|
+
message="The kernel appears to have died\n"
|
178
|
+
"as it can no longer be reached.\n\n"
|
179
|
+
"Do you want to restart the kernel?",
|
180
|
+
cb=self.kernel.restart,
|
181
|
+
)
|
168
182
|
|
169
183
|
async def load_history(self) -> None:
|
170
184
|
"""Load kernel history."""
|
@@ -191,9 +205,7 @@ class Console(KernelTab):
|
|
191
205
|
def validate_input(self, code: str) -> bool:
|
192
206
|
"""Determine if the entered code is ready to run."""
|
193
207
|
assert self.kernel is not None
|
194
|
-
completeness_status = self.kernel.is_complete(code
|
195
|
-
"status", "unknown"
|
196
|
-
)
|
208
|
+
completeness_status = self.kernel.is_complete(code).get("status", "unknown")
|
197
209
|
return not (
|
198
210
|
not code.strip()
|
199
211
|
or completeness_status == "incomplete"
|
@@ -404,12 +416,7 @@ class Console(KernelTab):
|
|
404
416
|
if ((json_cells and cell.id != json_cells[0].id) or i > 0) and (
|
405
417
|
(height_known and rows_above_layout > 0) or not height_known
|
406
418
|
):
|
407
|
-
children.append(
|
408
|
-
Window(
|
409
|
-
height=1,
|
410
|
-
dont_extend_height=True,
|
411
|
-
)
|
412
|
-
)
|
419
|
+
children.append(Window(height=1, dont_extend_height=True))
|
413
420
|
|
414
421
|
# Cell input
|
415
422
|
children.append(
|
@@ -441,9 +448,12 @@ class Console(KernelTab):
|
|
441
448
|
if outputs := cell.outputs:
|
442
449
|
# Add space before an output if last rendered cell did not have outputs
|
443
450
|
# or we are rendering a new output
|
444
|
-
if self.last_rendered is
|
445
|
-
|
446
|
-
|
451
|
+
if self.last_rendered is None or (
|
452
|
+
self.last_rendered is not None
|
453
|
+
and (
|
454
|
+
not self.last_rendered.outputs
|
455
|
+
or cell.execution_count != self.last_rendered.execution_count
|
456
|
+
)
|
447
457
|
):
|
448
458
|
children.append(
|
449
459
|
Window(
|
@@ -1,10 +1,10 @@
|
|
1
1
|
"""This package defines the euporie application and its components."""
|
2
2
|
|
3
3
|
__app_name__ = "euporie"
|
4
|
-
__version__ = "2.8.
|
4
|
+
__version__ = "2.8.7"
|
5
5
|
__logo__ = "⚈"
|
6
6
|
__strapline__ = "Jupyter in the terminal"
|
7
7
|
__author__ = "Josiah Outram Halstead"
|
8
8
|
__email__ = "josiah@halstead.email"
|
9
|
-
__copyright__ = f"©
|
9
|
+
__copyright__ = f"© 2025, {__author__}"
|
10
10
|
__license__ = "MIT"
|
@@ -7,13 +7,13 @@ from importlib.metadata import entry_points
|
|
7
7
|
from typing import TYPE_CHECKING
|
8
8
|
|
9
9
|
if TYPE_CHECKING:
|
10
|
-
from importlib.metadata import EntryPoint, EntryPoints
|
10
|
+
from importlib.metadata import EntryPoint, EntryPoints
|
11
11
|
|
12
12
|
|
13
13
|
@cache
|
14
14
|
def available_apps() -> dict[str, EntryPoint]:
|
15
15
|
"""Return a list of loadable euporie apps."""
|
16
|
-
eps: dict |
|
16
|
+
eps: dict | EntryPoints
|
17
17
|
try:
|
18
18
|
eps = entry_points(group="euporie.apps")
|
19
19
|
except TypeError:
|
@@ -1,5 +1,7 @@
|
|
1
1
|
"""Defines core settings."""
|
2
2
|
|
3
|
+
import json
|
4
|
+
|
3
5
|
from euporie.core import __version__
|
4
6
|
from euporie.core.config import add_setting
|
5
7
|
|
@@ -73,8 +75,11 @@ add_setting(
|
|
73
75
|
name="log_config",
|
74
76
|
group="euporie.core.log",
|
75
77
|
flags=["--log-config"],
|
76
|
-
type_=
|
77
|
-
default=
|
78
|
+
type_=json.loads,
|
79
|
+
default={},
|
80
|
+
schema={
|
81
|
+
"type": "object",
|
82
|
+
},
|
78
83
|
title="additional logging configuration",
|
79
84
|
help_="Additional logging configuration",
|
80
85
|
description="""
|
@@ -8,7 +8,7 @@ from prompt_toolkit.filters import buffer_has_focus
|
|
8
8
|
|
9
9
|
from euporie.core.app.current import get_app
|
10
10
|
from euporie.core.commands import add_cmd
|
11
|
-
from euporie.core.filters import tab_has_focus
|
11
|
+
from euporie.core.filters import tab_has_focus, tab_type_has_focus
|
12
12
|
|
13
13
|
if TYPE_CHECKING:
|
14
14
|
from prompt_toolkit.key_binding.key_processor import KeyPressEvent
|
@@ -20,18 +20,12 @@ def _quit() -> None:
|
|
20
20
|
get_app().exit()
|
21
21
|
|
22
22
|
|
23
|
-
@add_cmd(aliases=["
|
24
|
-
def
|
25
|
-
"""
|
26
|
-
from
|
23
|
+
@add_cmd(aliases=["q!"])
|
24
|
+
def _force_quit() -> None:
|
25
|
+
"""Quit euporie without saving any changes."""
|
26
|
+
from prompt_toolkit.application.application import Application
|
27
27
|
|
28
|
-
|
29
|
-
if (tab := get_app().tab) is not None:
|
30
|
-
try:
|
31
|
-
tab._save(UPath(event._arg) if event._arg else None)
|
32
|
-
except NotImplementedError:
|
33
|
-
pass
|
34
|
-
app.exit()
|
28
|
+
Application.exit(get_app())
|
35
29
|
|
36
30
|
|
37
31
|
@add_cmd(aliases=["bc"], filter=tab_has_focus, menu_title="Close File")
|
@@ -68,3 +62,17 @@ def _focus_previous() -> None:
|
|
68
62
|
def _clear_screen() -> None:
|
69
63
|
"""Clear the screen."""
|
70
64
|
get_app().renderer.clear()
|
65
|
+
|
66
|
+
|
67
|
+
@add_cmd(hidden=True, aliases=[""])
|
68
|
+
def _go_to(event: KeyPressEvent, index: int = 0) -> None:
|
69
|
+
"""Go to a line or cell by number."""
|
70
|
+
index = max(0, index - 1)
|
71
|
+
if buffer_has_focus():
|
72
|
+
buffer = get_app().current_buffer
|
73
|
+
buffer.cursor_position = len("".join(buffer.text.splitlines(True)[:index]))
|
74
|
+
elif tab_type_has_focus("euporie.notebook.tabs.notebook:Notebook")():
|
75
|
+
from euporie.notebook.tabs.notebook import Notebook
|
76
|
+
|
77
|
+
if isinstance(nb := get_app().tab, Notebook):
|
78
|
+
nb.select(index)
|
@@ -140,6 +140,8 @@ add_setting(
|
|
140
140
|
|
141
141
|
e.g.
|
142
142
|
|
143
|
+
.. code-block:: json
|
144
|
+
|
143
145
|
[
|
144
146
|
{"command": ["ruff", "format", "-"], "languages": ["python"]},
|
145
147
|
{"command": ["black", "-"], "languages": ["python"]},
|
@@ -281,6 +283,30 @@ add_setting(
|
|
281
283
|
""",
|
282
284
|
)
|
283
285
|
|
286
|
+
add_setting(
|
287
|
+
name="custom_styles",
|
288
|
+
group="euporie.core.style",
|
289
|
+
flags=["--custom-styles"],
|
290
|
+
type_=json.loads,
|
291
|
+
default={},
|
292
|
+
schema={
|
293
|
+
"type": "object",
|
294
|
+
},
|
295
|
+
help_="Additional style settings",
|
296
|
+
description="""
|
297
|
+
A JSON object mapping style names to prompt-toolkit style values.
|
298
|
+
|
299
|
+
The style keys used in euporie can be found in :py:func:`euporie.core.style.build_style`.
|
300
|
+
|
301
|
+
e.g.:
|
302
|
+
|
303
|
+
.. code-block:: json
|
304
|
+
|
305
|
+
{ "cell input prompt":"fg:purple", "cell output prompt": "fg:green" }
|
306
|
+
|
307
|
+
""",
|
308
|
+
)
|
309
|
+
|
284
310
|
add_setting(
|
285
311
|
name="key_bindings",
|
286
312
|
group="euporie.core.app.app",
|
@@ -288,19 +314,19 @@ add_setting(
|
|
288
314
|
type_=json.loads,
|
289
315
|
help_="Additional key binding definitions",
|
290
316
|
default={},
|
291
|
-
description="""
|
292
|
-
A mapping of component names to mappings of command name to key-binding lists.
|
293
|
-
""",
|
294
317
|
schema={
|
295
318
|
"type": "object",
|
296
319
|
},
|
320
|
+
description="""
|
321
|
+
A mapping of component names to mappings of command name to key-binding lists.
|
322
|
+
""",
|
297
323
|
)
|
298
324
|
|
299
325
|
add_setting(
|
300
326
|
name="graphics",
|
301
327
|
group="euporie.core.app.app",
|
302
328
|
flags=["--graphics"],
|
303
|
-
choices=["none", "sixel", "kitty", "iterm"],
|
329
|
+
choices=["none", "sixel", "kitty", "kitty-unicode", "iterm"],
|
304
330
|
type_=str,
|
305
331
|
default=None,
|
306
332
|
help_="The preferred graphics protocol",
|
@@ -375,6 +401,8 @@ add_setting(
|
|
375
401
|
description="""
|
376
402
|
Additional language servers can be defined here, e.g.:
|
377
403
|
|
404
|
+
.. code-block:: json
|
405
|
+
|
378
406
|
{
|
379
407
|
"ruff": {"command": ["ruff-lsp"], "languages": ["python"]},
|
380
408
|
"pylsp": {"command": ["pylsp"], "languages": ["python"]},
|
@@ -392,6 +420,8 @@ add_setting(
|
|
392
420
|
empty dictionary. For example, the following would disable the awk language
|
393
421
|
server:
|
394
422
|
|
423
|
+
.. code-block:: json
|
424
|
+
|
395
425
|
{
|
396
426
|
"awk-language-server": {},
|
397
427
|
}
|
@@ -520,14 +520,17 @@ class BaseApp(ConfigurableApp, Application, ABC):
|
|
520
520
|
@classmethod
|
521
521
|
def launch(cls) -> None:
|
522
522
|
"""Launch the app."""
|
523
|
+
from prompt_toolkit.utils import in_main_thread
|
524
|
+
|
523
525
|
super().launch()
|
524
526
|
# Run the application
|
525
527
|
with create_app_session(input=cls.load_input(), output=cls.load_output()):
|
526
528
|
# Create an instance of the app and run it
|
527
529
|
app = cls()
|
528
|
-
|
529
|
-
|
530
|
-
|
530
|
+
if in_main_thread():
|
531
|
+
# Handle SIGTERM while the app is running
|
532
|
+
original_sigterm = signal.getsignal(signal.SIGTERM)
|
533
|
+
signal.signal(signal.SIGTERM, app.cleanup)
|
531
534
|
# Set and run the app
|
532
535
|
with set_app(app):
|
533
536
|
try:
|
@@ -535,7 +538,8 @@ class BaseApp(ConfigurableApp, Application, ABC):
|
|
535
538
|
except (EOFError, KeyboardInterrupt):
|
536
539
|
result = None
|
537
540
|
finally:
|
538
|
-
|
541
|
+
if in_main_thread():
|
542
|
+
signal.signal(signal.SIGTERM, original_sigterm)
|
539
543
|
# Shut down any remaining LSP clients at exit
|
540
544
|
app.shutdown_lsps()
|
541
545
|
return result
|
@@ -582,14 +586,16 @@ class BaseApp(ConfigurableApp, Application, ABC):
|
|
582
586
|
path_mime = get_mime(path) or "text/plain"
|
583
587
|
log.debug("File %s has mime type: %s", path, path_mime)
|
584
588
|
|
585
|
-
|
589
|
+
# Use a set to automatically handle duplicates
|
590
|
+
tab_options: set[TabRegistryEntry] = set()
|
586
591
|
for entry in self.tab_registry:
|
587
592
|
for mime_type in entry.mime_types:
|
588
593
|
if PurePath(path_mime).match(mime_type):
|
589
|
-
tab_options.
|
594
|
+
tab_options.add(entry)
|
590
595
|
if path.suffix in entry.file_extensions:
|
591
|
-
tab_options.
|
596
|
+
tab_options.add(entry)
|
592
597
|
|
598
|
+
# Sort by weight (TabRegistryEntry.__lt__ handles this)
|
593
599
|
return sorted(tab_options, reverse=True)
|
594
600
|
|
595
601
|
def get_file_tab(self, path: Path) -> type[Tab] | None:
|
@@ -791,6 +797,13 @@ class BaseApp(ConfigurableApp, Application, ABC):
|
|
791
797
|
syntax_theme = "tango" if self.color_palette.bg.is_light else "euporie"
|
792
798
|
return syntax_theme
|
793
799
|
|
800
|
+
base_styles = (
|
801
|
+
Style(MIME_STYLE),
|
802
|
+
Style(HTML_STYLE),
|
803
|
+
Style(LOG_STYLE),
|
804
|
+
Style(IPYWIDGET_STYLE),
|
805
|
+
)
|
806
|
+
|
794
807
|
def create_merged_style(self) -> BaseStyle:
|
795
808
|
"""Generate a new merged style for the application.
|
796
809
|
|
@@ -801,6 +814,11 @@ class BaseApp(ConfigurableApp, Application, ABC):
|
|
801
814
|
Return a combined style to use for the application
|
802
815
|
|
803
816
|
"""
|
817
|
+
styles: list[BaseStyle] = [
|
818
|
+
style_from_pygments_cls(get_style_by_name(self.syntax_theme)),
|
819
|
+
*self.base_styles,
|
820
|
+
]
|
821
|
+
|
804
822
|
# Get foreground and background colors based on the configured colour scheme
|
805
823
|
theme_colors: dict[str, dict[str, str]] = {
|
806
824
|
"default": {},
|
@@ -844,7 +862,7 @@ class BaseApp(ConfigurableApp, Application, ABC):
|
|
844
862
|
)
|
845
863
|
|
846
864
|
# Build app style
|
847
|
-
|
865
|
+
styles.append(build_style(cp))
|
848
866
|
|
849
867
|
# Apply style transformations based on the configured color scheme
|
850
868
|
self.style_transformation = merge_style_transformations(
|
@@ -862,16 +880,11 @@ class BaseApp(ConfigurableApp, Application, ABC):
|
|
862
880
|
]
|
863
881
|
)
|
864
882
|
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
Style(LOG_STYLE),
|
871
|
-
Style(IPYWIDGET_STYLE),
|
872
|
-
app_style,
|
873
|
-
]
|
874
|
-
)
|
883
|
+
# Add user style customizations
|
884
|
+
if custom_style_dict := self.config.custom_styles:
|
885
|
+
styles.append(Style.from_dict(custom_style_dict))
|
886
|
+
|
887
|
+
return merge_styles(styles)
|
875
888
|
|
876
889
|
def update_style(self, query: Setting | None = None) -> None:
|
877
890
|
"""Update the application's style when the syntax theme is changed."""
|