python-package/lets_plot/frontend_context/_html_contexts.py (97 lines of code) (raw):

# Copyright (c) 2020. JetBrains s.r.o. # Use of this source code is governed by the MIT license that can be found in the LICENSE file. import os from ._frontend_ctx import FrontendContext from ._isolated_webview_panel_ctx import IsolatedWebviewPanelContext 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 def _create_html_frontend_context( isolated_frame: bool = None, offline: bool = None, dev_options: dict = None) -> FrontendContext: """ Configures Lets-Plot HTML output. See the docstring in `setup_html()` for details on parameters. """ if dev_options is None: dev_options = {} else: dev_options = dev_options.copy() # Extract and remove isolated_webview_panel from dev_options isolated_webview_panel = dev_options.pop('isolated_webview_panel', None) if isolated_webview_panel is None: isolated_webview_panel = _is_positron_console() if isolated_webview_panel: return IsolatedWebviewPanelContext(offline, **dev_options) if isolated_frame is None: isolated_frame = _use_isolated_frame() if isolated_frame: return StaticHtmlPageContext(offline, **dev_options) else: return JupyterNotebookContext(offline, **dev_options) def _create_wb_html_frontend_context(exec: str, new: bool) -> FrontendContext: """ Configures Lets-Plot HTML output for showing in a 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): return get_global_bool(HTML_ISOLATED_FRAME) # return _detect_isolated_frame() if not _is_IPython_display(): return True # fallback to a complete HTML page in the output # Some notebooks behave like a single HTML page where the JS library is loaded once per notebook. if (_is_jupyter_classic() or _is_kaggle() or _is_positron_notebook()): return False # no iframes in the output cell # Most online notebook platforms are showing cell output in iframe and require # a complete HTML page in the output which includes both: # - the script loading JS library and # - the script that uses this JS lib to create a plot. if (_is_google_colab() or _is_azure_notebook() or _is_deepnote() or _is_databricks() or _is_nextjournal() ): return True # complete HTML page in the output # if os.getenv("PLOTLY_RENDERER") == "colab": # # good enough - something colab-like # return True # Colab -> iframe # try: # shell = get_ipython().__class__.__name__ # if shell == 'ZMQInteractiveShell': # return False # Jupyter notebook or qtconsole -> load JS librarty once per notebook # elif shell == 'TerminalInteractiveShell': # return True # Terminal running IPython -> an isolated HTML page to show somehow # else: # return True # Other type (?) # except NameError: # return True # some other env (even standard Python interpreter) -> an isolated HTML page to show somehow # Fallback to a complete HTML page in the output return True # def _detect_isolated_frame() -> bool: # if not _is_IPython_display(): # return True # fallback to a complete HTML page in the output # # # Some notebooks behave like a single HTML page where the JS library is loaded once per notebook. # if (_is_jupyter_classic() or # _is_kaggle() or # _is_positron_notebook()): # return False # no iframes in the output cell # # # Most online notebook platforms are showing cell output in iframe and require # # a complete HTML page in the output which includes both: # # - the script loading JS library and # # - the script that uses this JS lib to create a plot. # # if (_is_google_colab() or # _is_azure_notebook() or # _is_deepnote() or # _is_databricks() or # _is_nextjournal() # ): # return True # complete HTML page in the output # # # if os.getenv("PLOTLY_RENDERER") == "colab": # # # good enough - something colab-like # # return True # Colab -> iframe # # # try: # # shell = get_ipython().__class__.__name__ # # if shell == 'ZMQInteractiveShell': # # return False # Jupyter notebook or qtconsole -> load JS librarty once per notebook # # elif shell == 'TerminalInteractiveShell': # # return True # Terminal running IPython -> an isolated HTML page to show somehow # # else: # # return True # Other type (?) # # except NameError: # # return True # some other env (even standard Python interpreter) -> an isolated HTML page to show somehow # # # Fallback to a complete HTML page in the output # return True def _is_IPython_display() -> bool: try: from IPython.display import display_html return True except ImportError: return False def _is_jupyter_classic() -> bool: # This also detects JupyterLab, which uses the same ZMQInteractiveShell # and also qtconsole (allegedly) try: from IPython import get_ipython except ImportError: return False shell = get_ipython() try: return shell is not None and shell.__class__.__name__ == "ZMQInteractiveShell" except AttributeError: return False def _is_google_colab() -> bool: try: import google.colab return True except ImportError: return False def _is_kaggle() -> bool: # This gives a false positive in Colab. # return os.path.exists("/kaggle/input") return 'KAGGLE_KERNEL_RUN_TYPE' in os.environ def _is_azure_notebook() -> bool: return "AZURE_NOTEBOOKS_HOST" in os.environ def _is_deepnote() -> bool: return "DEEPNOTE_PROJECT_ID" in os.environ def _is_databricks() -> bool: # As proposed: https://github.com/JetBrains/lets-plot/issues/602 return "databricks" in str(os.environ) def _is_nextjournal() -> bool: return "NEXTJOURNAL" in str(os.environ) def _is_positron_console(): try: from IPython import get_ipython except ImportError: return False shell = get_ipython() try: return shell is not None and shell.session_mode == "console" except AttributeError: return False def _is_positron_notebook(): try: from IPython import get_ipython except ImportError: return False shell = get_ipython() try: return shell is not None and shell.session_mode == "notebook" except AttributeError: return False