Skip to content

fix: new-name always wins when both old and new kwargs passed to args_mapping#198

Merged
Borda merged 13 commits into
mainfrom
fix/old-and--new
Jun 18, 2026
Merged

fix: new-name always wins when both old and new kwargs passed to args_mapping#198
Borda merged 13 commits into
mainfrom
fix/old-and--new

Conversation

@Borda

@Borda Borda commented Jun 17, 2026

Copy link
Copy Markdown
Owner
Before submitting
  • Was this discussed/approved via a Github issue? (no need for typos and docs improvements)
  • Did you make sure to update the docs?
  • Did you write any new necessary tests?

What does this PR do?

Before this fix the dict-comprehension in _apply_args_mapping (proxy) and _build_call_plan (deprecation) used last-write-wins semantics, so the winner depended on Python dict iteration order — fn(old=5, new=6) worked but fn(new=6, old=5) silently produced the wrong value.

  • Snapshot explicit new-name values before remap in both code paths; restore via result.update(explicit_new) so new-name always wins regardless of call-site argument order
  • Covers all four surfaces: callable-target proxy, ARGS_REMAP proxy, callable-target function decorator, ARGS_REMAP function decorator
  • Adds 9 tests (both argument orderings) across TestDataclassAutoExpand, TestArgsMapping, TestArgumentMapping, and TestArgsRemapMode

PR review

Anyone in the community is free to review the PR once the tests have passed.
If we didn't discuss your PR in Github issues there's a high chance it will not be merged.

Did you have fun?

Make sure you had fun coding 🙃

…_mapping

Before this fix the dict-comprehension in `_apply_args_mapping` (proxy) and
`_build_call_plan` (deprecation) used last-write-wins semantics, so the winner
depended on Python dict iteration order — `fn(old=5, new=6)` worked but
`fn(new=6, old=5)` silently produced the wrong value.

- Snapshot explicit new-name values before remap in both code paths; restore
  via `result.update(explicit_new)` so new-name always wins regardless of
  call-site argument order
- Covers all four surfaces: callable-target proxy, ARGS_REMAP proxy,
  callable-target function decorator, ARGS_REMAP function decorator
- Adds 9 tests (both argument orderings) across TestDataclassAutoExpand,
  TestArgsMapping, TestArgumentMapping, and TestArgsRemapMode

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

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.

✅ Ready to approve

The precedence fix is correctly implemented in both code paths and is backed by targeted regression tests; remaining feedback is limited to minor test-name clarity.

Note: this review does not count toward required approvals for merging.

Pull request overview

This PR fixes args_mapping collision semantics so that when callers pass both the old and new kwarg names, the explicitly provided new-name value always takes precedence (independent of call-site kwarg ordering). This removes the previous reliance on dict iteration order in both the proxy and decorator call-planning paths.

Changes:

  • Ensure “new-name wins” by snapshotting explicit new-name kwargs before remapping and restoring them after remap in both _DeprecatedProxy._apply_args_mapping and the decorator call-plan remap logic.
  • Add regression tests covering both kwarg orderings across proxy ARGS_REMAP, decorator ARGS_REMAP, callable-target forwarding, and dataclass auto-expand surfaces.
File summaries
File Description
src/deprecate/proxy.py Makes _apply_args_mapping deterministic by restoring explicitly provided new-name kwargs after remap.
src/deprecate/deprecation.py Applies the same precedence rule in the decorator call-plan kwargs remap path.
tests/unittests/test_proxy.py Adds unit coverage for proxy + dataclass auto-expand collision cases and kwarg ordering.
tests/integration/test_target_mode.py Adds integration coverage for ARGS_REMAP mode when both old and new kwargs are provided.
tests/integration/test_functions.py Adds integration coverage for callable-target forwarding when old/new kwargs collide.

