euporie 2.8.4__py3-none-any.whl → 2.8.6__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.
Files changed (131) hide show
  1. euporie/console/_commands.py +143 -0
  2. euporie/console/_settings.py +58 -0
  3. euporie/console/app.py +25 -71
  4. euporie/console/tabs/console.py +58 -62
  5. euporie/core/__init__.py +1 -1
  6. euporie/core/__main__.py +28 -11
  7. euporie/core/_settings.py +109 -0
  8. euporie/core/app/__init__.py +3 -0
  9. euporie/core/app/_commands.py +95 -0
  10. euporie/core/app/_settings.py +457 -0
  11. euporie/core/{app.py → app/app.py} +212 -576
  12. euporie/core/app/base.py +51 -0
  13. euporie/core/{current.py → app/current.py} +13 -4
  14. euporie/core/app/cursor.py +35 -0
  15. euporie/core/app/dummy.py +12 -0
  16. euporie/core/app/launch.py +28 -0
  17. euporie/core/bars/__init__.py +11 -0
  18. euporie/core/bars/command.py +205 -0
  19. euporie/core/bars/menu.py +258 -0
  20. euporie/core/{widgets → bars}/search.py +20 -16
  21. euporie/core/{widgets → bars}/status.py +6 -23
  22. euporie/core/clipboard.py +19 -80
  23. euporie/core/comm/base.py +8 -6
  24. euporie/core/comm/ipywidgets.py +16 -7
  25. euporie/core/comm/registry.py +2 -1
  26. euporie/core/commands.py +10 -20
  27. euporie/core/completion.py +3 -2
  28. euporie/core/config.py +368 -341
  29. euporie/core/convert/__init__.py +0 -30
  30. euporie/core/convert/datum.py +116 -53
  31. euporie/core/convert/formats/__init__.py +31 -0
  32. euporie/core/convert/formats/ansi.py +9 -23
  33. euporie/core/convert/formats/common.py +11 -23
  34. euporie/core/convert/formats/html.py +45 -40
  35. euporie/core/convert/formats/pil.py +1 -1
  36. euporie/core/convert/formats/png.py +3 -5
  37. euporie/core/convert/formats/sixel.py +3 -3
  38. euporie/core/convert/registry.py +4 -6
  39. euporie/core/convert/utils.py +41 -4
  40. euporie/core/diagnostics.py +2 -2
  41. euporie/core/filters.py +98 -40
  42. euporie/core/format.py +2 -3
  43. euporie/core/ft/ansi.py +1 -1
  44. euporie/core/ft/html.py +12 -21
  45. euporie/core/ft/table.py +1 -3
  46. euporie/core/ft/utils.py +4 -1
  47. euporie/core/graphics.py +386 -133
  48. euporie/core/history.py +2 -2
  49. euporie/core/inspection.py +3 -2
  50. euporie/core/io.py +207 -28
  51. euporie/core/kernel/__init__.py +1 -0
  52. euporie/core/{kernel.py → kernel/client.py} +45 -108
  53. euporie/core/kernel/manager.py +114 -0
  54. euporie/core/key_binding/bindings/__init__.py +1 -8
  55. euporie/core/key_binding/bindings/basic.py +47 -7
  56. euporie/core/key_binding/bindings/completion.py +3 -8
  57. euporie/core/key_binding/bindings/micro.py +1 -6
  58. euporie/core/key_binding/bindings/mouse.py +2 -2
  59. euporie/core/key_binding/bindings/terminal.py +193 -0
  60. euporie/core/key_binding/key_processor.py +43 -2
  61. euporie/core/key_binding/registry.py +2 -0
  62. euporie/core/key_binding/utils.py +22 -2
  63. euporie/core/keys.py +7156 -93
  64. euporie/core/layout/cache.py +3 -3
  65. euporie/core/layout/containers.py +48 -4
  66. euporie/core/layout/decor.py +2 -2
  67. euporie/core/layout/mouse.py +1 -1
  68. euporie/core/layout/print.py +2 -1
  69. euporie/core/layout/scroll.py +39 -34
  70. euporie/core/log.py +76 -64
  71. euporie/core/lsp.py +118 -24
  72. euporie/core/margins.py +1 -1
  73. euporie/core/path.py +62 -13
  74. euporie/core/renderer.py +58 -17
  75. euporie/core/style.py +57 -39
  76. euporie/core/suggest.py +103 -85
  77. euporie/core/tabs/__init__.py +32 -0
  78. euporie/core/tabs/_settings.py +113 -0
  79. euporie/core/tabs/base.py +80 -470
  80. euporie/core/tabs/kernel.py +419 -0
  81. euporie/core/tabs/notebook.py +24 -101
  82. euporie/core/utils.py +92 -15
  83. euporie/core/validation.py +1 -1
  84. euporie/core/widgets/_settings.py +188 -0
  85. euporie/core/widgets/cell.py +19 -50
  86. euporie/core/widgets/cell_outputs.py +25 -36
  87. euporie/core/widgets/decor.py +11 -41
  88. euporie/core/widgets/dialog.py +62 -27
  89. euporie/core/widgets/display.py +12 -15
  90. euporie/core/widgets/file_browser.py +2 -23
  91. euporie/core/widgets/forms.py +8 -5
  92. euporie/core/widgets/inputs.py +13 -70
  93. euporie/core/widgets/layout.py +2 -1
  94. euporie/core/widgets/logo.py +49 -0
  95. euporie/core/widgets/menu.py +10 -8
  96. euporie/core/widgets/pager.py +6 -10
  97. euporie/core/widgets/palette.py +6 -6
  98. euporie/hub/app.py +52 -35
  99. euporie/notebook/_commands.py +24 -0
  100. euporie/notebook/_settings.py +107 -0
  101. euporie/notebook/app.py +49 -171
  102. euporie/notebook/filters.py +1 -1
  103. euporie/notebook/tabs/__init__.py +46 -7
  104. euporie/notebook/tabs/_commands.py +714 -0
  105. euporie/notebook/tabs/_settings.py +32 -0
  106. euporie/notebook/tabs/display.py +4 -4
  107. euporie/notebook/tabs/edit.py +11 -44
  108. euporie/notebook/tabs/json.py +5 -5
  109. euporie/notebook/tabs/log.py +1 -18
  110. euporie/notebook/tabs/notebook.py +11 -660
  111. euporie/notebook/widgets/_commands.py +11 -0
  112. euporie/notebook/widgets/_settings.py +19 -0
  113. euporie/notebook/widgets/side_bar.py +14 -34
  114. euporie/preview/_settings.py +104 -0
  115. euporie/preview/app.py +6 -31
  116. euporie/preview/tabs/notebook.py +6 -72
  117. euporie/web/__init__.py +1 -0
  118. euporie/web/tabs/__init__.py +14 -0
  119. euporie/web/tabs/web.py +11 -6
  120. euporie/web/widgets/__init__.py +1 -0
  121. euporie/web/widgets/webview.py +5 -15
  122. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/METADATA +10 -8
  123. euporie-2.8.6.dist-info/RECORD +175 -0
  124. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/WHEEL +1 -1
  125. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/entry_points.txt +2 -2
  126. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/licenses/LICENSE +1 -1
  127. euporie/core/launch.py +0 -64
  128. euporie/core/terminal.py +0 -522
  129. euporie-2.8.4.dist-info/RECORD +0 -147
  130. {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-console.desktop +0 -0
  131. {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-notebook.desktop +0 -0
@@ -0,0 +1,11 @@
1
+ """Define commands for widgets."""
2
+
3
+ from euporie.core.commands import add_cmd
4
+
5
+
6
+ @add_cmd()
7
+ def _toggle_side_bar_pane() -> None:
8
+ """Open or close the current side-bar pane."""
9
+ from euporie.notebook.current import get_app
10
+
11
+ get_app().side_bar.toggle_pane()
@@ -0,0 +1,19 @@
1
+ """Define settings for the notebook app widgets."""
2
+
3
+ from euporie.core.config import add_setting
4
+
5
+ add_setting(
6
+ name="show_side_bar",
7
+ group="euporie.notebook.widgets.side_bar",
8
+ flags=["--show-side-bar"],
9
+ type_=bool,
10
+ title="side-bar",
11
+ help_="Show the side-bar",
12
+ default=False,
13
+ schema={
14
+ "type": "boolean",
15
+ },
16
+ description="""
17
+ Whether the side-bar should be shown at the side of the screen.
18
+ """,
19
+ )
@@ -16,14 +16,12 @@ from prompt_toolkit.layout.containers import (
16
16
  )
17
17
  from prompt_toolkit.layout.controls import FormattedTextControl
18
18
 
19
- from euporie.core.commands import add_cmd
20
- from euporie.core.config import add_setting
21
19
  from euporie.core.key_binding.registry import register_bindings
22
20
  from euporie.core.layout.decor import Line
23
21
  from euporie.core.widgets.forms import ToggleButton, ToggleButtons
24
22
 
25
23
  if TYPE_CHECKING:
26
- from typing import Sequence
24
+ from collections.abc import Sequence
27
25
 
28
26
  from prompt_toolkit.layout.containers import AnyContainer
29
27
 
@@ -39,13 +37,22 @@ class SideBarButtons(ToggleButtons):
39
37
  else:
40
38
  return "class:side_bar,buttons,separator"
41
39
 
40
+ def _get_sep_char(self, i: int) -> str:
41
+ if self.index in {i, i - 1}:
42
+ return "▄"
43
+ return ""
44
+
42
45
  def load_container(self) -> AnyContainer:
43
46
  """Load the widget's container."""
44
47
  self.buttons: list[ToggleButton] = []
45
48
  children: list[AnyContainer] = []
46
49
  for i, (label, selected) in enumerate(zip(self.labels, self.mask)):
47
50
  children.append(
48
- Window(char="▄", height=1, style=partial(self._get_sep_style, i))
51
+ Window(
52
+ char=partial(self._get_sep_char, i),
53
+ height=1,
54
+ style=partial(self._get_sep_style, i),
55
+ )
49
56
  )
50
57
  button = ToggleButton(
51
58
  text=label,
@@ -60,7 +67,7 @@ class SideBarButtons(ToggleButtons):
60
67
  children.extend(
61
68
  [
62
69
  Window(
63
- char="▄",
70
+ char=partial(self._get_sep_char, i),
64
71
  height=1,
65
72
  style=partial(self._get_sep_style, len(self.options)),
66
73
  ),
@@ -85,7 +92,7 @@ class SideBar:
85
92
  panels: Sequence[AnyContainer],
86
93
  ) -> None:
87
94
  """Initialize a new side-bar object."""
88
- from euporie.core.current import get_app
95
+ from euporie.core.app.current import get_app
89
96
 
90
97
  self.side_bar_buttons = SideBarButtons(
91
98
  options=list(icons),
@@ -158,7 +165,7 @@ class SideBar:
158
165
  ],
159
166
  style="class:side_bar",
160
167
  ),
161
- filter=get_app().config.filter("show_side_bar"),
168
+ filter=get_app().config.filters.show_side_bar,
162
169
  )
163
170
 
164
171
  def toggle_pane(self) -> None:
@@ -172,33 +179,6 @@ class SideBar:
172
179
  """Return the side_bar's main container."""
173
180
  return self.container
174
181
 
175
- # ################################### Settings ####################################
176
-
177
- add_setting(
178
- name="show_side_bar",
179
- flags=["--show-side-bar"],
180
- type_=bool,
181
- title="side-bar",
182
- help_="Show the side-bar",
183
- default=False,
184
- schema={
185
- "type": "boolean",
186
- },
187
- description="""
188
- Whether the side-bar should be shown at the side of the screen.
189
- """,
190
- )
191
-
192
- # ################################### Commands ####################################
193
-
194
- @staticmethod
195
- @add_cmd()
196
- def _toggle_side_bar_pane() -> None:
197
- """Open or close the current side-bar pane."""
198
- from euporie.notebook.current import get_app
199
-
200
- get_app().side_bar.toggle_pane()
201
-
202
182
  # ################################# Key Bindings ##################################
203
183
 
204
184
  register_bindings(
@@ -0,0 +1,104 @@
1
+ """Define settings for the preview app."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+
7
+ from upath import UPath
8
+
9
+ from euporie.core.config import add_setting
10
+
11
+ log = logging.getLogger(__name__)
12
+
13
+
14
+ add_setting(
15
+ name="output_file",
16
+ group="euporie.preview.app",
17
+ flags=["--output-file"],
18
+ nargs="?",
19
+ default="-",
20
+ const="-",
21
+ type_=UPath,
22
+ help_="Output path when previewing file",
23
+ description="""
24
+ When set to a file path, the formatted output will be written to the
25
+ given path. If no value is given (or the default "-" is passed) output
26
+ will be printed to standard output.
27
+ """,
28
+ )
29
+
30
+ add_setting(
31
+ name="page",
32
+ group="euporie.preview.app",
33
+ flags=["--page"],
34
+ type_=bool,
35
+ help_="Pass output to pager",
36
+ default=False,
37
+ description="""
38
+ Whether to pipe output to the system pager when previewing a notebook.
39
+ """,
40
+ )
41
+
42
+
43
+ add_setting(
44
+ name="run",
45
+ group="euporie.preview.app",
46
+ flags=["--run"],
47
+ type_=bool,
48
+ help_="Run the notebook files when loaded",
49
+ default=False,
50
+ description="""
51
+ If set, notebooks will be run automatically when opened, or if previewing a
52
+ file, the notebooks will be run before being output.
53
+ """,
54
+ )
55
+
56
+ add_setting(
57
+ name="save",
58
+ group="euporie.preview.app",
59
+ flags=["--save"],
60
+ type_=bool,
61
+ help_="Save the notebook after running it",
62
+ default=False,
63
+ description="""
64
+ If set, notebooks will be saved after they have been run. This setting only
65
+ has any affect if the :option:`run` setting is active.
66
+ """,
67
+ )
68
+
69
+ add_setting(
70
+ name="show_filenames",
71
+ group="euporie.preview.app",
72
+ flags=["--show-filenames"],
73
+ type_=bool,
74
+ help_="Show the notebook filenames when previewing multiple notebooks",
75
+ default=False,
76
+ description="""
77
+ If set, the notebook filenames will be printed above each notebook's output
78
+ when multiple notebooks are being previewed.
79
+ """,
80
+ )
81
+
82
+ add_setting(
83
+ name="cell_start",
84
+ group="euporie.preview.app",
85
+ flags=["--cell-start"],
86
+ type_=int,
87
+ help_="The first cell to include in the preview",
88
+ default=None,
89
+ description="""
90
+ When set, only cells after the given cell index will be shown.
91
+ """,
92
+ )
93
+
94
+ add_setting(
95
+ name="cell_stop",
96
+ group="euporie.preview.app",
97
+ flags=["--cell-stop"],
98
+ type_=int,
99
+ help_="The last cell to include in the preview",
100
+ default=None,
101
+ description="""
102
+ When set, only cells before the given cell index will be shown.
103
+ """,
104
+ )
euporie/preview/app.py CHANGED
@@ -12,10 +12,9 @@ from typing import TYPE_CHECKING, cast
12
12
  from prompt_toolkit.layout.containers import DynamicContainer, FloatContainer, Window
13
13
  from prompt_toolkit.output.defaults import create_output
14
14
  from prompt_toolkit.output.vt100 import Vt100_Output
15
- from upath import UPath
16
15
 
17
- from euporie.core.app import BaseApp, get_app
18
- from euporie.core.config import add_setting
16
+ from euporie.core.app.app import BaseApp
17
+ from euporie.core.app.current import get_app
19
18
  from euporie.core.io import PseudoTTY
20
19
  from euporie.core.key_binding.registry import register_bindings
21
20
  from euporie.preview.tabs.notebook import PreviewNotebook
@@ -55,6 +54,7 @@ class PreviewApp(BaseApp):
55
54
  kwargs.setdefault("max_render_postpone_time", 0)
56
55
  kwargs.setdefault("min_redraw_interval", 0)
57
56
  kwargs.setdefault("extend_renderer_height", True)
57
+ kwargs.setdefault("enable_page_navigation_bindings", False)
58
58
  # Adjust options if we are paging output
59
59
  if self.config.page:
60
60
  kwargs.setdefault("set_title", False)
@@ -126,7 +126,7 @@ class PreviewApp(BaseApp):
126
126
  # Use a temporary file as display output if we are going to page the output
127
127
  from tempfile import TemporaryFile
128
128
 
129
- output_file = TemporaryFile("w+")
129
+ output_file = TemporaryFile("w+") # noqa: SIM115
130
130
  # Make this file look like a tty so we get colorful output
131
131
  output_file = cast("TextIO", PseudoTTY(output_file, isatty=True))
132
132
 
@@ -192,33 +192,8 @@ class PreviewApp(BaseApp):
192
192
  def _update_invalidate_events(self) -> None:
193
193
  """Do nothing, as we don't need invalidation events for the preview app."""
194
194
 
195
- # ################################### Settings ####################################
196
-
197
- add_setting(
198
- name="output_file",
199
- flags=["--output-file"],
200
- nargs="?",
201
- default="-",
202
- const="-",
203
- type_=UPath,
204
- help_="Output path when previewing file",
205
- description="""
206
- When set to a file path, the formatted output will be written to the
207
- given path. If no value is given (or the default "-" is passed) output
208
- will be printed to standard output.
209
- """,
210
- )
211
-
212
- add_setting(
213
- name="page",
214
- flags=["--page"],
215
- type_=bool,
216
- help_="Pass output to pager",
217
- default=False,
218
- description="""
219
- Whether to pipe output to the system pager when previewing a notebook.
220
- """,
221
- )
195
+ # def load_key_bindings(self) -> None:
196
+ # """Do no load any additional key-bindings for the preview app."""
222
197
 
223
198
  # ################################# Key Bindings ##################################
224
199
 
@@ -11,7 +11,6 @@ from prompt_toolkit.layout.containers import (
11
11
  )
12
12
  from prompt_toolkit.layout.dimension import Dimension
13
13
 
14
- from euporie.core.config import add_setting
15
14
  from euporie.core.layout.containers import VSplit, Window
16
15
  from euporie.core.layout.print import PrintingContainer
17
16
  from euporie.core.tabs.notebook import BaseNotebook
@@ -26,9 +25,9 @@ if TYPE_CHECKING:
26
25
  from prompt_toolkit.formatted_text.base import StyleAndTextTuples
27
26
  from prompt_toolkit.layout.containers import AnyContainer
28
27
 
29
- from euporie.core.app import BaseApp
28
+ from euporie.core.app.app import BaseApp
30
29
  from euporie.core.comm.base import Comm
31
- from euporie.core.kernel import Kernel
30
+ from euporie.core.kernel.client import Kernel
32
31
 
33
32
  log = logging.getLogger(__name__)
34
33
 
@@ -36,8 +35,6 @@ log = logging.getLogger(__name__)
36
35
  class PreviewNotebook(BaseNotebook):
37
36
  """A notebook tab which renders cells sequentially."""
38
37
 
39
- bg_init = False
40
-
41
38
  def __init__(
42
39
  self,
43
40
  app: BaseApp,
@@ -132,7 +129,7 @@ class PreviewNotebook(BaseNotebook):
132
129
  ):
133
130
  self.print_title()
134
131
 
135
- if not self.json["cells"]:
132
+ if not self.json.get("cells", []):
136
133
  log.error("No cells")
137
134
  self.app.print_text([("", "(No cells to display)\n")])
138
135
  self.app.close_tab(self)
@@ -165,13 +162,12 @@ class PreviewNotebook(BaseNotebook):
165
162
 
166
163
  def load_container(self) -> AnyContainer:
167
164
  """Load the notebook's main container."""
165
+ no_expand = ~self.app.config.filters.expand
168
166
  return PrintingContainer(
169
167
  [
170
168
  VSplit(
171
169
  [
172
- ConditionalContainer(
173
- Window(), filter=~self.app.config.filter("expand")
174
- ),
170
+ ConditionalContainer(Window(), filter=no_expand),
175
171
  Box(
176
172
  body=DynamicContainer(lambda: self.cell),
177
173
  padding=0,
@@ -179,70 +175,8 @@ class PreviewNotebook(BaseNotebook):
179
175
  preferred=self.app.config.max_notebook_width
180
176
  ),
181
177
  ),
182
- ConditionalContainer(
183
- Window(), filter=~self.app.config.filter("expand")
184
- ),
178
+ ConditionalContainer(Window(), filter=no_expand),
185
179
  ]
186
180
  )
187
181
  ]
188
182
  )
189
-
190
- # ################################### Settings ####################################
191
-
192
- add_setting(
193
- name="run",
194
- flags=["--run"],
195
- type_=bool,
196
- help_="Run the notebook files when loaded",
197
- default=False,
198
- description="""
199
- If set, notebooks will be run automatically when opened, or if previewing a
200
- file, the notebooks will be run before being output.
201
- """,
202
- )
203
-
204
- add_setting(
205
- name="save",
206
- flags=["--save"],
207
- type_=bool,
208
- help_="Save the notebook after running it",
209
- default=False,
210
- description="""
211
- If set, notebooks will be saved after they have been run. This setting only
212
- has any affect if the :option:`run` setting is active.
213
- """,
214
- )
215
-
216
- add_setting(
217
- name="show_filenames",
218
- flags=["--show-filenames"],
219
- type_=bool,
220
- help_="Show the notebook filenames when previewing multiple notebooks",
221
- default=False,
222
- description="""
223
- If set, the notebook filenames will be printed above each notebook's output
224
- when multiple notebooks are being previewed.
225
- """,
226
- )
227
-
228
- add_setting(
229
- name="cell_start",
230
- flags=["--cell-start"],
231
- type_=int,
232
- help_="The first cell to include in the preview",
233
- default=None,
234
- description="""
235
- When set, only cells after the given cell index will be shown.
236
- """,
237
- )
238
-
239
- add_setting(
240
- name="cell_stop",
241
- flags=["--cell-stop"],
242
- type_=int,
243
- help_="The last cell to include in the preview",
244
- default=None,
245
- description="""
246
- When set, only cells before the given cell index will be shown.
247
- """,
248
- )
@@ -0,0 +1 @@
1
+ """A euporie web viewer component."""
@@ -0,0 +1,14 @@
1
+ """Tabs for use in euporie notebook editor."""
2
+
3
+ from euporie.core.tabs import _TAB_REGISTRY, TabRegistryEntry
4
+
5
+ _TAB_REGISTRY.extend(
6
+ [
7
+ TabRegistryEntry(
8
+ path="euporie.web.tabs.web:WebTab",
9
+ name="Web Viewer",
10
+ mime_types={"text/html", "text/markdown"},
11
+ weight=2,
12
+ ),
13
+ ]
14
+ )
euporie/web/tabs/web.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import asyncio
5
6
  import logging
6
7
  from typing import TYPE_CHECKING
7
8
 
@@ -10,13 +11,12 @@ from prompt_toolkit.layout.containers import HSplit, VSplit
10
11
  from prompt_toolkit.layout.dimension import Dimension
11
12
  from upath import UPath
12
13
 
14
+ from euporie.core.app.current import get_app
13
15
  from euporie.core.convert.mime import get_mime
14
- from euporie.core.current import get_app
15
16
  from euporie.core.data_structures import DiBool
16
17
  from euporie.core.layout.decor import FocusedStyle
17
18
  from euporie.core.margins import MarginContainer, ScrollbarMargin
18
19
  from euporie.core.tabs.base import Tab
19
- from euporie.core.utils import run_in_thread_with_context
20
20
  from euporie.core.widgets.display import DisplayWindow
21
21
  from euporie.core.widgets.forms import Button, Text
22
22
  from euporie.web.widgets.webview import WebViewControl
@@ -27,8 +27,8 @@ if TYPE_CHECKING:
27
27
 
28
28
  from prompt_toolkit.layout.containers import AnyContainer
29
29
 
30
- from euporie.core.app import BaseApp
31
- from euporie.core.widgets.status import StatusBarFields
30
+ from euporie.core.app.app import BaseApp
31
+ from euporie.core.bars.status import StatusBarFields
32
32
 
33
33
  log = logging.getLogger(__name__)
34
34
 
@@ -45,14 +45,19 @@ class WebTab(Tab):
45
45
  super().__init__(app, path)
46
46
  self.status: Callable[[], StatusBarFields] | None = None
47
47
 
48
+ # self.container = self.load_container()
49
+
48
50
  def _load() -> None:
51
+ old_container = self.container
49
52
  self.container = self.load_container()
53
+ if self.app.layout.has_focus(old_container):
54
+ self.focus()
55
+ self.app.invalidate()
50
56
 
51
- run_in_thread_with_context(_load)
57
+ self._load_task = app.create_background_task(asyncio.to_thread(_load))
52
58
 
53
59
  def focus(self) -> None:
54
60
  """Focus the webview when this tab is focused."""
55
- super().focus()
56
61
  self.app.layout.focus(self.webview)
57
62
 
58
63
  @property
@@ -0,0 +1 @@
1
+ """Contain widgets used in the web viewer."""
@@ -17,10 +17,10 @@ from prompt_toolkit.mouse_events import MouseButton, MouseEvent, MouseEventType
17
17
  from prompt_toolkit.utils import Event
18
18
  from upath import UPath
19
19
 
20
+ from euporie.core.app.current import get_app
20
21
  from euporie.core.commands import add_cmd
21
22
  from euporie.core.convert.datum import Datum, get_loop
22
23
  from euporie.core.convert.mime import get_format
23
- from euporie.core.current import get_app
24
24
  from euporie.core.ft.html import HTML, Node
25
25
  from euporie.core.ft.utils import fragment_list_width, paste
26
26
  from euporie.core.graphics import GraphicProcessor
@@ -31,9 +31,10 @@ from euporie.core.key_binding.registry import (
31
31
  from euporie.core.path import parse_path
32
32
 
33
33
  if TYPE_CHECKING:
34
+ from collections.abc import Iterable
34
35
  from concurrent.futures._base import Future
35
36
  from pathlib import Path
36
- from typing import Any, Callable, Iterable
37
+ from typing import Any, Callable
37
38
 
38
39
  from prompt_toolkit.formatted_text.base import AnyFormattedText, StyleAndTextTuples
39
40
  from prompt_toolkit.key_binding.key_bindings import (
@@ -102,9 +103,6 @@ class WebViewControl(UIControl):
102
103
  self._dom_cache: FastDictCache[tuple[Path], HTML] = FastDictCache(
103
104
  get_value=self.get_dom, size=100
104
105
  )
105
- self._line_cache: FastDictCache[
106
- tuple[HTML, int, int], list[StyleAndTextTuples]
107
- ] = FastDictCache(get_value=self.get_lines, size=100_000)
108
106
  self._content_cache: FastDictCache = FastDictCache(self.get_content, size=1_000)
109
107
 
110
108
  self.load_url(url)
@@ -134,16 +132,14 @@ class WebViewControl(UIControl):
134
132
  if changed:
135
133
  self.on_cursor_position_changed.fire()
136
134
 
137
- def get_dom(self, url: Path, x: bool = False) -> HTML:
135
+ def get_dom(self, url: Path) -> HTML:
138
136
  """Load a HTML page as renderable formatted text."""
139
137
  markup = str(
140
138
  Datum(
141
139
  data=url.read_text(),
142
140
  format=(format_ := get_format(url, default="html")),
143
141
  path=url,
144
- ).convert(
145
- to="html",
146
- )
142
+ ).convert(to="html")
147
143
  )
148
144
  return HTML(
149
145
  markup=markup,
@@ -174,12 +170,6 @@ class WebViewControl(UIControl):
174
170
  return dom.title
175
171
  return ""
176
172
 
177
- def get_lines(
178
- self, dom: HTML, width: int, height: int, assets_loaded: bool = False
179
- ) -> list[StyleAndTextTuples]:
180
- """Render a HTML page as lines of formatted text."""
181
- return list(split_lines(dom.render(width, height)))
182
-
183
173
  def load_url(self, url: str | Path, **kwargs: Any) -> None:
184
174
  """Load a new URL."""
185
175
  save_to_history = kwargs.get("save_to_history", True)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: euporie
3
- Version: 2.8.4
3
+ Version: 2.8.6
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
@@ -13,15 +13,15 @@ Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Framework :: Jupyter
15
15
  Classifier: Programming Language :: Python
16
- Classifier: Programming Language :: Python :: 3.8
17
16
  Classifier: Programming Language :: Python :: 3.9
18
17
  Classifier: Programming Language :: Python :: 3.10
19
18
  Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
20
21
  Classifier: Programming Language :: Python :: Implementation :: CPython
21
22
  Classifier: Programming Language :: Python :: Implementation :: PyPy
22
23
  Classifier: Topic :: Scientific/Engineering
23
- Requires-Python: >=3.8
24
- Requires-Dist: aenum<=3.1.12,~=3.1
24
+ Requires-Python: >=3.9
25
25
  Requires-Dist: fastjsonschema~=2.15
26
26
  Requires-Dist: flatlatex~=0.15
27
27
  Requires-Dist: fsspec[http]>=2022.12.0
@@ -37,12 +37,12 @@ Requires-Dist: platformdirs~=3.5
37
37
  Requires-Dist: prompt-toolkit~=3.0.36
38
38
  Requires-Dist: pygments~=2.11
39
39
  Requires-Dist: pyperclip~=1.8
40
- Requires-Dist: sixelcrop~=0.1.8
40
+ Requires-Dist: sixelcrop~=0.1.9
41
41
  Requires-Dist: timg~=1.1.6
42
42
  Requires-Dist: typing-extensions~=4.5
43
43
  Requires-Dist: universal-pathlib~=0.2.1
44
44
  Provides-Extra: hub
45
- Requires-Dist: asyncssh~=2.10.1; extra == 'hub'
45
+ Requires-Dist: asyncssh~=2.18; extra == 'hub'
46
46
  Description-Content-Type: text/x-rst
47
47
 
48
48
  |logo|
@@ -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/>`_ (recommended) or ``pip``:
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