Skip to content

Include Bluesky plan stubs by default #1691

Open

Description

@oliwenmandiamond

With bluesky/bluesky#2079 now merged, the plan stubs now have their typing improved. This means we should no longer need to rely on dodal to wrap plan stubs for strong typing, instead we should include the wrapped plan stubs from bluesky in blueapi by default and remove the duplicated wrapped plans in dodal.

This will do two things:

  • Reduce duplication, no longer need to maintain plan stubs in two different places.
  • Simplify configuration, we no longer need to specify plan stubs in services configuration, these should be included by default with blueapi.

Activity

  1. oliwenmandiamond commented on Oct 8, 2026

    @oliwenmandiamond
    ContributorAuthor

    @shree-iyengar-dls @ZohebShaikh @dan-fernandes

    As discussed, we first need Bluesky to have made a new release and then have blueapi use it.
    https://github.com/DiamondLightSource/blueapi/blob/main/src/blueapi/core/context.py#L219 is where the change will need to be done. So BlueskyContext.__post__init_ calls BlueskyContext.with_config which calls with_plan_modudle which calls register_plan. This is where plans are registered with blueapi from our plan repos and dodal wrapped plans as it loads in the module and extracts it out.

    The dodal wrapped plan stubs only exist due to typing. What I am proposing is we include them directly with blueapi now and cut out the middle man as every single beamline will need the plan stubs.

    from bluesky.plan_stubs as bps
    
    DEFAULT_PLAN_STUBS = [bps.mv, bps.mvr, bps.rd, ...]

    then inside __post__init_ we call

    for plan_stub in DEFAULT_PLAN_STUBS:
         self.register_plan(plan_stub)

    The other solution is if you still want this driven by config, you instead create a module e.g

    blueapi.plan_stubs.__init__.py and inside __all__ include all the default plan stubs listed above, then update the copier template to include

    planSource:
         blueapi.plan_stubs

    Basically, the aim of this change is we don't need the wrapped plan stubs at all once the typing is up to scratch, so we eliminate the duplicate definition and have blueapi include it by default and doesn't need to include dodal at all for it.

    We could go further and include plans, specifically scans, with this as well. However, they do need to wrapped to remove Callable per_step as these are not compatible with blueapi as not serialisable but there is an argument that this should go on the blueapi side instead as they are designed to work with blueapi specifically and again should be included by default. That is out of scope for now though, lets just focus on plan stubs

  2. shree-iyengar-dls commented on Oct 8, 2026

    @shree-iyengar-dls
    Contributor

    @oliwenmandiamond This is very helpful! Thanks for writing it out. I think I'll try with the first approach initially and then if that doesn't work, will try the second option of making a module and updating the copier template

  3. oliwenmandiamond commented on Oct 8, 2026

    @oliwenmandiamond
    ContributorAuthor

    One thing I do not know about is if blueapi can cope with plans using **kwargs as a lot of plan stubs use that in bluesky e.g allows you to specify timeout options or other bits a device might need. In dodal, there is an artificial blocker for plans and plan stubs to not use **kwargs. However, I don't think there would be anything stopping you actually doing it? The plan schema generated may not be as nice, but I don't think we should be putting artificial blockers when it is perfectly valid python and bluesky

  4. DiamondJoseph commented on Oct 19, 2026

    @DiamondJoseph
    Contributor

    Any untyped var-args, *args, **kwargs won't be able to be de-serialised, at best it may be possible to support *args: TypeA, **kwargs: TypeB, but without the typing information, Pydantic would never know to convert args=["stage.x", 0, 1, 4] into anything more meaningful.

  5. oliwenmandiamond commented on Oct 19, 2026

    @oliwenmandiamond
    ContributorAuthor

    Hey @DiamondJoseph, good to hear from you and thanks for responding!

    So anything that is untyped has been fixed directly in bluesky with bluesky/bluesky#2083 and bluesky/bluesky#2079. Just waiting on a new release. I have tested this with blueapi #1663 (proof of concept) supporting args and kwargs, but I do have to provide additional information as the schema alone is not enough currently. So this does assume a couple of things and this should be probably be put in draft until those are decided on and merged, but in theory in the future wrapped plans in dodal will no longer be needed and blueapi can include directly bluesky plan stubs by default. More testing will be required though!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions