lets-plot 4.8.1rc1__cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.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 (97) hide show
  1. lets_plot/__init__.py +382 -0
  2. lets_plot/_global_settings.py +192 -0
  3. lets_plot/_kbridge.py +197 -0
  4. lets_plot/_type_utils.py +133 -0
  5. lets_plot/_version.py +6 -0
  6. lets_plot/bistro/__init__.py +16 -0
  7. lets_plot/bistro/_plot2d_common.py +106 -0
  8. lets_plot/bistro/corr.py +448 -0
  9. lets_plot/bistro/im.py +196 -0
  10. lets_plot/bistro/joint.py +192 -0
  11. lets_plot/bistro/qq.py +207 -0
  12. lets_plot/bistro/residual.py +341 -0
  13. lets_plot/bistro/waterfall.py +332 -0
  14. lets_plot/export/__init__.py +6 -0
  15. lets_plot/export/ggsave_.py +172 -0
  16. lets_plot/frontend_context/__init__.py +8 -0
  17. lets_plot/frontend_context/_configuration.py +140 -0
  18. lets_plot/frontend_context/_dynamic_configure_html.py +115 -0
  19. lets_plot/frontend_context/_frontend_ctx.py +16 -0
  20. lets_plot/frontend_context/_html_contexts.py +223 -0
  21. lets_plot/frontend_context/_intellij_python_json_ctx.py +38 -0
  22. lets_plot/frontend_context/_isolated_webview_panel_ctx.py +81 -0
  23. lets_plot/frontend_context/_json_contexts.py +39 -0
  24. lets_plot/frontend_context/_jupyter_notebook_ctx.py +82 -0
  25. lets_plot/frontend_context/_mime_types.py +7 -0
  26. lets_plot/frontend_context/_static_html_page_ctx.py +76 -0
  27. lets_plot/frontend_context/_static_svg_ctx.py +26 -0
  28. lets_plot/frontend_context/_webbr_html_page_ctx.py +29 -0
  29. lets_plot/frontend_context/sandbox.py +5 -0
  30. lets_plot/geo_data/__init__.py +19 -0
  31. lets_plot/geo_data/core.py +335 -0
  32. lets_plot/geo_data/geocoder.py +988 -0
  33. lets_plot/geo_data/geocodes.py +512 -0
  34. lets_plot/geo_data/gis/__init__.py +0 -0
  35. lets_plot/geo_data/gis/fluent_dict.py +201 -0
  36. lets_plot/geo_data/gis/geocoding_service.py +42 -0
  37. lets_plot/geo_data/gis/geometry.py +91 -0
  38. lets_plot/geo_data/gis/json_request.py +232 -0
  39. lets_plot/geo_data/gis/json_response.py +308 -0
  40. lets_plot/geo_data/gis/request.py +492 -0
  41. lets_plot/geo_data/gis/response.py +247 -0
  42. lets_plot/geo_data/livemap_helper.py +65 -0
  43. lets_plot/geo_data/to_geo_data_frame.py +141 -0
  44. lets_plot/geo_data/type_assertion.py +34 -0
  45. lets_plot/geo_data_internals/__init__.py +4 -0
  46. lets_plot/geo_data_internals/constants.py +13 -0
  47. lets_plot/geo_data_internals/utils.py +33 -0
  48. lets_plot/mapping.py +115 -0
  49. lets_plot/package_data/lets-plot.min.js +3 -0
  50. lets_plot/plot/__init__.py +64 -0
  51. lets_plot/plot/_global_theme.py +14 -0
  52. lets_plot/plot/annotation.py +290 -0
  53. lets_plot/plot/coord.py +242 -0
  54. lets_plot/plot/core.py +1071 -0
  55. lets_plot/plot/expand_limits_.py +78 -0
  56. lets_plot/plot/facet.py +210 -0
  57. lets_plot/plot/font_features.py +71 -0
  58. lets_plot/plot/geom.py +9146 -0
  59. lets_plot/plot/geom_extras.py +53 -0
  60. lets_plot/plot/geom_function_.py +219 -0
  61. lets_plot/plot/geom_imshow_.py +393 -0
  62. lets_plot/plot/geom_livemap_.py +343 -0
  63. lets_plot/plot/ggbunch_.py +96 -0
  64. lets_plot/plot/gggrid_.py +139 -0
  65. lets_plot/plot/ggtb_.py +81 -0
  66. lets_plot/plot/guide.py +231 -0
  67. lets_plot/plot/label.py +187 -0
  68. lets_plot/plot/marginal_layer.py +181 -0
  69. lets_plot/plot/plot.py +245 -0
  70. lets_plot/plot/pos.py +344 -0
  71. lets_plot/plot/sampling.py +338 -0
  72. lets_plot/plot/sandbox_.py +26 -0
  73. lets_plot/plot/scale.py +3580 -0
  74. lets_plot/plot/scale_colormap_mpl.py +300 -0
  75. lets_plot/plot/scale_convenience.py +155 -0
  76. lets_plot/plot/scale_identity_.py +653 -0
  77. lets_plot/plot/scale_position.py +1342 -0
  78. lets_plot/plot/series_meta.py +209 -0
  79. lets_plot/plot/stat.py +585 -0
  80. lets_plot/plot/subplots.py +331 -0
  81. lets_plot/plot/subplots_util.py +24 -0
  82. lets_plot/plot/theme_.py +790 -0
  83. lets_plot/plot/theme_set.py +418 -0
  84. lets_plot/plot/tooltip.py +486 -0
  85. lets_plot/plot/util.py +267 -0
  86. lets_plot/settings_utils.py +244 -0
  87. lets_plot/tilesets.py +429 -0
  88. lets_plot-4.8.1rc1.dist-info/METADATA +221 -0
  89. lets_plot-4.8.1rc1.dist-info/RECORD +97 -0
  90. lets_plot-4.8.1rc1.dist-info/WHEEL +6 -0
  91. lets_plot-4.8.1rc1.dist-info/licenses/LICENSE +21 -0
  92. lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.FreeType +166 -0
  93. lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.ImageMagick +106 -0
  94. lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.expat +21 -0
  95. lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.fontconfig +200 -0
  96. lets_plot-4.8.1rc1.dist-info/top_level.txt +2 -0
  97. lets_plot_kotlin_bridge.cpython-311-x86_64-linux-gnu.so +0 -0