Copilot's findings

  • Files reviewed: 5/5 changed files
  • Comments generated: 4

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread tests/unittests/test_proxy.py Outdated
Comment thread tests/unittests/test_proxy.py Outdated
Comment thread tests/unittests/test_proxy.py Outdated
Comment thread tests/integration/test_target_mode.py Outdated
@dosubot dosubot Bot added bug / fix Something isn't working tests labels Jun 17, 2026
@kilo-code-bot

kilo-code-bot Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 new files)
  • src/deprecate/proxy.py — no issues
  • CHANGELOG.md — no issues
  • docs/llms-full.txt — no issues
  • docs/troubleshooting.md — no issues
  • tests/integration/test_callable_kinds.py — no issues
  • tests/integration/test_target_mode.py — no issues
  • tests/unittests/test_proxy.py — no issues
Previous Review Summaries (7 snapshots, latest commit ebf10d8)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit ebf10d8)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 new files)
  • src/deprecate/proxy.py — no issues
  • CHANGELOG.md — no issues
  • docs/llms-full.txt — no issues
  • docs/troubleshooting.md — no issues
  • tests/integration/test_callable_kinds.py — no issues
  • tests/integration/test_target_mode.py — no issues
  • tests/unittests/test_proxy.py — no issues

Previous review (commit 81cb32b)

Status: No Issues Found | Recommendation: Merge

All changes in this PR are correct:

Implementation (deprecation.py, proxy.py): The arg collision precedence fix correctly ensures the explicit new-name value wins when both old and new names are passed. The stacklevel=3 for the collision UserWarning is correct (direct warn call inside _build_call_plan reaches caller at level 3). The proxy's _apply_args_mapping correctly implements the same precedence logic.

Tests: New tests in test_functions.py, test_target_mode.py, and test_proxy.py properly cover the collision handling with good naming and clear scenario descriptions.

Documentation: The "silently discarded" phrasing in docs/guide/functions.md is acceptable - it describes the value being ignored, followed immediately by noting the UserWarning makes this visible to callers.

Files Reviewed (11 files)
  • src/deprecate/deprecation.py - no issues
  • src/deprecate/proxy.py - no issues
  • CHANGELOG.md - no issues
  • docs/guide/functions.md - no issues
  • docs/llms.txt - no issues
  • docs/llms-full.txt - no issues
  • docs/overrides/main.html - no issues
  • docs/troubleshooting.md - no issues
  • tests/integration/test_functions.py - no issues
  • tests/integration/test_target_mode.py - no issues
  • tests/unittests/test_proxy.py - no issues

Previous review (commit 90732d4)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

CRITICAL

File Line Issue

WARNING

File Line Issue
src/deprecate/deprecation.py 988 Collision warning stacklevel points at the wrapper instead of the caller.

SUGGESTION

File Line Issue
docs/guide/functions.md 151 "silently discarded" contradicts the UserWarning described in the same paragraph.
Other Observations (not in diff)

Previous inline comments remain active and were not duplicated:

File Line Issue
tests/unittests/test_proxy.py N/A Prior naming suggestions carried forward.
tests/integration/test_target_mode.py N/A Prior naming suggestion carried forward.
Files Reviewed (9 files)
  • AGENTS.md - no new issues
  • docs/guide/functions.md - 1 suggestion
  • docs/llms.txt - no new issues
  • docs/overrides/main.html - no new issues
  • docs/troubleshooting.md - no new issues
  • src/deprecate/deprecation.py - 1 warning
  • tests/integration/test_functions.py - no new issues
  • tests/unittests/test_proxy.py - previous inline comments carried forward
  • tests/integration/test_target_mode.py - previous inline comment carried forward

Fix these issues in Kilo Cloud

Previous review (commit 8119895)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (1 file)
  • docs/troubleshooting.md - documentation formatting change only (blank lines in code example)

Previous review (commit 32717f1)

Status: No Issues Found | Recommendation: Merge

Overview

Incremental review of changes since commit 3603d8861f66d097e05bc1e006ace19705a43b0e. The PR adds documentation updates (CHANGELOG, llms.txt, llms-full.txt, troubleshooting.md, JSON-LD FAQ) and test cases alongside the existing args_mapping precedence fix.

