DiamondLightSource / DiamondLightSource/fastcs
SPIKE (Opus/local): typed-command keyword-arg support via TYPE_CHECKING stub
- Dominant language
- Python
- Stars
- 6
- Forks
- 8
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 3
Description
**Not for the autonomous nightly job** — interactive, Opus-driven local spike (fast pyright feedback loop). Deliberately NOT labelled `api-convergence`.
## Context
Follow-up to #393 (typed commands). Core typed commands (ADR 0015 / #388 decision 5), in scope for #393 autonomously, cover:
- Args: `[]` | `[DT1, DT2, …]` (positional, known types)
- Returns: `None` | `DT` (0015 L97)
There is **no `Command[Any, Any]`** — a statically-declared command has fully-known `P`/`T`; a driver that knows nothing statically builds the whole controller (commands included) at runtime. So this spike is *not* about a partially-typed command; it is purely about the **keyword-arg** spelling on an otherwise fully-known signature.
## The spike
Keyword-argument commands are the hard part. coretl's sketch (0015 L91):
```python
def fn_spec(named_arg: float) -> int: ...
if TYPE_CHECKING:
def command_spec(spec: Callable[P, T]) -> Command[P, T]: ...
# runtime equivalent TBD
kw_known = command_spec(fn_spec)
```
Prototype a spelling giving pyright-checked keyword args on a typed command, with a runtime that builds the `Command`. Ref: bluesky/ophyd-async#1138 (discussion r2965959411).
## Resolved: no `Command[Any, Any]` needed
@Tom-Willemsen confirmed on [#402](https://github.com/DiamondLightSource/fastcs/pull/402#discussion_r3621453680) that SECoP devices are discovered entirely from an over-the-wire `describe` — you never statically know something is a command without also knowing its signature. There is no "known command, unknown args" middle case, so runtime `Command[Any, Any]` introspection is *not* a requirement. Fully-dynamic drivers build their commands programmatically at runtime (each with a concrete signature from the wire `datainfo`); statically-declared controllers get fully-known `Command[P, T]`. This spike therefore stands on its own merits — pyright-checked **keyword args** for statically-declared typed commands — rather than as an alternative to `Any`.
## When / How
Non-blocking; best *after* #393 core lands so you prototype against the real `Command[P, T]`. Fresh Claude Code **Opus** session pointed at this issue, scratch branch, tight `pyright` loop. Fold back as a follow-up PR to `refactor`.
Contributor guide
Research direction
Read ADR 0015 and follow #393 so the prototype uses the real Command[P, T] shape. Use a scratch branch and a tight pyright loop to test the TYPE_CHECKING command_spec spelling for keyword arguments, then determine how the runtime builds the Command. Done means pyright checks the keyword arguments and the runtime behavior is demonstrated for a fully known signature.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100