Skip to content

Commit 2ab482a

Browse files
committed
Replace removed BlueapiClient methods
Maintain backwards compatibility for now
1 parent 8435f42 commit 2ab482a

3 files changed

Lines changed: 221 additions & 18 deletions

File tree

src/blueapi/client/client.py

Lines changed: 190 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,22 @@
2424
from blueapi.service.authentication import SessionManager
2525
from blueapi.service.model import (
2626
DeviceModel,
27+
DeviceResponse,
2728
EnvironmentResponse,
2829
OIDCConfig,
2930
PlanModel,
31+
PlanResponse,
3032
PythonEnvironmentResponse,
3133
SourceInfo,
3234
TaskRequest,
3335
TaskResponse,
36+
TasksListResponse,
3437
WorkerTask,
3538
)
39+
from blueapi.utils import deprecated
3640
from blueapi.worker import WorkerEvent, WorkerState
3741
from blueapi.worker.event import ProgressEvent, TaskStatus
42+
from blueapi.worker.task_worker import TrackableTask
3843

3944
from .event_bus import AnyEvent, BlueskyStreamingError, EventBusClient, OnAnyEvent
4045
from .rest import BlueapiRestClient, BlueskyRemoteControlError
@@ -211,27 +216,14 @@ def __init__(
211216
self._callbacks = {}
212217
self._callback_id = itertools.count()
213218

214-
@cached_property
215-
@start_as_current_span(TRACER)
216-
def plans(self) -> PlanCache:
217-
return PlanCache(self, self._rest.get_plans().plans)
218-
219-
@cached_property
220-
@start_as_current_span(TRACER)
221-
def devices(self) -> DeviceCache:
222-
return DeviceCache(self._rest)
223-
224219
@classmethod
225220
def from_config_file(cls, config_file: str) -> Self:
226221
conf = ConfigLoader(ApplicationConfig)
227222
conf.use_values_from_yaml(Path(config_file))
228223
return cls.from_config(conf.load())
229224

230225
@classmethod
231-
def from_config(
232-
cls,
233-
config: ApplicationConfig,
234-
) -> Self:
226+
def from_config(cls, config: ApplicationConfig) -> Self:
235227
session_manager: SessionManager | None = None
236228
try:
237229
session_manager = SessionManager.from_cache(config.auth_token_path)
@@ -253,6 +245,16 @@ def from_config(
253245
else:
254246
return cls(rest)
255247

248+
@cached_property
249+
@start_as_current_span(TRACER)
250+
def plans(self) -> PlanCache:
251+
return PlanCache(self, self._rest.get_plans().plans)
252+
253+
@cached_property
254+
@start_as_current_span(TRACER)
255+
def devices(self) -> DeviceCache:
256+
return DeviceCache(self._rest)
257+
256258
@property
257259
def instrument_session(self) -> str:
258260
if self._instrument_session is None:
@@ -268,6 +270,43 @@ def with_instrument_session(self, session: str) -> Self:
268270
self.instrument_session = session
269271
return self
270272

273+
@start_as_current_span(TRACER)
274+
@deprecated("plans property")
275+
def get_plans(self) -> PlanResponse:
276+
"""
277+
List plans available
278+
279+
Returns:
280+
PlanResponse: Plans that can be run
281+
"""
282+
return self._rest.get_plans()
283+
284+
@start_as_current_span(TRACER, "name")
285+
@deprecated("plans[name]")
286+
def get_plan(self, name: str) -> PlanModel:
287+
"""
288+
Get details of a single plan
289+
290+
Args:
291+
name: Plan name
292+
293+
Returns:
294+
PlanModel: Details of the plan if found
295+
"""
296+
return self._rest.get_plan(name)
297+
298+
@start_as_current_span(TRACER)
299+
@deprecated("devices property")
300+
def get_devices(self) -> DeviceResponse:
301+
"""
302+
List devices available
303+
304+
Returns:
305+
DeviceResponse: Devices that can be used in plans
306+
"""
307+
308+
return self._rest.get_devices()
309+
271310
def add_callback(self, callback: OnAnyEvent) -> int:
272311
cb_id = next(self._callback_id)
273312
self._callbacks[cb_id] = callback
@@ -280,6 +319,21 @@ def remove_callback(self, id: int):
280319
def callbacks(self) -> Iterable[OnAnyEvent]:
281320
return self._callbacks.values()
282321

322+
@start_as_current_span(TRACER, "name")
323+
@deprecated("devices[name]")
324+
def get_device(self, name: str) -> DeviceModel:
325+
"""
326+
Get details of a single device
327+
328+
Args:
329+
name: Device name
330+
331+
Returns:
332+
DeviceModel: Details of the device if found
333+
"""
334+
335+
return self._rest.get_device(name)
336+
283337
@property
284338
@start_as_current_span(TRACER)
285339
def state(self) -> WorkerState:
@@ -292,6 +346,18 @@ def state(self) -> WorkerState:
292346

293347
return self._rest.get_state()
294348

349+
@start_as_current_span(TRACER)
350+
@deprecated("state property")
351+
def get_state(self) -> WorkerState:
352+
"""
353+
Get current state of the blueapi worker
354+
355+
Returns:
356+
WorkerState: Current state
357+
"""
358+
359+
return self.state
360+
295361
@start_as_current_span(TRACER, "defer")
296362
def pause(self, defer: bool = False) -> WorkerState:
297363
"""
@@ -320,6 +386,33 @@ def resume(self) -> WorkerState:
320386

321387
return self._rest.set_state(WorkerState.RUNNING, defer=False)
322388

389+
@start_as_current_span(TRACER, "task_id")
390+
@deprecated("rest client")
391+
def get_task(self, task_id: str) -> TrackableTask:
392+
"""
393+
Get a task stored by the worker
394+
395+
Args:
396+
task_id: Unique ID for the task
397+
398+
Returns:
399+
TrackableTask: Task details
400+
"""
401+
assert task_id, "Task ID not provided!"
402+
return self._rest.get_task(task_id)
403+
404+
@start_as_current_span(TRACER)
405+
@deprecated("rest client")
406+
def get_all_tasks(self) -> TasksListResponse:
407+
"""
408+
Get a list of all task stored by the worker
409+
410+
Returns:
411+
TasksListResponse: List of all Trackable Task
412+
"""
413+
414+
return self._rest.get_all_tasks()
415+
323416
@property
324417
@start_as_current_span(TRACER)
325418
def active_task(self) -> WorkerTask:
@@ -333,6 +426,19 @@ def active_task(self) -> WorkerTask:
333426

334427
return self._rest.get_active_task()
335428

429+
@start_as_current_span(TRACER)
430+
@deprecated("active_task property")
431+
def get_active_task(self) -> WorkerTask:
432+
"""
433+
Get the currently active task, if any
434+
435+
Returns:
436+
WorkerTask: The currently active task, the task the worker
437+
is executing right now.
438+
"""
439+
440+
return self.active_task
441+
336442
@start_as_current_span(TRACER, "task", "timeout")
337443
def run_task(
338444
self,
@@ -428,6 +534,51 @@ def create_and_start_task(self, task: TaskRequest) -> TaskResponse:
428534
f"but {worker_response.task_id} was started instead"
429535
)
430536

537+
@start_as_current_span(TRACER, "task")
538+
@deprecated("rest client")
539+
def create_task(self, task: TaskRequest) -> TaskResponse:
540+
"""
541+
Create a new task, does not start execution
542+
543+
Args:
544+
task: Request object for task to create on the worker
545+
546+
Returns:
547+
TaskResponse: Acknowledgement of request
548+
"""
549+
550+
return self._rest.create_task(task)
551+
552+
@start_as_current_span(TRACER)
553+
@deprecated("rest client")
554+
def clear_task(self, task_id: str) -> TaskResponse:
555+
"""
556+
Delete a stored task on the worker
557+
558+
Args:
559+
task_id: ID for the task
560+
561+
Returns:
562+
TaskResponse: Acknowledgement of request
563+
"""
564+
565+
return self._rest.clear_task(task_id)
566+
567+
@start_as_current_span(TRACER, "task")
568+
@deprecated("rest client")
569+
def start_task(self, task: WorkerTask) -> WorkerTask:
570+
"""
571+
Instruct the worker to start a stored task immediately
572+
573+
Args:
574+
task: WorkerTask to start
575+
576+
Returns:
577+
WorkerTask: Acknowledgement of request
578+
"""
579+
580+
return self._rest.update_worker_task(task)
581+
431582
@start_as_current_span(TRACER, "reason")
432583
def abort(self, reason: str | None = None) -> WorkerState:
433584
"""
@@ -470,6 +621,19 @@ def environment(self) -> EnvironmentResponse:
470621

471622
return self._rest.get_environment()
472623

624+
@start_as_current_span(TRACER)
625+
@deprecated("environment property")
626+
def get_environment(self) -> EnvironmentResponse:
627+
"""
628+
Get details of the worker environment
629+
630+
Returns:
631+
EnvironmentResponse: Details of the worker
632+
environment.
633+
"""
634+
635+
return self.environment
636+
473637
@start_as_current_span(TRACER, "timeout", "polling_interval")
474638
def reload_environment(
475639
self,
@@ -540,6 +704,18 @@ def oidc_config(self) -> OIDCConfig | None:
540704

541705
return self._rest.get_oidc_config()
542706

707+
@start_as_current_span(TRACER)
708+
@deprecated("oidc_config property")
709+
def get_oidc_config(self) -> OIDCConfig | None:
710+
"""
711+
Get oidc config from the server
712+
713+
Returns:
714+
OIDCConfig: Details of the oidc Config
715+
"""
716+
717+
return self.oidc_config
718+
543719
@start_as_current_span(TRACER)
544720
def get_python_env(
545721
self, name: str | None = None, source: SourceInfo | None = None

src/blueapi/utils/__init__.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from collections.abc import Callable
2+
from functools import wraps
3+
from typing import ParamSpec, TypeVar
4+
15
from .base_model import BlueapiBaseModel, BlueapiModelConfig, BlueapiPlanModelConfig
26
from .connect_devices import connect_devices, report_successful_devices
37
from .file_permissions import get_owner_gid, is_sgid_set
@@ -21,4 +25,31 @@
2125
"is_sgid_set",
2226
"get_owner_gid",
2327
"is_function_sourced_from_module",
28+
"deprecated",
2429
]
30+
31+
Args = ParamSpec("Args")
32+
Return = TypeVar("Return")
33+
34+
35+
def deprecated(alternative):
36+
from warnings import warn
37+
38+
def deprecated(func: Callable[Args, Return]) -> Callable[Args, Return]:
39+
called = False
40+
41+
@wraps(func)
42+
def wrapped(*args, **kwargs):
43+
nonlocal called
44+
if not called:
45+
warn(
46+
f"Function {func.__name__} is deprecated - use {alternative}",
47+
DeprecationWarning,
48+
stacklevel=2,
49+
)
50+
called = True
51+
return func(*args, **kwargs)
52+
53+
return wrapped
54+
55+
return deprecated

tests/system_tests/test_blueapi_system.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@
1717
BlueapiRestClient,
1818
BlueskyRemoteControlError,
1919
BlueskyRequestError,
20-
)
21-
from blueapi.client.rest import (
22-
BlueapiRestClient,
23-
BlueskyRequestError,
2420
ServiceUnavailableError,
2521
)
2622
from blueapi.config import (

0 commit comments

Comments
 (0)