From 2e222c6d445759791aef8fed57fe917d2b50ffc8 Mon Sep 17 00:00:00 2001 From: Valentin Sulzer Date: Sat, 5 Oct 2024 11:24:42 -0400 Subject: [PATCH] implement timeout --- pyproject.toml | 1 + src/pybamm/config.py | 24 +++++++++++++++++++++--- tests/unit/test_config.py | 18 ++++++++++++++++-- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1a527f783d..46c8850bc7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ dependencies = [ "pandas>=1.5.0", "pooch>=1.8.1", "posthog", + "inputimeout", ] [project.urls] diff --git a/src/pybamm/config.py b/src/pybamm/config.py index 8dd1b56e75..5095b42324 100644 --- a/src/pybamm/config.py +++ b/src/pybamm/config.py @@ -3,6 +3,7 @@ import platformdirs from pathlib import Path import pybamm +from inputimeout import inputimeout, TimeoutOccurred def is_running_tests(): # pragma: no cover @@ -41,10 +42,15 @@ def is_running_tests(): # pragma: no cover return False -def ask_user_opt_in(): +def ask_user_opt_in(timeout=10): """ Ask the user if they want to opt in to telemetry. + Parameters + ---------- + timeout: float, optional + The timeout for the user to respond to the prompt. Default is 20 seconds. + Returns ------- bool @@ -59,9 +65,21 @@ def ask_user_opt_in(): "This is entirely optional and does not impact the functionality of PyBaMM.\n" "For more information, see https://docs.pybamm.org/en/latest/source/user_guide/index.html#telemetry" ) + while True: - user_input = input("Do you want to enable telemetry? (Y/n): ").strip().lower() - if user_input in ["yes", "y"]: + try: + user_input = ( + inputimeout( + prompt="Do you want to enable telemetry? (Y/n): ", timeout=timeout + ) + .strip() + .lower() + ) + except TimeoutOccurred: + print("\nTimeout reached. Defaulting to not enabling telemetry.") + return False + + if user_input in ["yes", "y", ""]: return True elif user_input in ["no", "n"]: return False diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index 212d0eef78..6e262fb011 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -1,4 +1,5 @@ import pytest +from inputimeout import TimeoutOccurred import pybamm import uuid @@ -33,10 +34,23 @@ def test_write_read_uuid(self, tmp_path, write_opt_in): @pytest.mark.parametrize("user_opted_in, user_input", [(True, "y"), (False, "n")]) def test_ask_user_opt_in(self, monkeypatch, user_opted_in, user_input): - # Mock the input function to return invalid input first, then valid input + # Mock the inputimeout function to return invalid input first, then valid input inputs = iter(["invalid", user_input]) - monkeypatch.setattr("builtins.input", lambda _: next(inputs)) + monkeypatch.setattr( + "pybamm.config.inputimeout", lambda prompt, timeout: next(inputs) + ) # Call the function to ask the user if they want to opt in opt_in = pybamm.config.ask_user_opt_in() assert opt_in is user_opted_in + + def test_ask_user_opt_in_timeout(self, monkeypatch): + # Mock the inputimeout function to raise a TimeoutOccurred exception + def mock_inputimeout(*args, **kwargs): + raise TimeoutOccurred + + monkeypatch.setattr("pybamm.config.inputimeout", mock_inputimeout) + + # Call the function to ask the user if they want to opt in + opt_in = pybamm.config.ask_user_opt_in() + assert opt_in is False