-
Couldn't load subscription status.
- Fork 6
feat: Support for dataclasses as composite types #1242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1242 +/- ##
==========================================
+ Coverage 94.67% 94.69% +0.01%
==========================================
Files 41 41
Lines 2611 2618 +7
==========================================
+ Hits 2472 2479 +7
Misses 139 139 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
|
||
| ## Injecting multiple devices | ||
|
|
||
| If a plan requires multiple devices to be injected at once, rather than have a plan with several device parameters each of them with their own injection default, it is preferable to define a device composite which can be accepted as a parameter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't agree that it is preferable- if you require overriding one device you must override the whole Composite.
I just think it's an alternative option that may be useful quite often, depending on how a specific beamline operates.
I'll look through the code change later, but I am admitting upfront that I am opinionated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. Perhaps I should rephrase that to reflect the difference between UDC and non-UDC use cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure it's a UDC vs. non-UDC thing. It's just if you have loads of devices it's cleaner to use a composite. If you have a couple it's cleaner not to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's number but flexibility
class XYComposite(BaseModel):
x: Motor
y: Motor
def my_composite_plan(xy: XYComposite = inject()) -> MsgGenerator:
...
def my_individual_plan(x: Motor = inject(), y: Motor = inject()) -> MsgGenerator:
...the json for the former if I wanted to scan theta/y instead of x/y:
{"xy": {"x": "theta", "y": "y"}}compared to the latter:
{"x": "theta"}The more devices I have in my BaseModel, the more verbose my plan signature would become if I don't use one, but the more duplicates I need to have in my JSON if I want to replace one of them.
If I'm always scanning x, y or I have multiple plans that all need x, y then a composite is neater. I'd prefer to define a specific device like a Stage to enforce a meaning to the relationship between x and y, but it's not always possible.
Or we support multiple levels of injection:
class MyComposite(BaseModel):
x: Motor = inject()
y: Motor = inject()
def my_plan(xy: MyComposite = inject()) -> MsgGenerator: # uses x, y
...{"xy": {"x": "theta"}}Creating a new MyComposite with x=theta, y=inject("y") which finds y to pass in as the xy argument?
This modifies the previous PR #1231 and adds the following:
BaseModeland instead can be a dataclass