Skip to content

Update weakref from v3.14.2 - #6899

Merged
youknowone merged 2 commits into
RustPython:mainfrom
youknowone:weakref
Jan 30, 2026
Merged

youknowone merged 2 commits into
RustPython:mainfrom
youknowone:weakref

Conversation

@youknowone

@youknowone youknowone commented Jan 30, 2026 •

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Refactor
    • Improved internal handling of weak reference creation arguments for better type error reporting and consistency.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 30, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This pull request refactors argument handling for Python's WeakRef constructor by introducing a dedicated WeakNewArgs struct with explicit positional argument mappings and replacing the automatic binding approach with manual argument parsing in slot_new.

Changes

Cohort / File(s) Summary
WeakRef Argument Handling Refactoring
crates/vm/src/builtins/weakref.rs
Added new WeakNewArgs struct with FromArgs derive to explicitly define positional arguments (referent and optional callback). Modified slot_new to manually unpack positional arguments with explicit arity validation (1–2 arguments), generating type errors for incorrect argument counts. Updated downgrade_with_typ call to pass callback directly instead of converting via into_option().

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A WeakRef hops with cleaner grace,
Arguments parsed in their proper place,
No binding magic, but explicit and clear,
Callbacks and refs—now perfectly dear! 🌿

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is vague and lacks specificity about what changes were made to the weakref module. Use a more descriptive title that explains the actual changes, such as 'Refactor weakref new method argument parsing' or 'Update weakref with new WeakNewArgs struct'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@youknowone
youknowone marked this pull request as ready for review January 30, 2026 10:22
@github-actions

Copy link
Copy Markdown
Contributor

📦 Library Dependencies

The following Lib/ modules were modified. Here are their dependencies:

[x] lib: cpython/Lib/weakref.py
[x] lib: cpython/Lib/_weakrefset.py
[x] test: cpython/Lib/test/test_weakref.py (TODO: 27)

dependencies:

  • weakref

dependent tests: (146 tests)

  • weakref: test_array test_ast test_asyncio test_code test_concurrent_futures test_context test_contextlib test_copy test_deque test_descr test_dict test_exceptions test_file test_fileio test_functools test_generators test_genericalias test_importlib test_inspect test_io test_ipaddress test_itertools test_logging test_memoryview test_mmap test_ordered_dict test_pickle test_picklebuffer test_queue test_re test_scope test_set test_slice test_socket test_sqlite3 test_ssl test_struct test_tempfile test_thread test_threading test_threading_local test_types test_typing test_unittest test_uuid test_weakref test_weakset test_xml_etree
    • asyncio: test_asyncio test_builtin test_contextlib_async test_os test_sys_settrace test_unittest
    • concurrent.futures.process: test_concurrent_futures
    • copy: test_bytes test_codecs test_collections test_csv test_defaultdict test_dictviews test_email test_enum test_fractions test_http_cookies test_opcache test_optparse test_platform test_plistlib test_posix test_site test_statistics test_sysconfig test_tomllib test_xml_dom_minicompat test_zlib
      • dataclasses: test__colorize test_patma test_pprint test_regrtest test_zoneinfo
      • email.generator: test_email
      • http.cookiejar: test_http_cookiejar
      • http.server: test_httpservers test_robotparser test_urllib2_localnet
      • mailbox: test_mailbox
      • smtplib: test_smtplib test_smtpnet
      • tarfile: test_shutil test_tarfile
    • inspect: test_abc test_argparse test_asyncgen test_decimal test_grammar test_ntpath test_operator test_posixpath test_signal test_traceback test_yield_from test_zipimport
      • bdb: test_bdb
      • importlib.metadata: test_importlib
      • rlcompleter: test_rlcompleter
      • trace: test_trace
      • xmlrpc.server: test_docxmlrpc test_xmlrpc
    • multiprocessing: test_concurrent_futures test_fcntl test_multiprocessing_main_handling
    • symtable: test_symtable
    • tempfile: test_bz2 test_cmd_line test_compile test_compileall test_dis test_doctest test_ensurepip test_faulthandler test_filecmp test_fileinput test_importlib test_linecache test_pathlib test_pkg test_pkgutil test_py_compile test_runpy test_selectors test_string_literals test_subprocess test_support test_tabnanny test_threadedtempfile test_urllib test_urllib2 test_urllib_response test_venv test_zipapp test_zipfile test_zipfile64 test_zstd
      • urllib.request: test_urllib2net test_urllibnet

Legend:

  • [+] path exists in CPython
  • [x] up-to-date, [ ] outdated

@youknowone
youknowone enabled auto-merge January 30, 2026 10:23

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@crates/vm/src/builtins/weakref.rs`:
- Around line 44-58: slot_new currently ignores keyword args but must reject
them like CPython 3.14; in the slot_new function check args.kwargs and if not
empty return Err(vm.new_type_error("ref() takes no keyword
arguments".to_owned())); place this check before consuming positional args
(before referent.downgrade_with_typ) so calls like weakref.ref(obj, callback=cb)
raise a TypeError, matching CPython behavior and other builtins (use
args.kwargs, vm.new_type_error, and keep existing logic in slot_new intact).
🧹 Nitpick comments (1)
crates/vm/src/builtins/weakref.rs (1)

17-24: Consider narrowing WeakNewArgs visibility and avoid blanket allow(dead_code).

If this type isn’t used outside the module, pub(crate) (or removing pub) keeps the public API smaller, and dropping the lint suppression avoids masking real unused warnings.

♻️ Suggested tweak
-#[allow(dead_code)]
-pub struct WeakNewArgs {
+pub(crate) struct WeakNewArgs {

Comment on lines 44 to +58
fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
let Self::Args { referent, callback } = args.bind(vm)?;
let weak = referent.downgrade_with_typ(callback.into_option(), cls, vm)?;
// PyArg_UnpackTuple: only process positional args, ignore kwargs.
// Subclass __init__ will handle extra kwargs.
let mut positional = args.args.into_iter();
let referent = positional.next().ok_or_else(|| {
vm.new_type_error("__new__ expected at least 1 argument, got 0".to_owned())
})?;
let callback = positional.next();
if let Some(_extra) = positional.next() {
return Err(vm.new_type_error(format!(
"__new__ expected at most 2 arguments, got {}",
3 + positional.count()
)));
}
let weak = referent.downgrade_with_typ(callback, cls, vm)?;

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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, locate the file and verify its existence
find . -name "weakref.rs" -type f

Repository: RustPython/RustPython

Length of output: 134


🏁 Script executed:

#!/bin/bash
# Check Rust formatting and linting per guidelines
cd crates/vm && cargo fmt -- --check && echo "✓ Formatting OK" || echo "✗ Formatting issues found"

Repository: RustPython/RustPython

Length of output: 591


🏁 Script executed:

#!/bin/bash
# Run clippy with strict warnings
cd crates/vm && cargo clippy --all-targets --all-features -D warnings 2>&1 | head -100

Repository: RustPython/RustPython

Length of output: 604


🌐 Web query:

CPython 3.14 weakref.ref kwargs behavior - does it accept keyword arguments or raise TypeError

💡 Result:

In CPython 3.14, weakref.ref does not accept keyword arguments. Passing any **kwargs (including callback=) raises TypeError (e.g. “ref() takes no keyword arguments”). You must pass the optional callback positionally:

import weakref
r = weakref.ref(obj, cb)     # OK
r = weakref.ref(obj, callback=cb)  # TypeError on CPython 3.14

The documented constructor form is weakref.ref(object[, callback]) (positional parameters). [1]

Sources:
[1] https://docs.python.org/3/library/weakref.html


🏁 Script executed:

#!/bin/bash
# Examine the weakref.rs file to understand kwargs handling
cat -n crates/vm/src/builtins/weakref.rs | head -80

Repository: RustPython/RustPython

Length of output: 2932


🏁 Script executed:

#!/bin/bash
# Search for kwargs handling in weakref implementations
rg "args\.kwargs" crates/vm/src/builtins/weakref.rs -A 3 -B 3

Repository: RustPython/RustPython

Length of output: 47


🏁 Script executed:

#!/bin/bash
# Check if there's any validation/guard for kwargs in the slot_new context
rg "slot_new|FuncArgs|kwargs" crates/vm/src/builtins/weakref.rs -A 2 -B 2

Repository: RustPython/RustPython

Length of output: 1052


🏁 Script executed:

#!/bin/bash
# Look at the broader context of how Constructor trait handles kwargs
rg "impl Constructor" crates/vm/src/builtins/weakref.rs -A 20

Repository: RustPython/RustPython

Length of output: 918


🏁 Script executed:

#!/bin/bash
# Check the FuncArgs structure to understand how kwargs are passed
fd -e rs -e toml . crates/vm/src | xargs rg "struct FuncArgs" -A 5

Repository: RustPython/RustPython

Length of output: 452


🏁 Script executed:

#!/bin/bash
# Look for how Constructor trait slot_new is invoked - check if kwargs validation happens before slot_new
rg "trait Constructor" crates/vm/src -A 10 | head -40

Repository: RustPython/RustPython

Length of output: 850


🏁 Script executed:

#!/bin/bash
# Search for how Constructor.slot_new is called in the framework
rg "slot_new" crates/vm/src -B 3 -A 1 | grep -A 5 "Constructor"

Repository: RustPython/RustPython

Length of output: 12384


🏁 Script executed:

#!/bin/bash
# Check how other builtins handle kwargs validation in slot_new
rg "fn slot_new.*FuncArgs" crates/vm/src/builtins -A 8 | head -60

Repository: RustPython/RustPython

Length of output: 4347


🏁 Script executed:

#!/bin/bash
# Specifically check if any other builtin rejects kwargs explicitly
rg "args\.kwargs" crates/vm/src/builtins -B 5 -A 3 | head -80

Repository: RustPython/RustPython

Length of output: 5365


Add explicit kwargs validation to reject keyword arguments, matching CPython 3.14 behavior.

CPython 3.14's weakref.ref() rejects all keyword arguments with TypeError ("ref() takes no keyword arguments"), but the current slot_new silently ignores kwargs without validation. Add an explicit check:

if !args.kwargs.is_empty() {
    return Err(vm.new_type_error("ref() takes no keyword arguments".to_owned()))
}

This ensures compatibility with CPython's strict positional-only semantics and prevents silent acceptance of invalid calls like weakref.ref(obj, callback=cb). The pattern is used consistently in other builtins (e.g., PyBaseException, PyTemplate).

Note: Rust formatting/linting verification failed due to environment setup errors (LZMA extraction failures). Please recheck cargo fmt and cargo clippy when tools are available.

🤖 Prompt for AI Agents
In `@crates/vm/src/builtins/weakref.rs` around lines 44 - 58, slot_new currently
ignores keyword args but must reject them like CPython 3.14; in the slot_new
function check args.kwargs and if not empty return Err(vm.new_type_error("ref()
takes no keyword arguments".to_owned())); place this check before consuming
positional args (before referent.downgrade_with_typ) so calls like
weakref.ref(obj, callback=cb) raise a TypeError, matching CPython behavior and
other builtins (use args.kwargs, vm.new_type_error, and keep existing logic in
slot_new intact).

@youknowone
youknowone disabled auto-merge January 30, 2026 11:47
@youknowone
youknowone merged commit 9183661 into RustPython:main Jan 30, 2026
24 of 25 checks passed
@youknowone
youknowone deleted the weakref branch January 30, 2026 11:47
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