Skip to content

Update email library v3.13.11#6642

Merged
youknowone merged 7 commits into
RustPython:mainfrom
terryluan12:update_email
Jan 17, 2026
Merged

Update email library v3.13.11#6642
youknowone merged 7 commits into
RustPython:mainfrom
terryluan12:update_email

Conversation

@terryluan12

@terryluan12 terryluan12 commented Jan 4, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Improved bytes-to-text decoding with richer error-handling modes: strict, ignore, replace, backslashreplace, and surrogateescape for better control over encoding issues.
    • Added a new time.altzone() utility to obtain the alternative timezone offset on supported platforms.

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

@coderabbitai

coderabbitai Bot commented Jan 4, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

bytes_decode in crates/vm/src/bytes_inner.rs is rewritten to accept zelf and DecodeArgs, adding nuanced encoding resolution and branching on errors. crates/vm/src/stdlib/time.rs gains a new public altzone attribute returning c_long (platform-guarded).

Changes

Cohort / File(s) Summary
Bytes decoding signature & logic
crates/vm/src/bytes_inner.rs
bytes_decode signature changed to pub fn bytes_decode(zelf: PyObjectRef, args: DecodeArgs, vm: &VirtualMachine) -> PyResult<PyStrRef>; DecodeArgs extended to include errors: Option<PyStrRef>. Encoding resolution now uses Cow, handles invalid UTF-8 encodings with branches for "strict", "ignore", "replace", "backslashreplace", and "surrogateescape", and falls back to DEFAULT_ENCODING when encoding is None. Call sites changed to decode_text(zelf, &encoding, errors, vm).
Time module altzone attribute
crates/vm/src/stdlib/time.rs
Added #[pyattr] fn altzone(_vm: &VirtualMachine) -> core::ffi::c_long (excluded on MSVC and wasm32) returning c_timezone - 3600 with a FIXME for future C altzone integration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nibble bytes and mend each seam,

I chase encodings in a dream,
Errors sorted, surrogates play,
Altzone ticks an hour away,
Hooray—new hops for code today!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title states 'Update email library v3.13.11', but the actual changes modify bytes_inner.rs and time.rs with Cow encoding handling and altzone function additions, which are unrelated to email library updates. Update the PR title to accurately reflect the actual changes, such as 'Add altzone function to time module and refactor bytes_decode with Cow encoding handling' or revert unrelated changes to align with the stated email library update objective.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

@terryluan12 terryluan12 changed the title Update email library Update email library v3.13.11 Jan 4, 2026

@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

🧹 Nitpick comments (1)
crates/vm/src/stdlib/time.rs (1)

200-206: Hardcoded 3600-second DST offset may be incorrect for some timezones.

The calculation c_timezone - 3600 assumes DST offset is always 1 hour, but some regions use different DST offsets (e.g., Lord Howe Island uses 30 minutes). While the FIXME acknowledges this limitation, consider documenting which timezones may return incorrect values or adding a more prominent warning.

The implementation follows the existing pattern in this module and is acceptable as a placeholder until proper C altzone support is added.

📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8bfe927 and 2773e69.

⛔ Files ignored due to path filters (93)
  • Lib/email/_header_value_parser.py is excluded by !Lib/**
  • Lib/email/_parseaddr.py is excluded by !Lib/**
  • Lib/email/_policybase.py is excluded by !Lib/**
  • Lib/email/contentmanager.py is excluded by !Lib/**
  • Lib/email/feedparser.py is excluded by !Lib/**
  • Lib/email/generator.py is excluded by !Lib/**
  • Lib/email/header.py is excluded by !Lib/**
  • Lib/email/message.py is excluded by !Lib/**
  • Lib/email/parser.py is excluded by !Lib/**
  • Lib/email/utils.py is excluded by !Lib/**
  • Lib/test/support/testresult.py is excluded by !Lib/**
  • Lib/test/test_email/__init__.py is excluded by !Lib/**
  • Lib/test/test_email/__main__.py is excluded by !Lib/**
  • Lib/test/test_email/data/msg_01.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_02.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_03.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_04.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_05.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_06.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_07.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_08.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_09.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_10.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_11.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_12.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_12a.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_13.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_14.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_15.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_16.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_17.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_18.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_19.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_20.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_21.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_22.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_23.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_24.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_25.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_26.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_27.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_28.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_29.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_30.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_31.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_32.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_33.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_34.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_35.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_36.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_37.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_38.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_39.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_40.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_41.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_42.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_43.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_44.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_45.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_46.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_47.txt is excluded by !Lib/**
  • Lib/test/test_email/data/python.bmp is excluded by !**/*.bmp, !Lib/**
  • Lib/test/test_email/data/python.exr is excluded by !Lib/**
  • Lib/test/test_email/data/python.gif is excluded by !**/*.gif, !Lib/**
  • Lib/test/test_email/data/python.jpg is excluded by !**/*.jpg, !Lib/**
  • Lib/test/test_email/data/python.pbm is excluded by !Lib/**
  • Lib/test/test_email/data/python.pgm is excluded by !Lib/**
  • Lib/test/test_email/data/python.png is excluded by !**/*.png, !Lib/**
  • Lib/test/test_email/data/python.ppm is excluded by !Lib/**
  • Lib/test/test_email/data/python.ras is excluded by !Lib/**
  • Lib/test/test_email/data/python.sgi is excluded by !Lib/**
  • Lib/test/test_email/data/python.tiff is excluded by !**/*.tiff, !Lib/**
  • Lib/test/test_email/data/python.webp is excluded by !Lib/**
  • Lib/test/test_email/data/python.xbm is excluded by !Lib/**
  • Lib/test/test_email/data/sndhdr.aifc is excluded by !Lib/**
  • Lib/test/test_email/data/sndhdr.aiff is excluded by !Lib/**
  • Lib/test/test_email/data/sndhdr.au is excluded by !Lib/**
  • Lib/test/test_email/data/sndhdr.wav is excluded by !**/*.wav, !Lib/**
  • Lib/test/test_email/test__encoded_words.py is excluded by !Lib/**
  • Lib/test/test_email/test__header_value_parser.py is excluded by !Lib/**
  • Lib/test/test_email/test_asian_codecs.py is excluded by !Lib/**
  • Lib/test/test_email/test_contentmanager.py is excluded by !Lib/**
  • Lib/test/test_email/test_defect_handling.py is excluded by !Lib/**
  • Lib/test/test_email/test_email.py is excluded by !Lib/**
  • Lib/test/test_email/test_generator.py is excluded by !Lib/**
  • Lib/test/test_email/test_headerregistry.py is excluded by !Lib/**
  • Lib/test/test_email/test_inversion.py is excluded by !Lib/**
  • Lib/test/test_email/test_message.py is excluded by !Lib/**
  • Lib/test/test_email/test_parser.py is excluded by !Lib/**
  • Lib/test/test_email/test_pickleable.py is excluded by !Lib/**
  • Lib/test/test_email/test_policy.py is excluded by !Lib/**
  • Lib/test/test_email/test_utils.py is excluded by !Lib/**
  • Lib/test/test_email/torture_test.py is excluded by !Lib/**
📒 Files selected for processing (2)
  • crates/vm/src/bytes_inner.rs
  • crates/vm/src/stdlib/time.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.rs: Follow the default rustfmt code style by running cargo fmt to format Rust code
Always run clippy to lint 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/time.rs
  • crates/vm/src/bytes_inner.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). (11)
  • GitHub Check: Run rust tests (macos-latest)
  • GitHub Check: Run tests under miri
  • GitHub Check: Run rust tests (windows-latest)
  • GitHub Check: Run snippets and cpython tests (windows-latest)
  • GitHub Check: Run snippets and cpython tests (ubuntu-latest)
  • GitHub Check: Run snippets and cpython tests (macos-latest)
  • GitHub Check: Run rust tests (ubuntu-latest)
  • GitHub Check: Check Rust code with clippy
  • GitHub Check: Run snippets and cpython tests on wasm-wasi
  • GitHub Check: Ensure compilation on various targets
  • GitHub Check: Check the WASM package and demo
🔇 Additional comments (1)
crates/vm/src/bytes_inner.rs (1)

1091-1097: LGTM!

Adding the Debug derive to DecodeArgs improves debuggability. The struct definition is clean and follows the existing patterns in this file.

Comment thread crates/vm/src/bytes_inner.rs Outdated
@terryluan12 terryluan12 changed the title Update email library v3.13.11 Update email library + test.support v3.13.11 Jan 5, 2026
@terryluan12 terryluan12 closed this Jan 5, 2026
@terryluan12 terryluan12 deleted the update_email branch January 5, 2026 19:06
@terryluan12 terryluan12 restored the update_email branch January 5, 2026 19:06
@youknowone youknowone reopened this Jan 6, 2026
@youknowone

Copy link
Copy Markdown
Member

@terryluan12 was there problem in this PR?

@terryluan12

terryluan12 commented Jan 6, 2026

Copy link
Copy Markdown
Contributor Author

I don't remember closing this, whoops. Yes, there are many lol. Please don't merge. I'm planning to keep the PR open while I work on it, if that's alright

@terryluan12 terryluan12 marked this pull request as draft January 6, 2026 04:39
@terryluan12 terryluan12 force-pushed the update_email branch 2 times, most recently from be9a494 to af6bf40 Compare January 15, 2026 00:19
@github-actions

Copy link
Copy Markdown
Contributor

Code has been automatically formatted

The code in this PR has been formatted using:

  • cargo fmt --all
    Please pull the latest changes before pushing again:
git pull origin update_email

@terryluan12 terryluan12 force-pushed the update_email branch 4 times, most recently from 4d8deae to b672bd0 Compare January 16, 2026 03:19
@terryluan12 terryluan12 marked this pull request as ready for review January 16, 2026 04:44

@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/bytes_inner.rs`:
- Around line 1107-1128: The code panics because it calls s.as_str() on a
Surrogate-containing OsString (s) after s.to_str() returned None; update the
branch inside match encoding.as_ref() (the "ignore" | "replace" |
"backslashreplace" arm) to avoid s.as_str() and instead use a lossy conversion
(e.g., s.to_string_lossy()) when producing the fallback encoding string (keep
using crate::codecs::DEFAULT_ENCODING when encoding is None); ensure you still
respect the errors variable and return vm.new_unicode_encode_error where
appropriate.
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2773e69 and e870f9a.

⛔ Files ignored due to path filters (94)
  • Lib/email/_header_value_parser.py is excluded by !Lib/**
  • Lib/email/_parseaddr.py is excluded by !Lib/**
  • Lib/email/_policybase.py is excluded by !Lib/**
  • Lib/email/contentmanager.py is excluded by !Lib/**
  • Lib/email/feedparser.py is excluded by !Lib/**
  • Lib/email/generator.py is excluded by !Lib/**
  • Lib/email/header.py is excluded by !Lib/**
  • Lib/email/message.py is excluded by !Lib/**
  • Lib/email/parser.py is excluded by !Lib/**
  • Lib/email/utils.py is excluded by !Lib/**
  • Lib/test/test_context.py is excluded by !Lib/**
  • Lib/test/test_email/__init__.py is excluded by !Lib/**
  • Lib/test/test_email/__main__.py is excluded by !Lib/**
  • Lib/test/test_email/data/msg_01.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_02.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_03.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_04.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_05.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_06.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_07.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_08.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_09.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_10.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_11.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_12.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_12a.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_13.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_14.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_15.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_16.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_17.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_18.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_19.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_20.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_21.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_22.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_23.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_24.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_25.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_26.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_27.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_28.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_29.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_30.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_31.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_32.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_33.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_34.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_35.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_36.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_37.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_38.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_39.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_40.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_41.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_42.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_43.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_44.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_45.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_46.txt is excluded by !Lib/**
  • Lib/test/test_email/data/msg_47.txt is excluded by !Lib/**
  • Lib/test/test_email/data/python.bmp is excluded by !**/*.bmp, !Lib/**
  • Lib/test/test_email/data/python.exr is excluded by !Lib/**
  • Lib/test/test_email/data/python.gif is excluded by !**/*.gif, !Lib/**
  • Lib/test/test_email/data/python.jpg is excluded by !**/*.jpg, !Lib/**
  • Lib/test/test_email/data/python.pbm is excluded by !Lib/**
  • Lib/test/test_email/data/python.pgm is excluded by !Lib/**
  • Lib/test/test_email/data/python.png is excluded by !**/*.png, !Lib/**
  • Lib/test/test_email/data/python.ppm is excluded by !Lib/**
  • Lib/test/test_email/data/python.ras is excluded by !Lib/**
  • Lib/test/test_email/data/python.sgi is excluded by !Lib/**
  • Lib/test/test_email/data/python.tiff is excluded by !**/*.tiff, !Lib/**
  • Lib/test/test_email/data/python.webp is excluded by !Lib/**
  • Lib/test/test_email/data/python.xbm is excluded by !Lib/**
  • Lib/test/test_email/data/sndhdr.aifc is excluded by !Lib/**
  • Lib/test/test_email/data/sndhdr.aiff is excluded by !Lib/**
  • Lib/test/test_email/data/sndhdr.au is excluded by !Lib/**
  • Lib/test/test_email/data/sndhdr.wav is excluded by !**/*.wav, !Lib/**
  • Lib/test/test_email/test__encoded_words.py is excluded by !Lib/**
  • Lib/test/test_email/test__header_value_parser.py is excluded by !Lib/**
  • Lib/test/test_email/test_asian_codecs.py is excluded by !Lib/**
  • Lib/test/test_email/test_contentmanager.py is excluded by !Lib/**
  • Lib/test/test_email/test_defect_handling.py is excluded by !Lib/**
  • Lib/test/test_email/test_email.py is excluded by !Lib/**
  • Lib/test/test_email/test_generator.py is excluded by !Lib/**
  • Lib/test/test_email/test_headerregistry.py is excluded by !Lib/**
  • Lib/test/test_email/test_inversion.py is excluded by !Lib/**
  • Lib/test/test_email/test_message.py is excluded by !Lib/**
  • Lib/test/test_email/test_parser.py is excluded by !Lib/**
  • Lib/test/test_email/test_pickleable.py is excluded by !Lib/**
  • Lib/test/test_email/test_policy.py is excluded by !Lib/**
  • Lib/test/test_email/test_utils.py is excluded by !Lib/**
  • Lib/test/test_email/torture_test.py is excluded by !Lib/**
  • Lib/test/test_time.py is excluded by !Lib/**
📒 Files selected for processing (1)
  • crates/vm/src/bytes_inner.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.rs: Follow the default rustfmt code style using cargo fmt to format Rust code
Always run clippy to lint 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/bytes_inner.rs
🧠 Learnings (2)
📚 Learning: 2025-08-26T05:20:54.540Z
Learnt from: youknowone
Repo: RustPython/RustPython PR: 6110
File: vm/src/frame.rs:1311-1316
Timestamp: 2025-08-26T05:20:54.540Z
Learning: In RustPython's pattern matching implementation, only certain builtin types should have the SEQUENCE flag: list and tuple are confirmed sequences. The user youknowone indicated that bytes, bytearray are not considered sequences in this context, even though they implement sequence-like protocols.

Applied to files:

  • crates/vm/src/bytes_inner.rs
📚 Learning: 2025-08-26T05:20:54.540Z
Learnt from: youknowone
Repo: RustPython/RustPython PR: 6110
File: vm/src/frame.rs:1311-1316
Timestamp: 2025-08-26T05:20:54.540Z
Learning: In the RustPython codebase, only certain builtin types should be marked with the SEQUENCE flag for pattern matching. List and tuple are sequences, but bytes, bytearray, and range are not considered sequences in this context, even though they may implement sequence-like protocols.

Applied to files:

  • crates/vm/src/bytes_inner.rs

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread crates/vm/src/bytes_inner.rs Outdated
Comment on lines +1107 to +1128
let encoding: Cow<'_, str> = match encoding.as_ref() {
Some(s) => match s.to_str() {
Some(valid_str) => Cow::Borrowed(valid_str),
None => {
let Some(errors) = &errors else {
return Err(vm.new_unicode_encode_error(format!(
"'{}' codec can't encode characters: surrogates not allowed",
s
)));
};

match errors.as_str() {
"strict" => {
return Err(
vm.new_unicode_encode_error("Struct format must be a UTF-8 string")
);
}
"ignore" | "replace" | "backslashreplace" => Cow::Borrowed(
encoding
.as_ref()
.map_or(crate::codecs::DEFAULT_ENCODING, |s| s.as_str()),
),

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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find PyStr implementations and examine to_str/as_str methods
fd -g 'pystr*.rs' crates --exec rg -l "impl.*PyStr" {} \;

Repository: RustPython/RustPython

Length of output: 132


🏁 Script executed:

#!/bin/bash
# More comprehensive search for PyStr type and its methods
rg -n "fn (to_str|as_str|to_string_lossy)" crates/vm/src/ -A 3 | head -100

Repository: RustPython/RustPython

Length of output: 2229


🏁 Script executed:

#!/bin/bash
# Examine the exact code at the problematic lines
cat -n crates/vm/src/bytes_inner.rs | sed -n '1095,1145p'

Repository: RustPython/RustPython

Length of output: 2181


🏁 Script executed:

#!/bin/bash
# Verify the call to s.as_str() at line 1127 - trace through the logic
cat -n crates/vm/src/builtins/str.rs | sed -n '437,443p'

Repository: RustPython/RustPython

Length of output: 287


🏁 Script executed:

#!/bin/bash
# Verify as_str() panic behavior by checking the expect message context
cat -n crates/vm/src/builtins/str.rs | sed -n '464,467p'

Repository: RustPython/RustPython

Length of output: 263


Using as_str() on surrogate-containing string will panic.

At line 1108, s.to_str() returns None when encoding has surrogates. Then at line 1127, s.as_str() is called on that same string, which calls .expect("str has surrogates") and panics. Use to_string_lossy() instead, as the "surrogateescape" handler correctly does at line 1129.

🤖 Prompt for AI Agents
In `@crates/vm/src/bytes_inner.rs` around lines 1107 - 1128, The code panics
because it calls s.as_str() on a Surrogate-containing OsString (s) after
s.to_str() returned None; update the branch inside match encoding.as_ref() (the
"ignore" | "replace" | "backslashreplace" arm) to avoid s.as_str() and instead
use a lossy conversion (e.g., s.to_string_lossy()) when producing the fallback
encoding string (keep using crate::codecs::DEFAULT_ENCODING when encoding is
None); ensure you still respect the errors variable and return
vm.new_unicode_encode_error where appropriate.

@youknowone youknowone left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks! I need to understand better about Rust file changes. Please check the comments

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The changes in this file doesn't look directly related to email library.
Could you share what's the motivation and what is it exactly fixing?
Adding a test case under extra_test/snippets helps to understand it better.

Please open a separated PR for changes of bytes_decode. I have to research more about this to understand what's changing.

@terryluan12 terryluan12 Jan 17, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The new code partially implements the second argument of the decode* function

Relevant Python3 documentation here

I'll open a new PR soon, with the changes (Plus a couple more; I'll probably just try and implement all cases)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(The relevant test is test_invalid_character_in_charset btw, I just skipped the test)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Nevermind, I'm definitely wrong somewhere 🤦. Taking a look into it further

Comment thread crates/vm/src/bytes_inner.rs

@youknowone youknowone left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

@youknowone youknowone changed the title Update email library + test.support v3.13.11 Update email library v3.13.11 Jan 17, 2026
@youknowone youknowone merged commit 833f734 into RustPython:main Jan 17, 2026
13 checks passed
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.

2 participants