-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Fix winerror handling #6454
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix winerror handling #6454
Conversation
WalkthroughThis PR refactors OSError exception formatting in Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
crates/vm/src/stdlib/io.rs (1)
1076-1093: Use ofnew_os_subtype_errorfor non‑blocking write looks correct; consider passing errno/written later.Switching to
vm.new_os_subtype_error(vm.ctx.exceptions.blocking_io_error.to_owned(), None, "write could not complete without blocking".to_owned())keeps this in the OSError hierarchy and aligns with the newOSErrorBuilder/PyOSError::__str__flow; behavior for now is equivalent to the old “message‑only” BlockingIOError. When you get to the TODO, it would be good to thread through the underlying errno and the number of bytes written so you can construct the fullBlockingIOError(errno, msg, written)tuple for CPython parity, but that can be a separate change.crates/vm/src/exceptions.rs (1)
1721-1810: NewPyOSError::__str__formatting is consistent and field‑driven; edge cases mostly handled well.The new implementation:
- Reads
errno,strerror,filename,filename2, and (on Windows)winerrorvia attributes and ignores values that areNone, which is robust to partially‑initialized instances.- On Windows, prefers
winerrorand produces:
[WinError N] msg: filename -> filename2when both filenames are present,[WinError N] msg: filenamewhen only one is present,[WinError N] msgwhen onlywinerror/strerrorare present.- Otherwise (or when no
winerror), uses errno‑driven formats:
[Errno N] msg: filename -> filename2,[Errno N] msg: filename,[Errno N] msg(no filename),- and finally falls back to
BaseException.__str__when neither errno nor strerror is available.This lines up well with CPython’s user‑facing strings and works correctly with the updated
OSErrorBuilder/slot_initbehavior (e.g., your newBlockingIOErrorpath inio.rsstill falls back to the single‑argumentBaseExceptionformatting when no errno/filename are set). No functional issues stand out here.
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
crates/vm/src/exceptions.rs(2 hunks)crates/vm/src/stdlib/io.rs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.rs: Follow the default rustfmt code style by runningcargo fmtto format Rust code
Always run clippy to lint Rust code (cargo clippy) before completing tasks and fix any warnings or lints introduced by changes
Follow Rust best practices for error handling and memory management
Use the macro system (pyclass,pymodule,pyfunction, etc.) when implementing Python functionality in Rust
Files:
crates/vm/src/stdlib/io.rscrates/vm/src/exceptions.rs
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Applies to **/*.rs : Follow Rust best practices for error handling and memory management
📚 Learning: 2025-11-10T06:27:41.954Z
Learnt from: youknowone
Repo: RustPython/RustPython PR: 6243
File: vm/src/function/buffer.rs:123-129
Timestamp: 2025-11-10T06:27:41.954Z
Learning: In vm/src/function/buffer.rs, line 36 in the try_rw_bytes_like method intentionally uses TypeError (not BufferError) for the "buffer is not a read-write bytes-like object" error case, even though a similar error message in ArgMemoryBuffer::try_from_borrowed_object uses BufferError. The TypeError is the intended exception type for this specific code path.
Applied to files:
crates/vm/src/stdlib/io.rs
📚 Learning: 2025-12-09T08:46:58.660Z
Learnt from: youknowone
Repo: RustPython/RustPython PR: 6358
File: crates/vm/src/exception_group.rs:173-185
Timestamp: 2025-12-09T08:46:58.660Z
Learning: In crates/vm/src/exception_group.rs, the derive() method intentionally always creates a BaseExceptionGroup instance rather than preserving the original exception class type. This is a deliberate design decision that differs from CPython's behavior.
Applied to files:
crates/vm/src/stdlib/io.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Run snippets and cpython tests (windows-latest)
🔇 Additional comments (1)
crates/vm/src/exceptions.rs (1)
1665-1717: Thedowncast_ref::<PyOSError>()invariant is well-documented and maintained by the macro pattern.The concern about panicking is mitigated: all OSError subclasses in the codebase use
#[repr(transparent)]wrappingPyOSError, and this pattern is enforced by the#[pyexception(base = PyOSError, ...)]macro. The existing safety comment already documents this invariant clearly.However, a runtime debug assertion (e.g., before the
unwrap()) checkingcls.fast_issubclass(os_error)would provide an extra safety layer for detecting violations at runtime, should someone accidentally introduce a subclass without the#[repr(transparent)]wrapper in the future.The field population, Windows winerror-to-errno conversion, and arg truncation logic all look correct:
- Arguments 2–5 are properly mapped to errno/strerror/filename/winerror/filename2.
- Arg truncation only occurs when both
len ∈ [3, 5]andfilenameis non-None, matching CPython behavior.- The
__str__formatting correctly prioritizes Windows winerror, falls back to errno, and respects filenames with proper representation.
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.