Skip to content

Commit fd31529

Browse files
authored
Merge pull request #4 from mwakaba2/non-code-cell-prompt-issue
Fix: don't display prompt for non-code cells
2 parents beee1e1 + b34f771 commit fd31529

File tree

4 files changed

+118
-50
lines changed

4 files changed

+118
-50
lines changed

binder/environment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ channels:
44
dependencies:
55
- jupyterlab=3
66
- pip:
7-
- jupyterlab-notifications==0.1.3
7+
- jupyterlab-notifications==0.1.4

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jupyterlab-notifications",
3-
"version": "0.1.3",
3+
"version": "0.1.4",
44
"description": "Jupyterlab extension to show notebook cell completion browser notifications",
55
"keywords": [
66
"jupyter",

src/index.ts

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,49 @@ import {
22
JupyterFrontEnd,
33
JupyterFrontEndPlugin
44
} from '@jupyterlab/application';
5-
65
import { NotebookActions } from '@jupyterlab/notebook';
7-
6+
import { IObservableJSON } from '@jupyterlab/observables';
87
import { ISettingRegistry } from '@jupyterlab/settingregistry';
98

109
import { checkBrowserNotificationSettings } from './settings';
1110

11+
/**
12+
* Extracts Code Cell Start and End Time
13+
*/
14+
function extractExecutionMetadata(metadata: IObservableJSON): [Date, Date] {
15+
const executionMetadata = Object.assign({}, metadata.get('execution') as any);
16+
const cellStartTime = new Date(
17+
executionMetadata['shell.execute_reply.started']
18+
);
19+
const cellEndTime = new Date(executionMetadata['shell.execute_reply']);
20+
return [cellStartTime, cellEndTime];
21+
}
22+
23+
/**
24+
* Constructs notification message and displays it.
25+
*/
26+
function displayNotification(
27+
cellDuration: string,
28+
cellNumber: number,
29+
reportCellNumber: boolean,
30+
reportCellExecutionTime: boolean
31+
): void {
32+
const notificationPayload = {
33+
icon: '/static/favicon.ico',
34+
body: ''
35+
};
36+
let message = '';
37+
if (reportCellNumber && reportCellExecutionTime) {
38+
message = `Cell[${cellNumber}] Duration: ${cellDuration}`;
39+
} else if (reportCellNumber) {
40+
message = `Cell Number: ${cellNumber}`;
41+
} else if (reportCellExecutionTime) {
42+
message = `Cell Duration: ${cellDuration}`;
43+
}
44+
notificationPayload.body = message;
45+
new Notification('Notebook Cell Completed!', notificationPayload);
46+
}
47+
1248
const extension: JupyterFrontEndPlugin<void> = {
1349
id: 'jupyterlab-notifications:plugin',
1450
autoStart: true,
@@ -37,42 +73,31 @@ const extension: JupyterFrontEndPlugin<void> = {
3773
NotebookActions.executed.connect((_, args) => {
3874
if (enabled) {
3975
const { cell, notebook } = args;
76+
const codeCell = cell.model.type === 'code';
77+
const nonEmptyCell = cell.model.value.text.length > 0;
4078
const metadata = cell.model.metadata;
41-
if (metadata.has('execution')) {
42-
const executionMetadata = Object.assign(
43-
{},
44-
metadata.get('execution') as any
45-
);
46-
const cellStartTime = new Date(
47-
executionMetadata['shell.execute_reply.started']
48-
);
49-
const cellEndTime = new Date(
50-
executionMetadata['shell.execute_reply']
51-
);
52-
const diff = new Date(<any>cellEndTime - <any>cellStartTime);
53-
if (diff.getSeconds() >= minimumCellExecutionTime) {
54-
const notificationPayload = {
55-
icon: '/static/favicon.ico',
56-
body: ''
57-
};
58-
let message = '';
59-
const cellDuration = diff.toISOString().substr(11, 8);
60-
const cellNumber = notebook.activeCellIndex;
61-
if (reportCellNumber && reportCellExecutionTime) {
62-
message = `Cell[${cellNumber}] Duration: ${cellDuration}`;
63-
} else if (reportCellNumber) {
64-
message = `Cell Number: ${cellNumber}`;
65-
} else if (reportCellExecutionTime) {
66-
message = `Cell Duration: ${cellDuration}`;
79+
if (codeCell && nonEmptyCell) {
80+
if (metadata.has('execution')) {
81+
const [cellStartTime, cellEndTime] = extractExecutionMetadata(
82+
metadata
83+
);
84+
const diff = new Date(<any>cellEndTime - <any>cellStartTime);
85+
if (diff.getSeconds() >= minimumCellExecutionTime) {
86+
const cellDuration = diff.toISOString().substr(11, 8);
87+
const cellNumber = notebook.activeCellIndex;
88+
displayNotification(
89+
cellDuration,
90+
cellNumber,
91+
reportCellNumber,
92+
reportCellExecutionTime
93+
);
6794
}
68-
notificationPayload.body = message;
69-
new Notification('Notebook Cell Completed!', notificationPayload);
95+
} else {
96+
alert(
97+
'Notebook Cell Timing needs to be enabled for Jupyterlab Notifications to work. ' +
98+
'Please go to Settings -> Advanced Settings Editor -> Notebook and update setting to {"recordTiming": true}'
99+
);
70100
}
71-
} else {
72-
alert(
73-
'Notebook Cell Timing needs to be enabled for Jupyterlab Notifications to work. ' +
74-
'Please go to Settings -> Advanced Settings Editor -> Notebook and update setting to {"recordTiming": true}'
75-
);
76101
}
77102
}
78103
});

tutorial/demo.ipynb

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
"cells": [
33
{
44
"cell_type": "code",
5-
"execution_count": 18,
5+
"execution_count": 13,
66
"metadata": {
77
"execution": {
8-
"iopub.execute_input": "2021-03-19T03:37:14.667688Z",
9-
"iopub.status.busy": "2021-03-19T03:37:14.667455Z",
10-
"iopub.status.idle": "2021-03-19T03:37:14.671324Z",
11-
"shell.execute_reply": "2021-03-19T03:37:14.670402Z",
12-
"shell.execute_reply.started": "2021-03-19T03:37:14.667662Z"
8+
"iopub.execute_input": "2021-03-27T03:06:18.533459Z",
9+
"iopub.status.busy": "2021-03-27T03:06:18.533220Z",
10+
"iopub.status.idle": "2021-03-27T03:06:18.537331Z",
11+
"shell.execute_reply": "2021-03-27T03:06:18.536387Z",
12+
"shell.execute_reply.started": "2021-03-27T03:06:18.533425Z"
1313
},
1414
"tags": []
1515
},
@@ -28,14 +28,14 @@
2828
},
2929
{
3030
"cell_type": "code",
31-
"execution_count": 19,
31+
"execution_count": 14,
3232
"metadata": {
3333
"execution": {
34-
"iopub.execute_input": "2021-03-19T03:37:16.906751Z",
35-
"iopub.status.busy": "2021-03-19T03:37:16.906516Z",
36-
"iopub.status.idle": "2021-03-19T03:37:20.035526Z",
37-
"shell.execute_reply": "2021-03-19T03:37:20.034900Z",
38-
"shell.execute_reply.started": "2021-03-19T03:37:16.906728Z"
34+
"iopub.execute_input": "2021-03-27T03:06:19.213426Z",
35+
"iopub.status.busy": "2021-03-27T03:06:19.213237Z",
36+
"iopub.status.idle": "2021-03-27T03:06:22.337638Z",
37+
"shell.execute_reply": "2021-03-27T03:06:22.336868Z",
38+
"shell.execute_reply.started": "2021-03-27T03:06:19.213404Z"
3939
},
4040
"tags": []
4141
},
@@ -53,6 +53,49 @@
5353
"print(\"hello world!\")"
5454
]
5555
},
56+
{
57+
"cell_type": "markdown",
58+
"metadata": {},
59+
"source": [
60+
"## Hello World"
61+
]
62+
},
63+
{
64+
"cell_type": "raw",
65+
"metadata": {
66+
"execution": {
67+
"iopub.execute_input": "2021-03-27T02:29:48.597351Z",
68+
"iopub.status.busy": "2021-03-27T02:29:48.597122Z",
69+
"iopub.status.idle": "2021-03-27T02:29:48.602494Z",
70+
"shell.execute_reply": "2021-03-27T02:29:48.600860Z",
71+
"shell.execute_reply.started": "2021-03-27T02:29:48.597324Z"
72+
}
73+
},
74+
"source": [
75+
"<h1>Hello World</h1>"
76+
]
77+
},
78+
{
79+
"cell_type": "code",
80+
"execution_count": null,
81+
"metadata": {},
82+
"outputs": [],
83+
"source": []
84+
},
85+
{
86+
"cell_type": "code",
87+
"execution_count": null,
88+
"metadata": {},
89+
"outputs": [],
90+
"source": []
91+
},
92+
{
93+
"cell_type": "code",
94+
"execution_count": null,
95+
"metadata": {},
96+
"outputs": [],
97+
"source": []
98+
},
5699
{
57100
"cell_type": "code",
58101
"execution_count": null,
@@ -77,7 +120,7 @@
77120
"name": "python",
78121
"nbconvert_exporter": "python",
79122
"pygments_lexer": "ipython3",
80-
"version": "3.8.5"
123+
"version": "3.7.10"
81124
}
82125
},
83126
"nbformat": 4,

0 commit comments

Comments
 (0)