in metaflow/plugins/cards/card_cli.py [0:0]
def update_card(mf_card, mode, task, data, timeout_value=None):
"""
This method will be responsible for creating a card/data-update based on the `mode`.
There are three possible modes taken by this function.
- render :
- This will render the "final" card.
- This mode is passed at task completion.
- Setting this mode will call the `render` method of a MetaflowCard.
- It will result in the creation of an HTML page.
- render_runtime:
- Setting this mode will render a card during task "runtime".
- Setting this mode will call the `render_runtime` method of a MetaflowCard.
- It will result in the creation of an HTML page.
- refresh:
- Setting this mode will refresh the data update for a card.
- We support this mode because rendering a full card can be an expensive operation, but shipping tiny data updates can be cheap.
- Setting this mode will call the `refresh` method of a MetaflowCard.
- It will result in the creation of a JSON object.
Parameters
----------
mf_card : MetaflowCard
MetaflowCard object which will be used to render the card.
mode : str
Mode of rendering the card.
task : Task
Task object which will be passed to render the card.
data : dict
object created and passed down from `current.card._get_latest_data` method.
For more information on this object's schema have a look at `current.card._get_latest_data` method.
timeout_value : int
Timeout value for rendering the card.
Returns
-------
CardRenderInfo
- NamedTuple which will contain:
- `mode`: The mode of rendering the card.
- `is_implemented`: whether the function was implemented or not.
- `data` : output from rendering the card (Can be string/dict)
- `timed_out` : whether the function timed out or not.
- `timeout_stack_trace` : stack trace of the function if it timed out.
"""
def _add_token_html(html):
if html is None:
return None
return html.replace(
mf_card.RELOAD_POLICY_TOKEN,
_extract_reload_token(data=data, task=task, mf_card=mf_card),
)
def _add_token_json(json_msg):
if json_msg is None:
return None
return {
"reload_token": _extract_reload_token(
data=data, task=task, mf_card=mf_card
),
"data": json_msg,
"created_on": time.time(),
}
def _safe_call_function(func, *args, **kwargs):
"""
returns (data, is_implemented)
"""
try:
return func(*args, **kwargs), True
except NotImplementedError as e:
return None, False
def _call():
if mode == "render":
setattr(
mf_card.__class__,
"runtime_data",
property(fget=lambda _, data=data: data),
)
output = _add_token_html(mf_card.render(task))
return CardRenderInfo(
mode=mode,
is_implemented=True,
data=output,
timed_out=False,
timeout_stack_trace=None,
)
elif mode == "render_runtime":
# Since many cards created by metaflow users may not have implemented a
# `render_time` / `refresh` methods, it can result in an exception and thereby
# creation of error cards (especially for the `render_runtime` method). So instead
# we will catch the NotImplementedError and return None if users have not implemented it.
# If there any any other exception from the user code, it should be bubbled to the top level.
output, is_implemented = _safe_call_function(
mf_card.render_runtime, task, data
)
return CardRenderInfo(
mode=mode,
is_implemented=is_implemented,
data=_add_token_html(output),
timed_out=False,
timeout_stack_trace=None,
)
elif mode == "refresh":
output, is_implemented = _safe_call_function(mf_card.refresh, task, data)
return CardRenderInfo(
mode=mode,
is_implemented=is_implemented,
data=_add_token_json(output),
timed_out=False,
timeout_stack_trace=None,
)
render_info = None
if timeout_value is None or timeout_value < 0:
return _call()
else:
try:
with timeout(timeout_value):
render_info = _call()
except TimeoutError:
stack_trace = traceback.format_exc()
return CardRenderInfo(
mode=mode,
is_implemented=True,
data=None,
timed_out=True,
timeout_stack_trace=stack_trace,
)
return render_info