-
Notifications
You must be signed in to change notification settings - Fork 26
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
Make a concrete superset of types that Signal should allow #310
Comments
One idea is:
|
@burkeds this would make the following changes to
Would that be fine for the Tango backend? |
@coretl This shouldn't cause any major issues. I am in the process of doing some major refactoring of the tango backend so now would be a good time to implement a change like this. |
@evalott100 when the PCOMP change is done, this is higher priority than the layout ticket |
The array of types we should accept:
For the transport mechanisms:
Depends on #442 |
Query on the usecase for BaseModels |
It occurs to me that we should also allow signal = Signal(WhateverSignalBackend(Path))
assert isinstance(await signal.get_value(), Path)
await signal.set("some/path") # fails explaining the correct datatype. There's quite a lot of places across the codebase that we convert to string before setting the signal. |
@evalott100 see #122 |
Hmmm I'll probably still look into it, but I can see this logic. |
One thought I had today after realising that it would be lovely to be able to represent A new abstract class
This would allow you to have pydantic models, dataclasses, etc. which subclass the above that could then be used as backend datatypes. The new backend converter for p4p will then check for this on read write. |
Does the conversation literally go to/from a |
The user could choose whatever formatting for the object - it will have to end up as a dictionary though
ophyd-async/src/ophyd_async/fastcs/panda/_block.py Lines 52 to 53 in e4fb849
We could then do something like: class SeqTable(RootModel, PvaTableAbstraction):
root: NpNDArray
def convert_to_pva_table(self) -> Dict[str, NpNDArray]:
"""Convert root to the column-wise dict representation for backend put"""
@classmethod
def convert_from_pva_table(cls, pva_table: Dict[str, NpNDArray]):
"""For use in the backend."""
... # formatting
return cls(formatted_rows)
@model_validator(mode="before")
@classmethod
def check_valid_rows(cls, rows: Iterable):
if not (0 <= len(rows) < 4096):
raise ValueError(f"Length {len(rows)} not in range.")
if not all(isinstance(row, np.ndarray) for row in rows):
for row in rows:
if not isinstance(row, np.void):
raise ValueError(
f"Cannot construct a SeqTable, some rows {row} are not arrays {type(row)}."
)
raise ValueError("Cannot construct a SeqTable, some rows are not arrays.")
if not all(row.shape == _SEQ_TABLE_ROW_SHAPE for row in rows):
raise ValueError(
"Cannot construct a SeqTable, some rows have incorrect shapes."
)
if not all(row.dtype is SeqTableRowType for row in rows):
raise ValueError(
"Cannot construct a SeqTable, some rows have incorrect types."
)
return np.array(rows) Very rough draft. The general concept I'm going for is that we can represent the single signal pva dictionary as a much higher level class, and equip it with a way of converting to and from the dictionary only on write read. You could also include a public interface and keep the dictionary private within the class, then |
I agree, although I'm not sure whether it's the class' responsibility to covert itself to a valid PVA table or the signal backend's. I would lean towards the latter... |
This is so the backend can check: # Before connection
if issubclass(datatype, PvaTableAbstraction):
initial_value = datatype.convert_from_pva_table({})
# In PvaConverter, called on read
if issubclass(datatype, PvaTableAbstraction):
return datatype.convert_from_pva_table(value) Though actually it shouldn't be a class function. In the case of this SeqTable it should update and recalling the validator. |
decided to include this in the PR for #310
decided to include this in the PR for #310
This will require |
Downstream support (e.g. Tiled) for arbitrary BaseModels requires more use cases before we do this, so decided to support:
Support for arbitrary BaseModels is deferred until we have more use cases |
As a developer I would like to solidify the requirement for enum signals to also inherit from
str
so that I can have more confidence my enum signals will connect.Possible Solution
We don't want to pollute all the backends in a duplicating way so the check should go in
Signal
(@coretl?)For static type checking, only support certain data types for signals (via a
Union
)Acceptance Criteria
str
as wellstr
, an error is raisedThe text was updated successfully, but these errors were encountered: