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
@@ -9,16 +9,12 @@ from typing import TYPE_CHECKING, NamedTuple
9
9
  from prompt_toolkit.filters import Condition
10
10
  from prompt_toolkit.layout.containers import (
11
11
  ConditionalContainer,
12
- DynamicContainer,
13
12
  )
14
13
  from prompt_toolkit.layout.dimension import Dimension
15
14
 
15
+ from euporie.core.app.current import get_app
16
16
  from euporie.core.commands import add_cmd
17
- from euporie.core.convert.datum import Datum
18
- from euporie.core.convert.formats import BASE64_FORMATS
19
- from euporie.core.convert.mime import MIME_FORMATS
20
17
  from euporie.core.convert.registry import find_route
21
- from euporie.core.current import get_app
22
18
  from euporie.core.filters import pager_has_focus
23
19
  from euporie.core.key_binding.registry import (
24
20
  load_registered_bindings,
@@ -67,6 +63,10 @@ class PagerOutputDataElement(CellOutputDataElement):
67
63
  metadata: Any metadata relating to the data
68
64
  parent: The parent container the output-element is attached to
69
65
  """
66
+ from euporie.core.convert.datum import Datum
67
+ from euporie.core.convert.formats import BASE64_FORMATS
68
+ from euporie.core.convert.mime import MIME_FORMATS
69
+
70
70
  # Get internal format
71
71
  format_ = "ansi"
72
72
  mime_path = PurePath(mime)
@@ -139,11 +139,7 @@ class Pager:
139
139
  collapse=False,
140
140
  style="class:pager.border",
141
141
  ),
142
- Box(
143
- DynamicContainer(lambda: self.output),
144
- padding=0,
145
- padding_left=1,
146
- ),
142
+ Box(self.output, padding=0, padding_left=1),
147
143
  ],
148
144
  style="class:pager",
149
145
  key_bindings=load_registered_bindings(
@@ -14,15 +14,15 @@ from prompt_toolkit.layout.containers import ScrollOffsets
14
14
  from prompt_toolkit.layout.controls import UIContent, UIControl
15
15
  from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
16
16
 
17
+ from euporie.core.app.current import get_app
18
+ from euporie.core.bars.status import StatusContainer
17
19
  from euporie.core.commands import Command, add_cmd, commands
18
- from euporie.core.current import get_app
19
20
  from euporie.core.key_binding.registry import register_bindings
20
21
  from euporie.core.layout.containers import HSplit, VSplit, Window
21
22
  from euporie.core.layout.decor import FocusedStyle
22
23
  from euporie.core.margins import MarginContainer, ScrollbarMargin
23
24
  from euporie.core.widgets.dialog import Dialog
24
25
  from euporie.core.widgets.forms import Text
25
- from euporie.core.widgets.status import StatusContainer
26
26
 
27
27
  if TYPE_CHECKING:
28
28
  from prompt_toolkit.buffer import Buffer
@@ -31,8 +31,8 @@ if TYPE_CHECKING:
31
31
  from prompt_toolkit.key_binding.key_processor import KeyPressEvent
32
32
  from prompt_toolkit.layout.controls import GetLinePrefixCallable
33
33
 
34
- from euporie.core.app import BaseApp
35
- from euporie.core.widgets.status import StatusBarFields
34
+ from euporie.core.app.app import BaseApp
35
+ from euporie.core.bars.status import StatusBarFields
36
36
 
37
37
  log = logging.getLogger(__name__)
38
38
 
@@ -242,7 +242,7 @@ class CommandPalette(Dialog):
242
242
  regex = re.compile(
243
243
  "(?=({}))".format(".*?".join(map(re.escape, buffer.text))), re.IGNORECASE
244
244
  )
245
- for cmd in commands.values():
245
+ for cmd in set(commands.values()):
246
246
  if not cmd.hidden():
247
247
  matches = list(regex.finditer(cmd.title))
248
248
  if matches:
@@ -298,7 +298,7 @@ class CommandPalette(Dialog):
298
298
 
299
299
  register_bindings(
300
300
  {
301
- "euporie.core.app.BaseApp": {
301
+ "euporie.core.app.app:BaseApp": {
302
302
  "show-command-palette": "c-@",
303
303
  }
304
304
  }
euporie/hub/app.py CHANGED
@@ -4,7 +4,6 @@ from __future__ import annotations
4
4
 
5
5
  import logging
6
6
  from asyncio import get_event_loop
7
- from importlib.metadata import entry_points
8
7
  from typing import TYPE_CHECKING
9
8
 
10
9
  try:
@@ -18,16 +17,31 @@ except ModuleNotFoundError as err:
18
17
  from prompt_toolkit.contrib.ssh import PromptToolkitSSHSession
19
18
  from upath import UPath
20
19
 
21
- from euporie.core.app import BaseApp
20
+ from euporie.core.__main__ import available_apps
21
+ from euporie.core.app import APP_ALIASES
22
+ from euporie.core.app.base import ConfigurableApp
22
23
  from euporie.core.config import add_setting
23
- from euporie.core.log import setup_logs
24
24
 
25
25
  if TYPE_CHECKING:
26
- from typing import Awaitable
26
+ from collections.abc import Awaitable
27
+ from typing import Any, ClassVar
28
+
29
+ from euporie.core.app.app import BaseApp
27
30
 
28
31
  log = logging.getLogger(__name__)
29
32
 
30
33
 
34
+ def _euporie_hub_app_choices() -> list[str]:
35
+ """List known euporie-apps and their aliases."""
36
+ from euporie.core.__main__ import available_apps
37
+ from euporie.core.app import APP_ALIASES
38
+
39
+ return sorted(
40
+ {entry.name for entry in available_apps().values()} - {"launch", "hub"}
41
+ | APP_ALIASES.keys()
42
+ )
43
+
44
+
31
45
  class EuporieSSHServer(asyncssh.SSHServer): # type: ignore
32
46
  """Launch euporie hub, which serves a euporie app over SSH.
33
47
 
@@ -53,7 +67,7 @@ class EuporieSSHServer(asyncssh.SSHServer): # type: ignore
53
67
  return PromptToolkitSSHSession(self.app_cls.interact, enable_cpr=True) # type: ignore [call-arg]
54
68
 
55
69
 
56
- class HubApp(BaseApp):
70
+ class HubApp(ConfigurableApp):
57
71
  """Hub App.
58
72
 
59
73
  An app which runs as a multi-user SSH server.
@@ -62,25 +76,21 @@ class HubApp(BaseApp):
62
76
  """
63
77
 
64
78
  name = "hub"
65
-
66
- @classmethod
67
- def launch(cls) -> None:
68
- """Launch the HubApp SSH server."""
69
- # Default logging configuration
70
- setup_logs()
71
-
72
- # Configure some setting defaults
73
- cls.config.settings["log_file"].value = "-"
74
- cls.config.settings["log_level"].value = "info"
75
- cls.config.settings["log_config"].value = """
79
+ _config_defaults: ClassVar[dict[str, Any]] = {
80
+ "log_level_stdout": "info",
81
+ "log_config": """
76
82
  {
77
83
  "handlers": { "stdout": {"share_stream": false} },
78
84
  "loggers": { "asyncssh": { "handlers":["stdout"], "level": "DEBUG" } }
79
85
  }
80
- """
86
+ """,
87
+ }
81
88
 
