diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6414ed95..51b9c09e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 182cc14f..3e2538f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,11 @@ ### Updates +- Drop official Python 3.7 support, add Python 3.12 support - Updated pandas version to 2.x - Enable automated test run as required step for release process - Enable basic DependaBot scanning for pip packages and GitHub actions used in CI +- Address security vulnerabilities in dependencies - Add CI support for release proces with [release.yaml](.github/workflows/release.yml) workflow - Release documentation is updated acrodingly in [RELEASING.md](./RELEASING.md) - Update README.md with installation methods on newer Jupyter and JupyterLab releases diff --git a/sparkmagic/sparkmagic/tests/test_sparkkernelbase.py b/sparkmagic/sparkmagic/tests/test_sparkkernelbase.py index cc557c5f..f4a9d8ee 100644 --- a/sparkmagic/sparkmagic/tests/test_sparkkernelbase.py +++ b/sparkmagic/sparkmagic/tests/test_sparkkernelbase.py @@ -16,7 +16,8 @@ class TestSparkKernel(SparkKernelBase): def __init__(self, user_code_parser=None): kwargs = {"testing": True} if user_code_parser is None: - user_code_parser = MagicMock(return_value=code) + user_code_parser = MagicMock() + user_code_parser.get_code_to_run = MagicMock(return_value=code) super().__init__( None, None, None, None, None, LANG_PYTHON, user_code_parser, **kwargs @@ -26,7 +27,8 @@ def __init__(self, user_code_parser=None): def setup_function(): global kernel, execute_cell_mock, do_shutdown_mock, ipython_display - user_code_parser = MagicMock(return_value=code) + user_code_parser = MagicMock() + user_code_parser.get_code_to_run = MagicMock(return_value=code) kernel = TestSparkKernel(user_code_parser) kernel._execute_cell_for_user = execute_cell_mock = MagicMock( @@ -45,11 +47,12 @@ def test_execute_valid_code(): ret = kernel.do_execute(code, False) kernel.user_code_parser.get_code_to_run.assert_called_once_with(code) - assert execute_cell_mock.called_once_with(ret, True) - assert execute_cell_mock.return_value is ret - assert kernel._fatal_error is None - assert execute_cell_mock.called_once_with(code, True) + execute_cell_mock.assert_called_once_with(code, False, True, None, False) + assert ret is execute_cell_mock.return_value + + # no errors + assert kernel._fatal_error is None assert ipython_display.send_error.call_count == 0 @@ -57,12 +60,10 @@ def test_execute_throws_if_fatal_error_happened(): # Verify that if a fatal error already happened, we don't run the code and show the fatal error instead. fatal_error = "Error." kernel._fatal_error = fatal_error + kernel.do_execute(code, False) - ret = kernel.do_execute(code, False) - - assert execute_cell_mock.return_value is ret - assert kernel._fatal_error == fatal_error - assert execute_cell_mock.called_once_with("None", True) + # assert kernel._complete_cell ran after the error + execute_cell_mock.assert_called_once_with("None", False, True, None, False) assert ipython_display.send_error.call_count == 1 @@ -72,9 +73,9 @@ def test_execute_alerts_user_if_an_unexpected_error_happens(): kernel._fatal_error = "Something bad happened before" kernel._repeat_fatal_error = MagicMock(side_effect=ValueError) - ret = kernel.do_execute(code, False) - assert execute_cell_mock.return_value is ret - assert execute_cell_mock.called_once_with("None", True) + kernel.do_execute(code, False) + # assert kernel._complete_cell ran after the error + execute_cell_mock.assert_called_once_with("None", False, True, None, False) assert ipython_display.send_error.call_count == 1 @@ -88,12 +89,16 @@ def test_execute_throws_if_fatal_error_happens_for_execution(): execute_cell_mock.return_value = reply_content - ret = kernel._execute_cell( - code, False, shutdown_if_error=True, log_if_error=fatal_error - ) - assert execute_cell_mock.return_value is ret + kernel._execute_cell(code, False, shutdown_if_error=True, log_if_error=fatal_error) + assert kernel._fatal_error == message - assert execute_cell_mock.called_once_with("None", True) + + # expect two calls, one for the code execution attempt + # and one for kernel._complete_cell after the error + assert execute_cell_mock.call_count == 2 + execute_cell_mock.assert_any_call(code, False, True, None, False) + execute_cell_mock.assert_any_call("None", False, True, None, False) + assert ipython_display.send_error.call_count == 1