@@ -0,0 +1,172 @@
1
+ # Copyright (c) 2020. JetBrains s.r.o.
2
+ # Use of this source code is governed by the MIT license that can be found in the LICENSE file.
3
+
4
+ import os
5
+ from os.path import join
6
+ from typing import Union, Optional
7
+
8
+ from ..plot.core import PlotSpec
9
+ from ..plot.core import _to_svg, _to_html, _to_mvg, _export_as_raster
10
+ from ..plot.plot import GGBunch
11
+ from ..plot.subplots import SupPlotsSpec
12
+
13
+ __all__ = ['ggsave']
14
+
15
+ _DEF_EXPORT_DIR = "lets-plot-images"
16
+
17
+
18
+ def ggsave(plot: Union[PlotSpec, SupPlotsSpec, GGBunch], filename: str, *, path: str = None, iframe: bool = True,
19
+ scale: float = None, w: Optional[float] = None, h: Optional[float] = None, unit: Optional[str] = None,
20
+ dpi: Optional[int] = None) -> str:
21
+ """
22
+ Export plot to a file.
23
+ Supported formats: PNG, SVG, PDF, HTML.
24
+
25
+ The exported file is created in the directory ${user.dir}/lets-plot-images
26
+ if not specified otherwise (see the ``path`` parameter).
27
+
28
+ Parameters
29
+ ----------
30
+ plot : ``PlotSpec``
31
+ Plot specification to export.
32
+ filename : str
33
+ Name of the file. It must end with a file extension corresponding
34
+ to one of the supported formats: SVG, HTML (or HTM), PNG, PDF (requires the pillow library).
35
+ path : str
36
+ Path to a directory to save image files in.
37
+ By default, it is ${user.dir}/lets-plot-images.
38
+ iframe : bool, default=True
39
+ Whether to wrap the HTML page into an iFrame.
40
+ Only applicable when exporting to HTML.
41
+ Some browsers may not display some UTF-8 characters correctly when setting iframe=True
42
+ scale : float, default=2.0
43
+ Scaling factor for raster output.
44
+ Only applicable when exporting to PNG or PDF.
45
+ w : float, default=None
46
+ Width of the output image in units.
47
+ Only applicable when exporting to SVG, PNG, or PDF.
48
+ h : float, default=None
49
+ Height of the output image in units.
50
+ Only applicable when exporting to SVG, PNG, or PDF.
51
+ unit : {'in', 'cm', 'mm', 'px'}, default='in'
52
+ Unit of the output image. One of: 'in', 'cm', 'mm' or 'px'.
53
+ Only applicable when exporting to SVG, PNG, or PDF.
54
+ dpi : int, default=300
55
+ Resolution in dots per inch.
56
+ Only applicable when exporting to PNG or PDF.
57
+ The default value depends on the unit:
58
+
59
+ - for 'px' it is 96 (output image will have the same pixel size as ``w``, and ``h`` values)
60
+ - for physical units ('in', 'cm', 'mm') it is 300.
61
+
62
+ Returns
63
+ -------
64
+ str
65
+ Absolute pathname of the created file.
66
+
67
+ Notes
68
+ -----
69
+ Large plot dimensions without units require explicit unit specification.
70
+ When ``w`` or ``h`` value exceeds 20 without specifying units (e.g., ``ggsave(p, 300, 400)``),
71
+ we ask to specify units explicitly:
72
+ ``ggsave(p, 300, 400, unit='px')`` or ``ggsave(p, 3, 4, unit='in')``.
73
+
74
+ ----
75
+
76
+ The output format is inferred from the filename extension.
77
+
78
+ For PNG, and PDF formats:
79
+
80
+ - If ``w``, ``h``, ``unit``, and ``dpi`` are all specified:
81
+
82
+ - The plot's pixel size (default or set by `ggsize() <https://lets-plot.org/python/pages/api/lets_plot.ggsize.html>`__) is ignored.
83
+ - The output size is calculated using the specified ``w``, ``h``, ``unit`` and ``dpi``.
84
+
85
+ - The plot is resized to fit the specified ``w`` x ``h`` area, which may affect the layout, tick labels, and other elements.
86
+
87
+ - If only ``dpi`` is specified:
88
+
89
+ - The plot's pixel size (default or set by `ggsize() <https://lets-plot.org/python/pages/api/lets_plot.ggsize.html>`__) is converted to inches using the standard display PPI of 96.
90
+ - The output size is then calculated based on the specified DPI.
91
+
92
+ - The plot maintains its aspect ratio, preserving layout, tick labels, and other visual elements.
93
+ - Useful for printing - the plot will appear nearly the same size as on screen.
94
+
95
+ - If ``w``, ``h`` are not specified:
96
+
97
+ - The ``scale`` parameter is used to determine the output size.
98
+
99
+ - The plot maintains its aspect ratio, preserving layout, tick labels, and other visual elements.
100
+ - Useful for generating high-resolution images suitable for publication.
101
+
102
+ For SVG format:
103
+
104
+ - If ``w``, ``h``, and ``unit`` are specified:
105
+
106
+ - The plot's pixel size (default or set by `ggsize() <https://lets-plot.org/python/pages/api/lets_plot.ggsize.html>`__) is ignored.
107
+ - The output size is calculated using the specified ``w``, ``h``, and ``unit``.
108
+
109
+ ----
110
+
111
+ Plots with ``geom_livemap()`` can be saved to HTML only.
112
+
113
+
114
+ Examples
115
+ --------
116
+ .. jupyter-execute::
117
+ :linenos:
118
+ :emphasize-lines: 6
119
+
120
+ from IPython.display import Image
121
+ from lets_plot import *
122
+ LetsPlot.setup_html()
123
+ filename = 'plot.png'
124
+ plot = ggplot() + geom_point(x=0, y=0) + ggtitle(filename)
125
+ fullpath = ggsave(plot, filename, w=4, h=3)
126
+ Image(filename=fullpath, width=600, height=450)
127
+
128
+ |
129
+
130
+ .. jupyter-execute::
131
+ :linenos:
132
+ :emphasize-lines: 6
133
+
134
+ from IPython.display import HTML
135
+ from lets_plot import *
136
+ LetsPlot.setup_html()
137
+ filename = 'plot.html'
138
+ plot = ggplot() + geom_point(x=0, y=0) + ggtitle(filename)
139
+ fullpath = ggsave(plot, filename, iframe=False)
140
+ HTML(filename=fullpath)
141
+
142
+ """
143
+
144
+ if not (isinstance(plot, PlotSpec) or isinstance(plot, SupPlotsSpec) or isinstance(plot, GGBunch)):
145
+ raise ValueError("PlotSpec, SupPlotsSpec or GGBunch expected but was: {}".format(type(plot)))
146
+
147
+ filename = filename.strip()
148
+ name, ext = os.path.splitext(filename)
149
+
150
+ if not name:
151
+ raise ValueError("Malformed filename: '{}'.".format(filename))
152
+ if not ext:
153
+ raise ValueError("Missing file extension: '{}'.".format(filename))
154
+
155
+ if not path:
156
+ path = join(os.getcwd(), _DEF_EXPORT_DIR)
157
+
158
+ pathname = join(path, filename)
159
+
160
+ ext = ext[1:].lower()
161
+ if ext == 'svg':
162
+ return _to_svg(plot, pathname, w=w, h=h, unit=unit)
163
+ elif ext in ['html', 'htm']:
164
+ return _to_html(plot, pathname, iframe=iframe)
165
+ elif ext in ['png', 'pdf']:
166
+ return _export_as_raster(plot, pathname, scale, export_format=ext, w=w, h=h, unit=unit, dpi=dpi)
167
+ elif ext == 'mvg':
168
+ return _to_mvg(plot, pathname, scale, w=w, h=h, unit=unit, dpi=dpi)
169
+ else:
170
+ raise ValueError(
171
+ "Unsupported file extension: '{}'\nPlease use one of: 'png', 'svg', 'pdf', 'html', 'htm'".format(ext)
172
+ )
@@ -0,0 +1,8 @@
1
+ #
2
+ # Copyright (c) 2019. JetBrains s.r.o.
3
+ # Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4
+ #
5
+
6
+ from ._configuration import *
7
+
8
+ __all__ = _configuration.__all__
@@ -0,0 +1,140 @@
1
+ #
2
+ # Copyright (c) 2019. JetBrains s.r.o.
3
+ # Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4
+ #
5
+ from typing import Dict, Any
6
+
7
+ from ._frontend_ctx import FrontendContext
8
+ from ._html_contexts import _create_html_frontend_context, _create_wb_html_frontend_context
9
+ from ._json_contexts import _create_json_frontend_context, _is_Intellij_Python_Lets_Plot_Plugin
10
+ from ._mime_types import TEXT_HTML, LETS_PLOT_JSON
11
+ from ._static_svg_ctx import StaticSvgImageContext
12
+ from ._webbr_html_page_ctx import WebBrHtmlPageContext
13
+ from .._version import __version__
14
+ from ..plot.core import PlotSpec
15
+ from ..plot.plot import GGBunch
16
+ from ..plot.subplots import SupPlotsSpec
17
+
18
+ __all__ = []
19
+
20
+ _frontend_contexts: Dict[str, FrontendContext] = {}
21
+
22
+ _default_mimetype = TEXT_HTML
23
+ if _is_Intellij_Python_Lets_Plot_Plugin():
24
+ _default_mimetype = LETS_PLOT_JSON
25
+ _frontend_contexts[LETS_PLOT_JSON] = _create_json_frontend_context()
26
+
27
+
28
+ def _setup_html_context(*,
29
+ isolated_frame: bool = None,
30
+ offline: bool,
31
+ no_js: bool,
32
+ show_status: bool,
33
+ dev_options: Dict = None) -> None:
34
+ """
35
+ Configures Lets-Plot HTML output.
36
+ See the docstring in `setup_html()` for details on parameters.
37
+ """
38
+ global _default_mimetype
39
+ if _default_mimetype == LETS_PLOT_JSON:
40
+ # Plots will be rendered by Lets-Plot IntelliJ plugin.
41
+ # But still create HTML context in case it's necessary.
42
+ if show_status:
43
+ print(
44
+ 'Lets-Plot v{}: output mimetype {} configured by default. No need for HTML output.'.format(__version__,
45
+ LETS_PLOT_JSON))
46
+
47
+ if no_js:
48
+ ctx = StaticSvgImageContext()
49
+ else:
50
+ ctx = _create_html_frontend_context(isolated_frame, offline=offline, dev_options=dev_options)
51
+
52
+ ctx.configure(verbose=show_status)
53
+ _frontend_contexts[TEXT_HTML] = ctx
54
+
55
+
56
+ def _setup_wb_html_context(*,
57
+ exec: str,
58
+ new: bool) -> None:
59
+ """
60
+ Configures Lets-Plot HTML output for showing in a browser.
61
+
62
+ Parameters
63
+ ----------
64
+ exec : str, optional
65
+ Command to execute to open the plot in a web browser.
66
+ If not specified, the default browser will be used.
67
+ new : bool, default=False
68
+ If True, the URL is opened in a new window of the web browser.
69
+ If False, the URL is opened in the already opened web browser window.
70
+ """
71
+ ctx = _create_wb_html_frontend_context(exec, new)
72
+ _frontend_contexts[TEXT_HTML] = ctx
73
+
74
+
75
+ def _display_plot(spec: Any):
76
+ """
77
+ Draw plot or `bunch` of plots in the current frontend context
78
+ :param spec: PlotSpec or GGBunch object
79
+ """
80
+ if not (isinstance(spec, PlotSpec) or isinstance(spec, SupPlotsSpec) or isinstance(spec, GGBunch)):
81
+ raise ValueError("PlotSpec or SupPlotsSpec expected but was: {}".format(type(spec)))
82
+
83
+ if _default_mimetype == TEXT_HTML:
84
+ ctx = _frontend_contexts.get(TEXT_HTML)
85
+
86
+ if ctx is not None and isinstance(ctx, WebBrHtmlPageContext):
87
+ ctx.show(spec.as_dict())
88
+ return
89
+
90
+ # If ctx is None, _as_html() will try to initialize the context lazily
91
+ plot_html = _as_html(spec.as_dict())
92
+ try:
93
+ from IPython.display import display_html
94
+ display_html(plot_html, raw=True)
95
+ return
96
+ except ImportError:
97
+ pass
98
+
99
+ print(spec.as_dict())
100
+ return
101
+
102
+ if _default_mimetype == LETS_PLOT_JSON:
103
+ _frontend_contexts[LETS_PLOT_JSON].show(spec.as_dict())
104
+ return
105
+
106
+ # fallback to plain text.
107
+ print(spec.as_dict())
108
+
109
+
110
+ def _as_html(plot_spec: Dict) -> str:
111
+ """
112
+ Creates plot HTML using 'html' frontend context.
113
+
114
+ :param plot_spec: dict
115
+ """
116
+ ctx = _frontend_contexts.get(TEXT_HTML)
117
+
118
+ if ctx is None:
119
+ # Set up HTML context lazily
120
+ _setup_html_context(isolated_frame=None,
121
+ offline=False,
122
+ no_js=False,
123
+ show_status=False)
124
+
125
+ ctx = _frontend_contexts[TEXT_HTML]
126
+
127
+ # Check if this context allows lazy set-up.
128
+ requires_configure = getattr(ctx, 'requires_configure', False)
129
+ if requires_configure:
130
+ # Clear the context and return an error message
131
+ _frontend_contexts[TEXT_HTML] = None
132
+ return """\
133
+ <div style="color:darkred;">
134
+ Lets-plot `html` is not configured.<br>
135
+ Try to use `LetsPlot.setup_html()` before first occurrence of plot.
136
+ </div>
137
+ """
138
+
139
+ # Generate "display" HTML
140
+ return ctx.as_str(plot_spec)
@@ -0,0 +1,115 @@
1
+ #
2
+ # Copyright (c) 2025. JetBrains s.r.o.
3
+ # Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4
+ #
5
+ import os
6
+ import pkgutil
7
+ import random
8
+ import string
9
+
10
+ from .._global_settings import get_js_cdn_url
11
+
12
+ # Data-attributes used to store extra information about the meaning of 'script' elements
13
+ _ATT_SCRIPT_KIND = 'data-lets-plot-script'
14
+ _SCRIPT_KIND_LIB_LOADING = 'library'
15
+
16
+
17
+ def generate_dynamic_configure_html(offline: bool, verbose: bool) -> str:
18
+ """
19
+ Generate HTML for dynamic loading of lets-plot.js library.
20
+
21
+ Parameters
22
+ ----------
23
+ offline : bool
24
+ If True, embeds the JS library directly. If False, loads from CDN.
25
+ verbose : bool
26
+ If True, shows success/error messages to the user.
27
+
28
+ Returns
29
+ -------
30
+ str
31
+ HTML string that loads the lets-plot.js library and sets up the dynamic loading mechanism.
32
+ """
33
+ if offline:
34
+ return _configure_embedded_script(verbose)
35
+ else:
36
+ return _configure_connected_script(verbose)
37
+
38
+
39
+ def _configure_connected_script(verbose: bool) -> str:
40
+ """Generate HTML that loads lets-plot.js from CDN."""
41
+ url = get_js_cdn_url()
42
+ output_id = _rand_string()
43
+ success_message = """
44
+ var div = document.createElement("div");
45
+ div.style.color = 'darkblue';
46
+ div.textContent = 'Lets-Plot JS successfully loaded.';
47
+ document.getElementById("{id}").appendChild(div);
48
+ """.format(id=output_id) if verbose else ""
49
+
50
+ return """
51
+ <div id="{id}"></div>
52
+ <script type="text/javascript" {data_attr}="{script_kind}">
53
+ if(!window.letsPlotCallQueue) {{
54
+ window.letsPlotCallQueue = [];
55
+ }};
56
+ window.letsPlotCall = function(f) {{
57
+ window.letsPlotCallQueue.push(f);
58
+ }};
59
+ (function() {{
60
+ var script = document.createElement("script");
61
+ script.type = "text/javascript";
62
+ script.src = "{url}";
63
+ script.onload = function() {{
64
+ window.letsPlotCall = function(f) {{f();}};
65
+ window.letsPlotCallQueue.forEach(function(f) {{f();}});
66
+ window.letsPlotCallQueue = [];
67
+ {success_message}
68
+ }};
69
+ script.onerror = function(event) {{
70
+ window.letsPlotCall = function(f) {{}}; // noop
71
+ window.letsPlotCallQueue = [];
72
+ var div = document.createElement("div");
73
+ div.style.color = 'darkred';
74
+ div.textContent = 'Error loading Lets-Plot JS';
75
+ document.getElementById("{id}").appendChild(div);
76
+ }};
77
+ var e = document.getElementById("{id}");
78
+ e.appendChild(script);
79
+ }})()
80
+ </script>
81
+ """.format(
82
+ data_attr=_ATT_SCRIPT_KIND,
83
+ script_kind=_SCRIPT_KIND_LIB_LOADING,
84
+ id=output_id,
85
+ url=url,
86
+ success_message=success_message)
87
+
88
+
89
+ def _configure_embedded_script(verbose: bool) -> str:
90
+ """Generate HTML that embeds lets-plot.js directly."""
91
+ js_name = "lets-plot.min.js"
92
+ path = os.path.join("package_data", js_name)
93
+ js_code = pkgutil.get_data("lets_plot", path).decode("utf-8")
94
+ success_message = '<div style="color:darkblue;">Lets-Plot JS is embedded.</div>' if verbose else ""
95
+
96
+ return """
97
+ <script type="text/javascript" {data_attr}="{script_kind}">
98
+ window.letsPlotCall = function(f) {{f();}};
99
+ console.log('Embedding: {js_name}');
100
+ {js_code}
101
+ </script>
102
+ {success_message}
103
+ """.format(
104
+ data_attr=_ATT_SCRIPT_KIND,
105
+ script_kind=_SCRIPT_KIND_LIB_LOADING,
106
+ js_code=js_code,
107
+ js_name=js_name,
108
+ success_message=success_message)
109
+
110
+
111
+ def _rand_string(size=6) -> str:
112
+ """Generate a random string for unique element IDs."""
113
+ alphabet = string.ascii_letters + string.digits
114
+ # noinspection PyShadowingBuiltins
115
+ return ''.join([random.choice(alphabet) for _ in range(size)])
@@ -0,0 +1,16 @@
1
+ #
2
+ # Copyright (c) 2019. JetBrains s.r.o.
3
+ # Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4
+ #
5
+ from typing import Dict
6
+
7
+
8
+ class FrontendContext:
9
+ def configure(self, verbose: bool):
10
+ pass
11
+
12
+ def as_str(self, plot_spec: Dict) -> str:
13
+ pass
14
+
15
+ def show(self, plot_spec: Dict) -> str:
16
+ pass
@@ -0,0 +1,223 @@
1
+ # Copyright (c) 2020. JetBrains s.r.o.
2
+ # Use of this source code is governed by the MIT license that can be found in the LICENSE file.
3
+
4
+ import os
5
+
6
+ from ._frontend_ctx import FrontendContext
7
+ from ._isolated_webview_panel_ctx import IsolatedWebviewPanelContext
8
+ from ._jupyter_notebook_ctx import JupyterNotebookContext
9
+ from ._static_html_page_ctx import StaticHtmlPageContext
10
+ from ._webbr_html_page_ctx import WebBrHtmlPageContext
11
+ from .._global_settings import has_global_value, get_global_bool, HTML_ISOLATED_FRAME
12
+
13
+
14
+ def _create_html_frontend_context(
15
+ isolated_frame: bool = None,
16
+ offline: bool = None,
17
+ dev_options: dict = None) -> FrontendContext:
18
+ """
19
+ Configures Lets-Plot HTML output.
20
+ See the docstring in `setup_html()` for details on parameters.
21
+ """
22
+
23
+ if dev_options is None:
24
+ dev_options = {}
25
+ else:
26
+ dev_options = dev_options.copy()
27
+
28
+ # Extract and remove isolated_webview_panel from dev_options
29
+ isolated_webview_panel = dev_options.pop('isolated_webview_panel', None)
30
+
31
+ if isolated_webview_panel is None:
32
+ isolated_webview_panel = _is_positron_console()
33
+
34
+ if isolated_webview_panel:
35
+ return IsolatedWebviewPanelContext(offline, **dev_options)
36
+
37
+ if isolated_frame is None:
38
+ isolated_frame = _use_isolated_frame()
39
+
40
+ if isolated_frame:
41
+ return StaticHtmlPageContext(offline, **dev_options)
42
+ else:
43
+ return JupyterNotebookContext(offline, **dev_options)
44
+
45
+
46
+ def _create_wb_html_frontend_context(exec: str, new: bool) -> FrontendContext:
47
+ """
48
+ Configures Lets-Plot HTML output for showing in a web browser.
49
+
50
+ Parameters
51
+ ----------
52
+ exec : str, optional
53
+ The name of the web browser to use.
54
+ If not specified, the default browser will be used.
55
+ new : bool, default=False
56
+ If True, the URL is opened in a new window of the web browser.
57
+ If False, the URL is opened in the already opened web browser window.
58
+ """
59
+ return WebBrHtmlPageContext(exec, new)
60
+
61
+
62
+ def _use_isolated_frame() -> bool:
63
+ # check environment
64
+ if has_global_value(HTML_ISOLATED_FRAME):
65
+ return get_global_bool(HTML_ISOLATED_FRAME)
66
+
67
+ # return _detect_isolated_frame()
68
+ if not _is_IPython_display():
69
+ return True # fallback to a complete HTML page in the output
70
+
71
+ # Some notebooks behave like a single HTML page where the JS library is loaded once per notebook.
72
+ if (_is_jupyter_classic() or
73
+ _is_kaggle() or
74
+ _is_positron_notebook()):
75
+ return False # no iframes in the output cell
76
+
77
+ # Most online notebook platforms are showing cell output in iframe and require
78
+ # a complete HTML page in the output which includes both:
79
+ # - the script loading JS library and
80
+ # - the script that uses this JS lib to create a plot.
81
+
82
+ if (_is_google_colab() or
83
+ _is_azure_notebook() or
84
+ _is_deepnote() or
85
+ _is_databricks() or
86
+ _is_nextjournal()
87
+ ):
88
+ return True # complete HTML page in the output
89
+
90
+ # if os.getenv("PLOTLY_RENDERER") == "colab":
91
+ # # good enough - something colab-like
92
+ # return True # Colab -> iframe
93
+
94
+ # try:
95
+ # shell = get_ipython().__class__.__name__
96
+ # if shell == 'ZMQInteractiveShell':
97
+ # return False # Jupyter notebook or qtconsole -> load JS librarty once per notebook
98
+ # elif shell == 'TerminalInteractiveShell':
99
+ # return True # Terminal running IPython -> an isolated HTML page to show somehow
100
+ # else:
101
+ # return True # Other type (?)
102
+ # except NameError:
103
+ # return True # some other env (even standard Python interpreter) -> an isolated HTML page to show somehow
104
+
105
+ # Fallback to a complete HTML page in the output
106
+ return True
107
+
108
+
109
+ # def _detect_isolated_frame() -> bool:
110
+ # if not _is_IPython_display():
111
+ # return True # fallback to a complete HTML page in the output
112
+ #
113
+ # # Some notebooks behave like a single HTML page where the JS library is loaded once per notebook.
114
+ # if (_is_jupyter_classic() or
115
+ # _is_kaggle() or
116
+ # _is_positron_notebook()):
117
+ # return False # no iframes in the output cell
118
+ #
119
+ # # Most online notebook platforms are showing cell output in iframe and require
120
+ # # a complete HTML page in the output which includes both:
121
+ # # - the script loading JS library and
122
+ # # - the script that uses this JS lib to create a plot.
123
+ #
124
+ # if (_is_google_colab() or
125
+ # _is_azure_notebook() or
126
+ # _is_deepnote() or
127
+ # _is_databricks() or
128
+ # _is_nextjournal()
129
+ # ):
130
+ # return True # complete HTML page in the output
131
+ #
132
+ # # if os.getenv("PLOTLY_RENDERER") == "colab":
133
+ # # # good enough - something colab-like
134
+ # # return True # Colab -> iframe
135
+ #
136
+ # # try:
137
+ # # shell = get_ipython().__class__.__name__
138
+ # # if shell == 'ZMQInteractiveShell':
139
+ # # return False # Jupyter notebook or qtconsole -> load JS librarty once per notebook
140
+ # # elif shell == 'TerminalInteractiveShell':
141
+ # # return True # Terminal running IPython -> an isolated HTML page to show somehow
142
+ # # else:
143
+ # # return True # Other type (?)
144
+ # # except NameError:
145
+ # # return True # some other env (even standard Python interpreter) -> an isolated HTML page to show somehow
146
+ #
147
+ # # Fallback to a complete HTML page in the output
148
+ # return True
149
+
150
+
151
+ def _is_IPython_display() -> bool:
152
+ try:
153
+ from IPython.display import display_html
154
+ return True
155
+ except ImportError:
156
+ return False
157
+
158
+
159
+ def _is_jupyter_classic() -> bool:
160
+ # This also detects JupyterLab, which uses the same ZMQInteractiveShell
161
+ # and also qtconsole (allegedly)
162
+ try:
163
+ from IPython import get_ipython
164
+ except ImportError:
165
+ return False
166
+ shell = get_ipython()
167
+ try:
168
+ return shell is not None and shell.__class__.__name__ == "ZMQInteractiveShell"
169
+ except AttributeError:
170
+ return False
171
+
172
+
173
+ def _is_google_colab() -> bool:
174
+ try:
175
+ import google.colab
176
+ return True
177
+ except ImportError:
178
+ return False
179
+
180
+
181
+ def _is_kaggle() -> bool:
182
+ return os.path.exists("/kaggle/input")
183
+
184
+
185
+ def _is_azure_notebook() -> bool:
186
+ return "AZURE_NOTEBOOKS_HOST" in os.environ
187
+
188
+
189
+ def _is_deepnote() -> bool:
190
+ return "DEEPNOTE_PROJECT_ID" in os.environ
191
+
192
+
193
+ def _is_databricks() -> bool:
194
+ # As proposed: https://github.com/JetBrains/lets-plot/issues/602
195
+ return "databricks" in str(os.environ)
196
+
197
+
198
+ def _is_nextjournal() -> bool:
199
+ return "NEXTJOURNAL" in str(os.environ)
200
+
201
+
202
+ def _is_positron_console():
203
+ try:
204
+ from IPython import get_ipython
205
+ except ImportError:
206
+ return False
207
+ shell = get_ipython()
208
+ try:
209
+ return shell is not None and shell.session_mode == "console"
210
+ except AttributeError:
211
+ return False
212
+
213
+
214
+ def _is_positron_notebook():
215
+ try:
216
+ from IPython import get_ipython
217
+ except ImportError:
218
+ return False
219
+ shell = get_ipython()
220
+ try:
221
+ return shell is not None and shell.session_mode == "notebook"
222
+ except AttributeError:
223
+ return False