Skip to content

Commit d105f56

Browse files
authored
Databricks and CoCalc Renderers (#1703)
* Added CoCalc and Databricks renderers * Update databricks renderer to search parent frames for displayHTML function. Enable the renderer based on presence of an environment variable since this displayHTML function search takes a bit of time and we don't want to run it on import.
1 parent 22c495c commit d105f56

File tree

2 files changed

+103
-8
lines changed

2 files changed

+103
-8
lines changed

Diff for: packages/python/plotly/plotly/io/_base_renderers.py

+92-8
Original file line numberDiff line numberDiff line change
@@ -532,13 +532,15 @@ def __init__(
532532
post_script=None,
533533
animation_opts=None,
534534
include_plotlyjs=True,
535+
html_directory="iframe_figures",
535536
):
536537

537538
self.config = config
538539
self.auto_play = auto_play
539540
self.post_script = post_script
540541
self.animation_opts = animation_opts
541542
self.include_plotlyjs = include_plotlyjs
543+
self.html_directory = html_directory
542544

543545
def to_mimebundle(self, fig_dict):
544546
from plotly.io import write_html
@@ -559,15 +561,10 @@ def to_mimebundle(self, fig_dict):
559561
iframe_height = str(525 + iframe_buffer) + "px"
560562

561563
# Build filename using ipython cell number
562-
ip = IPython.get_ipython()
563-
cell_number = list(ip.history_manager.get_tail(1))[0][1] + 1
564-
dirname = "iframe_figures"
565-
filename = "{dirname}/figure_{cell_number}.html".format(
566-
dirname=dirname, cell_number=cell_number
567-
)
564+
filename = self.build_filename()
568565

569566
# Make directory for
570-
os.makedirs(dirname, exist_ok=True)
567+
os.makedirs(self.html_directory, exist_ok=True)
571568

572569
write_html(
573570
fig_dict,
@@ -595,11 +592,38 @@ def to_mimebundle(self, fig_dict):
595592
allowfullscreen
596593
></iframe>
597594
""".format(
598-
width=iframe_width, height=iframe_height, src=filename
595+
width=iframe_width, height=iframe_height, src=self.build_url(filename)
599596
)
600597

601598
return {"text/html": iframe_html}
602599

600+
def build_filename(self):
601+
ip = IPython.get_ipython()
602+
cell_number = list(ip.history_manager.get_tail(1))[0][1] + 1
603+
filename = "{dirname}/figure_{cell_number}.html".format(
604+
dirname=self.html_directory, cell_number=cell_number
605+
)
606+
return filename
607+
608+
def build_url(self, filename):
609+
return filename
610+
611+
612+
class CoCalcRenderer(IFrameRenderer):
613+
614+
_render_count = 0
615+
616+
def build_filename(self):
617+
filename = "{dirname}/figure_{render_count}.html".format(
618+
dirname=self.html_directory, render_count=CoCalcRenderer._render_count
619+
)
620+
621+
CoCalcRenderer._render_count += 1
622+
return filename
623+
624+
def build_url(self, filename):
625+
return "{filename}?fullscreen=kiosk".format(filename=filename)
626+
603627

604628
class ExternalRenderer(BaseRenderer):
605629
"""
@@ -707,6 +731,66 @@ def render(self, fig_dict):
707731
open_html_in_browser(html, self.using, self.new, self.autoraise)
708732

709733

734+
class DatabricksRenderer(ExternalRenderer):
735+
def __init__(
736+
self,
737+
config=None,
738+
auto_play=False,
739+
post_script=None,
740+
animation_opts=None,
741+
include_plotlyjs="cdn",
742+
):
743+
744+
self.config = config
745+
self.auto_play = auto_play
746+
self.post_script = post_script
747+
self.animation_opts = animation_opts
748+
self.include_plotlyjs = include_plotlyjs
749+
self._displayHTML = None
750+
751+
@property
752+
def displayHTML(self):
753+
import inspect
754+
755+
if self._displayHTML is None:
756+
for frame in inspect.getouterframes(inspect.currentframe()):
757+
global_names = set(frame.frame.f_globals)
758+
# Check for displayHTML plus a few others to reduce chance of a false
759+
# hit.
760+
if all(v in global_names for v in ["displayHTML", "display", "spark"]):
761+
self._displayHTML = frame.frame.f_globals["displayHTML"]
762+
break
763+
764+
if self._displayHTML is None:
765+
raise EnvironmentError(
766+
"""
767+
Unable to detect the Databricks displayHTML function. The 'databricks' renderer is only
768+
supported when called from within the Databricks notebook environment."""
769+
)
770+
771+
return self._displayHTML
772+
773+
def render(self, fig_dict):
774+
from plotly.io import to_html
775+
776+
html = to_html(
777+
fig_dict,
778+
config=self.config,
779+
auto_play=self.auto_play,
780+
include_plotlyjs=self.include_plotlyjs,
781+
include_mathjax="cdn",
782+
post_script=self.post_script,
783+
full_html=True,
784+
animation_opts=self.animation_opts,
785+
default_width="100%",
786+
default_height="100%",
787+
validate=False,
788+
)
789+
790+
# displayHTML is a Databricks notebook built-in function
791+
self.displayHTML(html)
792+
793+
710794
class SphinxGalleryRenderer(ExternalRenderer):
711795
def render(self, fig_dict):
712796
stack = inspect.stack()

Diff for: packages/python/plotly/plotly/io/_renderers.py

+11
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
BrowserRenderer,
2626
IFrameRenderer,
2727
SphinxGalleryRenderer,
28+
CoCalcRenderer,
29+
DatabricksRenderer,
2830
)
2931
from plotly.io._utils import validate_coerce_fig_to_dict
3032

@@ -406,6 +408,8 @@ def show(fig, renderer=None, validate=True, **kwargs):
406408
renderers["kaggle"] = KaggleRenderer(config=config)
407409
renderers["azure"] = AzureRenderer(config=config)
408410
renderers["colab"] = ColabRenderer(config=config)
411+
renderers["cocalc"] = CoCalcRenderer()
412+
renderers["databricks"] = DatabricksRenderer()
409413

410414
# JSON
411415
renderers["json"] = JsonRenderer()
@@ -475,6 +479,13 @@ def show(fig, renderer=None, validate=True, **kwargs):
475479
if not default_renderer and "NTERACT_EXE" in os.environ:
476480
default_renderer = "nteract"
477481

482+
# Check if we're running in CoCalc
483+
if not default_renderer and "COCALC_PROJECT_ID" in os.environ:
484+
default_renderer = "cocalc"
485+
486+
if not default_renderer and "DATABRICKS_RUNTIME_VERSION" in os.environ:
487+
default_renderer = "databricks"
488+
478489
# Check if we're running in spyder and orca is installed
479490
if not default_renderer and "SPYDER_ARGS" in os.environ:
480491
try:

0 commit comments

Comments
 (0)