cuiman 0.2.0.dev1__py3-none-any.whl → 0.2.1.dev1__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.
@@ -6,6 +6,7 @@ from abc import ABC, abstractmethod
6
6
  from typing import TYPE_CHECKING, Literal
7
7
 
8
8
  from cuiman.api.ishell import has_ishell
9
+ from cuiman.app.serve import ProxyMode
9
10
 
10
11
  from .config import ClientConfig
11
12
 
@@ -32,6 +33,7 @@ class ClientAppMixin(ABC):
32
33
  width: int | str = "100%",
33
34
  height: int | str = 600,
34
35
  display: Literal["browser", "notebook", "auto"] = "auto",
36
+ proxy: ProxyMode = "auto",
35
37
  ) -> "App":
36
38
  """
37
39
  Show the Cuiman app for this client.
@@ -77,6 +79,9 @@ class ClientAppMixin(ABC):
77
79
  height: Height of the notebook iframe.
78
80
  display: Where to show the app. ``"auto"`` embeds it in notebooks
79
81
  and opens it in a browser otherwise.
82
+ proxy: Whether notebook traffic uses ``jupyter-server-proxy``. ``"auto"``
83
+ uses it when available, ``"never"`` disables it, and ``"always"``
84
+ requires it.
80
85
  Return:
81
86
  An ``App`` instance.
82
87
  """
@@ -99,6 +104,7 @@ class ClientAppMixin(ABC):
99
104
  width=width,
100
105
  height=height,
101
106
  display=display_,
107
+ proxy=proxy,
102
108
  )
103
109
 
104
110
  return App(remote_store, serve_result)
cuiman/app/display.py CHANGED
@@ -5,28 +5,45 @@
5
5
  from __future__ import annotations
6
6
 
7
7
  import json
8
+ from importlib import resources
8
9
 
9
10
  from IPython.display import HTML, DisplayObject
10
11
 
12
+ _NOTEBOOK_DISPLAY_SCRIPT = (
13
+ resources.files("cuiman.app")
14
+ .joinpath("notebook-display.js")
15
+ .read_text(encoding="utf-8")
16
+ )
17
+
11
18
 
12
19
  def create_app_display_object(
13
20
  app_url: str,
21
+ *,
14
22
  auto_scheme: bool,
15
23
  width: int | str,
16
24
  height: int | str,
25
+ proxy_port: int | None = None,
26
+ proxy_app: bool = False,
27
+ auto_proxy: bool = False,
28
+ open_in_browser: bool = False,
17
29
  ) -> DisplayObject:
18
- if auto_scheme:
19
- return _get_iframe_auto_scheme_html(
20
- app_url,
21
- width=width,
22
- height=height,
23
- )
24
- else:
25
- return _get_iframe_html(
30
+ """Create the notebook display object for the Cuiman app."""
31
+ if auto_scheme or proxy_port is not None or open_in_browser:
32
+ return _get_iframe_script_html(
26
33
  app_url,
34
+ auto_scheme=auto_scheme,
27
35
  width=width,
28
36
  height=height,
37
+ proxy_port=proxy_port,
38
+ proxy_app=proxy_app,
39
+ auto_proxy=auto_proxy,
40
+ open_in_browser=open_in_browser,
29
41
  )
42
+ return _get_iframe_html(
43
+ app_url,
44
+ width=width,
45
+ height=height,
46
+ )
30
47
 
31
48
 
32
49
  def _get_iframe_html(
@@ -46,60 +63,37 @@ def _get_iframe_html(
46
63
  """)
47
64
 
48
65
 
49
- def _get_iframe_auto_scheme_html(
66
+ def _get_iframe_script_html(
50
67
  base_src: str,
51
68
  *,
69
+ auto_scheme: bool,
52
70
  width: int | str,
53
71
  height: int | str,
72
+ proxy_port: int | None,
73
+ proxy_app: bool,
74
+ auto_proxy: bool,
75
+ open_in_browser: bool,
54
76
  ) -> HTML:
77
+ config = {
78
+ "baseSrc": base_src,
79
+ "autoScheme": auto_scheme,
80
+ "width": _norm_size(width),
81
+ "height": _norm_size(height),
82
+ "proxyPort": proxy_port,
83
+ "proxyApp": proxy_app,
84
+ "autoProxy": auto_proxy,
85
+ "openInBrowser": open_in_browser,
86
+ }
87
+ config_json = json.dumps(config, separators=(",", ":")).replace("<", "\\u003c")
88
+
89
+ # Inline the package resource so notebook output needs no additional asset URL.
55
90
  return HTML(f"""
56
91
  <div class="eozilla-frame-root"></div>
92
+ <script type="application/json" class="eozilla-frame-config">
93
+ {config_json}
94
+ </script>
57
95
  <script>
58
- (() => {{
59
- function detectJupyterScheme() {{
60
- const body = document.body;
61
- const root = document.documentElement;
62
-
63
- const themeLight =
64
- body.getAttribute("data-jp-theme-light") ??
65
- root.getAttribute("data-jp-theme-light");
66
-
67
- if (themeLight === "true") return "light";
68
- if (themeLight === "false") return "dark";
69
-
70
- const bg =
71
- getComputedStyle(root).getPropertyValue("--jp-layout-color0") ||
72
- getComputedStyle(body).backgroundColor;
73
-
74
- const match = bg.match(/\\d+/g);
75
- if (match && match.length >= 3) {{
76
- const [r, g, b] = match.slice(0, 3).map(Number);
77
- const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
78
- return luminance < 0.5 ? "dark" : "light";
79
- }}
80
-
81
- return null;
82
- }}
83
-
84
- const root = document.currentScript.previousElementSibling;
85
- const scheme = detectJupyterScheme();
86
- const src = new URL({json.dumps(base_src)}, window.location.href);
87
-
88
- if (scheme) {{
89
- src.searchParams.set("scheme", scheme);
90
- }}
91
-
92
- const iframe = document.createElement("iframe");
93
- iframe.src = src.toString();
94
- iframe.width = {json.dumps(_norm_size(width))};
95
- iframe.height = {json.dumps(_norm_size(height))};
96
- iframe.style.border = "0";
97
- iframe.style.width = {json.dumps(_norm_size(width))};
98
- iframe.style.height = {json.dumps(_norm_size(height))};
99
- iframe.allow = "clipboard-read; clipboard-write";
100
-
101
- root.replaceChildren(iframe);
102
- }})();
96
+ {_NOTEBOOK_DISPLAY_SCRIPT}
103
97
  </script>
104
98
  """)
105
99