diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 526b1643..ddcf579e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Fixed a bug where `rsconnect deploy notebook --static` failed with `Unable to + include the file in the bundle: No such file or directory`. The + Python version string recorded for the manifest was passed to `nbconvert` as + if it were the local interpreter path; the actual interpreter is now used. - Fixed a bug where `rsconnect deploy manifest manifest.json` (and other deploy commands given a bare filename) failed to detect git metadata. The directory passed to git detection was empty in that case, which caused detection to be diff --git a/rsconnect/main.py b/rsconnect/main.py index fc4efe9c..2a78e554 100644 --- a/rsconnect/main.py +++ b/rsconnect/main.py @@ -1611,10 +1611,11 @@ def deploy_notebook( ce.validate_server().validate_app_mode(app_mode=app_mode) if app_mode == AppModes.STATIC: + assert environment.python_interpreter is not None ce.make_bundle( make_notebook_html_bundle, file, - environment.python, + environment.python_interpreter, hide_all_input, hide_tagged_input, ) diff --git a/tests/test_main.py b/tests/test_main.py index 3afe0784..b32ead9a 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -2,7 +2,9 @@ import os import re import shutil +import sys from os.path import join +from types import SimpleNamespace from unittest import TestCase, mock import click @@ -13,7 +15,7 @@ from rsconnect import VERSION from rsconnect.api import RSConnectClient, RSConnectServer from rsconnect.json_web_token import SECRET_KEY_ENV -from rsconnect.main import cli, env_management_callback +from rsconnect.main import cli, env_management_callback, make_notebook_html_bundle from .utils import ( apply_common_args, @@ -303,6 +305,33 @@ def post_application_deploy_callback(request, uri, response_headers): if original_server_value: os.environ["CONNECT_SERVER"] = original_server_value + def test_deploy_notebook_static_passes_interpreter_not_version(self): + # Regression test for #721: deploy_notebook must hand make_notebook_html_bundle + # the local interpreter *path* (used to run nbconvert), not environment.python, + # which is only a version string and made nbconvert fail with "No such file or + # directory". + fake_env = SimpleNamespace(python="3.12.1", python_interpreter=sys.executable) + + with mock.patch("rsconnect.main.Environment.create_python_environment", return_value=fake_env), mock.patch( + "rsconnect.main.RSConnectExecutor" + ) as MockExecutor: + ce = MockExecutor.return_value + + runner = CliRunner() + args = apply_common_args( + ["deploy", "notebook", get_dir(join("pip1", "dummy.ipynb"))], + server="http://fake_server", + key="FAKE_API_KEY", + ) + args += ["--static", "--no-verify"] + result = runner.invoke(cli, args) + + assert result.exit_code == 0, result.output + # make_bundle(make_notebook_html_bundle, file, , hide_all, hide_tagged) + bundle_args = ce.make_bundle.call_args.args + assert bundle_args[0] is make_notebook_html_bundle + assert bundle_args[2] == sys.executable + @httpretty.activate(verbose=True, allow_net_connect=False) def test_deploy_verify_before_activate(self, caplog): # Without --draft or --no-verify, the default flow deploys the bundle as a