No new issues found. The core fix remains correct:

  • src/deprecate/deprecation.py_explicit_new snapshot excludes dropped keys and is restored after remap; args_extra merges last.
  • src/deprecate/proxy.py — same precedence pattern in _apply_args_mapping.

Previous inline comments carry forward unchanged.

Files Reviewed (10 files)
  • CHANGELOG.md — added entry
  • docs/llms-full.txt — added anti-pattern note
  • docs/llms.txt — added anti-pattern note
  • docs/overrides/main.html — added FAQ entry
  • docs/troubleshooting.md — added troubleshooting section
  • src/deprecate/deprecation.py — args_mapping precedence fix (no change from prior review)
  • src/deprecate/proxy.py — args_mapping precedence fix (no change from prior review)
  • tests/collection_deprecate.py — added depr_collision_old_new_extra_wins fixture
  • tests/integration/test_functions.py — added tests for positional+kwarg collision and args_extra precedence
  • tests/unittests/test_proxy.py — added callable-target collision tests (old first / new first)

Previous review (commit 3603d88)

Status: No Issues Found | Recommendation: Merge

The incremental changes fix an args_mapping precedence bug where an explicitly provided new-name argument could be overwritten by a remapped old-value. The fix:

  1. Correctness: Both _build_call_plan (deprecation.py) and _apply_args_mapping (proxy.py) now snapshot explicit new-name values before remapping and restore them afterward, ensuring the caller's explicit value takes precedence.

  2. Test coverage: All three test files add test cases for both call orderings (old first, new first), confirming the fix works regardless of argument order.

  3. No regressions: The changes are minimal and targeted, with clear inline comments explaining the precedence logic.

Files Reviewed (6 files)
  • src/deprecate/deprecation.py - Lines 973-981: args_mapping precedence fix
  • src/deprecate/proxy.py - Lines 517-525: _apply_args_mapping precedence fix
  • tests/integration/test_functions.py - New tests for function decorator case
  • tests/integration/test_target_mode.py - New tests for ARGS_REMAP mode
  • tests/unittests/test_proxy.py - New tests for proxy cases

Previous review (commit 0d84fb6)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • src/deprecate/deprecation.py - Lines 973-981: args_mapping precedence fix
  • src/deprecate/proxy.py - Lines 517-525: _apply_args_mapping precedence fix
  • tests/integration/test_functions.py - New tests for function decorator case
  • tests/integration/test_target_mode.py - New tests for ARGS_REMAP mode
  • tests/unittests/test_proxy.py - New tests for proxy cases

Reviewed by nex-n2-pro:free · 760,287 tokens

Copilot finished work on behalf of Borda June 17, 2026 16:37
Borda and others added 6 commits June 17, 2026 19:33
When args_mapping maps old→new while also dropping new (e.g. {old:'new', new:None}),
the result.update(explicit_new) call previously reintroduced the key that args_to_drop
had just suppressed. One-token fix at both remap sites: add `and new_k not in
args_to_drop` (proxy) / `and new_k not in args_skip` (deprecation) to the
explicit_new comprehension condition so an explicit drop config always wins.

Also adds a one-sentence precedence note to _apply_args_mapping docstring and
the dep_cfg param description in _build_call_plan.

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
…xtra priority collision tests

Cover three scenarios the PR's existing test suite left untested:
- Callable-target proxy (_proxy_call_callable_with_mapping): two new tests using inline
  _DeprecatedProxy instances (num_warns=-1) confirm new_key wins over remapped old_key
  regardless of argument order at the call site (old_first and new_first).
- Positional old arg + new-name kwarg: depr_collision_old_new(5, new=6) confirms the fix
  fires correctly when the old name arrives via positional resolution.
