From 961564eb7da8e97e02063a57f01620808a089bea Mon Sep 17 00:00:00 2001 From: Francisco Hernandez Vivanco Date: Wed, 28 Jan 2026 12:51:18 +1100 Subject: [PATCH 1/3] support cancelling mxcube flows --- .../HardwareObjects/ANSTO/PrefectWorkflow.py | 69 ++++++++++--------- .../ANSTO/prefect_flows/abstract_flow.py | 3 +- .../full_dataset_collection_flow.py | 4 +- .../ANSTO/prefect_flows/grid_scan_flow.py | 10 ++- .../ANSTO/prefect_flows/one_shot_flow.py | 4 +- .../ANSTO/prefect_flows/partial_udc.py | 4 +- .../ANSTO/prefect_flows/screening_flow.py | 4 +- .../prefect_flows/sync_prefect_client.py | 39 ++++++++++- 8 files changed, 91 insertions(+), 46 deletions(-) diff --git a/mxcubecore/HardwareObjects/ANSTO/PrefectWorkflow.py b/mxcubecore/HardwareObjects/ANSTO/PrefectWorkflow.py index 93a0af9b6a..322c552f5b 100644 --- a/mxcubecore/HardwareObjects/ANSTO/PrefectWorkflow.py +++ b/mxcubecore/HardwareObjects/ANSTO/PrefectWorkflow.py @@ -1,10 +1,8 @@ -import asyncio import logging import os import pprint import time from os import path -from time import perf_counter from typing import Literal import gevent @@ -316,27 +314,34 @@ def abort(self) -> None: None """ logging.getLogger("HWR").info("Aborting current workflow") - loop = asyncio.get_event_loop() - if loop.is_running(): - # TODO: MXcube takes some significant time to cancel workflows (investigate why) - timeout = 30 - logging.getLogger("HWR").warning( - f"Loop is still running, waiting for {timeout} s to complete" + + if ( + self.current_flow.prefect_client is not None + and self.current_flow.prefect_client.flow_run_id is not None + ): + try: + self.current_flow.prefect_client.cancel_flow_run(wait=False) + logging.getLogger("user_level_log").info( + "Prefect workflow aborted successfully." + ) + except Exception as ex: + logging.getLogger("HWR").error( + f"Error aborting prefect flow: {str(ex)}" + ) + return + else: + logging.getLogger("user_level_log").warning( + "No prefect client available to abort the workflow" ) - t = perf_counter() - while loop.is_running(): - gevent.sleep(1) - logging.getLogger("HWR").warning(f"Loop is still running") - if perf_counter() > t + timeout: - raise QueueExecutionException("Asyncio Loop is still running", self) + return # If necessary unblock dialog if not self.gevent_event.is_set(): self.gevent_event.set() if self.workflow_name == PrefectFlows.grid_scan: - self.raster_flow.prefect_flow_aborted = True - self.raster_flow.mxcubecore_workflow_aborted = True + self.current_flow.prefect_flow_aborted = True + self.current_flow.mxcubecore_workflow_aborted = True self.state.value = "ON" @@ -428,68 +433,66 @@ def start_prefect_workflow(self, sample_id: int | None) -> None: if self.workflow_name == PrefectFlows.screen_sample: logging.getLogger("HWR").info(f"Starting workflow: {self.workflow_name}") - self.screening_flow = ScreeningFlow( + self.current_flow = ScreeningFlow( state=self._state, resolution=self.resolution, sample_id=sample_id ) - dialog_box_parameters = self.open_dialog(self.screening_flow.dialog_box()) + dialog_box_parameters = self.open_dialog(self.current_flow.dialog_box()) if dialog_box_parameters: logging.getLogger("HWR").info( f"Dialog box parameters: {dialog_box_parameters}" ) self.state.value = "ON" - self.screening_flow.run(dialog_box_parameters=dialog_box_parameters) + self.current_flow.run(dialog_box_parameters=dialog_box_parameters) else: self.state.value = "ON" raise QueueExecutionException("dialog_box_parameters is empty", self) elif self.workflow_name == PrefectFlows.collect_dataset: logging.getLogger("HWR").info(f"Starting workflow: {self.workflow_name}") - self.full_dataset_flow = FullDatasetFlow( + self.current_flow = FullDatasetFlow( state=self._state, resolution=self.resolution, sample_id=sample_id ) - dialog_box_parameters = self.open_dialog( - self.full_dataset_flow.dialog_box() - ) + dialog_box_parameters = self.open_dialog(self.current_flow.dialog_box()) if dialog_box_parameters: logging.getLogger("HWR").info( f"Dialog box parameters: {dialog_box_parameters}" ) - self.full_dataset_flow.run(dialog_box_parameters=dialog_box_parameters) + self.current_flow.run(dialog_box_parameters=dialog_box_parameters) else: self.state.value = "ON" raise QueueExecutionException("dialog_box_parameters is empty", self) elif self.workflow_name == PrefectFlows.grid_scan: logging.getLogger("HWR").info(f"Starting workflow: {self.workflow_name}") - self.raster_flow = GridScanFlow( + self.current_flow = GridScanFlow( sample_view=self.sample_view, state=self._state, redis_connection=self.redis_connection, resolution=self.resolution, sample_id=sample_id, ) - dialog_box_parameters = self.open_dialog(self.raster_flow.dialog_box()) + dialog_box_parameters = self.open_dialog(self.current_flow.dialog_box()) if dialog_box_parameters: logging.getLogger("HWR").info( f"Dialog box parameters: {dialog_box_parameters}" ) - self.raster_flow.run(dialog_box_parameters=dialog_box_parameters) + self.current_flow.run(dialog_box_parameters=dialog_box_parameters) else: self.state.value = "ON" raise QueueExecutionException("dialog_box_parameters is empty", self) elif self.workflow_name == PrefectFlows.one_shot: logging.getLogger("HWR").info(f"Starting workflow: {self.workflow_name}") - self.one_shot_flow = OneShotFlow( + self.current_flow = OneShotFlow( state=self._state, resolution=self.resolution, sample_id=sample_id ) - dialog_box_parameters = self.open_dialog(self.one_shot_flow.dialog_box()) + dialog_box_parameters = self.open_dialog(self.current_flow.dialog_box()) if dialog_box_parameters: logging.getLogger("HWR").info( f"Dialog box parameters: {dialog_box_parameters}" ) - self.one_shot_flow.run(dialog_box_parameters=dialog_box_parameters) + self.current_flow.run(dialog_box_parameters=dialog_box_parameters) else: self.state.value = "ON" raise QueueExecutionException("dialog_box_parameters is empty", self) @@ -497,17 +500,17 @@ def start_prefect_workflow(self, sample_id: int | None) -> None: elif self.workflow_name == PrefectFlows.partial_udc: logging.getLogger("HWR").info(f"Starting workflow: {self.workflow_name}") - self.partial_udc_flow = PartialUDCFlow( + self.current_flow = PartialUDCFlow( state=self._state, resolution=self.resolution, sample_id=sample_id, ) - dialog_box_parameters = self.open_dialog(self.partial_udc_flow.dialog_box()) + dialog_box_parameters = self.open_dialog(self.current_flow.dialog_box()) if dialog_box_parameters: logging.getLogger("HWR").info( f"Dialog box parameters: {dialog_box_parameters}" ) - self.partial_udc_flow.run(dialog_box_parameters=dialog_box_parameters) + self.current_flow.run(dialog_box_parameters=dialog_box_parameters) else: self.state.value = "ON" raise QueueExecutionException("dialog_box_parameters is empty", self) diff --git a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/abstract_flow.py b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/abstract_flow.py index df46552905..4d30be33f0 100644 --- a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/abstract_flow.py +++ b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/abstract_flow.py @@ -28,8 +28,8 @@ from .schemas.full_dataset import FullDatasetDialogBox from .schemas.grid_scan import GridScanDialogBox from .schemas.one_shot import OneShotDialogBox -from .schemas.prefect_workflow import PrefectFlows from .schemas.screening import ScreeningDialogBox +from .sync_prefect_client import MX3SyncPrefectClient class AbstractPrefectWorkflow(ABC): @@ -69,6 +69,7 @@ def __init__(self, state, resolution: Resolution, sample_id: int | None) -> None self.prefect_flow_aborted = False self.mxcubecore_workflow_aborted = False self.project_id_lab_name_map = None + self.prefect_client: None | MX3SyncPrefectClient = None if settings.BL_ACTIVE: self.robot_client = Client(host=settings.ROBOT_HOST, readonly=False) diff --git a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/full_dataset_collection_flow.py b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/full_dataset_collection_flow.py index dd9ecf3a2d..245f5f26b0 100644 --- a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/full_dataset_collection_flow.py +++ b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/full_dataset_collection_flow.py @@ -98,7 +98,7 @@ def run(self, dialog_box_parameters: dict) -> None: f"parameters sent to prefect flow {prefect_parameters}" ) - full_dataset_flow = MX3SyncPrefectClient( + self.prefect_client = MX3SyncPrefectClient( name=settings.FULL_DATASET_DEPLOYMENT_NAME, parameters=prefect_parameters ) @@ -106,7 +106,7 @@ def run(self, dialog_box_parameters: dict) -> None: self._save_dialog_box_params_to_redis(dialog_box_model) try: - full_dataset_flow.trigger_data_collection(sample_id) + self.prefect_client.trigger_data_collection(sample_id) logging.getLogger("user_level_log").info( "Dataset collection completed successfully." ) diff --git a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/grid_scan_flow.py b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/grid_scan_flow.py index 08e0ea2482..3b3180d1f5 100644 --- a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/grid_scan_flow.py +++ b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/grid_scan_flow.py @@ -182,12 +182,12 @@ def start_prefect_flow_and_get_results_from_redis( with the exception message. """ - grid_scan_flow = MX3SyncPrefectClient( + self.prefect_client = MX3SyncPrefectClient( name=settings.GRID_SCAN_DEPLOYMENT_NAME, parameters=prefect_parameters.model_dump(exclude_none=True), ) try: - flow_run_uuid = grid_scan_flow.trigger_grid_scan() + flow_run_uuid = self.prefect_client.trigger_grid_scan() logging.getLogger("HWR").info("Getting spotfinder results from redis...") logging.getLogger("HWR").info( @@ -238,6 +238,10 @@ def start_prefect_flow_and_get_results_from_redis( self.sample_view.set_grid_data( grid_id, heatmap_dict, data_file_path=None ) + else: + self._state.value = "ON" + self.mxcubecore_workflow_aborted = False + raise RuntimeError("Workflow aborted by the user.") self._state.value = "ON" self.mxcubecore_workflow_aborted = False @@ -246,7 +250,7 @@ def start_prefect_flow_and_get_results_from_redis( self._state.value = "ON" self.mxcubecore_workflow_aborted = False - grid_scan_flow.check_flow_state() + self.prefect_client.check_flow_state() logging.getLogger("user_level_log").error( f"Grid scan flow was not successful: {str(ex)}" diff --git a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/one_shot_flow.py b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/one_shot_flow.py index c4f5d81113..dd1d73785d 100644 --- a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/one_shot_flow.py +++ b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/one_shot_flow.py @@ -94,7 +94,7 @@ def run(self, dialog_box_parameters: dict) -> None: f"parameters sent to prefect flow {prefect_parameters}" ) - one_shot_flow = MX3SyncPrefectClient( + self.prefect_client = MX3SyncPrefectClient( name=settings.ONE_SHOT_DEPLOYMENT_NAME, parameters=prefect_parameters ) @@ -102,7 +102,7 @@ def run(self, dialog_box_parameters: dict) -> None: self._save_dialog_box_params_to_redis(dialog_box_model) try: - one_shot_flow.trigger_data_collection(sample_id) + self.prefect_client.trigger_data_collection(sample_id) logging.getLogger("user_level_log").info("One-shot completed successfully.") except Exception as ex: raise QueueExecutionException(str(ex), self) from ex diff --git a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/partial_udc.py b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/partial_udc.py index af80a588fc..b71bac0395 100644 --- a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/partial_udc.py +++ b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/partial_udc.py @@ -266,11 +266,11 @@ def run(self, dialog_box_parameters: dict) -> None: 1 if dialog_box_model.run_full_dataset else 0, ) - partial_udc_flow = MX3SyncPrefectClient( + self.prefect_client = MX3SyncPrefectClient( name=settings.PARTIAL_UDC_DEPLOYMENT_NAME, parameters=prefect_parameters ) try: - partial_udc_flow.trigger_data_collection(sample_id, mode="partial_udc") + self.prefect_client.trigger_data_collection(sample_id, mode="partial_udc") logging.getLogger("user_level_log").info( "Partial UDC completed successfully." ) diff --git a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/screening_flow.py b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/screening_flow.py index 360ca992fe..301e01415b 100644 --- a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/screening_flow.py +++ b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/screening_flow.py @@ -99,7 +99,7 @@ def run(self, dialog_box_parameters: dict) -> None: f"parameters sent to prefect flow {prefect_parameters}" ) - screening_flow = MX3SyncPrefectClient( + self.prefect_client = MX3SyncPrefectClient( name=settings.SCREENING_DEPLOYMENT_NAME, parameters=prefect_parameters ) @@ -107,7 +107,7 @@ def run(self, dialog_box_parameters: dict) -> None: self._save_dialog_box_params_to_redis(dialog_box_model) try: - screening_flow.trigger_data_collection(sample_id) + self.prefect_client.trigger_data_collection(sample_id) logging.getLogger("user_level_log").info( "Screening completed successfully." ) diff --git a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/sync_prefect_client.py b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/sync_prefect_client.py index ab71e121fe..d2935c1f10 100644 --- a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/sync_prefect_client.py +++ b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/sync_prefect_client.py @@ -1,5 +1,6 @@ import logging from enum import StrEnum +from time import perf_counter from typing import Literal from uuid import UUID @@ -54,7 +55,7 @@ def __init__(self, name: str, parameters: dict) -> None: """ self.parameters = parameters self.name = name - self.flow_run_id = None + self.flow_run_id: None | UUID = None self.redis_connection = redis.StrictRedis( host=settings.MXCUBE_REDIS_HOST, port=settings.MXCUBE_REDIS_PORT, @@ -150,6 +151,9 @@ def trigger_data_collection( if flow_state and flow_state.type == StateType.FAILED: logging.getLogger("user_level_log").error(flow_state.message) raise QueueExecutionException(flow_state.message, self) + if flow_state and flow_state.type == StateType.CANCELLED: + logging.getLogger("user_level_log").warning("Flow run was cancelled.") + raise QueueExecutionException("Flow run was cancelled.", self) def check_flow_state(self) -> None: """ @@ -167,6 +171,9 @@ def check_flow_state(self) -> None: if flow_state and flow_state.type == StateType.FAILED: logging.getLogger("user_level_log").error(flow_state.message) raise QueueExecutionException(flow_state.message, self) + if flow_state and flow_state.type == StateType.CANCELLED: + logging.getLogger("user_level_log").warning("Flow run was cancelled.") + raise QueueExecutionException("Flow run was cancelled.", self) def trigger_grid_scan(self) -> UUID: """ @@ -239,3 +246,33 @@ def get_flow_runs(self, flow_run_id: UUID, client: PrefectClient) -> list[FlowRu """ q = FlowRunFilter(id={"any_": [flow_run_id]}) return client.read_flow_runs(flow_run_filter=q) + + def cancel_flow_run(self, wait: bool = True, timeout: float = 10.0) -> bool: + """ + Cancel the current flow run. + """ + with get_client(sync_client=True) as client: + try: + client.set_flow_run_state( + self.flow_run_id, + state=State(type=StateType.CANCELLING, name="Cancelling"), + force=True, + ) + except Exception as ex: + logging.getLogger("HWR").error(f"Failed to cancel flow run: {ex}") + return False + + if not wait: + return True + + deadline = timeout + perf_counter() + flow_state = None + while flow_state != StateType.CANCELLED and perf_counter() < deadline: + flow_state = client.read_flow_run(self.flow_run_id).state + if flow_state and flow_state.type == StateType.CANCELLED: + return True + sleep(0.5) + logging.getLogger("HWR").warning( + "Flow run did not reach CANCELLED state within timeout" + ) + return False From 1d1fc636c521744ca8f2813d2e186bdd7a68af73 Mon Sep 17 00:00:00 2001 From: Francisco Hernandez Vivanco Date: Wed, 28 Jan 2026 14:31:03 +1100 Subject: [PATCH 2/3] update partial udc prefect payload and dialog box model --- .../ANSTO/prefect_flows/partial_udc.py | 8 +- .../prefect_flows/schemas/partial_udc.py | 179 +----------------- 2 files changed, 12 insertions(+), 175 deletions(-) diff --git a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/partial_udc.py b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/partial_udc.py index b71bac0395..f5f54a2de6 100644 --- a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/partial_udc.py +++ b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/partial_udc.py @@ -176,7 +176,7 @@ def run(self, dialog_box_parameters: dict) -> None: exposure_time=screening_model.exposure_time, number_of_passes=1, count_time=None, - number_of_frames=screening_model.number_of_frames, + degrees_per_frame=screening_model.degrees_per_frame, detector_distance=self._resolution_to_distance( screening_model.resolution, energy=photon_energy, @@ -194,7 +194,7 @@ def run(self, dialog_box_parameters: dict) -> None: exposure_time=full_dataset_model.exposure_time, number_of_passes=1, count_time=None, - number_of_frames=full_dataset_model.number_of_frames, + degrees_per_frame=full_dataset_model.degrees_per_frame, detector_distance=self._resolution_to_distance( full_dataset_model.resolution, energy=photon_energy, @@ -347,9 +347,9 @@ def dialog_box(self) -> dict: "required": [ "exposure_time", "omega_range", - "number_of_frames", "resolution", "transmission", + "degrees_per_frame", ], } } @@ -366,10 +366,10 @@ def dialog_box(self) -> dict: "required": [ "exposure_time", "omega_range", - "number_of_frames", "resolution", "transmission", "processing_pipeline", + "degrees_per_frame", ], } } diff --git a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/schemas/partial_udc.py b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/schemas/partial_udc.py index 7bbd786da0..0cf61ef281 100644 --- a/mxcubecore/HardwareObjects/ANSTO/prefect_flows/schemas/partial_udc.py +++ b/mxcubecore/HardwareObjects/ANSTO/prefect_flows/schemas/partial_udc.py @@ -66,178 +66,15 @@ class GridScanParams(BaseModel): class DataCollectionBase(BaseModel): - - start_omega: float = Field( - default=0, description="Output from PyBest. Measured in degrees." - ) - omega_range: PositiveFloat = Field( - description="Output from PyBest. Measured in degrees." - ) + omega_range: float + exposure_time: PositiveFloat number_of_passes: int = 1 - count_time: PositiveFloat | None = None - - detector_distance: PositiveFloat = Field( - default=0.3, description="Output from PyBest. Measured in m." - ) - photon_energy: PositiveFloat = Field( - default=13, description="Global default. Measured in keV." - ) - transmission: float = Field(strict=True, ge=0, le=1, default=0.1) - beam_size: tuple[PositiveInt, PositiveInt] | list[PositiveInt] = Field( - default=(80, 80), - description="Determined by the crystal finder. Not currently used. " - "Measured in um.", - ) - - # Any pair of the following parameters can be defined: - exposure_time: PositiveFloat | None = Field( - default=None, description="Measured in seconds." - ) - number_of_frames: PositiveInt | None = Field( - default=None, - ) - oscillation_speed: PositiveFloat | None = Field( - default=None, - description="Measured in degrees/s", - ) - frame_rate: PositiveFloat | None = Field( - default=None, - description="Measured in Hz", - ) - - @model_validator(mode="after") - def calculate_params(self): # noqa - if len(self.__dict__) == 0: - return self - - exposure_time = self.exposure_time - number_of_frames = self.number_of_frames - oscillation_speed = self.oscillation_speed - frame_rate = self.frame_rate - omega_range = self.omega_range - - # Ensure exactly two parameters are set - self.ensure_params_are_consistent( - exposure_time, number_of_frames, oscillation_speed, frame_rate, omega_range - ) - - # Calculate the missing parameters - if exposure_time is None: - exposure_time = self.calculate_exposure_time( - number_of_frames, oscillation_speed, frame_rate, omega_range - ) - self.exposure_time = exposure_time - if number_of_frames is None: - number_of_frames = self.calculate_number_of_frames( - exposure_time, oscillation_speed, frame_rate, omega_range - ) - self.number_of_frames = number_of_frames - if oscillation_speed is None: - oscillation_speed = self.calculate_oscillation_speed( - exposure_time, number_of_frames, frame_rate, omega_range - ) - self.oscillation_speed = oscillation_speed - if frame_rate is None: - frame_rate = self.calculate_frame_rate(exposure_time, number_of_frames) - self.frame_rate = frame_rate - - return self - - def ensure_params_are_consistent( - self, - exposure_time, - number_of_frames, - oscillation_speed, - frame_rate, - omega_range, - ): - set_params = [] - for param in [ - exposure_time, - number_of_frames, - oscillation_speed, - frame_rate, - ]: - if param is not None: - set_params.append(param) - - if len(set_params) == 4: - if round(exposure_time, 3) != round(number_of_frames / frame_rate, 3): - raise ConsistencyError( - "Exposure time, number of frames, and frame rate are inconsistent." - ) - if round(oscillation_speed, 3) != round( - omega_range * frame_rate / number_of_frames, 3 - ): - raise ConsistencyError( - "Oscillation speed, omega range, and number of frames are " - "inconsistent." - ) - elif len(set_params) == 3: - if exposure_time is None: - if round(oscillation_speed, 3) != round( - omega_range * frame_rate / number_of_frames, 3 - ): - raise ConsistencyError( - "Oscillation speed, omega range, and number of frames are " - "inconsistent." - ) - elif number_of_frames is None: - if round(exposure_time, 3) != round(omega_range / oscillation_speed, 3): - raise ConsistencyError( - "Exposure time, omega range, and oscillation speed are " - "inconsistent." - ) - elif oscillation_speed is None: - if round(exposure_time, 3) != round(number_of_frames / frame_rate, 3): - raise ConsistencyError( - "Exposure time, number of frames, and frame rate are inconsistent." - ) - elif frame_rate is None: - if round(exposure_time, 3) != round(omega_range / oscillation_speed, 3): - raise ConsistencyError( - "Exposure time, number of frames, and oscillation speed are " - "inconsistent." - ) - elif len(set_params) < 1: - raise ConsistencyError( - "Exactly 2 or more parameters of 'exposure_time', 'number_of_frames', " - "'oscillation_speed', 'frame_rate' must be set." - ) - - def calculate_exposure_time( - self, number_of_frames, oscillation_speed, frame_rate, omega_range - ): - if number_of_frames is None and frame_rate is not None: - number_of_frames = omega_range * frame_rate / oscillation_speed - elif number_of_frames and oscillation_speed: - frame_rate = number_of_frames * oscillation_speed / omega_range - return number_of_frames / frame_rate - - def calculate_number_of_frames( - self, exposure_time, oscillation_speed, frame_rate, omega_range - ): - if exposure_time and frame_rate: - return round(exposure_time * frame_rate) - elif exposure_time and oscillation_speed: - raise ValueError( - "Cannot calculate frame rate and number of frames " - "from exposure time and oscillation speed" - ) - - @staticmethod - def calculate_oscillation_speed( - exposure_time, number_of_frames, frame_rate, omega_range - ): - if number_of_frames is not None and exposure_time is not None: - frame_rate = number_of_frames / exposure_time - elif exposure_time is not None and frame_rate is not None: - number_of_frames = exposure_time * frame_rate - return omega_range * frame_rate / number_of_frames - - @staticmethod - def calculate_frame_rate(exposure_time, number_of_frames): - return number_of_frames / exposure_time + count_time: float | None = None + degrees_per_frame: float + detector_distance: PositiveFloat + photon_energy: PositiveFloat + transmission: float = Field(strict=True, ge=0, le=1) + beam_size: tuple[int, int] = (80, 80) class ScreeningParams(DataCollectionBase): From 7a1d2b92fed4c97733b9d87a38cb964657787dca Mon Sep 17 00:00:00 2001 From: Francisco Hernandez Vivanco Date: Wed, 28 Jan 2026 15:26:39 +1100 Subject: [PATCH 3/3] version bump --- poetry.lock | 417 ++++++++++++++++++++++++++++++++++++++----------- pyproject.toml | 6 +- 2 files changed, 328 insertions(+), 95 deletions(-) diff --git a/poetry.lock b/poetry.lock index f1d626b16d..0a22364fd7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -326,6 +326,27 @@ pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} [package.extras] dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] +[[package]] +name = "beartype" +version = "0.22.9" +description = "Unbearably fast near-real-time pure-Python runtime-static type-checker." +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version >= \"3.10\" and extra == \"prefect\"" +files = [ + {file = "beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2"}, + {file = "beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f"}, +] + +[package.extras] +dev = ["autoapi (>=0.9.0)", "celery", "click", "coverage (>=5.5)", "docutils (>=0.22.0)", "equinox ; sys_platform == \"linux\" and python_version < \"3.15.0\"", "fastmcp ; python_version < \"3.14.0\"", "jax[cpu] ; sys_platform == \"linux\" and python_version < \"3.15.0\"", "jaxtyping ; sys_platform == \"linux\"", "langchain ; python_version < \"3.14.0\" and sys_platform != \"darwin\" and platform_python_implementation != \"PyPy\"", "mypy (>=0.800) ; platform_python_implementation != \"PyPy\"", "nuitka (>=1.2.6) ; sys_platform == \"linux\" and python_version < \"3.14.0\"", "numba ; python_version < \"3.14.0\"", "numpy ; python_version < \"3.15.0\" and sys_platform != \"darwin\" and platform_python_implementation != \"PyPy\"", "pandera (>=0.26.0) ; python_version < \"3.14.0\"", "poetry", "polars ; python_version < \"3.14.0\"", "pydata-sphinx-theme (<=0.7.2)", "pygments", "pyinstaller", "pyright (>=1.1.370)", "pytest (>=6.2.0)", "redis", "rich-click", "setuptools", "sphinx", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)", "sqlalchemy", "torch ; sys_platform == \"linux\" and python_version < \"3.14.0\"", "tox (>=3.20.1)", "typer", "typing-extensions (>=3.10.0.0)", "xarray ; python_version < \"3.15.0\""] +doc-ghp = ["mkdocs-material[imaging] (>=9.6.0)", "mkdocstrings-python (>=1.16.0)", "mkdocstrings-python-xref (>=1.16.0)"] +doc-rtd = ["autoapi (>=0.9.0)", "pydata-sphinx-theme (<=0.7.2)", "setuptools", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)"] +test = ["celery", "click", "coverage (>=5.5)", "docutils (>=0.22.0)", "equinox ; sys_platform == \"linux\" and python_version < \"3.15.0\"", "fastmcp ; python_version < \"3.14.0\"", "jax[cpu] ; sys_platform == \"linux\" and python_version < \"3.15.0\"", "jaxtyping ; sys_platform == \"linux\"", "langchain ; python_version < \"3.14.0\" and sys_platform != \"darwin\" and platform_python_implementation != \"PyPy\"", "mypy (>=0.800) ; platform_python_implementation != \"PyPy\"", "nuitka (>=1.2.6) ; sys_platform == \"linux\" and python_version < \"3.14.0\"", "numba ; python_version < \"3.14.0\"", "numpy ; python_version < \"3.15.0\" and sys_platform != \"darwin\" and platform_python_implementation != \"PyPy\"", "pandera (>=0.26.0) ; python_version < \"3.14.0\"", "poetry", "polars ; python_version < \"3.14.0\"", "pygments", "pyinstaller", "pyright (>=1.1.370)", "pytest (>=6.2.0)", "redis", "rich-click", "sphinx", "sqlalchemy", "torch ; sys_platform == \"linux\" and python_version < \"3.14.0\"", "tox (>=3.20.1)", "typer", "typing-extensions (>=3.10.0.0)", "xarray ; python_version < \"3.15.0\""] +test-tox = ["celery", "click", "docutils (>=0.22.0)", "equinox ; sys_platform == \"linux\" and python_version < \"3.15.0\"", "fastmcp ; python_version < \"3.14.0\"", "jax[cpu] ; sys_platform == \"linux\" and python_version < \"3.15.0\"", "jaxtyping ; sys_platform == \"linux\"", "langchain ; python_version < \"3.14.0\" and sys_platform != \"darwin\" and platform_python_implementation != \"PyPy\"", "mypy (>=0.800) ; platform_python_implementation != \"PyPy\"", "nuitka (>=1.2.6) ; sys_platform == \"linux\" and python_version < \"3.14.0\"", "numba ; python_version < \"3.14.0\"", "numpy ; python_version < \"3.15.0\" and sys_platform != \"darwin\" and platform_python_implementation != \"PyPy\"", "pandera (>=0.26.0) ; python_version < \"3.14.0\"", "poetry", "polars ; python_version < \"3.14.0\"", "pygments", "pyinstaller", "pyright (>=1.1.370)", "pytest (>=6.2.0)", "redis", "rich-click", "sphinx", "sqlalchemy", "torch ; sys_platform == \"linux\" and python_version < \"3.14.0\"", "typer", "typing-extensions (>=3.10.0.0)", "xarray ; python_version < \"3.15.0\""] +test-tox-coverage = ["coverage (>=5.5)"] + [[package]] name = "beautifulsoup4" version = "4.14.2" @@ -1230,7 +1251,7 @@ description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.9\" and python_version < \"3.11\"" +markers = "python_version == \"3.9\"" files = [ {file = "coverage-7.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fc04cc7a3db33664e0c2d10eb8990ff6b3536f6842c9590ae8da4c614b9ed05a"}, {file = "coverage-7.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e201e015644e207139f7e2351980feb7040e6f4b2c2978892f3e3789d1c125e5"}, @@ -1351,7 +1372,7 @@ description = "Code coverage measurement for Python" optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\"" files = [ {file = "coverage-7.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eb53f1e8adeeb2e78962bade0c08bfdc461853c7969706ed901821e009b35e31"}, {file = "coverage-7.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9a03ec6cb9f40a5c360f138b88266fd8f58408d71e89f536b4f91d85721d075"}, @@ -1447,6 +1468,9 @@ files = [ {file = "coverage-7.11.0.tar.gz", hash = "sha256:167bd504ac1ca2af7ff3b81d245dfea0292c5032ebef9d66cc08a7d28c1b8050"}, ] +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + [package.extras] toml = ["tomli ; python_full_version <= \"3.11.0a6\""] @@ -1773,6 +1797,36 @@ files = [ [package.extras] yaml = ["PyYAML"] +[[package]] +name = "fakeredis" +version = "2.33.0" +description = "Python implementation of redis API, can be used for testing purposes." +optional = true +python-versions = ">=3.7" +groups = ["main"] +markers = "python_version >= \"3.10\" and extra == \"prefect\"" +files = [ + {file = "fakeredis-2.33.0-py3-none-any.whl", hash = "sha256:de535f3f9ccde1c56672ab2fdd6a8efbc4f2619fc2f1acc87b8737177d71c965"}, + {file = "fakeredis-2.33.0.tar.gz", hash = "sha256:d7bc9a69d21df108a6451bbffee23b3eba432c21a654afc7ff2d295428ec5770"}, +] + +[package.dependencies] +lupa = {version = ">=2.1", optional = true, markers = "extra == \"lua\""} +redis = [ + {version = ">=4.3", markers = "python_version > \"3.8\""}, + {version = ">=4.3", markers = "python_version >= \"3.10\""}, +] +sortedcontainers = ">=2" +typing-extensions = {version = ">=4.7,<5.0", markers = "python_version < \"3.11\""} + +[package.extras] +bf = ["pyprobables (>=0.6)"] +cf = ["pyprobables (>=0.6)"] +json = ["jsonpath-ng (>=1.6)"] +lua = ["lupa (>=2.1)"] +probabilistic = ["pyprobables (>=0.6)"] +valkey = ["valkey (>=6) ; python_version >= \"3.8\""] + [[package]] name = "fastapi" version = "0.120.2" @@ -1822,7 +1876,7 @@ description = "A platform independent file lock." optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.9\" and python_version < \"3.11\"" +markers = "python_version == \"3.9\"" files = [ {file = "filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d"}, {file = "filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58"}, @@ -1835,7 +1889,7 @@ description = "A platform independent file lock." optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\"" files = [ {file = "filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2"}, {file = "filelock-3.20.0.tar.gz", hash = "sha256:711e943b4ec6be42e1d4e6690b48dc175c822967466bb31c0c293f34334c13f4"}, @@ -2853,7 +2907,7 @@ description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.8" groups = ["dev"] -markers = "python_version < \"3.11\"" +markers = "python_version < \"3.10\"" files = [ {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, @@ -2866,7 +2920,7 @@ description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.10" groups = ["dev"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\"" files = [ {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, @@ -3042,7 +3096,7 @@ description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.8" groups = ["main"] -markers = "python_version < \"3.11\"" +markers = "python_version < \"3.10\"" files = [ {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8a9c83f75223d5e48b0bc9cb1bf2776cf01563e00ade8775ffe13b0b6e1af3a6"}, {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58370b1ffbd35407444d57057b57da5d6549d2d854fa30249771775c63b5fe17"}, @@ -3167,7 +3221,7 @@ description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.10" groups = ["main"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\"" files = [ {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b4b4d74bda2b8ebf4da5bd42af11d02d04428b2c32846e4c2c93219df8a7987b"}, {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fb3b8132019ea572f4611d770991000d7f58127560c4889729248eb5852a102f"}, @@ -3318,6 +3372,105 @@ opencv-python = ">=2.4" dev = ["black", "flake8", "pytest"] test = ["pytest"] +[[package]] +name = "lupa" +version = "2.6" +description = "Python wrapper around Lua and LuaJIT" +optional = true +python-versions = "*" +groups = ["main"] +markers = "python_version >= \"3.10\" and extra == \"prefect\"" +files = [ + {file = "lupa-2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b3dabda836317e63c5ad052826e156610f356a04b3003dfa0dbe66b5d54d671"}, + {file = "lupa-2.6-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8726d1c123bbe9fbb974ce29825e94121824e66003038ff4532c14cc2ed0c51c"}, + {file = "lupa-2.6-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:f4e159e7d814171199b246f9235ca8961f6461ea8c1165ab428afa13c9289a94"}, + {file = "lupa-2.6-cp310-cp310-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:202160e80dbfddfb79316692a563d843b767e0f6787bbd1c455f9d54052efa6c"}, + {file = "lupa-2.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5deede7c5b36ab64f869dae4831720428b67955b0bb186c8349cf6ea121c852b"}, + {file = "lupa-2.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86f04901f920bbf7c0cac56807dc9597e42347123e6f1f3ca920f15f54188ce5"}, + {file = "lupa-2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6deef8f851d6afb965c84849aa5b8c38856942df54597a811ce0369ced678610"}, + {file = "lupa-2.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:21f2b5549681c2a13b1170a26159d30875d367d28f0247b81ca347222c755038"}, + {file = "lupa-2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:66eea57630eab5e6f49fdc5d7811c0a2a41f2011be4ea56a087ea76112011eb7"}, + {file = "lupa-2.6-cp310-cp310-win32.whl", hash = "sha256:60a403de8cab262a4fe813085dd77010effa6e2eb1886db2181df803140533b1"}, + {file = "lupa-2.6-cp310-cp310-win_amd64.whl", hash = "sha256:e4656a39d93dfa947cf3db56dc16c7916cb0cc8024acd3a952071263f675df64"}, + {file = "lupa-2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6d988c0f9331b9f2a5a55186701a25444ab10a1432a1021ee58011499ecbbdd5"}, + {file = "lupa-2.6-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ebe1bbf48259382c72a6fe363dea61a0fd6fe19eab95e2ae881e20f3654587bf"}, + {file = "lupa-2.6-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:a8fcee258487cf77cdd41560046843bb38c2e18989cd19671dd1e2596f798306"}, + {file = "lupa-2.6-cp311-cp311-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:561a8e3be800827884e767a694727ed8482d066e0d6edfcbf423b05e63b05535"}, + {file = "lupa-2.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af880a62d47991cae78b8e9905c008cbfdc4a3a9723a66310c2634fc7644578c"}, + {file = "lupa-2.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80b22923aa4023c86c0097b235615f89d469a0c4eee0489699c494d3367c4c85"}, + {file = "lupa-2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:153d2cc6b643f7efb9cfc0c6bb55ec784d5bac1a3660cfc5b958a7b8f38f4a75"}, + {file = "lupa-2.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3fa8777e16f3ded50b72967dc17e23f5a08e4f1e2c9456aff2ebdb57f5b2869f"}, + {file = "lupa-2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8dbdcbe818c02a2f56f5ab5ce2de374dab03e84b25266cfbaef237829bc09b3f"}, + {file = "lupa-2.6-cp311-cp311-win32.whl", hash = "sha256:defaf188fde8f7a1e5ce3a5e6d945e533b8b8d547c11e43b96c9b7fe527f56dc"}, + {file = "lupa-2.6-cp311-cp311-win_amd64.whl", hash = "sha256:9505ae600b5c14f3e17e70f87f88d333717f60411faca1ddc6f3e61dce85fa9e"}, + {file = "lupa-2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:47ce718817ef1cc0c40d87c3d5ae56a800d61af00fbc0fad1ca9be12df2f3b56"}, + {file = "lupa-2.6-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7aba985b15b101495aa4b07112cdc08baa0c545390d560ad5cfde2e9e34f4d58"}, + {file = "lupa-2.6-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:b766f62f95b2739f2248977d29b0722e589dcf4f0ccfa827ccbd29f0148bd2e5"}, + {file = "lupa-2.6-cp312-cp312-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:00a934c23331f94cb51760097ebfab14b005d55a6b30a2b480e3c53dd2fa290d"}, + {file = "lupa-2.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21de9f38bd475303e34a042b7081aabdf50bd9bafd36ce4faea2f90fd9f15c31"}, + {file = "lupa-2.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf3bda96d3fc41237e964a69c23647d50d4e28421111360274d4799832c560e9"}, + {file = "lupa-2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a76ead245da54801a81053794aa3975f213221f6542d14ec4b859ee2e7e0323"}, + {file = "lupa-2.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8dd0861741caa20886ddbda0a121d8e52fb9b5bb153d82fa9bba796962bf30e8"}, + {file = "lupa-2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:239e63948b0b23023f81d9a19a395e768ed3da6a299f84e7963b8f813f6e3f9c"}, + {file = "lupa-2.6-cp312-cp312-win32.whl", hash = "sha256:325894e1099499e7a6f9c351147661a2011887603c71086d36fe0f964d52d1ce"}, + {file = "lupa-2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c735a1ce8ee60edb0fe71d665f1e6b7c55c6021f1d340eb8c865952c602cd36f"}, + {file = "lupa-2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:663a6e58a0f60e7d212017d6678639ac8df0119bc13c2145029dcba084391310"}, + {file = "lupa-2.6-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:d1f5afda5c20b1f3217a80e9bc1b77037f8a6eb11612fd3ada19065303c8f380"}, + {file = "lupa-2.6-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:26f2b3c085fe76e9119e48c1013c1cccdc1f51585d456858290475aa38e7089e"}, + {file = "lupa-2.6-cp313-cp313-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:60d2f902c7b96fb8ab98493dcff315e7bb4d0b44dc9dd76eb37de575025d5685"}, + {file = "lupa-2.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a02d25dee3a3250967c36590128d9220ae02f2eda166a24279da0b481519cbff"}, + {file = "lupa-2.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6eae1ee16b886b8914ff292dbefbf2f48abfbdee94b33a88d1d5475e02423203"}, + {file = "lupa-2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0edd5073a4ee74ab36f74fe61450148e6044f3952b8d21248581f3c5d1a58be"}, + {file = "lupa-2.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0c53ee9f22a8a17e7d4266ad48e86f43771951797042dd51d1494aaa4f5f3f0a"}, + {file = "lupa-2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:de7c0f157a9064a400d828789191a96da7f4ce889969a588b87ec80de9b14772"}, + {file = "lupa-2.6-cp313-cp313-win32.whl", hash = "sha256:ee9523941ae0a87b5b703417720c5d78f72d2f5bc23883a2ea80a949a3ed9e75"}, + {file = "lupa-2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b1335a5835b0a25ebdbc75cf0bda195e54d133e4d994877ef025e218c2e59db9"}, + {file = "lupa-2.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:dcb6d0a3264873e1653bc188499f48c1fb4b41a779e315eba45256cfe7bc33c1"}, + {file = "lupa-2.6-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:a37e01f2128f8c36106726cb9d360bac087d58c54b4522b033cc5691c584db18"}, + {file = "lupa-2.6-cp314-cp314-macosx_11_0_x86_64.whl", hash = "sha256:458bd7e9ff3c150b245b0fcfbb9bd2593d1152ea7f0a7b91c1d185846da033fe"}, + {file = "lupa-2.6-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:052ee82cac5206a02df77119c325339acbc09f5ce66967f66a2e12a0f3211cad"}, + {file = "lupa-2.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96594eca3c87dd07938009e95e591e43d554c1dbd0385be03c100367141db5a8"}, + {file = "lupa-2.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8faddd9d198688c8884091173a088a8e920ecc96cda2ffed576a23574c4b3f6"}, + {file = "lupa-2.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:daebb3a6b58095c917e76ba727ab37b27477fb926957c825205fbda431552134"}, + {file = "lupa-2.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f3154e68972befe0f81564e37d8142b5d5d79931a18309226a04ec92487d4ea3"}, + {file = "lupa-2.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e4dadf77b9fedc0bfa53417cc28dc2278a26d4cbd95c29f8927ad4d8fe0a7ef9"}, + {file = "lupa-2.6-cp314-cp314-win32.whl", hash = "sha256:cb34169c6fa3bab3e8ac58ca21b8a7102f6a94b6a5d08d3636312f3f02fafd8f"}, + {file = "lupa-2.6-cp314-cp314-win_amd64.whl", hash = "sha256:b74f944fe46c421e25d0f8692aef1e842192f6f7f68034201382ac440ef9ea67"}, + {file = "lupa-2.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0e21b716408a21ab65723f8841cf7f2f37a844b7a965eeabb785e27fca4099cf"}, + {file = "lupa-2.6-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:589db872a141bfff828340079bbdf3e9a31f2689f4ca0d88f97d9e8c2eae6142"}, + {file = "lupa-2.6-cp314-cp314t-macosx_11_0_x86_64.whl", hash = "sha256:cd852a91a4a9d4dcbb9a58100f820a75a425703ec3e3f049055f60b8533b7953"}, + {file = "lupa-2.6-cp314-cp314t-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:0334753be028358922415ca97a64a3048e4ed155413fc4eaf87dd0a7e2752983"}, + {file = "lupa-2.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:661d895cd38c87658a34780fac54a690ec036ead743e41b74c3fb81a9e65a6aa"}, + {file = "lupa-2.6-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6aa58454ccc13878cc177c62529a2056be734da16369e451987ff92784994ca7"}, + {file = "lupa-2.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1425017264e470c98022bba8cff5bd46d054a827f5df6b80274f9cc71dafd24f"}, + {file = "lupa-2.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:224af0532d216e3105f0a127410f12320f7c5f1aa0300bdf9646b8d9afb0048c"}, + {file = "lupa-2.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9abb98d5a8fd27c8285302e82199f0e56e463066f88f619d6594a450bf269d80"}, + {file = "lupa-2.6-cp314-cp314t-win32.whl", hash = "sha256:1849efeba7a8f6fb8aa2c13790bee988fd242ae404bd459509640eeea3d1e291"}, + {file = "lupa-2.6-cp314-cp314t-win_amd64.whl", hash = "sha256:fc1498d1a4fc028bc521c26d0fad4ca00ed63b952e32fb95949bda76a04bad52"}, + {file = "lupa-2.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9591700991e333b70dd92b48f152eb4731b8b24af671a9f6f721b74d68ed4499"}, + {file = "lupa-2.6-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:ef8dfa7fe08bc3f4591411b8945bbeb15af8512c3e7ad5e9b1e3a9036cdbbce7"}, + {file = "lupa-2.6-cp38-cp38-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:728c466e91174dad238f8a9c1cbdb8e69ffe559df85f87ee76edac3395300949"}, + {file = "lupa-2.6-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c781170bc7134704ae317a66204d30688b41d3e471e17e659987ea4947e11f20"}, + {file = "lupa-2.6-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241f4ddab33b9a686fc76667241bebc39a06b74ec40d79ec222f5add9000fe57"}, + {file = "lupa-2.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:c17f6b6193ced33cc7ca0b2b08b319a1b3501b014a3a3f9999c01cafc04c40f5"}, + {file = "lupa-2.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:fa6c1379e83d4104065c151736250a09f3a99e368423c7a20f9c59b15945e9fc"}, + {file = "lupa-2.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aef1a8bc10c50695e1a33a07dbef803b93eb97fc150fdb19858d704a603a67dd"}, + {file = "lupa-2.6-cp38-cp38-win32.whl", hash = "sha256:10c191bc1d5565e4360d884bea58320975ddb33270cdf9a9f55d1a1efe79aa03"}, + {file = "lupa-2.6-cp38-cp38-win_amd64.whl", hash = "sha256:05681f8ffb41f0c7fbb9ca859cc3a7e4006e9c6350d25358b535c5295c6a9928"}, + {file = "lupa-2.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8897dc6c3249786b2cdf2f83324febb436193d4581b6a71dea49f77bf8b19bb0"}, + {file = "lupa-2.6-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:4446396ca3830be0c106c70db4b4f622c37b2d447874c07952cafb9c57949a4a"}, + {file = "lupa-2.6-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:5826e687c89995a6eaafeae242071ba16448eec1a9ee8e17ed48551b5d1e21c2"}, + {file = "lupa-2.6-cp39-cp39-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:5871935cb36d1d22f9c04ac0db75c06751bd95edcfa0d9309f732de908e297a9"}, + {file = "lupa-2.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:43eb6e43ea8512d0d65b995d36dd9d77aa02598035e25b84c23a1b58700c9fb2"}, + {file = "lupa-2.6-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:559714053018d9885cc8c36a33c5b7eb9aad30fb6357719cac3ce4dc6b39157e"}, + {file = "lupa-2.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:57ac88a00ce59bd9d4ddcd4fca8e02564765725f5068786b011c9d1be3de20c5"}, + {file = "lupa-2.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:b683fbd867c2e54c44a686361b75eee7e7a790da55afdbe89f1f23b106de0274"}, + {file = "lupa-2.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d2f656903a2ed2e074bf2b7d300968028dfa327a45b055be8e3b51ef0b82f9bf"}, + {file = "lupa-2.6-cp39-cp39-win32.whl", hash = "sha256:bf28f68ae231b72008523ab5ac23835ba0f76e0e99ec38b59766080a84eb596a"}, + {file = "lupa-2.6-cp39-cp39-win_amd64.whl", hash = "sha256:b4b2e9b3795a9897cf6cfcc58d08210fdc0d13ab47c9a0e13858c68932d8353c"}, + {file = "lupa-2.6.tar.gz", hash = "sha256:9a770a6e89576be3447668d7ced312cd6fd41d3c13c2462c9dc2c2ab570e45d9"}, +] + [[package]] name = "lxml" version = "4.9.4" @@ -3739,7 +3892,7 @@ description = "Python plotting package" optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_version >= \"3.9\" and python_version < \"3.11\"" +markers = "python_version == \"3.9\"" files = [ {file = "matplotlib-3.9.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c5fdd7abfb706dfa8d307af64a87f1a862879ec3cd8d0ec8637458f0885b9c50"}, {file = "matplotlib-3.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d89bc4e85e40a71d1477780366c27fb7c6494d293e1617788986f74e2a03d7ff"}, @@ -3806,7 +3959,7 @@ description = "Python plotting package" optional = false python-versions = ">=3.10" groups = ["main"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\"" files = [ {file = "matplotlib-3.10.7-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7ac81eee3b7c266dd92cee1cd658407b16c57eed08c7421fa354ed68234de380"}, {file = "matplotlib-3.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:667ecd5d8d37813a845053d8f5bf110b534c3c9f30e69ebd25d4701385935a6d"}, @@ -3886,7 +4039,7 @@ description = "Collection of plugins for markdown-it-py" optional = false python-versions = ">=3.8" groups = ["docs"] -markers = "python_version < \"3.11\"" +markers = "python_version < \"3.10\"" files = [ {file = "mdit_py_plugins-0.4.2-py3-none-any.whl", hash = "sha256:0c673c3f889399a33b95e88d2f0d111b4447bdfea7f237dab2d488f459835636"}, {file = "mdit_py_plugins-0.4.2.tar.gz", hash = "sha256:5f2cd1fdb606ddf152d37ec30e46101a60512bc0e5fa1a7002c36647b09e26b5"}, @@ -3907,7 +4060,7 @@ description = "Collection of plugins for markdown-it-py" optional = false python-versions = ">=3.10" groups = ["docs"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\"" files = [ {file = "mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f"}, {file = "mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6"}, @@ -4049,7 +4202,7 @@ resolved_reference = "0933859b08ce3509a9aae7e7f0018d3b4d353b7c" [[package]] name = "mx3-beamline-library" -version = "2.4.6" +version = "2.4.8" description = "Ophyd devices and bluesky plans." optional = false python-versions = ">=3.11,<3.13" @@ -4092,8 +4245,8 @@ as-dependencies = ["as-acquisition-library @ git+https://bitbucket.synchrotron.o [package.source] type = "git" url = "https://github.com/AustralianSynchrotron/mx3-beamline-library.git" -reference = "v2.4.6" -resolved_reference = "b3550fa82ad2e2da5da11e5803c4906a1e8383d1" +reference = "v2.4.8" +resolved_reference = "da7e6a326f955d54863d231c6a09eb2daf54ee61" [[package]] name = "myst-parser" @@ -4228,7 +4381,7 @@ description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_version >= \"3.9\" and python_version < \"3.11\"" +markers = "python_version == \"3.9\"" files = [ {file = "numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece"}, {file = "numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04"}, @@ -4284,7 +4437,7 @@ description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.10" groups = ["main"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\"" files = [ {file = "numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb"}, {file = "numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90"}, @@ -5026,7 +5179,7 @@ description = "A small Python package for determining appropriate platform-speci optional = false python-versions = ">=3.9" groups = ["dev"] -markers = "python_version >= \"3.9\" and python_version < \"3.11\"" +markers = "python_version == \"3.9\"" files = [ {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"}, {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"}, @@ -5044,11 +5197,11 @@ description = "A small Python package for determining appropriate platform-speci optional = false python-versions = ">=3.10" groups = ["main", "dev"] -markers = "python_version == \"3.11\"" files = [ {file = "platformdirs-4.5.0-py3-none-any.whl", hash = "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3"}, {file = "platformdirs-4.5.0.tar.gz", hash = "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312"}, ] +markers = {main = "python_version == \"3.11\"", dev = "python_version >= \"3.10\""} [package.extras] docs = ["furo (>=2025.9.25)", "proselint (>=0.14)", "sphinx (>=8.2.3)", "sphinx-autodoc-typehints (>=3.2)"] @@ -5103,12 +5256,12 @@ version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.9" -groups = ["dev"] -markers = "python_version >= \"3.9\"" +groups = ["main", "dev"] files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, ] +markers = {main = "python_version >= \"3.10\" and extra == \"prefect\"", dev = "python_version >= \"3.9\""} [package.extras] dev = ["pre-commit", "tox"] @@ -5156,15 +5309,15 @@ virtualenv = ">=20.10.0" [[package]] name = "prefect" -version = "3.4.22" +version = "3.6.10" description = "Workflow orchestration and management." optional = true -python-versions = "<3.14,>=3.9" +python-versions = "<3.15,>=3.10" groups = ["main"] markers = "python_version >= \"3.10\" and extra == \"prefect\"" files = [ - {file = "prefect-3.4.22-py3-none-any.whl", hash = "sha256:41743e2817195e1ef8fdef2e65c4b16da1308cf8f5dd1a85e679c8cbe7186710"}, - {file = "prefect-3.4.22.tar.gz", hash = "sha256:4b46a793e9907a4c8539b04bb2fdbc609c9810f690d7673a3bc8d0c9aebdfc84"}, + {file = "prefect-3.6.10-py3-none-any.whl", hash = "sha256:6544c33fe87be657a7b3187f4ef42edd1b153ffc75531717cc05afcb2c8392fe"}, + {file = "prefect-3.6.10.tar.gz", hash = "sha256:b300aecdb26fde32f34c6689d29a2f9782fdcbe54107460470ba6097201e3179"}, ] [package.dependencies] @@ -5198,34 +5351,36 @@ orjson = ">=3.7,<4.0" packaging = ">=21.3,<25.1" pathspec = ">=0.8.0" pendulum = {version = ">=3.0.0,<4", markers = "python_version < \"3.13\""} +pluggy = ">=1.6.0" prometheus-client = ">=0.20.0" pydantic = ">=2.10.1,<2.11.0 || >2.11.0,<2.11.1 || >2.11.1,<2.11.2 || >2.11.2,<2.11.3 || >2.11.3,<2.11.4 || >2.11.4,<3.0.0" pydantic-core = ">=2.12.0,<3.0.0" pydantic-extra-types = ">=2.8.2,<3.0.0" pydantic-settings = ">2.2.1,<2.9.0 || >2.9.0,<3.0.0" +pydocket = ">=0.16.2" python-dateutil = ">=2.8.2,<3.0.0" python-slugify = ">=5.0,<9.0" -python-socks = {version = ">=2.5.3,<3.0", extras = ["asyncio"]} pytz = ">=2021.1,<2026" pyyaml = ">=5.4.1,<7.0.0" readchar = ">=4.0.0,<5.0.0" rfc3339-validator = ">=0.1.4,<0.2.0" rich = ">=11.0,<15.0" ruamel-yaml = ">=0.17.0" +ruamel-yaml-clib = {version = ">=0.2.8", markers = "platform_python_implementation == \"CPython\""} semver = ">=3.0.4" sniffio = ">=1.3.0,<2.0.0" sqlalchemy = {version = ">=2.0,<3.0.0", extras = ["asyncio"]} toml = ">=0.10.0" -typer = ">=0.12.0,<0.12.2 || >0.12.2,<0.20.0" +typer = ">=0.16.0,<0.21.0" typing-extensions = ">=4.10.0,<5.0.0" -uv = ">=0.6.0" uvicorn = ">=0.14.0,<0.29.0 || >0.29.0" -websockets = ">=13.0,<16.0" +websockets = ">=15.0.1,<16.0" [package.extras] aws = ["prefect-aws (>=0.5.8)"] azure = ["prefect-azure (>=0.4.0)"] bitbucket = ["prefect-bitbucket (>=0.3.0)"] +bundles = ["uv (>=0.6.0)"] dask = ["prefect-dask (>=0.3.0)"] databricks = ["prefect-databricks (>=0.3.0)"] dbt = ["prefect-dbt (>=0.6.0)"] @@ -5309,6 +5464,60 @@ files = [ [package.extras] test = ["enum34 ; python_version <= \"3.4\"", "ipaddress ; python_version < \"3.0\"", "mock ; python_version < \"3.0\"", "pywin32 ; sys_platform == \"win32\"", "wmi ; sys_platform == \"win32\""] +[[package]] +name = "py-key-value-aio" +version = "0.3.0" +description = "Async Key-Value" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version >= \"3.10\" and extra == \"prefect\"" +files = [ + {file = "py_key_value_aio-0.3.0-py3-none-any.whl", hash = "sha256:1c781915766078bfd608daa769fefb97e65d1d73746a3dfb640460e322071b64"}, + {file = "py_key_value_aio-0.3.0.tar.gz", hash = "sha256:858e852fcf6d696d231266da66042d3355a7f9871650415feef9fca7a6cd4155"}, +] + +[package.dependencies] +beartype = ">=0.20.0" +cachetools = {version = ">=5.0.0", optional = true, markers = "extra == \"memory\""} +py-key-value-shared = "0.3.0" +redis = {version = ">=4.3.0", optional = true, markers = "extra == \"redis\""} + +[package.extras] +disk = ["diskcache (>=5.0.0)", "pathvalidate (>=3.3.1)"] +duckdb = ["duckdb (>=1.1.1)", "pytz (>=2025.2)"] +dynamodb = ["aioboto3 (>=13.3.0)", "types-aiobotocore-dynamodb (>=2.16.0)"] +elasticsearch = ["aiohttp (>=3.12)", "elasticsearch (>=8.0.0)"] +filetree = ["aiofile (>=3.5.0)", "anyio (>=4.4.0)"] +keyring = ["keyring (>=25.6.0)"] +keyring-linux = ["dbus-python (>=1.4.0)", "keyring (>=25.6.0)"] +memcached = ["aiomcache (>=0.8.0)"] +memory = ["cachetools (>=5.0.0)"] +mongodb = ["pymongo (>=4.0.0)"] +pydantic = ["pydantic (>=2.11.9)"] +redis = ["redis (>=4.3.0)"] +rocksdb = ["rocksdict (>=0.3.2) ; python_full_version < \"3.12.0\"", "rocksdict (>=0.3.24) ; python_full_version >= \"3.12.0\""] +valkey = ["valkey-glide (>=2.1.0)"] +vault = ["hvac (>=2.3.0)", "types-hvac (>=2.3.0)"] +wrappers-encryption = ["cryptography (>=45.0.0)"] + +[[package]] +name = "py-key-value-shared" +version = "0.3.0" +description = "Shared Key-Value" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version >= \"3.10\" and extra == \"prefect\"" +files = [ + {file = "py_key_value_shared-0.3.0-py3-none-any.whl", hash = "sha256:5b0efba7ebca08bb158b1e93afc2f07d30b8f40c2fc12ce24a4c0d84f42f9298"}, + {file = "py_key_value_shared-0.3.0.tar.gz", hash = "sha256:8fdd786cf96c3e900102945f92aa1473138ebe960ef49da1c833790160c28a4b"}, +] + +[package.dependencies] +beartype = ">=0.20.0" +typing-extensions = ">=4.15.0" + [[package]] name = "py4j" version = "0.10.9.7" @@ -5584,6 +5793,36 @@ files = [ [package.extras] dev = ["tox"] +[[package]] +name = "pydocket" +version = "0.17.3" +description = "A distributed background task system for Python functions" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version >= \"3.10\" and extra == \"prefect\"" +files = [ + {file = "pydocket-0.17.3-py3-none-any.whl", hash = "sha256:9ef2c6e855f52a3210acff300bcbcc45773d79295e2deddcc7aef7f67b2a5ba7"}, + {file = "pydocket-0.17.3.tar.gz", hash = "sha256:8922b4ca5f3f428e69b7695b9b5a313bbedc3ce35c74045cadcd89f7c0e6ac2d"}, +] + +[package.dependencies] +cloudpickle = ">=3.1.1" +exceptiongroup = {version = ">=1.2.0", markers = "python_version < \"3.11\""} +fakeredis = {version = ">=2.32.1", extras = ["lua"]} +opentelemetry-api = ">=1.33.0" +prometheus-client = ">=0.21.1" +py-key-value-aio = {version = ">=0.3.0", extras = ["memory", "redis"]} +python-json-logger = ">=2.0.7" +redis = ">=5" +rich = ">=13.9.4" +taskgroup = {version = ">=0.2.2", markers = "python_version < \"3.11\""} +typer = ">=0.15.1" +typing-extensions = ">=4.12.0" + +[package.extras] +metrics = ["opentelemetry-sdk (>=1.33.0)"] + [[package]] name = "pyepics" version = "3.5.7" @@ -5627,10 +5866,10 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pyjwt" version = "2.10.1" description = "JSON Web Token implementation in Python" -optional = false +optional = true python-versions = ">=3.9" groups = ["main"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\" and extra == \"prefect\" or python_version == \"3.11\"" files = [ {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, @@ -5916,6 +6155,22 @@ files = [ [package.extras] cli = ["click (>=5.0)"] +[[package]] +name = "python-json-logger" +version = "4.0.0" +description = "JSON Log Formatter for the Python Logging Package" +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version >= \"3.10\" and extra == \"prefect\"" +files = [ + {file = "python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2"}, + {file = "python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f"}, +] + +[package.extras] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "black", "build", "freezegun", "mdx_truly_sane_lists", "mike", "mkdocs", "mkdocs-awesome-pages-plugin", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-material (>=8.5)", "mkdocstrings[python]", "msgspec ; implementation_name != \"pypy\"", "mypy", "orjson ; implementation_name != \"pypy\"", "pylint", "pytest", "tzdata", "validate-pyproject[all]"] + [[package]] name = "python-ldap" version = "3.4.5" @@ -5950,28 +6205,6 @@ text-unidecode = ">=1.3" [package.extras] unidecode = ["Unidecode (>=1.1.1)"] -[[package]] -name = "python-socks" -version = "2.7.2" -description = "Proxy (SOCKS4, SOCKS5, HTTP CONNECT) client for Python" -optional = true -python-versions = ">=3.8.0" -groups = ["main"] -markers = "python_version >= \"3.10\" and extra == \"prefect\"" -files = [ - {file = "python_socks-2.7.2-py3-none-any.whl", hash = "sha256:d311aefbacc0ddfaa1fa1c32096c436d4fe75b899c24d78e677e1b0623c52c48"}, - {file = "python_socks-2.7.2.tar.gz", hash = "sha256:4c845d4700352bc7e7382f302dfc6baf0af0de34d2a6d70ba356b2539d4dbb62"}, -] - -[package.dependencies] -async-timeout = {version = ">=4.0", optional = true, markers = "python_version < \"3.11\" and extra == \"asyncio\""} - -[package.extras] -anyio = ["anyio (>=3.3.4,<5.0.0)"] -asyncio = ["async-timeout (>=4.0) ; python_version < \"3.11\""] -curio = ["curio (>=1.4)"] -trio = ["trio (>=0.24)"] - [[package]] name = "pytz" version = "2025.2" @@ -6117,10 +6350,10 @@ files = [ name = "redis" version = "5.3.1" description = "Python client for Redis database and key-value store" -optional = false +optional = true python-versions = ">=3.8" groups = ["main"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\" and extra == \"prefect\" or python_version == \"3.11\"" files = [ {file = "redis-5.3.1-py3-none-any.whl", hash = "sha256:dc1909bd24669cc31b5f67a039700b16ec30571096c5f1f0d9d2324bff31af97"}, {file = "redis-5.3.1.tar.gz", hash = "sha256:ca49577a531ea64039b5a36db3d6cd1a0c7a60c34124d46924a45b956e8cf14c"}, @@ -6158,7 +6391,7 @@ description = "JSON Referencing + Python" optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_version >= \"3.9\" and python_version < \"3.11\"" +markers = "python_version == \"3.9\"" files = [ {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, @@ -6176,7 +6409,7 @@ description = "JSON Referencing + Python" optional = false python-versions = ">=3.10" groups = ["main"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\"" files = [ {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, @@ -6536,7 +6769,7 @@ description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_version >= \"3.9\" and python_version < \"3.11\"" +markers = "python_version == \"3.9\"" files = [ {file = "rpds_py-0.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef"}, {file = "rpds_py-0.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be"}, @@ -6702,7 +6935,7 @@ description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.10" groups = ["main"] -markers = "python_version == \"3.11\"" +markers = "python_version >= \"3.10\"" files = [ {file = "rpds_py-0.28.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7b6013db815417eeb56b2d9d7324e64fcd4fa289caeee6e7a78b2e11fc9b438a"}, {file = "rpds_py-0.28.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a4c6b05c685c0c03f80dabaeb73e74218c49deea965ca63f76a752807397207"}, @@ -7154,6 +7387,19 @@ files = [ {file = "snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895"}, ] +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = true +python-versions = "*" +groups = ["main"] +markers = "python_version >= \"3.10\" and extra == \"prefect\"" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + [[package]] name = "soupsieve" version = "2.7" @@ -7580,6 +7826,23 @@ files = [ {file = "suds_py3-1.4.5.0-py3-none-any.whl", hash = "sha256:0915a7f825c80fa2f0593e040e046bcbc156dd24ba988bb9da6c6604d70155b9"}, ] +[[package]] +name = "taskgroup" +version = "0.2.2" +description = "backport of asyncio.TaskGroup, asyncio.Runner and asyncio.timeout" +optional = true +python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\" and extra == \"prefect\"" +files = [ + {file = "taskgroup-0.2.2-py2.py3-none-any.whl", hash = "sha256:e2c53121609f4ae97303e9ea1524304b4de6faf9eb2c9280c7f87976479a52fb"}, + {file = "taskgroup-0.2.2.tar.gz", hash = "sha256:078483ac3e78f2e3f973e2edbf6941374fbea81b9c5d0a96f51d297717f4752d"}, +] + +[package.dependencies] +exceptiongroup = "*" +typing_extensions = ">=4.12.2,<5" + [[package]] name = "text-unidecode" version = "1.3" @@ -7684,7 +7947,7 @@ files = [ {file = "tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b"}, {file = "tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549"}, ] -markers = {main = "python_version < \"3.11\" and (extra == \"prefect\" or python_full_version <= \"3.10.0\")", dev = "python_version < \"3.11\""} +markers = {main = "python_full_version <= \"3.10.0\" or python_version < \"3.11\" and extra == \"prefect\"", dev = "python_version < \"3.11\""} [[package]] name = "toolz" @@ -7872,36 +8135,6 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] -[[package]] -name = "uv" -version = "0.9.6" -description = "An extremely fast Python package and project manager, written in Rust." -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version >= \"3.10\" and extra == \"prefect\"" -files = [ - {file = "uv-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:b2f934737c93f88c906b6a47bcc083170210fe5d66565e80a7c139599e5cbf2f"}, - {file = "uv-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a7c6067919d87208c4a6092033c3bc9799cb8be1c8bc6ef419a1f6d42a755329"}, - {file = "uv-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:95a62c1f668272555ad0c446bf44a9924dee06054b831d04c162e0bad736dc28"}, - {file = "uv-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:0169a85d3ba5ef1c37089d64ff26de573439ca84ecf549276a2eee42d7f833f2"}, - {file = "uv-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f0ba311b3ca49d246f36d444d3ee81571619ef95e5f509eb694a81defcbed262"}, - {file = "uv-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e89c964f614fa3f0481060cac709d6da50feac553e1e11227d6c4c81c87af7c"}, - {file = "uv-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ea67369918af24ea7e01991dfc8b8988d1b0b7c49cb39d9e5bc0c409930a0a3f"}, - {file = "uv-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:90122a76e6441b8c580fc9faf06bd8c4dbe276cb1c185ad91eceb2afa78e492a"}, - {file = "uv-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86e05782f9b75d39ab1c0af98bf11e87e646a36a61d425021d5b284073e56315"}, - {file = "uv-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c2c2b2b093330e603d838fec26941ab6f62e8d62a012f9fa0d5ed88da39d907"}, - {file = "uv-0.9.6-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:e700b2098f9d365061c572d0729b4e8bc71c6468d83dfaae2537cd66e3cb1b98"}, - {file = "uv-0.9.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:6403176b55388cf94fb8737e73b26ee2a7b1805a9139da5afa951210986d4fcd"}, - {file = "uv-0.9.6-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:62e3f057a9ae5e5003a7cd56b617e940f519f6dabcbb22d36cdd0149df25d409"}, - {file = "uv-0.9.6-py3-none-musllinux_1_1_i686.whl", hash = "sha256:538716ec97f8d899baa7e1c427f4411525459c0ef72ea9b3625ce9610c9976e6"}, - {file = "uv-0.9.6-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:b31377ebf2d0499afc5abe3fe1abded5ca843f3a1161b432fe26eb0ce15bab8e"}, - {file = "uv-0.9.6-py3-none-win32.whl", hash = "sha256:0fde18c22376c8b02954c7db3847bc75ac42619932c44b43f49d056e5cfb05f9"}, - {file = "uv-0.9.6-py3-none-win_amd64.whl", hash = "sha256:d1072db92cc9525febdf9d113c23916dfc20ca03e21218cc7beefe7185a90631"}, - {file = "uv-0.9.6-py3-none-win_arm64.whl", hash = "sha256:166175ba952d2ad727e1dbd57d7cfc1782dfe7b8d79972174a46a7aa33ddceec"}, - {file = "uv-0.9.6.tar.gz", hash = "sha256:547fd27ab5da7cd1a833288a36858852451d416a056825f162ecf2af5be6f8b8"}, -] - [[package]] name = "uvicorn" version = "0.38.0" @@ -8149,7 +8382,7 @@ files = [ {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, ] -markers = {main = "python_version >= \"3.9\" and extra == \"prefect\" or python_version == \"3.9\" or python_version == \"3.11\"", docs = "python_version == \"3.9\""} +markers = {main = "python_version == \"3.9\" or python_version >= \"3.9\" and extra == \"prefect\" or python_version == \"3.11\"", docs = "python_version == \"3.9\""} [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""] @@ -8309,4 +8542,4 @@ tango = ["PyTango"] [metadata] lock-version = "2.1" python-versions = ">=3.8,<3.12" -content-hash = "9efc9766c0cba126f8b27ccb6fa2da89a2d89d244bb19154bd74eb4aab85c870" +content-hash = "380b09c0e690507cf285d7a834f108a44da9a6830a8b9a30ec8a4fc18c618e23" diff --git a/pyproject.toml b/pyproject.toml index 449b122a16..722208d495 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "mxcubecore" -version = "1.195.0.50" +version = "1.195.0.51" license = "LGPL-3.0-or-later" description = "Core libraries for the MXCuBE application" authors = ["The MXCuBE collaboration "] @@ -49,9 +49,9 @@ PyTango = { version = "^9.3.6"} python-ldap = "^3.4.0" requests = "^2.31.0" colorama = "^0.4.6" -prefect = { version = "3.4.22", optional = true, python = ">=3.10" } +prefect = { version = "3.6.10", optional = true, python = ">=3.10" } cachetools = ">=5.3.3" -mx3-beamline-library = { git = "https://github.com/AustralianSynchrotron/mx3-beamline-library.git", rev = "v2.4.6", python = ">=3.11,<3.12" } +mx3-beamline-library = { git = "https://github.com/AustralianSynchrotron/mx3-beamline-library.git", rev = "v2.4.8", python = ">=3.11,<3.12" } [tool.poetry.dev-dependencies] pre-commit = "^3.5.0"