Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Displaying plots in an external browser when executing code in the console #1024

Merged
merged 1 commit into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Displaying plots in an external browser when executing code in the co…
…nsole
  • Loading branch information
RYangazov committed Feb 23, 2024
commit 1ef55943db9b6def1343dac02618ba6c7f5c212a
3 changes: 2 additions & 1 deletion future_changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@
- Can't set None for coord limit [[#486](https://github.com/JetBrains/lets-plot/issues/486)].
- Scale limits don't work for bars/area [[LPK-219](https://github.com/JetBrains/lets-plot-kotlin/issues/219)], [[#978](https://github.com/JetBrains/lets-plot/issues/978)].
- No gridlines when axis_ontop=True [[#1012](https://github.com/JetBrains/lets-plot/issues/1012)].
- bar-plot: do not draw bar border adjacent to the axis [[#845](https://github.com/JetBrains/lets-plot/issues/845)].
- bar-plot: do not draw bar border adjacent to the axis [[#845](https://github.com/JetBrains/lets-plot/issues/845)].
- Displaying plots in an external browser when executing code in the console [[#738](https://github.com/JetBrains/lets-plot/issues/738)].
52 changes: 52 additions & 0 deletions python-package/lets_plot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,58 @@ class LetsPlot:
Initialize the library and its options.
"""

@classmethod
def setup_show_ext(cls, *,
exec: str = None,
new: bool = False) -> None:
"""
Configures Lets-Plot HTML output for showing in a browser.

Parameters
----------
exec : str, optional
Command to execute to open the plot in a web browser.
If not specified, the default browser will be used.
new : bool, default=False
If `True`, the URL is opened in a new window of the web browser.
If `False`, the URL is opened in the already opened web browser window.

Examples
--------
.. jupyter-execute::
:linenos:
:emphasize-lines: 2

from lets_plot import *
LetsPlot.setup_show_ext()
p = ggplot({'x': [0], 'y': [0]}, aes('x', 'y')) + geom_point()
p.show()

|

.. jupyter-execute::
:linenos:
:emphasize-lines: 2

from lets_plot import *
LetsPlot.setup_show_ext(exec = 'chrome.exe --app=%s')
p = ggplot({'x': [0], 'y': [0]}, aes('x', 'y')) + geom_point()
p.show()

|

.. jupyter-execute::
:linenos:
:emphasize-lines: 2

from lets_plot import *
LetsPlot.setup_show_ext(exec = 'open -a safari %s', new=True)
p = ggplot({'x': [0], 'y': [0]}, aes('x', 'y')) + geom_point()
p.show()

"""
cfg._setup_wb_html_context(exec=exec, new=new)

@classmethod
def setup_html(cls, *,
isolated_frame: bool = None,
Expand Down
27 changes: 25 additions & 2 deletions python-package/lets_plot/frontend_context/_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
from typing import Dict, Any

from ._frontend_ctx import FrontendContext
from ._html_contexts import _create_html_frontend_context, _use_isolated_frame
from ._html_contexts import _create_html_frontend_context, _use_isolated_frame, _create_wb_html_frontend_context
from ._json_contexts import _create_json_frontend_context, _is_Intellij_Python_Lets_Plot_Plugin
from ._mime_types import TEXT_HTML, LETS_PLOT_JSON
from ._static_svg_ctx import StaticSvgImageContext
from ._webbr_html_page_ctx import WebBrHtmlPageContext
from .._version import __version__
from ..plot.core import PlotSpec
from ..plot.plot import GGBunch
Expand Down Expand Up @@ -68,6 +69,25 @@ def _setup_html_context(*,
_frontend_contexts[TEXT_HTML] = ctx


def _setup_wb_html_context(*,
exec: str,
new: bool) -> None:
"""
Configures Lets-Plot HTML output for showing in a browser.

Parameters
----------
exec : str, optional
Command to execute to open the plot in a web browser.
If not specified, the default browser will be used.
new : bool, default=False
If `True`, the URL is opened in a new window of the web browser.
If `False`, the URL is opened in the already opened web browser window.
"""
ctx = _create_wb_html_frontend_context(exec, new)
_frontend_contexts[TEXT_HTML] = ctx


def _display_plot(spec: Any):
"""
Draw plot or `bunch` of plots in the current frontend context
Expand All @@ -77,6 +97,10 @@ def _display_plot(spec: Any):
raise ValueError("PlotSpec, SupPlotsSpec or GGBunch expected but was: {}".format(type(spec)))

if _default_mimetype == TEXT_HTML:
if isinstance(_frontend_contexts[TEXT_HTML], WebBrHtmlPageContext):
_frontend_contexts[TEXT_HTML].show(spec.as_dict())
return

plot_html = _as_html(spec.as_dict())
try:
from IPython.display import display_html
Expand All @@ -85,7 +109,6 @@ def _display_plot(spec: Any):
except ImportError:
pass

# ToDo: show HTML in a browser window.
print(spec.as_dict())
return

Expand Down
17 changes: 17 additions & 0 deletions python-package/lets_plot/frontend_context/_html_contexts.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from ._frontend_ctx import FrontendContext
from ._jupyter_notebook_ctx import JupyterNotebookContext
from ._static_html_page_ctx import StaticHtmlPageContext
from ._webbr_html_page_ctx import WebBrHtmlPageContext
from .._global_settings import has_global_value, get_global_bool, HTML_ISOLATED_FRAME


Expand Down Expand Up @@ -33,6 +34,22 @@ def _create_html_frontend_context(isolated_frame: bool = None, offline: bool = N
return JupyterNotebookContext(offline)


def _create_wb_html_frontend_context(exec: str, new: bool) -> FrontendContext:
"""
Configures Lets-Plot HTML output for showing in web browser.

Parameters
----------
exec : str, optional
The name of the web browser to use.
If not specified, the default browser will be used.
new : bool, default=False
If `True`, the URL is opened in a new window of the web browser.
If `False`, the URL is opened in the already opened web browser window.
"""
return WebBrHtmlPageContext(exec, new)


def _use_isolated_frame() -> bool:
# check environment
if has_global_value(HTML_ISOLATED_FRAME):
Expand Down
27 changes: 27 additions & 0 deletions python-package/lets_plot/frontend_context/_webbr_html_page_ctx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# Copyright (c) 2019. JetBrains s.r.o.
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.
#
import io
import webbrowser
import tempfile
from typing import Dict

from ._frontend_ctx import FrontendContext
from .. import _kbridge as kbr


class WebBrHtmlPageContext(FrontendContext):

def __init__(self, exec: str, new: bool) -> None:
super().__init__()
self.exec = exec
self.new = new

def show(self, plot_spec: Dict) -> str:
html_page = kbr._generate_static_html_page(plot_spec, iframe=False)

path = tempfile.NamedTemporaryFile(suffix=".html", delete=False).name
io.open(path, 'w').write(html_page)

webbrowser.get(self.exec).open('file:https://' + path, new=1 if self.new else 2)