Skip to content

fix(blocks): Dict block exposes N inputs and returns list#35

Open
PhotonicVelocity wants to merge 1 commit into
petercorke:mainfrom
PhotonicVelocity:fix/dict-block-nin-and-output
Open

fix(blocks): Dict block exposes N inputs and returns list#35
PhotonicVelocity wants to merge 1 commit into
petercorke:mainfrom
PhotonicVelocity:fix/dict-block-nin-and-output

Conversation

@PhotonicVelocity

@PhotonicVelocity PhotonicVelocity commented Jun 13, 2026

Copy link
Copy Markdown

Summary

Two bugs in bdsim.blocks.connections.Dict. Together they make
bd.DICT([...]) unusable for any keys list longer than 1 (and broken
even then, since the output isn't list-wrapped).

Bug 1 — nin not propagated

class Dict(FunctionBlock):
    nin = 1  # ← class attribute
    def __init__(self, keys: list[str], **blockargs: Any) -> None:
        super().__init__(**blockargs)   # ← nin=len(keys) missing

bd.DICT(["a", "b", "c"]) exposes only input 0. Wiring to
dict_blk[1] or dict_blk[2] fails at compile with:

error connecting wire ... --> .../dict.0[1]: list index out of range

Bug 2 — output() returns bare dict

def output(self, t: float, inputs: list[Any], x: Any) -> Any:
    return {key: inputs[i] for i, key in enumerate(self.keys)}

bdsim expects output() to return list[Any] (one entry per output
port). Even after fixing bug 1, running a diagram with a Dict block
fails:

AssertionError: block Block.function(... type=dict, nout=1) output
... must be a list: <class 'dict'>

Fix

nin: int = -1
...
super().__init__(nin=len(keys), **blockargs)
...
def output(self, t: float, inputs: list[Any], x: Any) -> list[Any]:
    return [{key: inputs[i] for i, key in enumerate(self.keys)}]

Mirrors the variable-input pattern in Mux (~30 lines below in the
same file), which is correct: nin: int = -1 + super().__init__( nin=nin, ...) + list-wrapped output.

History

The original class Dict introduced in 5b2bc33 (May 2021) was
actually an Item-extractor (1 dict input → 1 value out). A later
refactor (f7ba8b4) split Item into its own class and rewrote
Dict.output() to do the correct N→dict pack, but kept the
nin = 1 from the original Item-as-Dict implementation and forgot
the list-wrap.

Base

This PR is against 12b26c2 ("add the tagline") rather than current
main HEAD because of #34 (current main can't import bdsim — a
missing graphics_block.py from a recent move). The fix is in
connections.py and is orthogonal to the graphics breakage, so it
should rebase cleanly onto fixed-main.

Test plan

  • bd.DICT(["a", "b", "c"]) reports nin == 3.
  • Wire three CONSTANT blocks to the three slots; diagram compiles
    and runs.
  • Output dict has the three expected keys with the wired values.

No tests added to the bdsim test suite — leaving that to a broader
testing pass.

The Dict block class declares `nin = 1` and its __init__ never tells
the base block how many ports the instance actually has, so
`bd.DICT(["a", "b", "c"])` only exposes input 0 — wiring to dict[1] or
dict[2] fails at compile with "list index out of range".

The block's `output()` also returns a bare dict, but bdsim expects
`list[Any]` (one entry per output port). Even after fixing nin the
diagram errors with "block ... output ... must be a list:
<class 'dict'>".

Both issues are leftovers from the 2021-era refactor that split Item
out of an Item-masquerading-as-Dict class. The neighboring Mux block
already shows the correct variable-input pattern (`super().__init__(
nin=nin, ...)` + list-wrapped `output()` return).
@codacy-production

codacy-production Bot commented Jun 13, 2026

Copy link
Copy Markdown

Not up to standards ⛔

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant