Skip to content

Support dict unpacking in dict literals in the local Python executor - #2553

Open
himanshu748 wants to merge 2 commits into
huggingface:mainfrom
himanshu748:fix-dict-unpacking-in-literals
Open

Support dict unpacking in dict literals in the local Python executor#2553
himanshu748 wants to merge 2 commits into
huggingface:mainfrom
himanshu748:fix-dict-unpacking-in-literals

Conversation

@himanshu748

Copy link
Copy Markdown

Fixes #2552.

What happens today

Dict unpacking inside a dict literal, one of the most common patterns in model-generated code, crashes the local executor with an error that points nowhere:

{**{"a": 1}, "b": 2}
# InterpreterError: NoneType is not supported.

The ast.Dict branch in evaluate_ast evaluates every element of expression.keys, but a **mapping entry has None as its AST key, so None reaches evaluate_ast and fails with the unrelated message. The model gets no signal that ** is the problem and typically retries the same syntax until the run dies.

The fix

Evaluate the dict literal pairwise: a None key marks a **mapping entry whose evaluated value is merged with dict.update, matching CPython semantics (in-order merge, later keys win). Unpacking a non-mapping now raises the same message CPython gives:

{**[1, 2]}
# InterpreterError: 'list' object is not a mapping

Key and value evaluation order for normal entries is preserved (key before value).

Tests

7 new tests: merge with literal keys, double unpack, later-key override in both directions, unpacking a stored variable, empty unpack and the non-mapping error. All fail on current main and pass on this branch. Full test file: 404 passed, 2 skipped. Ruff check and format are clean.

Copilot AI review requested due to automatic review settings July 20, 2026 06:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7eef5d78c0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/smolagents/local_python_executor.py Outdated
for key_node, value_node in zip(expression.keys, expression.values):
if key_node is None:
value = evaluate_ast(value_node, *common_params)
if not isinstance(value, Mapping):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow mapping-protocol objects in dict unpacking

When ** is used with objects that implement the normal mapping protocol but do not inherit/register with collections.abc.Mapping (for example a user-defined class with keys() and __getitem__(), or third-party mapping-like objects), CPython accepts {**obj} but this check rejects it with 'MyMap' object is not a mapping. Since the executor supports user-defined classes and the change is intended to match Python dict-unpacking semantics, this still breaks valid Python code in those contexts; consider trying result.update(value) and translating its TypeError instead of pre-filtering by the ABC.

Useful? React with 👍 / 👎.

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.

BUG: dict unpacking in dict literals fails with misleading 'NoneType is not supported'

2 participants