82
- # Load the app's configuration
83
- cls.config.load(cls)
89
+ @classmethod
90
+ def launch(cls) -> None:
91
+ """Launch the HubApp SSH server."""
92
+ # Configure some setting defaults
93
+ super().launch()
84
94
 
85
95
  if not cls.config.auth:
86
96
  log.warning(
@@ -88,17 +98,16 @@ class HubApp(BaseApp):
88
98
  "meaning anyone can connect"
89
99
  )
90
100
 
101
+ # Detect selected app
102
+ chosen_app = cls.config.hub_app
103
+ chosen_app = APP_ALIASES.get(chosen_app, chosen_app)
104
+
91
105
  # Import the hubbed app
92
- eps = entry_points()
93
- if isinstance(eps, dict):
94
- points = eps.get("euporie.apps")
95
- else:
96
- points = eps.select(group="euporie.apps")
97
- apps = {x.name: x for x in points} if points else {}
98
- if entry_point := apps.get(cls.config.app):
99
- app_cls = entry_point.load()
106
+ apps = available_apps()
107
+ if entry := apps.get(chosen_app):
108
+ app_cls = entry.load()
100
109
  else:
101
- raise ValueError("Application `%s` not found", cls.config.app)
110
+ raise ModuleNotFoundError("Application `%s` not found", cls.config.app)
102
111
 
