@@ -737,6 +737,45 @@ def test_widgets(self):
737
737
assert 'version_major' in wdata
738
738
assert 'version_minor' in wdata
739
739
740
+ def test_execution_hook (self ):
741
+ filename = os .path .join (current_dir , 'files' , 'HelloWorld.ipynb' )
742
+ with open (filename ) as f :
743
+ input_nb = nbformat .read (f , 4 )
744
+ cell_hook = MagicMock ()
745
+ execution_hook = MagicMock ()
746
+
747
+ executor = NotebookClient (
748
+ input_nb ,
749
+ resources = NBClientTestsBase ().build_resources (),
750
+ on_cell_start = cell_hook ,
751
+ on_cell_complete = cell_hook ,
752
+ on_cell_error = cell_hook ,
753
+ on_execution_start = execution_hook ,
754
+ )
755
+ executor .execute ()
756
+ execution_hook .assert_called_once ()
757
+ assert cell_hook .call_count == 2
758
+
759
+ def test_error_execution_hook_error (self ):
760
+ filename = os .path .join (current_dir , 'files' , 'Error.ipynb' )
761
+ with open (filename ) as f :
762
+ input_nb = nbformat .read (f , 4 )
763
+ cell_hook = MagicMock ()
764
+ execution_hook = MagicMock ()
765
+
766
+ executor = NotebookClient (
767
+ input_nb ,
768
+ resources = NBClientTestsBase ().build_resources (),
769
+ on_cell_start = cell_hook ,
770
+ on_cell_complete = cell_hook ,
771
+ on_cell_error = cell_hook ,
772
+ on_execution_start = execution_hook ,
773
+ )
774
+ with pytest .raises (CellExecutionError ):
775
+ executor .execute ()
776
+ execution_hook .assert_called_once ()
777
+ assert cell_hook .call_count == 3
778
+
740
779
741
780
class TestRunCell (NBClientTestsBase ):
742
781
"""Contains test functions for NotebookClient.execute_cell"""
@@ -1520,3 +1559,47 @@ def test_no_source(self, executor, cell_mock, message_mock):
1520
1559
assert message_mock .call_count == 0
1521
1560
# Should also consume the message stream
1522
1561
assert cell_mock .outputs == []
1562
+
1563
+ @prepare_cell_mocks ()
1564
+ def test_cell_hooks (self , executor , cell_mock , message_mock ):
1565
+ hook1 , hook2 , hook3 , hook4 = MagicMock (), MagicMock (), MagicMock (), MagicMock ()
1566
+ executor .on_cell_start = hook1
1567
+ executor .on_cell_complete = hook2
1568
+ executor .on_cell_error = hook3
1569
+ executor .on_execution_start = hook4
1570
+ executor .execute_cell (cell_mock , 0 )
1571
+ assert hook1 .call_count == 1
1572
+ assert hook2 .call_count == 1
1573
+ assert hook3 .call_count == 0
1574
+ assert hook4 .call_count == 0
1575
+ hook1 .assert_called_once_with (cell = cell_mock , cell_index = 0 )
1576
+ hook2 .assert_called_once_with (cell = cell_mock , cell_index = 0 )
1577
+
1578
+ @prepare_cell_mocks (
1579
+ {
1580
+ 'msg_type' : 'error' ,
1581
+ 'header' : {'msg_type' : 'error' },
1582
+ 'content' : {'ename' : 'foo' , 'evalue' : 'bar' , 'traceback' : ['Boom' ]},
1583
+ },
1584
+ reply_msg = {
1585
+ 'msg_type' : 'execute_reply' ,
1586
+ 'header' : {'msg_type' : 'execute_reply' },
1587
+ # ERROR
1588
+ 'content' : {'status' : 'error' },
1589
+ },
1590
+ )
1591
+ def test_error_cell_hooks (self , executor , cell_mock , message_mock ):
1592
+ hook1 , hook2 , hook3 , hook4 = MagicMock (), MagicMock (), MagicMock (), MagicMock ()
1593
+ executor .on_cell_start = hook1
1594
+ executor .on_cell_complete = hook2
1595
+ executor .on_cell_error = hook3
1596
+ executor .on_execution_start = hook4
1597
+ with self .assertRaises (CellExecutionError ):
1598
+ executor .execute_cell (cell_mock , 0 )
1599
+ assert hook1 .call_count == 1
1600
+ assert hook2 .call_count == 1
1601
+ assert hook3 .call_count == 1
1602
+ assert hook4 .call_count == 0
1603
+ hook1 .assert_called_once_with (cell = cell_mock , cell_index = 0 )
1604
+ hook2 .assert_called_once_with (cell = cell_mock , cell_index = 0 )
1605
+ hook3 .assert_called_once_with (cell = cell_mock , cell_index = 0 )
0 commit comments