Skip to content

Commit 858e103

Browse files
Merge pull request #195 from kevin-bates/clear-execution-metadata
Clear execution metadata, prefer msg header date when recording times
2 parents f688790 + 74d0a6e commit 858e103

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

nbclient/client.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from queue import Empty
1010
from textwrap import dedent
1111
from time import monotonic
12+
from typing import Optional
1213

1314
from jupyter_client import KernelManager
1415
from jupyter_client.client import KernelClient
@@ -28,7 +29,22 @@
2829
from .util import ensure_async, run_sync
2930

3031

31-
def timestamp() -> str:
32+
def timestamp(msg: Optional[Dict] = None) -> str:
33+
if msg and 'header' in msg: # The test mocks don't provide a header, so tolerate that
34+
msg_header = msg['header']
35+
if 'date' in msg_header and isinstance(msg_header['date'], datetime.datetime):
36+
try:
37+
# reformat datetime into expected format
38+
formatted_time = datetime.datetime.strftime(
39+
msg_header['date'], '%Y-%m-%dT%H:%M:%S.%fZ'
40+
)
41+
if (
42+
formatted_time
43+
): # docs indicate strftime may return empty string, so let's catch that too
44+
return formatted_time
45+
except Exception:
46+
pass # fallback to a local time
47+
3248
return datetime.datetime.utcnow().isoformat() + 'Z'
3349

3450

@@ -618,7 +634,7 @@ async def _async_poll_for_reply(
618634
msg = await ensure_async(self.kc.shell_channel.get_msg(timeout=new_timeout))
619635
if msg['parent_header'].get('msg_id') == msg_id:
620636
if self.record_timing:
621-
cell['metadata']['execution']['shell.execute_reply'] = timestamp()
637+
cell['metadata']['execution']['shell.execute_reply'] = timestamp(msg)
622638
try:
623639
await asyncio.wait_for(task_poll_output_msg, self.iopub_timeout)
624640
except (asyncio.TimeoutError, Empty):
@@ -796,7 +812,7 @@ async def async_execute_cell(
796812
self.log.debug("Skipping tagged cell %s", cell_index)
797813
return cell
798814

799-
if self.record_timing and 'execution' not in cell['metadata']:
815+
if self.record_timing: # clear execution metadata prior to execution
800816
cell['metadata']['execution'] = {}
801817

802818
self.log.debug("Executing cell:\n%s", cell.source)
@@ -894,11 +910,11 @@ def process_message(
894910
if self.record_timing:
895911
if msg_type == 'status':
896912
if content['execution_state'] == 'idle':
897-
cell['metadata']['execution']['iopub.status.idle'] = timestamp()
913+
cell['metadata']['execution']['iopub.status.idle'] = timestamp(msg)
898914
elif content['execution_state'] == 'busy':
899-
cell['metadata']['execution']['iopub.status.busy'] = timestamp()
915+
cell['metadata']['execution']['iopub.status.busy'] = timestamp(msg)
900916
elif msg_type == 'execute_input':
901-
cell['metadata']['execution']['iopub.execute_input'] = timestamp()
917+
cell['metadata']['execution']['iopub.execute_input'] = timestamp(msg)
902918

903919
if msg_type == 'status':
904920
if content['execution_state'] == 'idle':

0 commit comments

Comments
 (0)