You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by pa...@apache.org on 2020/10/08 19:24:54 UTC

[beam] branch master updated: [BEAM-11039] Resolve conflicts between TFMA and Facets imports

This is an automated email from the ASF dual-hosted git repository.

pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 710cbd7  [BEAM-11039] Resolve conflicts between TFMA and Facets imports
     new 61fc430  Merge pull request #13045 from [BEAM-11039] Resolve conflicts between TFMA and Facets imports
710cbd7 is described below

commit 710cbd7029df234fdd4abf141e81df6b3c9bd2c7
Author: Ning Kang <ni...@google.com>
AuthorDate: Wed Oct 7 15:27:05 2020 -0700

    [BEAM-11039] Resolve conflicts between TFMA and Facets imports
    
    1. Enclosed facets HTML templates into iframes in Interactive Beam and
       removed unnecessary HTML imports from Interactive Beam and the side
       panel extension.
    2. This resolved the conflicts between TFMA libarary and Facets HTML
       import; this also resolved potential misbehaviors of rendering Facets
       widgets in JupyterLab.
---
 .../interactive/display/pcoll_visualization.py     | 63 ++++++++++++++--------
 .../src/inspector/InteractiveInspectorWidget.tsx   |  5 --
 .../runners/interactive/interactive_environment.py |  4 --
 3 files changed, 40 insertions(+), 32 deletions(-)

diff --git a/sdks/python/apache_beam/runners/interactive/display/pcoll_visualization.py b/sdks/python/apache_beam/runners/interactive/display/pcoll_visualization.py
index fc32fd1..615758d 100644
--- a/sdks/python/apache_beam/runners/interactive/display/pcoll_visualization.py
+++ b/sdks/python/apache_beam/runners/interactive/display/pcoll_visualization.py
@@ -27,6 +27,7 @@ from __future__ import division
 
 import base64
 import datetime
+import html
 import logging
 from datetime import timedelta
 
@@ -68,30 +69,46 @@ _CSS = """
             </style>"""
 _DIVE_SCRIPT_TEMPLATE = """
             try {{
-              document.querySelector("#{display_id}").data = {jsonstr};
+              document
+                .getElementById("{display_id}")
+                .contentDocument
+                .getElementById("{display_id}")
+                .data = {jsonstr};
             }} catch (e) {{
               // NOOP when the user has cleared the output from the notebook.
             }}"""
 _DIVE_HTML_TEMPLATE = _CSS + """
-            <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.3.3/webcomponents-lite.js"></script>
-            <link rel="import" href="https://raw.githubusercontent.com/PAIR-code/facets/1.0.0/facets-dist/facets-jupyter.html">
-            <facets-dive sprite-image-width="{sprite_size}" sprite-image-height="{sprite_size}" id="{display_id}" height="600"></facets-dive>
-            <script>
-              document.querySelector("#{display_id}").data = {jsonstr};
-            </script>"""
+            <iframe id={display_id} style="border:none" width="100%" height="600px"
+              srcdoc='
+                <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.3.3/webcomponents-lite.js"></script>
+                <link rel="import" href="https://raw.githubusercontent.com/PAIR-code/facets/1.0.0/facets-dist/facets-jupyter.html">
+                <facets-dive sprite-image-width="{sprite_size}" sprite-image-height="{sprite_size}" id="{display_id}" height="600"></facets-dive>
+                <script>
+                  document.getElementById("{display_id}").data = {jsonstr};
+                </script>
+              '>
+            </iframe>"""
 _OVERVIEW_SCRIPT_TEMPLATE = """
               try {{
-                document.querySelector("#{display_id}").protoInput = "{protostr}";
+                document
+                  .getElementById("{display_id}")
+                  .contentDocument
+                  .getElementById("{display_id}")
+                  .protoInput = "{protostr}";
               }} catch (e) {{
                 // NOOP when the user has cleared the output from the notebook.
               }}"""
 _OVERVIEW_HTML_TEMPLATE = _CSS + """
