From ae3272fa404bcd26a5d833bb7278477b92a96e3a Mon Sep 17 00:00:00 2001 From: Tadeja Kadunc Date: Tue, 21 Jul 2026 18:27:15 +0200 Subject: [PATCH 1/6] Retry failing Chrome load_arrow step --- python/scripts/run_emscripten_tests.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/python/scripts/run_emscripten_tests.py b/python/scripts/run_emscripten_tests.py index 002698a77e2b..1331355f64f4 100644 --- a/python/scripts/run_emscripten_tests.py +++ b/python/scripts/run_emscripten_tests.py @@ -31,6 +31,7 @@ from io import BytesIO from selenium import webdriver +from selenium.common.exceptions import TimeoutException class TemplateOverrider(http.server.SimpleHTTPRequestHandler): @@ -209,10 +210,21 @@ def load_pyodide(self, dist_dir): pass def load_arrow(self): - self.execute_python( - f"import pyodide_js as pjs\n" - f"await pjs.loadPackage('{PYARROW_WHEEL_PATH.name}')\n" - ) + code = (f"import pyodide_js as pjs\n" + f"await pjs.loadPackage('{PYARROW_WHEEL_PATH.name}')\n") + self.driver.set_script_timeout(300) + try: + for attempt in range(3): + try: + return self.execute_python(code) + except TimeoutException: + if attempt == 2: + raise + print("Timed out loading PyArrow in browser. Retrying", + flush=True) + self.driver.refresh() + finally: + self.driver.set_script_timeout(1200) def execute_python(self, code, wait_for_terminate=True): if wait_for_terminate: From 5a5b0f1aa84405ae449147db27134d52f60e2632 Mon Sep 17 00:00:00 2001 From: Tadeja Kadunc Date: Tue, 21 Jul 2026 22:49:59 +0200 Subject: [PATCH 2/6] Restarting browser --- python/scripts/run_emscripten_tests.py | 33 ++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/python/scripts/run_emscripten_tests.py b/python/scripts/run_emscripten_tests.py index 1331355f64f4..07ea4d20dde2 100644 --- a/python/scripts/run_emscripten_tests.py +++ b/python/scripts/run_emscripten_tests.py @@ -35,6 +35,12 @@ class TemplateOverrider(http.server.SimpleHTTPRequestHandler): + def handle(self): + try: + super().handle() + except (BrokenPipeError, ConnectionResetError): + pass + def log_request(self, code="-", size="-"): # don't log successful requests but log errors if isinstance(code, int) and code >= 400: @@ -201,8 +207,13 @@ def wait_for_done(self): class BrowserDriver: def __init__(self, hostname, port, driver): + self.hostname = hostname + self.port = port self.driver = driver - self.driver.get(f"http://{hostname}:{port}/test.html") + self._open_test_page() + + def _open_test_page(self): + self.driver.get(f"http://{self.hostname}:{self.port}/test.html") # Chrome on CI takes longer than locally to compile. self.driver.set_script_timeout(1200) @@ -220,12 +231,15 @@ def load_arrow(self): except TimeoutException: if attempt == 2: raise - print("Timed out loading PyArrow in browser. Retrying", + print("Timed out loading PyArrow in browser. Restarting browser", flush=True) - self.driver.refresh() + self.restart_browser() finally: self.driver.set_script_timeout(1200) + def restart_browser(self): + self._open_test_page() + def execute_python(self, code, wait_for_terminate=True): if wait_for_terminate: self.driver.execute_async_script( @@ -268,7 +282,8 @@ def wait_for_done(self): class ChromeDriver(BrowserDriver): - def __init__(self, hostname, port): + @staticmethod + def _make_driver(): from selenium.webdriver.chrome.options import Options options = Options() @@ -276,7 +291,15 @@ def __init__(self, hostname, port): options.add_argument("--no-sandbox") driver = webdriver.Chrome(options=options) driver.command_executor._client_config.timeout = 1200 - super().__init__(hostname, port, driver) + return driver + + def __init__(self, hostname, port): + super().__init__(hostname, port, self._make_driver()) + + def restart_browser(self): + self.driver.quit() + self.driver = self._make_driver() + self._open_test_page() class FirefoxDriver(BrowserDriver): From 2c1cf0604de3c8b160dd1cdbc71e80554b5feffa Mon Sep 17 00:00:00 2001 From: Tadeja Kadunc Date: Tue, 21 Jul 2026 23:03:09 +0200 Subject: [PATCH 3/6] Restarting browser cont. --- python/scripts/run_emscripten_tests.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/python/scripts/run_emscripten_tests.py b/python/scripts/run_emscripten_tests.py index 07ea4d20dde2..3039cd547824 100644 --- a/python/scripts/run_emscripten_tests.py +++ b/python/scripts/run_emscripten_tests.py @@ -207,13 +207,9 @@ def wait_for_done(self): class BrowserDriver: def __init__(self, hostname, port, driver): - self.hostname = hostname - self.port = port + self.url = f"http://{hostname}:{port}/test.html" self.driver = driver - self._open_test_page() - - def _open_test_page(self): - self.driver.get(f"http://{self.hostname}:{self.port}/test.html") + self.driver.get(self.url) # Chrome on CI takes longer than locally to compile. self.driver.set_script_timeout(1200) @@ -238,7 +234,7 @@ def load_arrow(self): self.driver.set_script_timeout(1200) def restart_browser(self): - self._open_test_page() + self.driver.get(self.url) def execute_python(self, code, wait_for_terminate=True): if wait_for_terminate: @@ -299,7 +295,8 @@ def __init__(self, hostname, port): def restart_browser(self): self.driver.quit() self.driver = self._make_driver() - self._open_test_page() + self.driver.get(self.url) + self.driver.set_script_timeout(1200) class FirefoxDriver(BrowserDriver): From fa439d80e468c7f801add4a8fb041907fa36d3f1 Mon Sep 17 00:00:00 2001 From: Tadeja Kadunc Date: Wed, 22 Jul 2026 14:30:51 +0200 Subject: [PATCH 4/6] Fix snappy_ep error on newer CMake 4.4 --- cpp/cmake_modules/ThirdpartyToolchain.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/cmake_modules/ThirdpartyToolchain.cmake b/cpp/cmake_modules/ThirdpartyToolchain.cmake index 1677b188b9ff..c34bd87edd79 100644 --- a/cpp/cmake_modules/ThirdpartyToolchain.cmake +++ b/cpp/cmake_modules/ThirdpartyToolchain.cmake @@ -1451,8 +1451,7 @@ macro(build_snappy) # ignore linker flag errors, as Snappy sets # -Werror -Wall, and Emscripten doesn't support -soname list(APPEND SNAPPY_CMAKE_ARGS - "-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}" - "-Wno-error=linkflags") + "-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}") endif() externalproject_add(snappy_ep From 0bc24a3027a879daa3586df3733a967820e275be Mon Sep 17 00:00:00 2001 From: Tadeja Kadunc Date: Thu, 23 Jul 2026 16:46:28 +0200 Subject: [PATCH 5/6] Redo setting timeout per review --- python/scripts/run_emscripten_tests.py | 29 ++++++++++++++------------ 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/python/scripts/run_emscripten_tests.py b/python/scripts/run_emscripten_tests.py index 3039cd547824..5ffc164931a0 100644 --- a/python/scripts/run_emscripten_tests.py +++ b/python/scripts/run_emscripten_tests.py @@ -39,6 +39,8 @@ def handle(self): try: super().handle() except (BrokenPipeError, ConnectionResetError): + # Browser restart while downloading wheel closes connection + # before server response is written so ignore harmless errors pass def log_request(self, code="-", size="-"): @@ -219,19 +221,20 @@ def load_pyodide(self, dist_dir): def load_arrow(self): code = (f"import pyodide_js as pjs\n" f"await pjs.loadPackage('{PYARROW_WHEEL_PATH.name}')\n") - self.driver.set_script_timeout(300) - try: - for attempt in range(3): - try: - return self.execute_python(code) - except TimeoutException: - if attempt == 2: - raise - print("Timed out loading PyArrow in browser. Restarting browser", - flush=True) - self.restart_browser() - finally: - self.driver.set_script_timeout(1200) + for attempt in range(3): + # Set temporary timeout for every attempt as Chrome restart creates a new driver + self.driver.set_script_timeout(300) + try: + self.execute_python(code) + except TimeoutException: + if attempt == 2: + raise + print("Timed out loading PyArrow in browser. Restarting browser", + flush=True) + self.restart_browser() + else: + self.driver.set_script_timeout(1200) + return def restart_browser(self): self.driver.get(self.url) From 63072d2cd32f2fa767f1c55b14d758b92e74837e Mon Sep 17 00:00:00 2001 From: Tadeja Kadunc Date: Thu, 23 Jul 2026 17:25:33 +0200 Subject: [PATCH 6/6] Python lint --- python/scripts/run_emscripten_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/scripts/run_emscripten_tests.py b/python/scripts/run_emscripten_tests.py index 5ffc164931a0..9ac3e0d8d7f8 100644 --- a/python/scripts/run_emscripten_tests.py +++ b/python/scripts/run_emscripten_tests.py @@ -222,7 +222,7 @@ def load_arrow(self): code = (f"import pyodide_js as pjs\n" f"await pjs.loadPackage('{PYARROW_WHEEL_PATH.name}')\n") for attempt in range(3): - # Set temporary timeout for every attempt as Chrome restart creates a new driver + # Set temporary timeout each attempt as Chrome restart creates a driver self.driver.set_script_timeout(300) try: self.execute_python(code)