Skip to content

Commit

Permalink
Migrating HTML reprs to jinja2 (#5188)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobtomlinson committed Aug 11, 2021
1 parent 2801f11 commit 0528d8d
Show file tree
Hide file tree
Showing 27 changed files with 477 additions and 489 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
recursive-include distributed *.py
recursive-include distributed *.js
recursive-include distributed *.j2
recursive-include distributed *.coffee
recursive-include distributed *.html
recursive-include distributed *.css
Expand Down
1 change: 1 addition & 0 deletions continuous_integration/environment-3.7.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies:
- h5py
- ipykernel
- ipywidgets
- jinja2
- joblib
- jupyter_client
- msgpack-python
Expand Down
1 change: 1 addition & 0 deletions continuous_integration/environment-3.8.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies:
- h5py
- ipykernel
- ipywidgets
- jinja2
- joblib
- jupyter_client
- msgpack-python
Expand Down
1 change: 1 addition & 0 deletions continuous_integration/environment-3.9.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies:
- h5py
- ipykernel
- ipywidgets
- jinja2
- joblib # overridden by git tip below
- jupyter_client
- lz4 # Only tested here
Expand Down
119 changes: 17 additions & 102 deletions distributed/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import atexit
import copy
import errno
import html
import inspect
import json
import logging
Expand Down Expand Up @@ -82,11 +81,11 @@
TimeoutError,
format_dashboard_link,
has_keyword,
key_split,
log_errors,
no_default,
sync,
thread_state,
typename,
)
from .utils_comm import (
WrappedKey,
Expand All @@ -96,6 +95,7 @@
scatter_to_workers,
unpack_remotedata,
)
from .widgets import get_template
from .worker import get_client, get_worker, secede

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -401,39 +401,18 @@ def __del__(self):

def __repr__(self):
if self.type:
try:
typ = self.type.__module__.split(".")[0] + "." + self.type.__name__
except AttributeError:
typ = str(self.type)
return f"<Future: {self.status}, type: {typ}, key: {self.key}>"
return (
f"<Future: {self.status}, type: {typename(self.type)}, key: {self.key}>"
)
else:
return f"<Future: {self.status}, key: {self.key}>"

