From d4bdb4de6862e55d410b7e03e9f9e4aa8e1a4236 Mon Sep 17 00:00:00 2001 From: Ghraven Date: Mon, 31 Aug 2026 20:42:58 +0800 Subject: [PATCH 1/2] fix(cli): bound readiness poll requests --- burr/cli/__main__.py | 3 ++- tests/test_cli_open_when_ready.py | 43 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/test_cli_open_when_ready.py diff --git a/burr/cli/__main__.py b/burr/cli/__main__.py index 8967602d9..1819ff8c3 100644 --- a/burr/cli/__main__.py +++ b/burr/cli/__main__.py @@ -48,6 +48,7 @@ # Clear default handlers setup_logging(logging.INFO) +OPEN_WHEN_READY_TIMEOUT_SECONDS = 5 def _command(command: str, capture_output: bool, addl_env: dict | None = None) -> str: @@ -100,7 +101,7 @@ def _locate_package_root() -> Optional[str]: def open_when_ready(check_url: str, open_url: str): while True: try: - response = requests.get(check_url) + response = requests.get(check_url, timeout=OPEN_WHEN_READY_TIMEOUT_SECONDS) if response.status_code == 200: webbrowser.open(open_url) return diff --git a/tests/test_cli_open_when_ready.py b/tests/test_cli_open_when_ready.py new file mode 100644 index 000000000..06227c66f --- /dev/null +++ b/tests/test_cli_open_when_ready.py @@ -0,0 +1,43 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from burr.cli import __main__ as cli_main + + +def test_open_when_ready_bounds_readiness_request(monkeypatch): + calls = [] + + class Response: + status_code = 200 + + def fake_get(url, **kwargs): + calls.append((url, kwargs)) + return Response() + + opened = [] + monkeypatch.setattr(cli_main.requests, "get", fake_get) + monkeypatch.setattr(cli_main.webbrowser, "open", opened.append) + + cli_main.open_when_ready("http://localhost:7241/health", "http://localhost:7241") + + assert calls == [ + ( + "http://localhost:7241/health", + {"timeout": cli_main.OPEN_WHEN_READY_TIMEOUT_SECONDS}, + ) + ] + assert opened == ["http://localhost:7241"] From 823774360ee865a882eea66d265995b797c8d144 Mon Sep 17 00:00:00 2001 From: Ghraven Date: Mon, 5 Oct 2026 09:25:07 +0800 Subject: [PATCH 2/2] test: cover readiness timeout retry and optional CLI imports --- burr/cli/__main__.py | 6 ++++-- tests/test_cli_open_when_ready.py | 29 ++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/burr/cli/__main__.py b/burr/cli/__main__.py index 1819ff8c3..60675bb2c 100644 --- a/burr/cli/__main__.py +++ b/burr/cli/__main__.py @@ -48,10 +48,9 @@ # Clear default handlers setup_logging(logging.INFO) -OPEN_WHEN_READY_TIMEOUT_SECONDS = 5 -def _command(command: str, capture_output: bool, addl_env: dict | None = None) -> str: +def _command(command: str, capture_output: bool, addl_env: Optional[dict] = None) -> str: """Runs a simple command""" if addl_env is None: addl_env = {} @@ -98,6 +97,9 @@ def _locate_package_root() -> Optional[str]: return None +OPEN_WHEN_READY_TIMEOUT_SECONDS = 5 + + def open_when_ready(check_url: str, open_url: str): while True: try: diff --git a/tests/test_cli_open_when_ready.py b/tests/test_cli_open_when_ready.py index 06227c66f..394c8b3b8 100644 --- a/tests/test_cli_open_when_ready.py +++ b/tests/test_cli_open_when_ready.py @@ -15,7 +15,11 @@ # specific language governing permissions and limitations # under the License. -from burr.cli import __main__ as cli_main +import pytest + +pytest.importorskip("loguru") + +from burr.cli import __main__ as cli_main # noqa: E402 def test_open_when_ready_bounds_readiness_request(monkeypatch): @@ -41,3 +45,26 @@ def fake_get(url, **kwargs): ) ] assert opened == ["http://localhost:7241"] + + +def test_open_when_ready_retries_read_timeout(monkeypatch): + calls, opened, sleeps = [], [], [] + + def fake_get(url, **kwargs): + calls.append((url, kwargs)) + if len(calls) == 1: + raise cli_main.requests.exceptions.ReadTimeout("server did not answer") + return type("Response", (), {"status_code": 200})() + + monkeypatch.setattr(cli_main.requests, "get", fake_get) + monkeypatch.setattr(cli_main.webbrowser, "open", opened.append) + monkeypatch.setattr(cli_main.time, "sleep", sleeps.append) + cli_main.open_when_ready("http://localhost:7241/health", "http://localhost:7241") + + assert ( + calls + == [("http://localhost:7241/health", {"timeout": cli_main.OPEN_WHEN_READY_TIMEOUT_SECONDS})] + * 2 + ) + assert sleeps == [1] + assert opened == ["http://localhost:7241"]