Skip to content

launch: thread "expects options" flag through type_map instead of runtime hasattr #361

@gilesknap

Description

@gilesknap

Context

Follow-up cleanup from PR #360 (slice #354 — multi-class launch()).

_build_entry_model decides at build time whether a registered Controller class takes an options arg, by either adding a controller field to its entry model or not. Then _instantiate_controllers re-discovers that decision at runtime via hasattr(entry, "controller"):

# src/fastcs/launch.py:184-203
for id, entry in controllers_options.items():
    cls = type_map[entry.type]
    if hasattr(entry, "controller"):
        controller = cls(entry.controller)
    else:
        controller = cls()
    controller.set_id(id)
    controllers.append(controller)

It works, but the build-time and runtime branches are kept in sync only by duck-typing on a dynamic Pydantic model. Touching either side without the other is a silent footgun.

What to build

Thread the "this class expects options" flag forward from _build_entry_model so _instantiate_controllers reads off the same source of truth. Two reasonable shapes:

  • type_map: dict[str, tuple[type[Controller], bool]] keyed by discriminator, value = (class, expects_options)
  • A tiny _RegisteredClass dataclass with cls, expects_options (and any future per-class metadata)

Either way, the hasattr check goes away and _instantiate_controllers becomes data-driven.

Acceptance criteria

  • _instantiate_controllers no longer uses hasattr on the entry model
  • Build-time and instantiate-time decisions about "options arg present?" share one source of truth
  • Existing tests/test_launch.py cases still green; no behaviour change for users
  • Full test suite stays green

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions