Add MachineLibrary.get(name) public lookup method #45

Closed
opened 2026-06-22 16:23:21 +00:00 by Mark · 1 comment
Owner

API gap

src/machine/machine_library.py exposes self.machines as a dict.
Consumers (CLI, service, tests) reach into it directly:

profile = lib.machines["brother_se600"]

This couples consumers to the internal storage shape. If the storage
changes (e.g. moves to a database, a config file, a per-machine JSON
file), every consumer breaks.

What to add

A public get(name: str) -> MachineProfile method:

def get(self, name: str) -> MachineProfile:
    """Return the machine profile for the given name, or raise KeyError
    with a list of valid names in the message."""
    if name not in self.machines:
        available = ", ".join(sorted(self.machines.keys()))
        raise KeyError(f"Unknown machine profile: {name!r}. Available: {available}")
    return self.machines[name]

Plus a list_names() -> list[str] for introspection.

Why it matters

The HTTP service (per "Add HTTP service layer") needs to resolve
machine_profile="brother-pr10" from the request into a MachineProfile
object. Going through lib.machines["brother-pr10"] works today but:

  • No helpful error if the name is wrong (just KeyError: 'brother_pr10').
  • Couples the service to the storage shape.
  • Makes it awkward to add a "default profile" fallback — a public get()
    with an optional default would handle that cleanly.

Acceptance

  • MachineLibrary.get("brother_se600") returns the SE600 profile.
  • MachineLibrary.get("nonexistent") raises KeyError with a message
    listing all available profile names.
  • MachineLibrary.list_names() returns a sorted list of all profile names.
  • The HTTP service uses get() instead of direct dict access.
## API gap `src/machine/machine_library.py` exposes `self.machines` as a dict. Consumers (CLI, service, tests) reach into it directly: ```python profile = lib.machines["brother_se600"] ``` This couples consumers to the internal storage shape. If the storage changes (e.g. moves to a database, a config file, a per-machine JSON file), every consumer breaks. ## What to add A public `get(name: str) -> MachineProfile` method: ```python def get(self, name: str) -> MachineProfile: """Return the machine profile for the given name, or raise KeyError with a list of valid names in the message.""" if name not in self.machines: available = ", ".join(sorted(self.machines.keys())) raise KeyError(f"Unknown machine profile: {name!r}. Available: {available}") return self.machines[name] ``` Plus a `list_names() -> list[str]` for introspection. ## Why it matters The HTTP service (per "Add HTTP service layer") needs to resolve `machine_profile="brother-pr10"` from the request into a `MachineProfile` object. Going through `lib.machines["brother-pr10"]` works today but: - No helpful error if the name is wrong (just `KeyError: 'brother_pr10'`). - Couples the service to the storage shape. - Makes it awkward to add a "default profile" fallback — a public `get()` with an optional default would handle that cleanly. ## Acceptance - `MachineLibrary.get("brother_se600")` returns the SE600 profile. - `MachineLibrary.get("nonexistent")` raises `KeyError` with a message listing all available profile names. - `MachineLibrary.list_names()` returns a sorted list of all profile names. - The HTTP service uses `get()` instead of direct dict access.
Author
Owner

Cross-link: ThreadCraft #11 — public MachineLibrary.get() is the lookup API the wrapper uses.

**Cross-link:** ThreadCraft #11 — public MachineLibrary.get() is the lookup API the wrapper uses.
Mark 2026-06-22 20:10:11 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Mark/easystitch#45
No description provided.