-
Notifications
You must be signed in to change notification settings - Fork 2
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
Update to use new attribute API and pyright #57
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,8 +5,8 @@ | |
from typing import Any, Literal | ||
|
||
import numpy as np | ||
from fastcs.attributes import Attribute, AttrR, AttrRW, AttrW | ||
from fastcs.controller import Controller, SubController | ||
from fastcs.attributes import Attribute, AttrR, AttrRW, AttrW, Handler | ||
from fastcs.controller import BaseController, Controller, SubController | ||
from fastcs.datatypes import Bool, Float, Int, String | ||
from fastcs.wrappers import command, scan | ||
from PIL import Image | ||
|
@@ -62,10 +62,10 @@ | |
""" | ||
|
||
uri: str | ||
update_period: float = 0.2 | ||
update_period: float | None = 0.2 | ||
|
||
async def put( | ||
self, controller: "EigerSubsystemController", _: AttrW, value: Any | ||
self, controller: "EigerSubsystemController", attr: AttrW, value: Any | ||
) -> None: | ||
parameters_to_update = await controller.connection.put(self.uri, value) | ||
if not parameters_to_update: | ||
|
@@ -86,10 +86,15 @@ | |
|
||
await controller.queue_update(parameters_to_update) | ||
|
||
async def update(self, controller: "EigerController", attr: AttrR) -> None: | ||
async def update(self, controller: "EigerSubsystemController", attr: AttrR) -> None: | ||
try: | ||
response = await controller.connection.get(self.uri) | ||
await attr.set(response["value"]) | ||
value = response["value"] | ||
if isinstance(value, list) and all( | ||
isinstance(s, str) for s in value | ||
): # error is a list of strings | ||
value = ", ".join(value) | ||
await attr.set(value) | ||
except Exception as e: | ||
print(f"Failed to get {self.uri}:\n{e.__class__.__name__} {e}") | ||
|
||
|
@@ -116,15 +121,16 @@ | |
|
||
|
||
@dataclass | ||
class LogicHandler: | ||
class LogicHandler(Handler): | ||
""" | ||
Handler for FastCS Attribute Creation | ||
|
||
Dataclass that is called using the AttrR, AttrRW function. | ||
Used for dynamically created attributes that are added for additional logic | ||
""" | ||
|
||
async def put(self, _: "EigerController", attr: AttrW, value: Any) -> None: | ||
async def put(self, controller: BaseController, attr: AttrW, value: Any) -> None: | ||
assert isinstance(attr, AttrR) # AttrW does not implement set | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this necessary if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AttrW doesn't have set so pyright complains if we're trying to call set if we don't verify it's an AttrR (or I guess AttrRW). |
||
await attr.set(value) | ||
|
||
|
||
|
@@ -227,13 +233,21 @@ | |
print("\nAn HTTP request failed while introspecting detector:\n") | ||
raise | ||
|
||
def get_subsystem_controllers(self) -> list["EigerSubsystemController"]: | ||
return [ | ||
controller | ||
for controller in self.get_sub_controllers().values() | ||
if isinstance(controller, EigerSubsystemController) | ||
] | ||
|
||
@scan(0.1) | ||
async def update(self): | ||
"""Periodically check for parameters that need updating from the detector.""" | ||
subsystem_controllers = self.get_subsystem_controllers() | ||
await self.stale_parameters.set( | ||
any(c.stale_parameters.get() for c in self.get_sub_controllers().values()) | ||
any(c.stale_parameters.get() for c in subsystem_controllers) | ||
) | ||
controller_updates = [c.update() for c in self.get_sub_controllers().values()] | ||
controller_updates = [c.update() for c in subsystem_controllers] | ||
await asyncio.gather(*controller_updates) | ||
|
||
|
||
|
@@ -283,7 +297,7 @@ | |
attributes = self._create_attributes(parameters) | ||
|
||
for name, attribute in attributes.items(): | ||
setattr(self, name, attribute) | ||
self.attributes[name] = attribute | ||
|
||
@classmethod | ||
def _group(cls, parameter: EigerParameter): | ||
|
@@ -314,18 +328,19 @@ | |
datatype = String() | ||
case _: | ||
print(f"Failed to handle {parameter}") | ||
continue | ||
|
||
group = cls._group(parameter) | ||
match parameter.response["access_mode"]: | ||
case "r": | ||
attributes[parameter.attribute_name] = AttrR( | ||
datatype, | ||
datatype, # type: ignore | ||
handler=EIGER_HANDLERS[parameter.mode](parameter.uri), | ||
group=group, | ||
) | ||
case "rw": | ||
attributes[parameter.attribute_name] = AttrRW( | ||
datatype, | ||
datatype, # type: ignore | ||
handler=EIGER_HANDLERS[parameter.mode](parameter.uri), | ||
group=group, | ||
allowed_values=parameter.response.get("allowed_values", None), | ||
|
@@ -362,10 +377,8 @@ | |
if key in IGNORED_KEYS: | ||
continue | ||
attr_name = _key_to_attribute_name(key) | ||
match getattr(self, attr_name, None): | ||
# TODO: mypy doesn't understand AttrR as a type for some reason: | ||
# `error: Expected type in class pattern; found "Any" [misc]` | ||
case AttrR(updater=EigerConfigHandler() as updater) as attr: # type: ignore [misc] | ||
match self.attributes.get(attr_name, None): | ||
case AttrR(updater=EigerConfigHandler() as updater) as attr: | ||
jsouter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
parameter_updates.append(updater.config_update(self, attr)) | ||
case _ as attr: | ||
print(f"Failed to handle update for {key}: {attr}") | ||
|
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.
Formatting it like this might make it look like two messages is actually one, so it is probably clearer to just do
str(value)
Or maybe use a different separator, like|
?I do wonder if this should be implemented in FastCS with
String().validate(value)
.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 have a feeling that in a previous release lists did automatically get cast to strings, though I may be misremembering and that was just in a dev branch I never pushed anywhere.