Skip to content

Conversation

@rtuck99
Copy link
Contributor

@rtuck99 rtuck99 commented Oct 10, 2025

This introduces support for composite devices in blueapi plan signatures.

Composite devices must extend from pydantic BaseModel, and the devices contained in them will be obtained from the BlueskyContext

@codecov
Copy link

codecov bot commented Oct 10, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.67%. Comparing base (d894018) to head (944be07).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1231      +/-   ##
==========================================
+ Coverage   94.66%   94.67%   +0.01%     
==========================================
  Files          41       41              
  Lines        2604     2611       +7     
==========================================
+ Hits         2465     2472       +7     
  Misses        139      139              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rtuck99 rtuck99 marked this pull request as ready for review October 14, 2025 13:04
@rtuck99 rtuck99 requested a review from a team as a code owner October 14, 2025 13:04
Comment on lines 416 to 425
def _inject_composite(self, composite_class: type[C]) -> C:
devices = {
field: self.find_device(info.default)
if info.annotation is not None
and is_bluesky_type(info.annotation)
and isinstance(info.default, str)
else info.default
for field, info in composite_class.model_fields.items()
}
return composite_class(**devices)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This handling requires that all devices are registered before any plan that uses a Composite BaseModel, which previously was not a requirement. We can either document that, or possibly we could recursively treat the BaseModel by passing it back into _type_spec_for_function? Then the Device classes in the Composite get replaced by References that know how to be deserialised from the context, and devices can be registered after plans?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated it such that the factory it returns is a genuine factory rather than a factory wrapping an instance.
I don't think there's a requirement that the device composites support nesting, at least there certainly isn't for Hyperion

default_factory = (
self._composite_factory(arg_type)
if isclass(arg_type)
and issubclass(arg_type, BaseModel)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the only weird edge case I can think of here is if someone has made a Device that extends BaseModel, but I think that breaks the child handling.

The use of a default factory here is much simpler than what I was thinking, I really like this.

@rtuck99 rtuck99 force-pushed the 506_composite_devices_2 branch from 1313d57 to 944be07 Compare October 17, 2025 11:17
@rtuck99 rtuck99 merged commit 812c427 into main Oct 17, 2025
19 checks passed
@rtuck99 rtuck99 deleted the 506_composite_devices_2 branch October 17, 2025 11:47
rtuck99 added a commit that referenced this pull request Dec 4, 2025
This modifies the previous PR #1231 and adds the following:

* Simplifies the creation of composites, the composite no longer needs
to be an instance of `BaseModel` and instead can be a dataclass
* The composite does not need to specify a default and instead
determines the device to inject from the attribute name
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants