diff --git a/openeo/internal/jupyter.py b/openeo/internal/jupyter.py
new file mode 100644
index 000000000..7a8d28a26
--- /dev/null
+++ b/openeo/internal/jupyter.py
@@ -0,0 +1,61 @@
+import json
+
+SCRIPT_URL = 'https://cdn.jsdelivr.net/npm/@openeo/vue-components@2.0.0-rc.2/assets/openeo.min.js'
+COMPONENT_MAP = {
+ 'file-format': 'format',
+ 'file-formats': 'formats',
+ 'service-type': 'service',
+ 'service-types': 'services',
+ 'udf-runtime': 'runtime',
+ 'udf-runtimes': 'runtimes',
+}
+
+def render_component(component: str, data = None, parameters: dict = {}):
+ # Set the data as the corresponding parameter in the Vue components
+ key = COMPONENT_MAP.get(component, component)
+ if data != None:
+ parameters[key] = data
+
+ # Construct HTML, load Vue Components source files only if the openEO HTML tag is not yet defined
+ return """
+
+
+
+
+ """.format(
+ script = SCRIPT_URL,
+ component = component,
+ props = json.dumps(parameters)
+ )
+
+# These classes are proxies to visualize openEO responses nicely in Jupyter
+# To show the actual list or dict in Jupyter, use repr() or print()
+
+class VisualDict(dict):
+
+ def __init__(self, component: str, data : dict, parameters: dict = {}):
+ dict.__init__(self, data)
+
+ self.component = component
+ self.parameters = parameters
+
+ def _repr_html_(self):
+ return render_component(self.component, self, self.parameters)
+
+
+class VisualList(list):
+
+ def __init__(self, component: str, data : list, parameters: dict = {}):
+ list.__init__(self, data)
+
+ self.component = component
+ self.parameters = parameters
+
+ def _repr_html_(self):
+ return render_component(self.component, self, self.parameters)
\ No newline at end of file
diff --git a/openeo/metadata.py b/openeo/metadata.py
index 8ced84a60..a3a319be6 100644
--- a/openeo/metadata.py
+++ b/openeo/metadata.py
@@ -3,6 +3,7 @@
from typing import List, Union, Tuple, Callable
from openeo.util import deep_get
+from openeo.internal.jupyter import render_component
class MetadataException(Exception):
@@ -392,3 +393,6 @@ def add_dimension(self, name: str, label: Union[str, float], type: str = None) -
else:
dim = Dimension(type=type or "other", name=name)
return self._clone_and_update(dimensions=self._dimensions + [dim])
+
+ def _repr_html_(self):
+ return render_component('collection', data = self._orig_metadata)
diff --git a/openeo/rest/connection.py b/openeo/rest/connection.py
index dc565ba7c..859b195bd 100644
--- a/openeo/rest/connection.py
+++ b/openeo/rest/connection.py
@@ -31,6 +31,7 @@
from openeo.rest.rest_capabilities import RESTCapabilities
from openeo.rest.udp import RESTUserDefinedProcess, Parameter
from openeo.util import ensure_list, legacy_alias, dict_no_none
+from openeo.internal.jupyter import VisualDict, VisualList
_log = logging.getLogger(__name__)
@@ -522,7 +523,8 @@ def list_collections(self) -> List[dict]:
:return: list of collection meta data dictionaries
"""
- return self.get('/collections').json()["collections"]
+ data = self.get('/collections').json()["collections"]
+ return VisualList("collections", data = data)
def list_collection_ids(self) -> List[str]:
"""
@@ -539,7 +541,7 @@ def capabilities(self) -> RESTCapabilities:
:return: data_dict: Dict All available data types
"""
if "capabilities" not in self._capabilities_cache:
- self._capabilities_cache["capabilities"] = RESTCapabilities(self.get('/').json())
+ self._capabilities_cache["capabilities"] = RESTCapabilities(self.get('/').json(), self._orig_url)
return self._capabilities_cache["capabilities"]
@@ -558,7 +560,7 @@ def list_file_formats(self) -> dict:
"""
if "file_formats" not in self._capabilities_cache:
self._capabilities_cache["file_formats"] = self.get('/file_formats').json()
- return self._capabilities_cache["file_formats"]
+ return VisualDict("file-formats", data = self._capabilities_cache["file_formats"])
def list_service_types(self) -> dict:
"""
@@ -566,7 +568,19 @@ def list_service_types(self) -> dict:
:return: data_dict: Dict All available service types
"""
- return self.get('/service_types').json()
+ if "service_types" not in self._capabilities_cache:
+ self._capabilities_cache["service_types"] = self.get('/service_types').json()
+ return VisualDict("service-types", data = self._capabilities_cache["service_types"])
+
+ def list_udf_runtimes(self) -> dict:
+ """
+ Loads all available UDF runtimes.
+
+ :return: data_dict: Dict All available UDF runtimes
+ """
+ if "udf_runtimes" not in self._capabilities_cache:
+ self._capabilities_cache["udf_runtimes"] = self.get('/udf_runtimes').json()
+ return VisualDict("udf-runtimes", data = self._capabilities_cache["udf_runtimes"])
def list_services(self) -> dict:
"""
@@ -585,7 +599,8 @@ def describe_collection(self, name) -> dict:
:param name: String Id of the collection
:return: data_dict: Dict Detailed information about the collection
"""
- return self.get('/collections/{}'.format(name)).json()
+ data = self.get('/collections/{}'.format(name)).json()
+ return VisualDict("collection", data = data)
def collection_metadata(self, name) -> CollectionMetadata:
return CollectionMetadata(metadata=self.describe_collection(name))
@@ -597,7 +612,8 @@ def list_processes(self) -> List[dict]:
:return: processes_dict: Dict All available processes of the back end.
"""
- return self.get('/processes').json()["processes"]
+ data = self.get('/processes').json()["processes"]
+ return VisualList("processes", data = data)
def list_jobs(self) -> dict:
"""
diff --git a/openeo/rest/rest_capabilities.py b/openeo/rest/rest_capabilities.py
index e1c151b07..8cbc4bd5f 100644
--- a/openeo/rest/rest_capabilities.py
+++ b/openeo/rest/rest_capabilities.py
@@ -1,12 +1,14 @@
from openeo.capabilities import Capabilities
+from openeo.internal.jupyter import render_component
class RESTCapabilities(Capabilities):
"""Represents REST capabilities of a connection / back end."""
- def __init__(self, data: dict):
+ def __init__(self, data: dict, url: str = None):
super(RESTCapabilities, self).__init__(data)
self.capabilities = data
+ self.url = url
def api_version(self) -> str:
""" Get openEO version."""
@@ -32,3 +34,6 @@ def currency(self):
def list_plans(self):
""" List all billing plans."""
return self.capabilities.get('billing', {}).get('plans')
+
+ def _repr_html_(self):
+ return render_component("capabilities", data = self.capabilities, parameters = {"url": self.url})