def _repr_html_(self):
text = "<b>Future: %s</b> " % html.escape(key_split(self.key))
text += (
'<font style="color: var(--jp-ui-font-color2, gray)">status: </font>'
'<font style="color: %(color)s">%(status)s</font>, '
) % {
"status": self.status,
"color": "var(--jp-error-color0, red)"
if self.status == "error"
else "var(--jp-ui-font-color0, black)",
}
if self.type:
try:
typ = self.type.__module__.split(".")[0] + "." + self.type.__name__
except AttributeError:
typ = str(self.type)
text += (
'<font style="color: var(--jp-ui-font-color2, gray)">type: </font>%s, '
% typ
)
text += (
'<font style="color: var(--jp-ui-font-color2, gray)">key: </font>%s'
% html.escape(str(self.key))
return get_template("future.html.j2").render(
key=str(self.key),
type=typename(self.type),
status=self.status,
)
return text

def __await__(self):
return self.result().__await__()
Expand Down Expand Up @@ -921,78 +900,14 @@ def __repr__(self):
def _repr_html_(self):
scheduler, info = self._get_scheduler_info()

if scheduler is None:
child_repr = """<p>No scheduler connected.</p>"""
elif self.cluster:
child_repr = f"""
<details>
<summary style="margin-bottom: 20px;"><h3 style="display: inline;">Cluster Info</h3></summary>
{self.cluster._repr_html_()}
</details>
"""
else:
child_repr = f"""
<details>
<summary style="margin-bottom: 20px;"><h3 style="display: inline;">Scheduler Info</h3></summary>
{info._repr_html_()}
</details>
"""

client_status = ""

if not self.cluster and not self.scheduler_file:
client_status += """
<tr>
<td style="text-align: left;"><strong>Connection method:</strong> Direct</td>
<td style="text-align: left;"></td>
</tr>
"""

if self.cluster:
client_status += f"""
<tr>
<td style="text-align: left;"><strong>Connection method:</strong> Cluster object</td>
<td style="text-align: left;"><strong>Cluster type:</strong> {type(self.cluster).__name__}</td>
</tr>
"""
elif self.scheduler_file:
client_status += f"""
<tr>
<td style="text-align: left;"><strong>Connection method:</strong> Scheduler file</td>
<td style="text-align: left;"><strong>Scheduler file:</strong> {self.scheduler_file}</td>
</tr>
"""

if self.dashboard_link:
client_status += f"""
<tr>
<td style="text-align: left;">
<strong>Dashboard: </strong>
<a href="{self.dashboard_link}">{self.dashboard_link}</a>
</td>
<td style="text-align: left;"></td>
</tr>
"""

return f"""
<div>
<div style="
width: 24px;
height: 24px;
background-color: #e1e1e1;
border: 3px solid #9D9D9D;
border-radius: 5px;
position: absolute;"> </div>
<div style="margin-left: 48px;">
<h3 style="margin-bottom: 0px;">Client</h3>
<p style="color: #9D9D9D; margin-bottom: 0px;">{self.id}</p>
<table style="width: 100%; text-align: left;">
{client_status}
</table>
{child_repr}
</div>
</div>
"""
return get_template("client.html.j2").render(
id=self.id,
scheduler=scheduler,
info=info,
cluster=self.cluster,
scheduler_file=self.scheduler_file,
dashboard_link=self.dashboard_link,
)

def start(self, **kwargs):
"""Start scheduler running in separate thread"""
Expand Down
52 changes: 9 additions & 43 deletions distributed/deploy/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from ..core import Status
from ..objects import SchedulerInfo
from ..utils import Log, Logs, format_dashboard_link, log_errors, sync, thread_state
from ..widgets import get_template
from .adaptive import Adaptive

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -364,54 +365,19 @@ def update():

def _repr_html_(self, cluster_status=None):

if not cluster_status:
cluster_status = ""

cluster_status += f"""
<tr>
<td style="text-align: left;">
<strong>Dashboard:</strong> <a href="{self.dashboard_link}">{self.dashboard_link}</a>
</td>
<td style="text-align: left;"><strong>Workers:</strong> {len(self.scheduler_info["workers"])}</td>
</tr>
<tr>
<td style="text-align: left;">
<strong>Total threads:</strong>
{sum([w["nthreads"] for w in self.scheduler_info["workers"].values()])}
</td>
<td style="text-align: left;">
<strong>Total memory:</strong>
{format_bytes(sum([w["memory_limit"] for w in self.scheduler_info["workers"].values()]))}
</td>
</tr>
"""
try:
scheduler_info_repr = self.scheduler_info._repr_html_()
except AttributeError:
scheduler_info_repr = "Scheduler not started yet."

return f"""
<div class="jp-RenderedHTMLCommon jp-RenderedHTML jp-mod-trusted jp-OutputArea-output">
<div style="
width: 24px;
height: 24px;
background-color: #e1e1e1;
border: 3px solid #9D9D9D;
border-radius: 5px;
position: absolute;"> </div>
<div style="margin-left: 48px;">
<h3 style="margin-bottom: 0px; margin-top: 0px;">{type(self).__name__}</h3>
<p style="color: #9D9D9D; margin-bottom: 0px;">{self.name}</p>
<table style="width: 100%; text-align: left;">
{cluster_status}
</table>
<details>
<summary style="margin-bottom: 20px;"><h3 style="display: inline;">Scheduler Info</h3></summary>
{scheduler_info_repr}
</details>
</div>
</div>
"""
return get_template("cluster.html.j2").render(
type=type(self).__name__,
name=self.name,
workers=self.scheduler_info["workers"],
dashboard_link=self.dashboard_link,
scheduler_info_repr=scheduler_info_repr,
cluster_status=cluster_status,
)

def _ipython_display_(self, **kwargs):
widget = self._widget()
Expand Down
14 changes: 6 additions & 8 deletions distributed/deploy/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from ..nanny import Nanny
from ..scheduler import Scheduler
from ..security import Security
from ..widgets import get_template
from ..worker import Worker, parse_memory_limit
from .spec import SpecCluster
from .utils import nprocesses_nthreads
Expand Down Expand Up @@ -249,14 +250,11 @@ def start_worker(self, *args, **kwargs):
)

def _repr_html_(self, cluster_status=None):
if cluster_status is None:
cluster_status = ""
cluster_status += f"""
<tr>
<td style="text-align: left;"><strong>Status:</strong> {self.status.name}</td>
<td style="text-align: left;"><strong>Using processes:</strong> {self.processes}</td>
</tr>
"""
cluster_status = get_template("local_cluster.html.j2").render(
status=self.status.name,
processes=self.processes,
cluster_status=cluster_status,
)
return super()._repr_html_(cluster_status=cluster_status)


Expand Down

0 comments on commit 0528d8d

Please sign in to comment.