103
112
  # Run the HubApp in an SSH server
104
113
  loop = get_event_loop()
@@ -112,24 +121,28 @@ class HubApp(BaseApp):
112
121
  )
113
122
  )
114
123
  log.info("Running euporie hub on port %s", cls.config.port)
115
- loop.run_forever()
124
+ try:
125
+ loop.run_forever()
126
+ except KeyboardInterrupt:
127
+ log.info("Exiting euporie hub")
116
128
 
117
129
  # ################################### Settings ####################################
118
130
 
119
131
  add_setting(
120
- name="app",
121
- flags=["--app"],
122
- default="notebook",
132
+ name="hub_app",
133
+ group="euporie.hub.app",
134
+ flags=["hub_app"],
123
135
  type_=str,
124
- choices=["notebook", "console"],
125
- help_="App to run under euporie hub",
136
+ help_="The application to launch",
137
+ choices=_euporie_hub_app_choices,
126
138
  description="""
127
- Determine which euporie app should be launched under euporie hub.
139
+ The name of the application to launch.
128
140
  """,
129
141
  )
130
142
 
131
143
  add_setting(
132
144
  name="host",
145
+ group="euporie.hub.app",
133
146
  flags=["--host"],
134
147
  type_=str,
135
148
  help_="The host address to bind to",
@@ -141,6 +154,7 @@ class HubApp(BaseApp):
141
154
 
142
155
  add_setting(
143
156
  name="port",
157
+ group="euporie.hub.app",
144
158
  flags=["--port"],
145
159
  type_=int,
146
160
  help_="The port for the ssh server to use",
@@ -157,6 +171,7 @@ class HubApp(BaseApp):
157
171
 
158
172
  add_setting(
159
173
  name="host_keys",
174
+ group="euporie.hub.app",
160
175
  flags=["--host-keys"],
161
176
  nargs="*",
162
177
  type_=UPath,
@@ -176,6 +191,7 @@ class HubApp(BaseApp):
176
191
 
177
192
  add_setting(
178
193
  name="client_keys",
194
+ group="euporie.hub.app",
179
195
  flags=["--client-keys"],
180
196
  nargs="*",
181
197
  type_=UPath,
@@ -196,6 +212,7 @@ class HubApp(BaseApp):
196
212
 
197
213
  add_setting(
198
214
  name="auth",
215
+ group="euporie.hub.app",
199
216
  flags=["--auth"],
200
217
  type_=bool,
201
218
  help_="Allow unauthenticated access to euporie hub",
@@ -0,0 +1,24 @@
1
+ """Commands for the notebook app."""
2
+
3
+ from euporie.core.commands import add_cmd
4
+
5
+
6
+ @add_cmd(aliases=["n"])
7
+ def _new_notebook() -> None:
8
+ """Create a new file."""
9
+ from euporie.notebook.current import get_app
10
+ from euporie.notebook.tabs.notebook import Notebook
11
+
12
+ app = get_app()
13
+ app.add_tab(tab := Notebook(app, None))
14
+ tab.focus()
15
+
16
+
17
+ @add_cmd()
18
+ def _view_documentation() -> None:
19
+ """Open the documentation in a web-view tab."""
20
+ from upath import UPath
21
+
22
+ from euporie.core.app.current import get_app
23
+
24
+ get_app().open_file(UPath("https://euporie.readthedocs.io/"))
@@ -0,0 +1,107 @@
1
+ """Define settings for the notebook app."""
2
+
3
+ from euporie.core.config import add_setting
4
+ from euporie.notebook.enums import TabMode
5
+
6
+ add_setting(
7
+ name="tab_mode",
8
+ group="euporie.notebook.app",
9
+ flags=["--tab-mode"],
10
+ type_=str,
11
+ choices=[mode.value for mode in TabMode],
12
+ default="stack",
13
+ help_="The method used to display multiple tabs",
14
+ description="""
15
+ Determines how multiple tabs are displayed when more than one tab is open.
16
+ * ``stack`` displays one tab at a time with a tab-bar
17
+ * ``tile_horizontally`` displays tabs side-by-side
18
+ * ``tile_vertically`` displays tabs one-atop-the-next
19
+ """,
20
+ )
21
+
22
+ add_setting(
23
+ name="always_show_tab_bar",
24
+ group="euporie.notebook.app",
25
+ flags=["--always-show-tab-bar"],
26
+ type_=bool,
27
+ help_="Always show the tab bar",
28
+ default=False,
29
+ description="""
30
+ When set, the tab bar will always be shown - otherwise the tab bar is only
31
+ shown when multiple tabs are open.
32
+ """,
33
+ )
34
+
35
+ add_setting(
36
+ name="background_pattern",
37
+ group="euporie.notebook.app",
38
+ flags=["--background-pattern", "--bg-pattern"],
39
+ type_=int,
40
+ choices=list(range(6)),
41
+ help_="The background pattern to use",
42
+ default=2,
43
+ schema={
44
+ "minimum": 0,
45
+ "maximum": 5,
46
+ },
47
+ description="""
48
+ The background pattern to use when the notebook is narrower than the
49
+ available width. Zero mean no pattern is used.
50
+ """,
51
+ )
52
+
53
+ add_setting(
54
+ name="background_character",
55
+ group="euporie.notebook.app",
56
+ flags=["--background-character", "--bg-char"],
57
+ type_=str,
58
+ help_="Character for background pattern",
59
+ default="·",
60
+ schema={
61
+ "maxLength": 1,
62
+ },
63
+ description="""
64
+ The character to use when drawing the background pattern.
65
+
66
+ Recommended characters include: "·", "⬤", "╳", "╱", "╲", "░", "▒", "▓", "▞", "╬"
67
+ """, # ,
68
+ )
69
+
70
+ add_setting(
71
+ name="run_after_external_edit",
72
+ group="euporie.notebook.app",
73
+ flags=["--run-after-external-edit"],
74
+ type_=bool,
75
+ help_="Run cells after editing externally",
76
+ default=False,
77
+ description="""
78
+ Whether to execute a cell immediately after editing in `$EDITOR`.
79
+ """,
80
+ )
81
+
82
+ add_setting(
83
+ name="run",
84
+ group="euporie.notebook.app",
85
+ flags=["--run"],
86
+ type_=bool,
87
+ help_="Run the notebook files when loaded",
88
+ default=False,
89
+ description="""
90
+ If set, notebooks will be run automatically when opened, or if previewing a
91
+ file, the notebooks will be run before being output.
92
+ """,
93
+ )
94
+
95
+ add_setting(
96
+ name="show_top_bar",
97
+ group="euporie.notebook.app",
98
+ flags=["--show-top-bar"],
99
+ type_=bool,
100
+ title="top bar",
101
+ help_="Show the top bar",
102
+ default=True,
103
+ schema={"type": "boolean"},
104
+ description="""
105
+ Whether the top bar should be shown at the top of the screen.
106
+ """,
107
+ )