Skip to content

Commit

Permalink
Update jupyter web_visualizer for ipywidgets 8 (#6239)
Browse files Browse the repository at this point in the history
Changed some status messages from Info to Debug
Update jupyter_packaging to 0.12
  • Loading branch information
ssheorey authored Jul 10, 2023
1 parent 5676513 commit 6ddbcd5
Show file tree
Hide file tree
Showing 14 changed files with 78 additions and 109 deletions.
16 changes: 8 additions & 8 deletions cpp/open3d/visualization/webrtc_server/PeerConnectionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,19 +140,19 @@ PeerConnectionManager::PeerConnectionManager(
// Register api in http server.
func_["/api/getMediaList"] = [this](const struct mg_request_info *req_info,
const Json::Value &in) -> Json::Value {
utility::LogInfo("[Called HTTP API] /api/getMediaList");
utility::LogDebug("[Called HTTP API] /api/getMediaList");
return this->GetMediaList();
};

func_["/api/getIceServers"] = [this](const struct mg_request_info *req_info,
const Json::Value &in) -> Json::Value {
utility::LogInfo("[Called HTTP API] /api/getIceServers");
utility::LogDebug("[Called HTTP API] /api/getIceServers");
return this->GetIceServers();
};

func_["/api/call"] = [this](const struct mg_request_info *req_info,
const Json::Value &in) -> Json::Value {
utility::LogInfo("[Called HTTP API] /api/call");
utility::LogDebug("[Called HTTP API] /api/call");
std::string peerid;
std::string url; // window_uid.
std::string options;
Expand All @@ -167,7 +167,7 @@ PeerConnectionManager::PeerConnectionManager(
func_["/api/getIceCandidate"] =
[this](const struct mg_request_info *req_info,
const Json::Value &in) -> Json::Value {
utility::LogInfo("[Called HTTP API] /api/getIceCandidate");
utility::LogDebug("[Called HTTP API] /api/getIceCandidate");
std::string peerid;
if (req_info->query_string) {
CivetServer::getParam(req_info->query_string, "peerid", peerid);
Expand All @@ -178,7 +178,7 @@ PeerConnectionManager::PeerConnectionManager(
func_["/api/addIceCandidate"] =
[this](const struct mg_request_info *req_info,
const Json::Value &in) -> Json::Value {
utility::LogInfo("[Called HTTP API] /api/addIceCandidate");
utility::LogDebug("[Called HTTP API] /api/addIceCandidate");
std::string peerid;
if (req_info->query_string) {
CivetServer::getParam(req_info->query_string, "peerid", peerid);
Expand All @@ -188,7 +188,7 @@ PeerConnectionManager::PeerConnectionManager(

func_["/api/hangup"] = [this](const struct mg_request_info *req_info,
const Json::Value &in) -> Json::Value {
utility::LogInfo("[Called HTTP API] /api/hangup");
utility::LogDebug("[Called HTTP API] /api/hangup");
std::string peerid;
if (req_info->query_string) {
CivetServer::getParam(req_info->query_string, "peerid", peerid);
Expand Down Expand Up @@ -713,8 +713,8 @@ void PeerConnectionManager::SendInitFramesToPeer(const std::string &peerid) {

void PeerConnectionManager::CloseWindowConnections(
const std::string &window_uid) {
utility::LogInfo("PeerConnectionManager::CloseWindowConnections: {}",
window_uid);
utility::LogDebug("PeerConnectionManager::CloseWindowConnections: {}",
window_uid);
std::set<std::string> peerids;
{
std::lock_guard<std::mutex> mlock(window_uid_to_peerids_mutex_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ class PeerConnectionManager {
const std::string state =
webrtc::DataChannelInterface::DataStateString(
data_channel_->state());
utility::LogInfo(
utility::LogDebug(
"DataChannelObserver::OnStateChange label: {}, state: {}, "
"peerid: {}",
label, state, peerid_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ void WebRTCWindowSystem::SendInitFrames(const std::string &window_uid) {
std::string WebRTCWindowSystem::CallHttpAPI(const std::string &entry_point,
const std::string &query_string,
const std::string &data) const {
utility::LogInfo("[Called HTTP API (custom handshake)] {}", entry_point);
utility::LogDebug("[Called HTTP API (custom handshake)] {}", entry_point);

std::string query_string_trimmed = "";
if (!query_string.empty() && query_string[0] == '?') {
Expand Down
2 changes: 1 addition & 1 deletion cpp/pybind/make_install_pip_package.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
# Note: Since `make python-package` clears PYTHON_COMPILED_MODULE_DIR every time,
# it is guaranteed that there is only one wheel in ${PYTHON_PACKAGE_DST_DIR}/pip_package/*.whl
file(GLOB WHEEL_FILE "${PYTHON_PACKAGE_DST_DIR}/pip_package/*.whl")
execute_process(COMMAND ${Python3_EXECUTABLE} -m pip uninstall open3d --yes)
execute_process(COMMAND ${Python3_EXECUTABLE} -m pip uninstall open3d open3d-cpu --yes)
execute_process(COMMAND ${Python3_EXECUTABLE} -m pip install ${WHEEL_FILE} -U)
8 changes: 8 additions & 0 deletions python/js/amd-public-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// In an AMD module, we set the public path using the magic requirejs "module" dependency
// See https://github.com/requirejs/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#module
// Since "module" is a requirejs magic module, we must include "module" in the webpack externals configuration.
var module = require("module");
var url = new URL(module.uri, document.location);
// Using lastIndexOf("/")+1 gives us the empty string if there is no "/", so pathname becomes "/"
url.pathname = url.pathname.slice(0, url.pathname.lastIndexOf("/") + 1);
__webpack_public_path__ = `${url.origin}${url.pathname}`;
9 changes: 0 additions & 9 deletions python/js/lib/embed.js

This file was deleted.

8 changes: 1 addition & 7 deletions python/js/lib/extension.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
// This file contains the javascript that is run when the notebook is loaded.
// It contains some requirejs configuration and the `load_ipython_extension`
// which is required for any notebook extension.
//
// Some static assets may be required by the custom widget javascript. The base
// url for the notebook is not known at build time and is therefore computed
// dynamically.
__webpack_public_path__ = document.querySelector('body').getAttribute('data-base-url') + 'nbextensions/open3d';


// Configure requirejs
if (window.require) {
Expand All @@ -21,5 +15,5 @@ if (window.require) {

// Export the required load_ipython_extension
module.exports = {
load_ipython_extension: function() {}
load_ipython_extensionn() {}
};
13 changes: 6 additions & 7 deletions python/js/lib/labplugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ var base = require('@jupyter-widgets/base');
module.exports = {
id: 'open3d:plugin',
requires: [base.IJupyterWidgetRegistry],
activate: function(app, widgets) {
widgets.registerWidget({
name: 'open3d',
version: plugin.version,
exports: plugin
});
activate: (app, widgets) => {
widgets.registerWidget({
name: 'open3d',
version: plugin.version,
exports: plugin
});
},
autoStart: true
};

81 changes: 32 additions & 49 deletions python/js/lib/web_visualizer.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,8 @@
// ----------------------------------------------------------------------------
// - Open3D: www.open3d.org -
// - Open3D: www.open3d.org -
// ----------------------------------------------------------------------------
// The MIT License (MIT)
//
// Copyright (c) 2018-2023 www.open3d.org
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// Copyright(c) 2018-2023 www.open3d.org
// SPDX - License - Identifier: MIT
// ----------------------------------------------------------------------------

// Jupyter widget for Open3D WebRTC visualizer. See web_visualizer.py for the
Expand All @@ -44,49 +25,51 @@ let WebRtcStreamer = require("./webrtcstreamer");
//
// When serializing the entire widget state for embedding, only values that
// differ from the defaults will be specified.
let WebVisualizerModel = widgets.DOMWidgetModel.extend({
defaults: _.extend(widgets.DOMWidgetModel.prototype.defaults(), {
_model_name: "WebVisualizerModel",
_view_name: "WebVisualizerView",
_model_module: "open3d",
_view_module: "open3d",
// @...@ is configured by cpp/pybind/make_python_package.cmake.
_model_module_version: "@PROJECT_VERSION_THREE_NUMBER@",
_view_module_version: "@PROJECT_VERSION_THREE_NUMBER@",
}),
});
class WebVisualizerModel extends widgets.DOMWidgetModel {
defaults() {
return _.extend(widgets.DOMWidgetModel.prototype.defaults(), {
_model_name: "WebVisualizerModel",
_view_name: "WebVisualizerView",
_model_module: "open3d",
_view_module: "open3d",
// @...@ is configured by cpp/pybind/make_python_package.cmake.
_model_module_version: "@PROJECT_VERSION_THREE_NUMBER@",
_view_module_version: "@PROJECT_VERSION_THREE_NUMBER@",
});
}
}

// Custom View. Renders the widget model.
let WebVisualizerView = widgets.DOMWidgetView.extend({
sleep: function (time_ms) {
class WebVisualizerView extends widgets.DOMWidgetView {
sleep(time_ms) {
return new Promise((resolve) => setTimeout(resolve, time_ms));
},
}

logAndReturn: function (value) {
logAndReturn(value) {
console.log("logAndReturn: ", value);
return value;
},
}

callResultReady: function (callId) {
callResultReady(callId) {
let pyjs_channel = this.model.get("pyjs_channel");
console.log("Current pyjs_channel:", pyjs_channel);
let callResultMap = JSON.parse(this.model.get("pyjs_channel"));
return callId in callResultMap;
},
}

extractCallResult: function (callId) {
extractCallResult(callId) {
if (!this.callResultReady(callId)) {
throw "extractCallResult not ready yet.";
}
let callResultMap = JSON.parse(this.model.get("pyjs_channel"));
return callResultMap[callId];
},
}

/**
* Hard-coded to call "call_http_api". Args and return value are all
* strings.
*/
callPython: async function (func, args = []) {
async callPython(func, args = []) {
let callId = this.callId.toString();
this.callId++;
let message = {
Expand Down Expand Up @@ -116,9 +99,9 @@ let WebVisualizerView = widgets.DOMWidgetView.extend({
json_result
);
return json_result;
},
}

commsCall: function (url, data = {}) {
commsCall(url, data = {}) {
// https://stackoverflow.com/a/736970/1255535
// parseUrl(url).hostname
// parseUrl(url).entryPoint
Expand Down Expand Up @@ -180,9 +163,9 @@ let WebVisualizerView = widgets.DOMWidgetView.extend({
} else {
throw "Unsupported entryPoint: " + entryPoint;
}
},
}

render: function () {
render() {
let windowUID = this.model.get("window_uid");
let onClose = function () {
console.log("onClose() called for window_uid:", windowUID);
Expand Down Expand Up @@ -214,8 +197,8 @@ let WebVisualizerView = widgets.DOMWidgetView.extend({
this.commsCall.bind(this)
);
this.webRtcClient.connect(windowUID);
},
});
}
}

module.exports = {
WebVisualizerModel: WebVisualizerModel,
Expand Down
6 changes: 3 additions & 3 deletions python/js/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "open3d",
"version": "@PROJECT_VERSION_THREE_NUMBER@",
"description": "Open3D: A Modern Library for 3D Data Processing",
"author": "Open3D.org",
"description": "@PROJECT_DESCRIPTION@",
"author": "@PROJECT_EMAIL@",
"main": "lib/index.js",
"repository": {
"type": "git",
Expand Down Expand Up @@ -36,7 +36,7 @@
"rimraf": "^2.6.1"
},
"dependencies": {
"@jupyter-widgets/base": "^1.1 || ^2 || ^3 || ^4",
"@jupyter-widgets/base": "^2 || ^3 || ^4 || ^5 || ^6",
"lodash": "^4.17.4",
"webrtc-adapter": "^4.2.2"
},
Expand Down
34 changes: 14 additions & 20 deletions python/js/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ module.exports = (env, argv) => {
// some configuration for requirejs, and provides the legacy
// "load_ipython_extension" function which is required for any notebook
// extension.
//
entry: "./lib/extension.js",
output: {
filename: "extension.js",
path: path.resolve(__dirname, "..", "open3d", "nbextension"),
libraryTarget: "amd",
publicPath: "", // publicPath is set in extension.js
},
devtool,
},
Expand All @@ -32,47 +30,43 @@ module.exports = (env, argv) => {
// This bundle contains the implementation for the custom widget views and
// custom widget.
// It must be an amd module
//
entry: "./lib/index.js",
entry: ["./amd-public-path.js", "./lib/index.js"],
output: {
filename: "index.js",
path: path.resolve(__dirname, "..", "open3d", "nbextension"),
libraryTarget: "amd",
publicPath: "",
publicPath: "", // Set in amd-public-path.js
},
devtool,
module: {
rules: rules,
},
externals: ["@jupyter-widgets/base"],
// "module" is the magic requirejs dependency used to set the publicPath
externals: ["@jupyter-widgets/base", "module"]
},
{
// Embeddable open3d bundle
//
// This bundle is generally almost identical to the notebook bundle
// containing the custom widget views and models.
//
// The only difference is in the configuration of the webpack public path
// for the static assets.
//
// It will be automatically distributed by unpkg to work with the static
// widget embedder.
//
// The target bundle is always `dist/index.js`, which is the path required
// by the custom widget embedder.
// This bundle is identical to the notebook bundle containing the custom
// widget views and models. The only difference is it is placed in the
// dist/ directory and shipped with the npm package for use from a CDN
// like jsdelivr.
//
entry: "./lib/embed.js",
// The target bundle is always `dist/index.js`, which is the path
// required by the custom widget embedder.
entry: ["./amd-public-path.js", "./lib/index.js"],
output: {
filename: "index.js",
path: path.resolve(__dirname, "dist"),
libraryTarget: "amd",
publicPath: "https://unpkg.com/open3d@" + version + "/dist/",
publicPath: "", // Set in amd-public-path.js
},
devtool,
module: {
rules: rules,
},
externals: ["@jupyter-widgets/base"],
// "module" is the magic requirejs dependency used to set the publicPath
externals: ["@jupyter-widgets/base", "module"]
},
];
};
2 changes: 1 addition & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[build-system]
requires = ["ipywidgets>=7.6.0", "pygments>=2.7.4", "jupyter_packaging~=0.10", "jupyterlab>=3.0.0,==3.*", "setuptools>=40.8.0", "wheel"]
requires = ["ipywidgets>=8.0.3", "pygments>=2.7.4", "jupyter_packaging~=0.12", "jupyterlab>=3.0.0,==3.*", "setuptools>=50.3.2", "wheel==0.38.4"]
build-backend = "setuptools.build_meta"
2 changes: 1 addition & 1 deletion python/requirements_jupyter_build.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pywinpty==2.0.2; sys_platform=='win32' and python_version=='3.6'
ipywidgets>=8.0.4
pygments>=2.7.4
jupyter_packaging~=0.10
jupyter_packaging~=0.12
jupyterlab>=3.0.0,==3.*
Loading

0 comments on commit 6ddbcd5

Please sign in to comment.