From 336b743f4e8b78156f2d2585bdca23eddda66e90 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Mon, 13 Oct 2025 08:24:58 +0100 Subject: [PATCH 1/2] Run tests on Python 3.14; drop Python 3.10 --- .github/workflows/Lint-and-test.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test-against-main.yml | 6 +++--- pyproject.toml | 5 +++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/Lint-and-test.yml b/.github/workflows/Lint-and-test.yml index 26bd207b..b548ca55 100644 --- a/.github/workflows/Lint-and-test.yml +++ b/.github/workflows/Lint-and-test.yml @@ -6,7 +6,7 @@ jobs: strategy: matrix: os: [ "ubuntu-latest", "windows-latest" ] - version: ['3.10', '3.11', '3.12'] + version: ['3.11', '3.12', '3.13', '3.14'] fail-fast: false steps: - uses: actions/checkout@v5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5bef542d..621900dc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v6 with: - python-version: "3.11" + python-version: "3.13" - name: Install pypa/build run: >- python3 -m diff --git a/.github/workflows/test-against-main.yml b/.github/workflows/test-against-main.yml index 1db05dd1..84332df0 100644 --- a/.github/workflows/test-against-main.yml +++ b/.github/workflows/test-against-main.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - version: ['3.11', "3.12"] + version: ['3.11', '3.12', '3.13', '3.14'] steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 @@ -17,8 +17,8 @@ jobs: python-version: ${{ matrix.version }} - name: install requirements run: pip install -e .[dev] - - name: install latest bluesky and ophyd-async - run: pip install --upgrade --force-reinstall git+https://github.com/bluesky/bluesky.git@main git+https://github.com/bluesky/ophyd-async.git@main + - name: install latest bluesky, ophyd-async and event-model + run: pip install --upgrade --force-reinstall git+https://github.com/bluesky/bluesky.git@main git+https://github.com/bluesky/ophyd-async.git@main git+https://github.com/bluesky/event-model.git@main - name: run ruff run: python -m ruff check if: always() diff --git a/pyproject.toml b/pyproject.toml index 34d1fb65..27ad7f68 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ name = "ibex-bluesky-core" # REQUIRED, is the only field that cannot be marked dynamic = ["version"] description = "Core bluesky plan stubs & devices for use at ISIS" readme = "README.md" -requires-python = ">=3.10" +requires-python = ">=3.11" license-files = ["LICENSE"] authors = [ @@ -33,9 +33,10 @@ classifiers = [ # that you indicate you support Python 3. These classifiers are *not* # checked by "pip install". See instead "requires-python" key in this file. "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: 3 :: Only", ] From a097253902768b55dc505d7688f83756db62e3d7 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Mon, 13 Oct 2025 08:35:40 +0100 Subject: [PATCH 2/2] Remove outdated version checks --- src/ibex_bluesky_core/devices/block.py | 5 +---- tests/devices/test_block.py | 19 ++++++------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/ibex_bluesky_core/devices/block.py b/src/ibex_bluesky_core/devices/block.py index 8268a441..8de15747 100644 --- a/src/ibex_bluesky_core/devices/block.py +++ b/src/ibex_bluesky_core/devices/block.py @@ -2,7 +2,6 @@ import asyncio import logging -import sys from collections.abc import Callable from dataclasses import dataclass from typing import Generic, TypeVar @@ -58,8 +57,6 @@ # looking at the global moving flag. GLOBAL_MOVING_FLAG_PRE_WAIT = 0.1 -aio_timeout_error = asyncio.exceptions.TimeoutError if sys.version_info < (3, 11) else TimeoutError - @dataclass(kw_only=True, frozen=True) class BlockWriteConfig(Generic[T]): @@ -286,7 +283,7 @@ async def set_and_settle(setpoint: T) -> None: else: try: await set_and_settle(value) - except aio_timeout_error as e: + except TimeoutError as e: logger.info( "block set %s value=%s failed with %s, but continuing anyway because " "continue_on_failed_write is set.", diff --git a/tests/devices/test_block.py b/tests/devices/test_block.py index f74be819..a1de0da4 100644 --- a/tests/devices/test_block.py +++ b/tests/devices/test_block.py @@ -1,6 +1,4 @@ # pyright: reportMissingParameterType=false -import asyncio -import sys from contextlib import nullcontext from unittest.mock import ANY, MagicMock, call, patch @@ -25,11 +23,6 @@ ) from tests.conftest import MOCK_PREFIX -if sys.version_info < (3, 11): - aio_timeout_error = asyncio.exceptions.TimeoutError -else: - aio_timeout_error = TimeoutError - async def _make_block(clazz): block = clazz(float, MOCK_PREFIX, "float_block") @@ -192,7 +185,7 @@ async def test_block_set_with_timeout(): set_mock_value(block.readback, 10) - with pytest.raises(aio_timeout_error): + with pytest.raises(TimeoutError): await block.set(20) func.assert_called_once_with(20, 10) @@ -234,7 +227,7 @@ async def test_block_set_waiting_for_global_moving_flag_timeout(): set_mock_value(block.global_moving, True) with patch("ibex_bluesky_core.devices.block.asyncio.sleep") as mock_aio_sleep: - with pytest.raises(aio_timeout_error): + with pytest.raises(TimeoutError): await block.set(10) # Only check first call, as wait_for_value from ophyd_async gives us a few more... assert mock_aio_sleep.mock_calls[0] == call(GLOBAL_MOVING_FLAG_PRE_WAIT) @@ -379,13 +372,13 @@ async def test_block_mot_set_outside_limits(mot_block): async def test_block_failing_write(timeout_is_error): block = await _block_with_write_config(BlockWriteConfig(timeout_is_error=timeout_is_error)) - get_mock_put(block.setpoint).side_effect = aio_timeout_error + get_mock_put(block.setpoint).side_effect = TimeoutError - with pytest.raises(aio_timeout_error) if timeout_is_error else nullcontext(): + with pytest.raises(TimeoutError) if timeout_is_error else nullcontext(): await block.set(1) async def test_block_failing_write_with_default_write_config(writable_block): - get_mock_put(writable_block.setpoint).side_effect = aio_timeout_error - with pytest.raises(aio_timeout_error): + get_mock_put(writable_block.setpoint).side_effect = TimeoutError + with pytest.raises(TimeoutError): await writable_block.set(1)