* Modularize rustls as work towards providers
`rustls`'s architecture is very clean and trait-driven. There are many
providers for `rustls` including the built-in `aws-lc-rs` and `ring` as
well as backends for `boringssl`, `graviola`, `openssl`, `mbedtls`, etc.
This commit removes the hard dependency on `aws-lc-rs` and adds support
for `ring`. It works towards #7059 as well.
* Clean up rustls features
* Remove ring as an explicit feature
* ssl-rustls is the default and implies aws-lc
* Support custom rustls crypto providers
The new feature, `ssl-rustls-no-provider`, enables custom rustls
providers. By default, `aws-lc-rs` is enabled which matches the old
behavior and keeps backward compatibility.
I wrote a new type that abstracts what we need from crypto providers.
CryptoExt encapsulates the ticketer as well as cipher suites and KX
groups. I wrote fallbacks to help select a reasonable default if a
provider is missing features (they all seem to support the same things
though).
I also wrote an example to show how to actually use custom providers.
* Fix duplicate VERIFY_X509 constants and unused imports in ssl module
Remove duplicate VERIFY_X509_STRICT/VERIFY_X509_PARTIAL_CHAIN definitions
from compat.rs (already defined in _ssl module with #[pyattr]).
Remove unused imports: ClientConnection, ServerConnection.
* no-provider as default
* Fix CI failures: openssl build, wasm target, cargo-shear
- Update openssl.rs to use renamed sock_wait/SockWaitKind and add vm parameter
- Add skip_ssl for wasm32-wasip2 target (aws-lc-sys cannot build for wasm)
- Remove unused workspace dependency aws-lc-rs
- Fix foreign-types-shared version to match openssl's dependency (0.1)
- Restore Cargo.lock from upstream/main
---------
Co-authored-by: Jeong, YunWon <jeong@youknowone.org>
* Add `rapidhash` to list of dependencies
* Use `rapidhash::quality::RandomState` in `codegen` crate
* Use `rapidhash::quality::RandomState` in `stdlib` crate
* Use `rapidhash::quality::RandomState` in `vm` crate
* Remove `ahash` from lists of dependencies
* Convert host_env Windows path/argv params from raw *const u16 to &WideCStr
* Migrate remaining winapi raw u16 pointer signatures to typed references
* Migrate winreg pub unsafe fn string parameters to typed references
* Add ToPyException impls for host_env error types (PyPy wrap_oserror analog)
* Add CheckLibcResult helper and apply to socket/fcntl/shm/posix_wasi
* Add Win32 BOOL/HANDLE check helpers; apply check helpers across host_env
* Apply Win32/libc check helpers to overlapped/testconsole/os.rs
* Apply Win32 check helpers to winapi.rs (partial)
* Apply Win32 check helpers across more winapi.rs functions
* Apply Win32 check helpers to nt.rs (partial)
* Add CheckWin32Sentinel helper; apply to nt.rs INVALID_HANDLE_VALUE/INVALID_FILE_ATTRIBUTES patterns
* Add OwnedHandle / HandleToOwned helper; apply to mmap create_named_mapping leak path
* Use OwnedHandle RAII in nt::pipe to eliminate manual cleanup on error path
* Use OwnedHandle in nt::chmod_follow; hoist HandleToOwned import
* Drop rustix dependency from vm crate
Remove unused IntoPyException impl for rustix::io::Errno and the
rustix entry in crates/vm/Cargo.toml. rustix is now only depended on
by host_env.
* Fix CI failures: cross-platform regressions
- winapi.rs: pass None to create_event_w; the recent Option<&WideCStr>
migration left one call site still passing a raw null pointer.
- exceptions.rs: gate ToPyException for LockfError with
cfg(any(unix, target_os = "wasi")), matching host_env::fcntl's own
cfg. The previous cfg let it compile on wasm32-unknown-unknown where
host_env::fcntl does not exist.
- io_unsupported.rs: derive Eq on FileMode alongside PartialEq to
satisfy clippy::derive_partial_eq_without_eq.
* Fix CI failures: cfg gates and unused imports
- exceptions.rs: gate ToPyException for LockfError with
cfg(all(unix, not(target_os = "redox"))) to match the type's own
cfg in host_env/src/fcntl.rs (LockfError is not built on wasi).
- signal.rs: CheckLibcResult is only used in unix-gated functions;
split import so it is not pulled in for windows.
- mmap.rs: remove CheckWin32Handle from imports; no longer used after
switching to HandleToOwned-based RAII.
- overlapped.rs: remove INVALID_HANDLE_VALUE from connect_pipe import;
the call now uses .check_valid().
* Fix CI failures: rustfmt and windows unused import
- signal.rs: reorder cfg-gated imports per rustfmt.
- socket.rs: gate ToPyException import to cfg(all(unix, not(target_os = "redox")));
it is only used inside sendmsg which has the same gate, so it was unused
on windows.
* Push remaining libc/extern callsites from vm into host_env
Add host_env wrappers and replace the corresponding vm call sites:
- host_env::errno::strerror_string for libc::strerror
- host_env::io::write_stderr_raw for libc::write(STDERR_FILENO,...)
- host_env::locale::localeconv_data reused from vm::format
- host_env::os::abort for the inline abort extern
- host_env::os::urandom wraps getrandom; getrandom moves from vm to host_env
- host_env::posix::lchmod for the macOS/BSD lchmod extern
- host_env::posix::fcopyfile for the macOS fcopyfile extern
- host_env::nt::wputenv for the Windows _wputenv extern
vm/format.rs's get_locale_info now uses host_env on both unix and windows
instead of the unix-only libc::localeconv path.
* Move time tz state and winsound FFI into host_env
- host_env::time::tz: wraps the libc tzset/timezone/daylight/tzname
globals on non-msvc, non-wasm32 targets. vm::stdlib::time now reads
these via the typed wrappers instead of declaring its own externs.
- host_env::winsound (windows): exposes PlaySoundW (via a typed
PlaySoundSource enum), Beep, and MessageBeep. vm::stdlib::winsound
drops its inline FFI block and routes through host_env.
* Migrate unsetenv to host_env::nt::wputenv; rustfmt
- vm::stdlib::os::unsetenv had a second _wputenv call site that still
referenced the removed inline extern. Route it through
host_env::nt::wputenv like putenv.
- rustfmt fixups in exceptions.rs (boolean chain layout) and the two
winsound files.
* Address PR review comments
- host_env::winapi::create_process: assert that the command_line buffer
is NUL-terminated and that the env block ends with a double-NUL,
matching the Win32 CreateProcessW contract.
- stdlib::overlapped CreateEvent: replace WideCString::from_str_truncate
with the fallible from_str(), so embedded NULs in the event name
surface as ValueError instead of being silently truncated.
- vm::exceptions::ReadlinkError::NotSymbolicLink now maps to OSError
(matches Win32 ERROR_NOT_A_REPARSE_POINT semantics) rather than
ValueError.
- winreg::ConnectRegistry: route the non-zero return through the
existing os_error_from_windows_code helper so the resulting exception
carries the real winerror/message instead of a generic OSError.
* Fix CI failures and address review follow-ups
CI failures:
- rustfmt cleanup in exceptions.rs after the ReadlinkError change.
- vm/stdlib/os.rs: drop unused ToWideString import that the wputenv
migration left behind.
- vm/stdlib/winsound.rs: replace explicit `&*buf` with `&buf` to
satisfy clippy::explicit_auto_deref.
- Lib/test/test_format.py, Lib/test/test_types.py: drop the now-stale
expectedFailureIfWindows decorators on the locale-format tests; the
Windows path now reads real `localeconv` data via host_env so these
tests pass.
Review follow-ups:
- host_env::winapi::create_process: switch the new buffer terminator
checks from `assert!` to fallible validators returning
`io::ErrorKind::InvalidInput`, so bad inputs stay recoverable at
the API boundary.
- host_env::winsound::play_sound: reject `Memory(_)` together with
`SND_ASYNC` (lifetime-unsafe) and `SND_MEMORY` without a
`Memory(_)` source. Expand `PlaySoundError` into a variant enum.
- vm::stdlib::_winapi::CreateProcess: route the Win32 path/argv strings
through `as_wtf8().to_wide_cstring()` like the rest of the Windows
API surface; `expect_str()` could panic on Python strings containing
lone surrogates.
RustPython used an ancient, unmaintained version of the `dirs` crate.
This pulled in `winapi-rs` on Windows, which is an old crate that has
been deprecated in favor of `windows-rs`. `windows-rs` is maintained by
Microsoft. Bumping `dirs` to the latest version removes more `winapi-rs`
from Cargo.lock.
As for `uname`, `rustix` handles it safely so the additional crate isn't
needed.
The `page_size` crate is a simple libc wrapper for Unix and uses
`winapi-rs` for Windows. `windows-sys` and `windows-rs` are the modern
alternatives for the unmaintained `winapi-rs`. Both crates are
maintained by Microsoft - they're official. Getting the page size is a
simple call for both Unix and Windows.
Besides Unix and Windows, I also added the page size for wasm32 which
the `page_size` crate did not support. `wasm32`'s page size is a
constant that is defined by the spec, so I hard coded it without adding
additional dependencies.
Finally, I dropped `maplit` which is seven years old and only used in
one place. Calling `collect()` with a single item iterator is idiomatic
as well as better in this case because Rust can optimize it. `maplit`
called `HashMap::insert` which over allocates to amortize future allocs.
* PyBytes.title should be ASCII-only.
* Use icu_casemap over unicode-casing for titles
`icu_casemap` is consistently maintained, official, and tracks the
latest Unicode versions. RustPython is also using other `icu4x` crates,
so using `icu_casemap` is more consistent.
As with islower and isupper, tracking the latest Unicode version is
important because character definitions shift over time which causes
discrepancies between RustPython and CPython.
This commit fixes title().
* Use icu_casemap for capitalize()
I dropped unicode-casing because it's cleaner to use icu4x for
everything. `icu4x` will also stay up to date whereas unicode-casing
will need to be periodically updated with new Unicode tables. Dropping
unicode-casing also removes some binary bloat due to the tables.
`capitalize()` mimics CPython behavior more closely now as well.
Notably, I implemented CPython's sigma edge case handler.
* Match CPython's title() exactly
* Remove unused rust impl for formatting dis output
* remove `examples/dis.rs`
* Added tests
* Update lock
* Try to set snapshot dir
* Remove verbose flag
* Regenerate snapshots after #7711
* Revert "Bump insta from 1.46.3 to 1.47.2 (#7706)"
This reverts commit e6d9ea6bfe.
* Debug info
* Show diff as well
* Show debug faster
* CI: true env
* Recert CI
* Add `CI: true` in ci emv
* Reapply "Bump insta from 1.46.3 to 1.47.2 (#7706)"
This reverts commit 693ca8cbe4d7885a81162a9be31e8bb567db885a.
* simplify macro
* trim on function side
* Force insta workspace root
* fix merge
* fix: Python-Rust combining char diff in isalnum
Related to: #7518
Rust and Python differ on alphanumeric characters. Rust follows the
Unicode standard closer than Python. This means that is_alphanumeric
(char function in Rust) is different from isalnum (Python). To fix the
discrepancy, RustPython needs to mimic Python by rejecting certain
characters. Some classes of combining characters count as alphanumeric
in Rust but not Python. Combining characters are accent marks
that are combined with other characters to create a single grapheme.
It's possible that this PR is not exhaustive. I fixed the combining
character issue BUT I don't know the full range of discrepancies.
* fix: Ignore combining characters in SRE
Closes: #7518