- args_extra priority: new depr_collision_old_new_extra_wins fixture (args_extra={"new": 99})
  pins the documented precedence — args_extra merge runs last and always wins over
  both explicit new-name kwargs and remapped old-name values.

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
… fix (#198)

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
… llms, FAQPage

New troubleshooting entry: "I passed both the old and new argument names at
the same time — which value wins?" Explains the precedence hierarchy:
args_extra > explicit new-name kwarg > remapped old-name value > source defaults,
with runnable examples for each tier.

Also adds the precedence rule as an Anti-Pattern bullet to llms.txt and
llms-full.txt so AI agents generating migration code are aware it is not
dict-insertion-order-dependent, and a matching FAQ entry to the FAQPage
JSON-LD in docs/overrides/main.html.

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
When a caller passes both the deprecated old name and its replacement new
name in the same call, the old value was silently discarded. Add a
UserWarning identifying the ignored argument so callers can clean up the
call site.

- `_build_call_plan`: collect collision pairs before remap; emit
  `UserWarning: Both \`old\` (deprecated) and \`new\` were supplied to
  \`fn()\`; \`old\` is ignored.` per pair when stream is set
- Add test `test_user_warning_emitted_when_both_old_and_new_supplied`
- Update troubleshooting.md, llms.txt, FAQPage JSON-LD, functions.md guide
- Extend AGENTS.md sync table: "Public API behavior change" now explicitly
  includes docs/troubleshooting.md + FAQPage to prevent future omissions

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Comment thread src/deprecate/deprecation.py Outdated
Comment thread docs/guide/functions.md
Applies ≥3-char arg naming across all collision-story docs examples:
- troubleshooting.md: args_mapping, code blocks, prose, classmethod section
- guide/functions.md: ARGS_REMAP, score/score_predictions examples, admonition
- llms.txt: anti-pattern note, thin-adapter snippet
- overrides/main.html: FAQ collision answer, positional-only FAQ

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Comment thread src/deprecate/deprecation.py Outdated

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.

⚠️ Not ready to approve

Documentation currently claims the collision UserWarning applies to proxy surfaces and uses a non-standard # warns: annotation format that should be corrected to match implemented behavior and docs-test conventions.

Copilot's findings
  • Files reviewed: 13/13 changed files
  • Comments generated: 4

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.

Comment thread docs/troubleshooting.md Outdated
Comment thread docs/troubleshooting.md
Comment thread docs/overrides/main.html
Comment thread docs/llms.txt
Borda and others added 4 commits June 18, 2026 18:26
Add collision UserWarning to `_apply_args_mapping` in proxy.py (stacklevel=4)
so `deprecated_class()` now emits UserWarning when both old and new kwarg
names are supplied, matching the existing @deprecated decorator path.

- proxy.py: UserWarning in `_apply_args_mapping` when `explicit_new` non-empty
- proxy.py: fix stale `args_extra` docstrings (args_extra wins, not caller)
- CHANGELOG.md + docs/llms-full.txt: fix single-char `x`/`old_x` example names
- CHANGELOG.md: remove false `deprecated_instance()` args_mapping claim
- docs/troubleshooting.md: fix non-standard `# warns: FutureWarning + UserWarning` format
- tests: add UserWarning proxy test, ARGS_REMAP UserWarning test, async collision test

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
…_args_mapping

Replace the separate dict-comprehension + warning-loop (both iterating the same
condition) with a single `collision_pairs` list computed once, then reused for
building `explicit_new` and emitting UserWarning.

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Both deprecation.py and proxy.py had identical collision-detection +
UserWarning logic. Extract to utils._apply_args_mapping_collisions;
callers pass stacklevel accounting for the added frame (4 in deprecation,
5 in proxy).

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Table padding wastes tokens for AI agents reading the file; a bullet list
carries identical information with less whitespace.

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
@Borda Borda merged commit 48648b4 into main Jun 18, 2026
50 checks passed
@Borda Borda deleted the fix/old-and--new branch June 18, 2026 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug / fix Something isn't working tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants