diff --git a/compute_endpoint/globus_compute_endpoint/version.py b/compute_endpoint/globus_compute_endpoint/version.py index d8da54b01..f155b6270 100644 --- a/compute_endpoint/globus_compute_endpoint/version.py +++ b/compute_endpoint/globus_compute_endpoint/version.py @@ -1,6 +1,6 @@ # single source of truth for package version, # see https://packaging.python.org/en/latest/single_source_version/ -__version__ = "2.30.0" +__version__ = "2.30.1" # TODO: remove after a `globus-compute-sdk` release # this is needed because it's imported by `globus-compute-sdk` to do the version check diff --git a/compute_endpoint/setup.py b/compute_endpoint/setup.py index 04ea4014c..d452a1aa9 100644 --- a/compute_endpoint/setup.py +++ b/compute_endpoint/setup.py @@ -6,7 +6,7 @@ REQUIRES = [ "requests>=2.31.0,<3", "globus-sdk", # version will be bounded by `globus-compute-sdk` - "globus-compute-sdk==2.30.0", + "globus-compute-sdk==2.30.1", "globus-compute-common==0.4.1", "globus-identity-mapping==0.3.0", # table printing used in list-endpoints diff --git a/compute_sdk/globus_compute_sdk/sdk/auth/globus_app.py b/compute_sdk/globus_compute_sdk/sdk/auth/globus_app.py index 1ff7651f1..cd2c719dc 100644 --- a/compute_sdk/globus_compute_sdk/sdk/auth/globus_app.py +++ b/compute_sdk/globus_compute_sdk/sdk/auth/globus_app.py @@ -3,7 +3,7 @@ import platform import sys -from globus_sdk import ClientApp, GlobusAppConfig, UserApp +from globus_sdk import ClientApp, GlobusApp, GlobusAppConfig, UserApp from .client_login import get_client_creds from .token_storage import get_token_storage @@ -22,8 +22,10 @@ def get_globus_app(environment: str | None = None): client_id, client_secret = get_client_creds() config = GlobusAppConfig(token_storage=get_token_storage(environment=environment)) + app: GlobusApp # silly mypy + if client_id and client_secret: - return ClientApp( + app = ClientApp( app_name=app_name, client_id=client_id, client_secret=client_secret, @@ -37,16 +39,22 @@ def get_globus_app(environment: str | None = None): "variables, or unset them to use a normal login." ) - # The authorization-via-web-link flow requires stdin; the user must visit - # the web link and enter generated code. - elif (not sys.stdin.isatty() or sys.stdin.closed) and not _is_jupyter(): - # Not technically necessary; the login flow would just die with an EOF - # during input(), but adding this message here is much more direct -- - # handle the non-happy path by letting the user know precisely the issue - raise RuntimeError( - "Unable to run native app login flow: stdin is closed or is not a TTY." - ) - else: client_id = client_id or DEFAULT_CLIENT_ID - return UserApp(app_name=app_name, client_id=client_id, config=config) + app = UserApp(app_name=app_name, client_id=client_id, config=config) + + # The authorization-via-web-link flow requires stdin; the user must visit + # the web link and enter generated code. + if ( + app.login_required() + and (not sys.stdin.isatty() or sys.stdin.closed) + and not _is_jupyter() + ): + # Not technically necessary; the login flow would just die with an EOF + # during input(), but adding this message here is much more direct -- + # handle the non-happy path by letting the user know precisely the issue + raise RuntimeError( + "Unable to run native app login flow: stdin is closed or is not a TTY." + ) + + return app diff --git a/compute_sdk/globus_compute_sdk/version.py b/compute_sdk/globus_compute_sdk/version.py index 87e008b87..8242a6ba8 100644 --- a/compute_sdk/globus_compute_sdk/version.py +++ b/compute_sdk/globus_compute_sdk/version.py @@ -3,7 +3,7 @@ # single source of truth for package version, # see https://packaging.python.org/en/latest/single_source_version/ -__version__ = "2.30.0" +__version__ = "2.30.1" def compare_versions( diff --git a/compute_sdk/tests/unit/auth/test_globus_app.py b/compute_sdk/tests/unit/auth/test_globus_app.py index 69db57380..a336ab29f 100644 --- a/compute_sdk/tests/unit/auth/test_globus_app.py +++ b/compute_sdk/tests/unit/auth/test_globus_app.py @@ -2,7 +2,7 @@ import pytest from globus_compute_sdk.sdk.auth.globus_app import DEFAULT_CLIENT_ID, get_globus_app -from globus_sdk import ClientApp, UserApp +from globus_sdk import ClientApp, GlobusApp, UserApp from pytest_mock import MockerFixture _MOCK_BASE = "globus_compute_sdk.sdk.auth.globus_app." @@ -54,18 +54,32 @@ def test_client_app_requires_creds(mocker: MockerFixture): assert "GLOBUS_COMPUTE_CLIENT_SECRET must be set" in str(err.value) -def test_user_app_requires_stdin(mocker: MockerFixture): +@pytest.mark.parametrize("login_required", [True, False]) +@pytest.mark.parametrize("stdin_isatty", [True, False]) +@pytest.mark.parametrize("stdin_closed", [True, False]) +@pytest.mark.parametrize("is_jupyter", [True, False]) +def test_user_app_login_requires_stdin( + mocker: MockerFixture, + login_required: bool, + stdin_isatty: bool, + stdin_closed: bool, + is_jupyter: bool, +): + mock_login_required = mocker.patch.object(GlobusApp, "login_required") + mock_is_jupyter = mocker.patch(f"{_MOCK_BASE}_is_jupyter") mock_stdin = mocker.patch(f"{_MOCK_BASE}sys.stdin") - mock_stdin.isatty.return_value = False - - with pytest.raises(RuntimeError) as err: - get_globus_app() - assert "stdin is closed" in err.value.args[0] - assert "is not a TTY" in err.value.args[0] - assert "native app" in err.value.args[0] - mock_stdin.isatty.return_value = True - mock_stdin.closed = False - - app = get_globus_app() - assert isinstance(app, UserApp) + mock_login_required.return_value = login_required + mock_stdin.closed = stdin_closed + mock_stdin.isatty.return_value = stdin_isatty + mock_is_jupyter.return_value = is_jupyter + + if login_required and (not stdin_isatty or stdin_closed) and not is_jupyter: + with pytest.raises(RuntimeError) as err: + get_globus_app() + assert "stdin is closed" in err.value.args[0] + assert "is not a TTY" in err.value.args[0] + assert "native app" in err.value.args[0] + else: + app = get_globus_app() + assert isinstance(app, UserApp) diff --git a/docs/changelog.rst b/docs/changelog.rst index 28fc8f085..4a5d5d0b2 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -3,6 +3,18 @@ Changelog .. scriv-insert-here +.. _changelog-2.30.1: + +globus-compute-sdk & globus-compute-endpoint v2.30.1 +---------------------------------------------------- + +Bug Fixes +^^^^^^^^^ + +- In cases where stdin is closed or not a TTY, we now only raise an error + if the user requires an interactive login flow (i.e., does not have cached + credentials). + .. _changelog-2.30.0: globus-compute-sdk & globus-compute-endpoint v2.30.0