-            <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.3.3/webcomponents-lite.js"></script>
-            <link rel="import" href="https://raw.githubusercontent.com/PAIR-code/facets/1.0.0/facets-dist/facets-jupyter.html">
-            <facets-overview id="{display_id}"></facets-overview>
-            <script>
-              document.querySelector("#{display_id}").protoInput = "{protostr}";
-            </script>"""
+            <iframe id={display_id} style="border:none" width="100%" height="600px"
+              srcdoc='
+                <script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.3.3/webcomponents-lite.js"></script>
+                <link rel="import" href="https://raw.githubusercontent.com/PAIR-code/facets/1.0.0/facets-dist/facets-jupyter.html">
+                <facets-overview id="{display_id}"></facets-overview>
+                <script>
+                  document.getElementById("{display_id}").protoInput = "{protostr}";
+                </script>
+              '>
+            </iframe>"""
 _DATATABLE_INITIALIZATION_CONFIG = """
             bAutoWidth: false,
             columns: {columns},
@@ -312,11 +329,11 @@ class PCollectionVisualization(object):
           display_id=update._dive_display_id, jsonstr=jsonstr)
       display_javascript(Javascript(script))
     else:
-      html = _DIVE_HTML_TEMPLATE.format(
+      html_str = _DIVE_HTML_TEMPLATE.format(
           display_id=self._dive_display_id,
-          jsonstr=jsonstr,
+          jsonstr=html.escape(jsonstr),
           sprite_size=sprite_size)
-      display(HTML(html))
+      display(HTML(html_str))
 
   def _display_overview(self, data, update=None):
     if (not data.empty and self._include_window_info and
@@ -335,9 +352,9 @@ class PCollectionVisualization(object):
           display_id=update._overview_display_id, protostr=protostr)
       display_javascript(Javascript(script))
     else:
-      html = _OVERVIEW_HTML_TEMPLATE.format(
+      html_str = _OVERVIEW_HTML_TEMPLATE.format(
           display_id=self._overview_display_id, protostr=protostr)
-      display(HTML(html))
+      display(HTML(html_str))
 
   def _display_dataframe(self, data, update=None):
     table_id = 'table_{}'.format(
@@ -371,9 +388,9 @@ class PCollectionVisualization(object):
       display_javascript(Javascript(script_in_jquery_with_datatable))
     else:
       if data.empty:
-        html = _NO_DATA_TEMPLATE.format(id=table_id)
+        html_str = _NO_DATA_TEMPLATE.format(id=table_id)
       else:
-        html = _DATAFRAME_PAGINATION_TEMPLATE.format(
+        html_str = _DATAFRAME_PAGINATION_TEMPLATE.format(
             table_id=table_id,
             script_in_jquery_with_datatable=script_in_jquery_with_datatable)
       if update:
@@ -384,10 +401,10 @@ class PCollectionVisualization(object):
                   ie._JQUERY_WITH_DATATABLE_TEMPLATE.format(
                       customized_script=_NO_DATA_REMOVAL_SCRIPT.format(
                           id=table_id))))
-          display(HTML(html), display_id=update._df_display_id)
+          display(HTML(html_str), display_id=update._df_display_id)
           update._is_datatable_empty = False
       else:
-        display(HTML(html), display_id=self._df_display_id)
+        display(HTML(html_str), display_id=self._df_display_id)
         if not data.empty:
           self._is_datatable_empty = False
 
diff --git a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InteractiveInspectorWidget.tsx b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InteractiveInspectorWidget.tsx
index 11c2b51..15dd37d 100644
--- a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InteractiveInspectorWidget.tsx
+++ b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InteractiveInspectorWidget.tsx
@@ -16,7 +16,6 @@ import { ISessionContext, ReactWidget } from '@jupyterlab/apputils';
 
 import { InspectableViewModel } from './InspectableViewModel';
 import { InteractiveInspector } from './InteractiveInspector';
-import { importHtml } from '../common/HtmlView';
 
 /**
  * Converts the React component InteractiveInspector into a lumino widget used
@@ -25,10 +24,6 @@ import { importHtml } from '../common/HtmlView';
 export class InteractiveInspectorWidget extends ReactWidget {
   constructor(sessionContext: ISessionContext) {
     super();
-    importHtml([
-      // Used by facets visualization.
-      'https://raw.githubusercontent.com/PAIR-code/facets/1.0.0/facets-dist/facets-jupyter.html'
-    ]);
     this._sessionContext = sessionContext;
     // The model is shared by Inspectables and InspectableView so that
     // sub-components of Inspectables can trigger events that alters the
diff --git a/sdks/python/apache_beam/runners/interactive/interactive_environment.py b/sdks/python/apache_beam/runners/interactive/interactive_environment.py
index b1b087a..b0d5129 100644
--- a/sdks/python/apache_beam/runners/interactive/interactive_environment.py
+++ b/sdks/python/apache_beam/runners/interactive/interactive_environment.py
@@ -202,10 +202,6 @@ class InteractiveEnvironment(object):
           'ipython kernel is not connected any notebook frontend.')
     if self._is_in_notebook:
       self.load_jquery_with_datatable()
-      self.import_html_to_head([
-          'https://raw.githubusercontent.com/PAIR-code/facets/1.0.0/facets-dist'
-          '/facets-jupyter.html'
-      ])
       register_ipython_log_handler()
 
     # A singleton inspector instance to message information of current